Skip to content

add interface to build npy_array_list objects from C #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading