Incorporate extbigarray
This set of work aims to incorporate all of Extbigarray's functionality but using monomorphic (consequently faster) functions via bigarray_fold_ppx.
@hcarty I'd like to get your opinion on this approach. I've used a ppx to write all of the operations where specifying the kind would generate faster code using for loops that do exactly that. Some of the rough performance tests show a 3x-10x speed up on some of these operations, so I think this is a better approach. Then I use cppo to automate the invocation of this ppx with the various combinations. I've only implemented mono and dimorphic (wrt. the Bigarray kind) functions so far and only for Array1:
module Array1 :
sig
type ('a, 'b, 'c) t = ('a, 'b, 'c) Bigarray.Array1.t
val create :
('a, 'b) Bigarray.kind -> 'c Bigarray.layout -> int -> ('a, 'b, 'c) t
(* .... same as original, the new stuff is: *)
val init :
('a, 'b) Bigarray.kind ->
'c Bau__BigarrayExt.layout -> int -> (int -> 'a) -> ('a, 'b, 'c) t
val copy : ('a, 'b, 'c) t -> ('a, 'b, 'c) t
val to_array : f:('a -> 'b) -> ('a, 'c, 'd) t -> 'b array
(* If you know one kind then use one of these nested modules: *)
module Float32 : sig ... end
module Float64 : sig ... end
module Int8_signed : sig ... end
module Int8_unsigned : sig ... end
module Int16_signed : sig ... end
module Int16_unsigned : sig ... end
module Int : sig ... end
module Int32 : sig ... end
module Int64 : sig ... end
module Nativeint : sig ... end
module Complex32 : sig ... end
module Complex64 : sig ... end
module Char : sig ... end
end
and they contain
module Array1.Float32 :
sig
val fold_left :
f:('a -> float -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t -> 'a
val fold_right :
f:(float -> 'a -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t -> 'a
val foldi :
f:('a -> int -> float -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t -> 'a
val reduce_left :
f:(float -> float -> float) ->
(float, float32_elt, 'a) Array1.t ->
float
val reduce_right :
f:(float -> float -> float) ->
(float, float32_elt, 'a) Array1.t ->
float
val reducei :
f:(float -> int -> float -> float) ->
(float, float32_elt, 'a) Array1.t ->
float
val iter :
f:(float -> unit) ->
(float, float32_elt, 'a) Array1.t ->
unit
val iteri :
f:(int -> float -> unit) ->
(float, float32_elt, 'a) Array1.t ->
unit
val modify :
f:(float -> float) ->
(float, float32_elt, 'a) Array1.t ->
unit
val modifyi :
f:(int -> float -> float) ->
(float, float32_elt, 'a) Array1.t ->
unit
val init :
f:(int -> float) ->
'a Bigarray.layout ->
int ->
(float, float32_elt, 'a) Array1.t
val to_array :
(float, float32_elt, 'a) Array1.t ->
float array
val of_array :
float array ->
'a layout ->
(float, float32_elt, 'a) Array1.t
(* When you know the 2nd kind, even more nested modules *)
module Float32 : sig ... end
module Float64 : sig ... end
module Int8_signed : sig ... end
module Int8_unsigned : sig ... end
module Int16_signed : sig ... end
module Int16_unsigned : sig ... end
module Int : sig ... end
module Int32 : sig ... end
module Int64 : sig ... end
module Nativeint : sig ... end
module Complex32 : sig ... end
module Complex64 : sig ... end
module Char : sig ... end
end
and those 2x nested modules look like:
module Array1.Float32.Float64 :
sig
val fold_left2 :
f:('a -> float -> float -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t ->
(float, float64_elt, 'c) Array1.t -> 'a
val fold_right2 :
f:(float -> float -> 'a -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t ->
(float, float64_elt, 'c) Array1.t -> 'a
val foldi2 :
f:('a -> int -> float -> float -> 'a) ->
init:'a ->
(float, float32_elt, 'b) Array1.t ->
(float, float64_elt, 'c) Array1.t -> 'a
val iter2 :
f:(float -> float -> unit) ->
(float, float32_elt, 'a) Array1.t ->
(float, float64_elt, 'b) Array1.t ->
unit
val iteri2 :
f:(int -> float -> float -> unit) ->
(float, float32_elt, 'a) Array1.t ->
(float, float64_elt, 'b) Array1.t ->
unit
val map :
f:(float -> float) ->
(float, float32_elt, 'a) Array1.t ->
(float, float64_elt, 'a) Array1.t
val mapi :
f:(int -> float -> float) ->
(float, float32_elt, 'a) Array1.t ->
(float, float64_elt, 'a) Array1.t
end
All in all writing something like
let norms v = Array1.Complex64.Float64.map ~f:Complex.norm v
doesn't seem to be that bad. Thoughts?
That looks good to me! The ppx removes/centralizes most of the potential for typos in the codebase, so it's nice to have that much flexibility in nesting.
I like it.