# Chapter 29 The bigarray library

- Module `Bigarray`: large, multi-dimensional, numerical arrays
- Big arrays in the OCaml-C interface

The `bigarray` library implements large, multi-dimensional, numerical arrays. These arrays are called “big arrays” to distinguish them from the standard OCaml arrays described in Module `Array`. The main differences between “big arrays” and standard OCaml arrays are as follows:

- Big arrays are not limited in size, unlike OCaml arrays (`float array` are limited to 2097151 elements on a 32-bit platform, other `array` types to 4194303 elements).
- Big arrays are multi-dimensional. Any number of dimensions between 1 and 16 is supported. In contrast, OCaml arrays are mono-dimensional and require encoding multi-dimensional arrays as arrays of arrays.
- Big arrays can only contain integers and floating-point numbers, while OCaml arrays can contain arbitrary OCaml data types. However, big arrays provide more space-efficient storage of integer and floating-point elements, in particular because they support “small” types such as single-precision floats and 8 and 16-bit integers, in addition to the standard OCaml types of double-precision floats and 32 and 64-bit integers.
- The memory layout of big arrays is entirely compatible with that of arrays in C and Fortran, allowing large arrays to be passed back and forth between OCaml code and C / Fortran code with no data copying at all.
- Big arrays support interesting high-level operations that normal arrays do not provide efficiently, such as extracting sub-arrays and “slicing” a multi-dimensional array along certain dimensions, all without any copying.

Programs that use the `bigarray` library must be linked as follows:

            ocamlc other options bigarray.cma other files
            ocamlopt other options bigarray.cmxa other files

For interactive use of the `bigarray` library, do:

            ocamlmktop -o mytop bigarray.cma
            ./mytop

or (if dynamic linking of C libraries is supported on your platform), start `ocaml` and type `#load "bigarray.cma";;`.

## 29.1 Module `Bigarray`: large, multi-dimensional, numerical arrays

- Module `Bigarray`

## 29.2 Big arrays in the OCaml-C interface

C stub code that interface C or Fortran code with OCaml code, as described in chapter 19, can exploit big arrays as follows.

### 29.2.1 Include file

The include file `<caml/bigarray.h>` must be included in the C stub file. It declares the functions, constants and macros discussed below.

### 29.2.2 Accessing an OCaml bigarray from C or Fortran

If v is a OCaml `value` representing a big array, the expression `Data_bigarray_val(`v`)` returns a pointer to the data part of the array. This pointer is of type `void *` and can be cast to the appropriate C type for the array (e.g. `double []`, `char [][10]`, etc).

Various characteristics of the OCaml big array can be consulted from C as follows:

C expression | Returns
`Bigarray_val(`v`)->num_dims` | number of dimensions
`Bigarray_val(`v`)->dim[`i`]` | i-th dimension
`Bigarray_val(`v`)->flags & BIGARRAY_KIND_MASK` | kind of array elements

The kind of array elements is one of the following constants:

Constant | Element kind
`BIGARRAY_FLOAT32` | 32-bit single-precision floats
`BIGARRAY_FLOAT64` | 64-bit double-precision floats
`BIGARRAY_SINT8` | 8-bit signed integers
`BIGARRAY_UINT8` | 8-bit unsigned integers
`BIGARRAY_SINT16` | 16-bit signed integers
`BIGARRAY_UINT16` | 16-bit unsigned integers
`BIGARRAY_INT32` | 32-bit signed integers
`BIGARRAY_INT64` | 64-bit signed integers
`BIGARRAY_CAML_INT` | 31- or 63-bit signed integers
`BIGARRAY_NATIVE_INT` | 32- or 64-bit (platform-native) integers

The following example shows the passing of a two-dimensional big array to a C function and a Fortran function.

        extern void my_c_function(double * data, int dimx, int dimy);
        extern void my_fortran_function_(double * data, int * dimx, int * dimy);

        value caml_stub(value bigarray)
        {
          int dimx = Bigarray_val(bigarray)->dim[0];
          int dimy = Bigarray_val(bigarray)->dim[1];
          /* C passes scalar parameters by value */
          my_c_function(Data_bigarray_val(bigarray), dimx, dimy);
          /* Fortran passes all parameters by reference */
          my_fortran_function_(Data_bigarray_val(bigarray), &dimx, &dimy);
          return Val_unit;
        }

### 29.2.3 Wrapping a C or Fortran array as an OCaml big array

A pointer p to an already-allocated C or Fortran array can be wrapped and returned to OCaml as a big array using the `alloc_bigarray` or `alloc_bigarray_dims` functions.

- `alloc_bigarray(`kind `|` layout, numdims, p, dims`)`

  Return an OCaml big array wrapping the data pointed to by p. kind is the kind of array elements (one of the `BIGARRAY_` kind constants above). layout is `BIGARRAY_C_LAYOUT` for an array with C layout and `BIGARRAY_FORTRAN_LAYOUT` for an array with Fortran layout. numdims is the number of dimensions in the array. dims is an array of numdims long integers, giving the sizes of the array in each dimension.

- `alloc_bigarray_dims(`kind `|` layout, numdims, p, `(long)` dim1, `(long)` dim2, …, `(long)` dimnumdims`)`

  Same as `alloc_bigarray`, but the sizes of the array in each dimension are listed as extra arguments in the function call, rather than being passed as an array.

The following example illustrates how statically-allocated C and Fortran arrays can be made available to OCaml.

        extern long my_c_array[100][200];
        extern float my_fortran_array_[300][400];

        value caml_get_c_array(value unit)
        {
          long dims[2];
          dims[0] = 100; dims[1] = 200;
          return alloc_bigarray(BIGARRAY_NATIVE_INT | BIGARRAY_C_LAYOUT,
                                2, my_c_array, dims);
        }

        value caml_get_fortran_array(value unit)
        {
          return alloc_bigarray_dims(BIGARRAY_FLOAT32 | BIGARRAY_FORTRAN_LAYOUT,
                                     2, my_fortran_array_, 300L, 400L);
        }