CAMLprim value caml_ba_reshape(value vb, value vdim) { CAMLparam2 (vb, vdim); CAMLlocal1 (res); #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) intnat dim[CAML_BA_MAX_NUM_DIMS]; mlsize_t num_dims; uintnat num_elts; int i; num_dims = Wosize_val(vdim); if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS) caml_invalid_argument("Bigarray.reshape: bad number of dimensions"); num_elts = 1; for (i = 0; i < num_dims; i++) { dim[i] = Long_val(Field(vdim, i)); if (dim[i] < 0) caml_invalid_argument("Bigarray.reshape: negative dimension"); num_elts *= dim[i]; } /* Check that sizes agree */ if (num_elts != caml_ba_num_elts(b)) caml_invalid_argument("Bigarray.reshape: size mismatch"); /* Create bigarray with same data and new dimensions */ res = caml_ba_alloc(b->flags, num_dims, b->data, dim); /* Create or update proxy in case of managed bigarray */ caml_ba_update_proxy(b, Caml_ba_array_val(res)); /* Return result */ CAMLreturn (res); #undef b }
value caml_ba_change_flags(value vb, value vkind, value vlen) { CAMLparam3 (vb, vkind, vlen); CAMLlocal1 (res); #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) int flags = Int_val(vkind) | CAML_BA_C_LAYOUT | CAML_BA_MANAGED; intnat len = Long_val(vlen); res = caml_ba_alloc(flags, b->num_dims, b->data, b->dim); Caml_ba_array_val(res)->dim[0] = len; caml_ba_update_proxy(b, Caml_ba_array_val(res)); CAMLreturn (res); #undef b }
CAMLprim value caml_ba_slice(value vb, value vind) { CAMLparam2 (vb, vind); #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) CAMLlocal1 (res); intnat index[CAML_BA_MAX_NUM_DIMS]; int num_inds, i; intnat offset; intnat * sub_dims; char * sub_data; /* Check number of indices < number of dimensions of array */ num_inds = Wosize_val(vind); if (num_inds >= b->num_dims) caml_invalid_argument("Bigarray.slice: too many indices"); /* Compute offset and check bounds */ if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { /* We slice from the left */ for (i = 0; i < num_inds; i++) index[i] = Long_val(Field(vind, i)); for (/*nothing*/; i < b->num_dims; i++) index[i] = 0; offset = caml_ba_offset(b, index); sub_dims = b->dim + num_inds; } else { /* We slice from the right */ for (i = 0; i < num_inds; i++) index[b->num_dims - num_inds + i] = Long_val(Field(vind, i)); for (i = 0; i < b->num_dims - num_inds; i++) index[i] = 1; offset = caml_ba_offset(b, index); sub_dims = b->dim; } sub_data = (char *) b->data + offset * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; /* Allocate an OCaml bigarray to hold the result */ res = caml_ba_alloc(b->flags, b->num_dims - num_inds, sub_data, sub_dims); /* Create or update proxy in case of managed bigarray */ caml_ba_update_proxy(b, Caml_ba_array_val(res)); /* Return result */ CAMLreturn (res); #undef b }
CAMLprim value caml_ba_sub(value vb, value vofs, value vlen) { CAMLparam3 (vb, vofs, vlen); CAMLlocal1 (res); #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) intnat ofs = Long_val(vofs); intnat len = Long_val(vlen); int i, changed_dim; intnat mul; char * sub_data; /* Compute offset and check bounds */ if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { /* We reduce the first dimension */ mul = 1; for (i = 1; i < b->num_dims; i++) mul *= b->dim[i]; changed_dim = 0; } else { /* We reduce the last dimension */ mul = 1; for (i = 0; i < b->num_dims - 1; i++) mul *= b->dim[i]; changed_dim = b->num_dims - 1; ofs--; /* Fortran arrays start at 1 */ } if (ofs < 0 || len < 0 || ofs + len > b->dim[changed_dim]) caml_invalid_argument("Bigarray.sub: bad sub-array"); sub_data = (char *) b->data + ofs * mul * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; /* Allocate an OCaml bigarray to hold the result */ res = caml_ba_alloc(b->flags, b->num_dims, sub_data, b->dim); /* Doctor the changed dimension */ Caml_ba_array_val(res)->dim[changed_dim] = len; /* Create or update proxy in case of managed bigarray */ caml_ba_update_proxy(b, Caml_ba_array_val(res)); /* Return result */ CAMLreturn (res); #undef b }