Skip to content

Commit

Permalink
add interface to build npy_array_list objects from C (#30)
Browse files Browse the repository at this point in the history
* add interface to build npy_array_list objects from C

* rename to deepcopy

---------

Co-authored-by: Lennart Klebl (alcubierre-drive)
  • Loading branch information
alcubierre-drive authored Sep 20, 2024
1 parent f88c015 commit 80a0b2c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
*~
*.npy
*.npz
Makefile
*.so
*.pc
*.d
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ And the linked list structure for `.npz` files:
} npy_array_list_t;

## API
The API is really simple. There is only ~~ten~~eleven public functions:
The API is really simple. There is only ~~eleven~~twelve public functions:

/* These are the four functions for loading and saving .npy files */
npy_array_t* npy_array_load ( const char *filename);
npy_array_t* npy_array_mmap ( const char *filename);
npy_array_t* npy_array_alloc ( const npy_array_t *m );
void npy_array_dump ( const npy_array_t *m );
void npy_array_save ( const char *filename, const npy_array_t *m );
void npy_array_free ( npy_array_t *m );
Expand Down Expand Up @@ -156,6 +157,27 @@ You can then run example with a _NumPy_ file as argument.
return 0;
}

## Saving lists of numpy arrays (and building them)
Here is an example of saving multiple arrays into a single .npz file. You can
compile this with:

gcc -O3 -Wall -Wextra -pedantic -std=c11 -c example_list.c
gcc -o example_list example_list.o npy_array.o npy_array_list.o -lzip

You can the run example_list with a filename (_NumPy_ compressed) as argument.

#include "npy_array_list.h"
int main(int argc, char *argv[])
{
if( argc != 2 ) return -1;
double data[] = {0,1,2,3,4,5};
npy_array_list_t* list = NULL;
list = npy_array_list_append( list, NPY_ARRAY_ALLOCATOR(data, SHAPE(3,2), NPY_DTYPE_FLOAT64), "matrix" );
list = npy_array_list_append( list, NPY_ARRAY_ALLOCATOR(data, SHAPE(2,1,2), NPY_DTYPE_FLOAT64), "tensor" );
npy_array_list_save_compressed( argv[1], list, ZIP_CM_DEFAULT, 0 );
npy_array_list_free( list );
}

## Saving other arraylike data as _NumPy_ format.
You may have a pointer to an N-dimensional array, which you want to store as NumPy format, such
that you can load it in Python/Jupiter and plot in matplotlib or whatever you find more
Expand Down
23 changes: 22 additions & 1 deletion npy_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ctype.h>
#include <assert.h>

#define NPY_ARRAY_MAGIC_STRING {0x93,'N','U','M','P','Y'}
#define NPY_ARRAY_MAGIC_STRING {-109,'N','U','M','P','Y'}
#define NPY_ARRAY_MAJOR_VERSION_IDX 6
#define NPY_ARRAY_MINOR_VERSION_IDX 7

Expand Down Expand Up @@ -397,3 +397,24 @@ void npy_array_free( npy_array_t *m )

free( m );
}

#define MIN( x, y ) ((x) < (y) ? (x) : (y))
npy_array_t* npy_array_deepcopy( const npy_array_t* m ) {
npy_array_t* ary = calloc( 1, sizeof(*ary) );
if (!ary) {
fprintf(stderr, "Cannot allocate data structure!\n");
return NULL;
}
ary->ndim = MIN( m->ndim, NPY_ARRAY_MAX_DIMENSIONS );
memcpy( ary->shape, m->shape, sizeof(ary->shape) );
ary->typechar = m->typechar;
ary->elem_size = m->elem_size;
ary->data = malloc( npy_array_calculate_datasize(ary) );
if (!ary->data) {
fprintf(stderr, "Cannot allocate memory!\n");
free(ary);
return NULL;
}
memcpy( ary->data, m->data, npy_array_calculate_datasize(ary) );
return ary;
}
3 changes: 3 additions & 0 deletions npy_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ typedef struct _npy_array_t {

npy_array_t* npy_array_load ( const char *filename );
npy_array_t* npy_array_mmap ( const char *filename );
npy_array_t* npy_array_deepcopy ( const npy_array_t *m );
void npy_array_dump ( const npy_array_t *m );
void npy_array_save ( const char *filename, const npy_array_t *m );
void npy_array_free ( npy_array_t *m );
Expand All @@ -86,6 +87,8 @@ npy_array_t * _read_matrix( void *fp, reader_func read_func );
#define SHAPE(...) .shape = {__VA_ARGS__}, .ndim = _NARG(__VA_ARGS__)
#define NPY_ARRAY_BUILDER(_data,_shape,...) \
&(npy_array_t){ .data=(char*)_data, _shape, __VA_ARGS__ }
#define NPY_ARRAY_ALLOCATOR(...) \
npy_array_deepcopy(NPY_ARRAY_BUILDER(__VA_ARGS__))

#define NPY_DTYPE_FLOAT16 .typechar='f', .elem_size=2
#define NPY_DTYPE_FLOAT32 .typechar='f', .elem_size=4
Expand Down

0 comments on commit 80a0b2c

Please sign in to comment.