Capturing the Bigarray indexing syntax

Currently, Owl has a multidimensional Array module which uses only Bigarray.Genarray.t and never the specialized Array{1,2,3}.t. The best syntax Owl can currently provide for array element access is e.g. a.%{[|0|]} . Compared to a.{0} that’s twice the number of characters. Considering element access is very common, this is annoying.

Using a trick, it is possible to repurpose the indexing syntax of standard OCaml modules.
It goes as follows:

module S = struct 
  include String 
  let get s i = 
    let c = String.get s i in
    print_endline "getting the character for you!"; c
end
module String = S
"sdfsdf".[2]

Is it possible to do a similar thing for Bigarray.Array{1,2,3} and Bigarray.Genarray simultaneously, so that in the end, one could have a module Arr with a single type which would support all of the following:

let a, b, c, d = Arr.(zeros [|1|], zeros [|1;1|], zeros [|1;1;1|] , zeros [|1;1;1;1|])
open Arr (* or whatever is required *)
let element_list = [a.{0}, b.{0,0}, c.{0,0,0}, d.{0,0,0,0}]

and where a.{0,0} would raise a runtime error? The idea is that opening Arr (or maybe redefining Bigarray.Array{1,2,3} in some way) would capture and reuse the various Bigarray indexing syntaxes. It’s ok if Bigarray gets butchered in the process – access to arrays is handled by Arr anyway.

How often do you need to index multidimensional array of generic dimension? It seems perfectly doable to do have an indexing submodule by dimension:

 vec.Vec.%{ k }, mat.Mat.%{i,j}, t4.T4.%{i,j,k,l} 

This is why @lpw25 rightly insisted to have the qualified syntax in 4.06 . Then, the generic syntax will be only used for the rare very high dimensional array.

If you really need a better syntax for array of generic dimension, please open a ticket on Mantis with a good motivating example, rather than try to hijack the Bigarray module.There are still some room in the 4.06 syntax to interpret x.!{ 1; 2; 3 } as x.!{ [| 1; 2; 3 |] } or x.!{[1;2;3]}, but this is not the case anymore in the dev version of 4.07.

p.s. : to answer, yes it is possible to hijack the Bigarray module, but you need to define the indexing function in each submodule of Bigarray (i.e. Genarray, Array1, Array2 and Array3).

Thanks for this input. I agree that fixed-dimension modules are useful, and indeed there already is a Mat module and I believe Vec is planned. However, a uniform n-dimensional Array type is still useful. For instance, one may want to take slices of it along one or more dimensions, which may reduce the dimensionality in dynamic (i.e. only known at runtime) ways. Or one can increase dimensionality by grouping etc.

While I admit that true dynamic dimensionality is probably rather rare, I would say it’s quite common to freely manipulate the shape and dimensionality of generic arrays in numerical computing. If one later wants to index the result, it would be a bit unnatural to have to resort to specialized modules whenever it happens to be 1,2,3-dimensional IMO.

I think x.!{1;2;3} etc would be a satisfying solution. (I guess x.!{1,2,3} is already interpreted as a tuple of fixed length?)

This is indeed the case.

x.%{1; 2; 3} seems a very good solution to me if this can be associated with Genarray.get/set. This will make Owl’s applications even more concise and readable.

x.!{...} has been associated with Owl’s fancy indexing :slight_smile:

I opened an issue on Mantis

For the record: https://caml.inria.fr/mantis/view.php?id=7757

2 Likes

This issue has priority ‘feature’. IIUC, @octachron suggested that it would not be possible to add new syntax in 4.07? Does this mean I should try to increase the priority?

I think feature is the right priority. It might be harder to change the syntax after 4.07, but this is not an absolute.