Skip to content

NDArray

NDArray is used for representing data in multiple dimensions. The NDArray structure allows you to set the rank, dimensions and values stored in memory. The values are stored as a contigious array. Strides are used to perform indexing in 2 or more dimensions.

Array Utilities

Method Description
ndarray(int rank, int *shape) Creates instance of ndarray data structure
reshape(ndarray_t *t, int rank, int *shape) Reshape ndarray with new rank and shape dimensions
int nindex(ndarray_t *t, int *indices) Gets one dimensional index value from array of indices
int *indices(ndarray_t *t, int index) Get's indices associated with contigous index value
double nidx(ndarray_t *t, int *indices) Get's value associated with indices
void nset(ndarray_t *t, int *indices, double value) Set value at specific permutation of indices
void save_ndarray(ndarray_t *t, char *filename) Save NDArray values to file in memory
ndarray_t *load_ndarray(char *filename) Load NDArray values from saved file

ndarray(rank, shape)


  • Parameters
    • rank: Integer value that represents amount of dimensions in value. Eg. 2d, 3d Arrays
    • shape : Array of integers that correspond to the dimensions of the value. Example values: (2, 3), (6, 6).

Notes: This method creates the NDArray using the ndarray_t structure from the core library. This does not work from C -> python (backwards compatible)

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});
print_ndarray(t);

/* create 2 X 2 X 2 3d array */ 
ndarray_t *t1 = ndarray(3, (int[]){2, 2, 2});
print_ndarray(t1);


reshape(t,rank,shape)


  • Parameters
    • t : Reference to instance of ndarray that will be reshaped
    • rank: Integer value that represents amount of dimensions in value. Eg. 2d, 3d Arrays
    • shape : Array of integers that correspond to the dimensions of the value. Example values: (2, 3), (6, 6).

Notes: This method requires you to provide a new rank and shape, even if the prior rank was the same.

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});
print_ndarray(t);

/* reshape ndarray */
reshape(t, 3, (int[]){2, 2, 2})


nindex(t, indices)


  • Parameters
    • t : Reference to instance of ndarray that will be reshaped
    • indices: Set of indices to map to one dimensional index. Length of indices is the rank of the value

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});

/* example nindex usage for Unit tests */
int index = 0; 
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        int test_index =  nindex(t, (int[]){i, j});
        assert(test_index == index);    
        index += 1;     
    }
}


indices(t,index)


  • Parameters
    • t : Reference to instance of ndarray
    • index: Integer value that maps to index of contiguous array

Notes: This method is a helper for flattening and performing transposes/contractions

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});
print_ndarray(t);


/*  set values of ndarray   */ 
int index = 0; 
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        nset(t, (int[]){i, j}, index+1);
        index += 1;     
    }
}

/* validate indexs match */
index = 0;
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        int *idxs = indices(t, index); 
        assert(idxs[0] == i);
        assert(idxs[1] == j);  
        index += 1; 
    }
}


nidx(t,indices)


  • Parameters
    • t : Reference to instance of ndarray
    • indices: Array of indices to map to value in ndarray

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});

/*  set values of ndarray   */ 
int index = 0; 
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        nset(t, (int[]){i, j}, index+1);
        index += 1;     
    }
}

double value = nidx(t, (int[]){0, 0}) /* grab value at  (0, 0) */ 
double value1 = nidx(t, (int[]){0, 1}) /* grab value at  (0, 1) */ 


nset(t,indices, value)


  • Parameters
    • t : Reference to instance of ndarray
    • indices: Array of indices to map to value in ndarray
    • value: Value we want to set in ndarray

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});

/*  set values of ndarray   */ 
int index = 0; 
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        nset(t, (int[]){i, j}, index+1); /* set value */
        index += 1;     
    }
}


save_ndarray(t,filename)


  • Parameters
    • t : Reference to instance of ndarray
    • filename: Path to save ndarray in memory

Example Code:

/* create 3 X 3 2d array */ 
ndarray_t *t = ndarray(2, (int[]){3, 3});

/*  set values of ndarray   */ 
int index = 0; 
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        nset(t, (int[]){i, j}, index+1); /* set value */
        index += 1;     
    }
}

/* save ndarray  to path */
save_ndarray(t, "path/to/file/values")


load_ndarray(filename)


  • Parameters
    • filename: Path reference to saved ndarray

Note: The loaded ndarray will set your shape and dimensions for you, all you need is the filepath.

Example Code:

/* load saved ndarray */
ndarray_t *loaded = load_ndarray("path/to/file/values");


Operations

Method Description
ndot(ndarray_t *a, ndarray_t *b) Dot Product of two ndarray's
nadd(ndarray_t *t, ndarray_t *val) Add two ndarray's
nsubtract(ndarray_t *t1, ndarray_t *t2) Subtract two ndarray's
nscale_add(ndarray_t *a, ndarray_t *b) Add A ndarray by vector
ntranspose(ndarray_t *t) Tranpose of ndarray instance (rows as columns)
permute(ndarray_t *t, int *indice_order) Contract NDArray and reorder indices

ndot(a, b)


  • Parameters
    • a: First tensor to perform dot product
    • b: Second tensor to perform dot product

Note: Operation returns a new ndarray with the result of a and b.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(2, (int[]){3, 3}); 
ndarray_t *t2 = ndarray(2, (int[]){3, 3}); 
ndarray_t *result = ndot(t1, t2);


nadd(a, b)


  • Parameters
    • a: First tensor to add
    • b: Second tensor to add

Note: Operation returns a new ndarray with the result of a and b.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(2, (int[]){3, 3}); 
ndarray_t *t2 = ndarray(2, (int[]){3, 3}); 
ndarray_t *result = nadd(t1, t2);


nsubtract(t1, t2)


  • Parameters
    • t1: First tensor to subtract
    • t2: Second tensor to subtract

Note: Operation returns a new ndarray with the result of a and b.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(2, (int[]){3, 3}); 
ndarray_t *t2 = ndarray(2, (int[]){3, 3}); 
ndarray_t *result = nsubtract(t1, t2);


nscale_add(a, b)


  • Parameters
    • a: First tensor to scale add
    • b: Second tensor to scale add

Note: Operation returns a new ndarray with the result of a and b.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(2, (int[]){3, 3}); 
ndarray_t *t2 = ndarray(2, (int[]){1, 3}); /* 1  X 3 */
ndarray_t *result = nscale_add(t1, t2);


ntranspose(t)


  • Parameters
    • t: Instance of ndarray to perform transpose on

Note: Operation returns a new ndarray with the result of tranpose operation.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(2, (int[]){3, 4}); 
ndarray_t *result = ntranspose(t1); /* 4 X 3 ndarray */


permute(t)


  • Parameters
    • t: Instance of ndarray to perform permute/contraction on

Note: Operation returns a new ndarray with the result of contraction.

Example Code:

/* add two 3 X 3 ndarrays */
ndarray_t *t1 = ndarray(3, (int[]){3, 4, 5}); 
ndarray_t *result = permute(t1, (int[]){2, 1, 0}); /* 5 X 4 X 3  ndarray */