time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.c (5264B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2021 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 #include "stdlib/ndarray/base/napi/addon_arguments.h"
     20 #include "stdlib/ndarray/ctor.h"
     21 #include <node_api.h>
     22 #include <assert.h>
     23 #include <stdbool.h>
     24 #include <stdint.h>
     25 #include <stdlib.h>
     26 
     27 /**
     28 * Validates, extracts, and transforms (to native C types) function arguments provided to an ndarray Node-API add-on interface.
     29 *
     30 * ## Notes
     31 *
     32 * -   The function assumes the following argument order:
     33 *
     34 *     ```text
     35 *     [ ib1, im1, ib2, im2, ..., ob1, om1, ob2, om2, ... ]
     36 *     ```
     37 *
     38 *     where
     39 *
     40 *     -   `ib#` is a data buffer for an input ndarray
     41 *     -   `im#` is meta data for an input ndarray
     42 *     -   `ob#` is a data buffer for an output ndarray
     43 *     -   `om#` is meta data for an output ndarray
     44 *
     45 * -   The function may return one of the following JavaScript errors:
     46 *
     47 *     -   `Error`: unable to allocate memory when processing input ndarray
     48 *     -   `Error`: unable to allocate memory when processing output ndarray
     49 *
     50 * @param env      environment under which the function is invoked
     51 * @param argv     ndarray function arguments
     52 * @param nargs    total number of expected arguments
     53 * @param nin      number of input ndarrays
     54 * @param arrays   destination array for storing pointers to both input and output ndarrays
     55 * @param err      pointer for storing a JavaScript error
     56 * @return         status code indicating success or failure (returns `napi_ok` if success)
     57 *
     58 * @example
     59 * #include "stdlib/ndarray/base/napi/addon_arguments.h"
     60 * #include "stdlib/ndarray/ctor.h"
     61 * #include <node_api.h>
     62 * #include <stdint.h>
     63 * #include <assert.h>
     64 *
     65 * // Add-on function...
     66 * napi_value addon( napi_env env, napi_callback_info info ) {
     67 *     napi_status status;
     68 *
     69 *     // ...
     70 *
     71 *     int64_t nargs = 6;
     72 *     int64_t nin = 2;
     73 *
     74 *     // Get callback arguments:
     75 *     size_t argc = 6;
     76 *     napi_value argv[ 6 ];
     77 *     status = napi_get_cb_info( env, info, &argc, argv, nullptr, nullptr );
     78 *     assert( status == napi_ok );
     79 *
     80 *     // ...
     81 *
     82 *     // Process the provided arguments:
     83 *     struct ndarray *arrays[ 3 ];
     84 *
     85 *     napi_value err;
     86 *     status = stdlib_ndarray_napi_addon_arguments( env, argv, nargs, nin, arrays, &err );
     87 *     assert( status == napi_ok );
     88 *
     89 *     // ...
     90 *
     91 * }
     92 */
     93 napi_status stdlib_ndarray_napi_addon_arguments( const napi_env env, const napi_value *argv, const int64_t nargs, const int64_t nin, struct ndarray *arrays[], napi_value *err ) {
     94 	napi_status status;
     95 
     96 	// Reset the output error:
     97 	*err = NULL;
     98 
     99 	// Compute the index of the first output array argument:
    100 	int64_t iout = nin * 2;
    101 
    102 	// For each ndarray, we expect 2 arguments: the data buffer and the array meta data...
    103 	for ( int64_t i = 0; i < nargs; i += 2 ) {
    104 		// Retrieve the ndarray data buffer:
    105 		uint8_t *data;
    106 		status = napi_get_typedarray_info( env, argv[ i ], NULL, NULL, (void *)&data, NULL, NULL );
    107 		assert( status == napi_ok );
    108 
    109 		// Retrieve the ndarray meta data:
    110 		uint8_t *meta;
    111 		size_t byteoffset;
    112 		status = napi_get_dataview_info( env, argv[ i+1 ], NULL, (void *)&meta, NULL, &byteoffset );
    113 		assert( status == napi_ok );
    114 
    115 		// Retrieve ndarray properties...
    116 		uint8_t *ptr = meta + byteoffset + 1; // +1 as the first byte is the endianness, which we ignore based on the assumption that the endianness is the same for both C and JavaScript
    117 		int16_t dtype = *(int16_t *)ptr;
    118 
    119 		ptr += 2;
    120 		int64_t ndims = *(int64_t *)ptr;
    121 
    122 		ptr += 8;
    123 		int64_t *shape = (int64_t *)ptr;
    124 
    125 		ptr += ndims * 8;
    126 		int64_t *strides = (int64_t *)ptr;
    127 
    128 		ptr += ndims * 8;
    129 		int64_t offset = *(int64_t *)ptr;
    130 
    131 		ptr += 8;
    132 		int8_t order = *(int8_t *)ptr;
    133 
    134 		ptr += 1;
    135 		int8_t imode = *(int8_t *)ptr;
    136 
    137 		ptr += 1;
    138 		int64_t nsubmodes = *(int64_t *)ptr;
    139 
    140 		ptr += 8;
    141 		int8_t *submodes = (int8_t *)ptr;
    142 
    143 		// Allocate a new ndarray:
    144 		struct ndarray *arr = stdlib_ndarray_allocate( dtype, data, ndims, shape, strides, offset, order, imode, nsubmodes, submodes );
    145 		if ( arr == NULL ) {
    146 			napi_value msg;
    147 			if ( i < iout ) {
    148 				status = napi_create_string_utf8( env, "runtime exception. Unable to allocate memory when processing an input ndarray.", NAPI_AUTO_LENGTH, &msg );
    149 			} else {
    150 				status = napi_create_string_utf8( env, "runtime exception. Unable to allocate memory when processing an output ndarray.", NAPI_AUTO_LENGTH, &msg );
    151 			}
    152 			assert( status == napi_ok );
    153 
    154 			napi_value code;
    155 			status = napi_create_string_utf8( env, "ERR_MEMORY_ALLOCATION_FAILED", NAPI_AUTO_LENGTH, &code );
    156 			assert( status == napi_ok );
    157 
    158 			napi_value error;
    159 			status = napi_create_error( env, code, msg, &error );
    160 			assert( status == napi_ok );
    161 
    162 			*err = error;
    163 			return napi_ok;
    164 		}
    165 		// Set the output data:
    166 		arrays[ i/2 ] = arr;
    167 	}
    168 	return napi_ok;
    169 }