-
-
Notifications
You must be signed in to change notification settings - Fork 1
Array Creation
NumcArray is the core tensor type. It supports N-dimensional data with any of the 10 numeric types, contiguous and non-contiguous memory layouts, and zero-copy views.
Creates an array with uninitialized memory. Fastest option -- use when you plan to fill it immediately.
size_t shape[] = {2, 3};
NumcArray *a = numc_array_create(ctx, shape, 2, NUMC_DTYPE_FLOAT32);
// a contains garbage data -- write before reading!The second argument (shape) is an array of dimension sizes, and the third (2) is the number of dimensions.
Creates an array with all elements set to zero:
NumcArray *z = numc_array_zeros(ctx, (size_t[]){3, 3}, 2, NUMC_DTYPE_INT32);
// All elements are 0Creates an array where every element has the same value. The value pointer must match the dtype:
// Float32 array filled with 3.14
float val = 3.14f;
NumcArray *f = numc_array_fill(ctx, (size_t[]){2, 4}, 2,
NUMC_DTYPE_FLOAT32, &val);
// Int32 array filled with 42
int32_t ival = 42;
NumcArray *g = numc_array_fill(ctx, (size_t[]){5}, 1,
NUMC_DTYPE_INT32, &ival);Tip: for inline float values, use a compound literal:
NumcArray *f = numc_array_fill(ctx, shape, 2, NUMC_DTYPE_FLOAT32,
&(float){2.0f});To create a scalar (0-dimensional) array:
float val = 10.0f;
NumcArray *scalar = numc_array_fill(ctx, NULL, 0, NUMC_DTYPE_FLOAT32, &val);Creates a new array with the same shape, dtype, and data as the original:
NumcArray *original = numc_array_rand(ctx, (size_t[]){4, 4}, 2,
NUMC_DTYPE_FLOAT64);
NumcArray *copy = numc_array_copy(original);
// Modifying copy does not affect originalThe copy is allocated in the same context as the original.
Copies raw bytes from a buffer into the array's data. The buffer must contain exactly numc_array_size(arr) * numc_array_elem_size(arr) bytes in row-major order:
// 1D array
size_t shape1[] = {4};
NumcArray *a = numc_array_create(ctx, shape1, 1, NUMC_DTYPE_FLOAT32);
float data1[] = {1.0f, 2.0f, 3.0f, 4.0f};
numc_array_write(a, data1);
// 2D array (row-major: rows are contiguous)
size_t shape2[] = {2, 3};
NumcArray *b = numc_array_create(ctx, shape2, 2, NUMC_DTYPE_INT32);
int32_t data2[] = {1, 2, 3, // row 0
4, 5, 6}; // row 1
numc_array_write(b, data2);
// 3D array
size_t shape3[] = {2, 2, 4};
NumcArray *c = numc_array_create(ctx, shape3, 3, NUMC_DTYPE_INT32);
int32_t data3[][2][4] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
};
numc_array_write(c, data3);Creates a 2-D one-hot encoded array from a 1-D integer label array. Essential for classification tasks in neural networks (e.g., encoding MNIST digit labels for cross-entropy loss).
// Labels: [0, 2, 1, 3] with 4 classes
int32_t data[] = {0, 2, 1, 3};
NumcArray *labels = numc_array_create(ctx, (size_t[]){4}, 1, NUMC_DTYPE_INT32);
numc_array_write(labels, data);
NumcArray *oh = numc_one_hot(ctx, labels, 4, NUMC_DTYPE_FLOAT32);
// Shape: (4, 4)
// [[1, 0, 0, 0],
// [0, 0, 1, 0],
// [0, 1, 0, 0],
// [0, 0, 0, 1]]Parameters:
-
labels-- 1-D array with any integer dtype (int8 through uint64) -
num_classes-- number of columns in the output -
dtype-- output dtype (must beNUMC_DTYPE_FLOAT32orNUMC_DTYPE_FLOAT64)
Behavior:
- Out-of-bounds or negative label values produce an all-zero row (no error)
- OpenMP parallelized for batches larger than 100K rows
- Works with non-contiguous label arrays (e.g., sliced views)
See Random Initialization for numc_array_rand, numc_array_randn, and weight initializers.
// Quick preview
NumcArray *r = numc_array_rand(ctx, (size_t[]){3, 3}, 2, NUMC_DTYPE_FLOAT32);
// Each element is uniform random in [0, 1)NumcArray *a = numc_array_fill(ctx, (size_t[]){2, 3, 4}, 3,
NUMC_DTYPE_FLOAT32, &(float){1.0f});
// Number of dimensions
size_t ndim = numc_array_ndim(a); // 3
// Total number of elements
size_t size = numc_array_size(a); // 24 (2*3*4)
// Allocated capacity in elements
size_t cap = numc_array_capacity(a); // >= 24
// Size of one element in bytes
size_t es = numc_array_elem_size(a); // 4 (sizeof(float))
// Data type
NumcDType dt = numc_array_dtype(a); // NUMC_DTYPE_FLOAT32
// Raw data pointer
void *ptr = numc_array_data(a);
// Is the memory layout contiguous?
bool contig = numc_array_is_contiguous(a); // true (freshly created)Shape and strides are copied into a buffer you provide:
size_t ndim = numc_array_ndim(a);
size_t shape[ndim], strides[ndim];
numc_array_shape(a, shape);
// shape = {2, 3, 4}
numc_array_strides(a, strides);
// strides = {48, 16, 4} (bytes: 3*4*4, 4*4, 4)Strides are in bytes, not elements. For a contiguous float32 array with shape {2, 3, 4}:
-
strides[2] = 4(one float32) -
strides[1] = 16(4 elements * 4 bytes) -
strides[0] = 48(3 * 4 elements * 4 bytes)
numc_array_print(a);Prints the array contents to stdout in a nested bracket format similar to NumPy.
Use numc_array_data() to get a pointer to the raw data buffer, then cast to the appropriate type:
NumcArray *a = numc_array_create(ctx, (size_t[]){4}, 1, NUMC_DTYPE_FLOAT32);
float data[] = {1.0f, 2.0f, 3.0f, 4.0f};
numc_array_write(a, data);
float *raw = (float *)numc_array_data(a);
printf("First element: %f\n", raw[0]); // 1.0
printf("Last element: %f\n", raw[3]); // 4.0Warning: Only index raw data directly if the array is contiguous (
numc_array_is_contiguous(a) == true). Non-contiguous arrays (from transpose or slice) have non-trivial strides, so flat indexing will access wrong elements.