time-to-botec

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

main.c (10702B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 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/ctor.h"
     20 #include "stdlib/ndarray/base/bytes_per_element.h"
     21 #include "stdlib/ndarray/base/iteration_order.h"
     22 #include "stdlib/ndarray/base/minmax_view_buffer_index.h"
     23 #include "stdlib/ndarray/base/numel.h"
     24 #include "stdlib/ndarray/base/strides2order.h"
     25 #include "stdlib/ndarray/dtypes.h"
     26 #include "stdlib/ndarray/index_modes.h"
     27 #include "stdlib/ndarray/orders.h"
     28 #include <stdlib.h>
     29 #include <stdint.h>
     30 
     31 // NOTE: keep functions in alphabetical order...
     32 
     33 /**
     34 * Returns a pointer to a dynamically allocated ndarray.
     35 *
     36 * ## Notes
     37 *
     38 * -   The user is responsible for freeing the allocated memory.
     39 *
     40 * @param dtype      data type
     41 * @param data       pointer to the underlying byte array
     42 * @param ndims      number of dimensions
     43 * @param shape      array shape (dimensions)
     44 * @param strides    array strides (in bytes)
     45 * @param offset     byte offset specifying the location of the first element
     46 * @param order      specifies whether an array is row-major (C-style) or column-major (Fortran-style)
     47 * @param imode      specifies how to handle indices which exceed array dimensions
     48 * @param nsubmodes  number of subscript modes
     49 * @param submodes   specifies how to handle subscripts which exceed array dimensions on a per dimension basis (if provided fewer submodes than dimensions, submodes are recycled using modulo arithmetic)
     50 * @return           pointer to a dynamically allocated ndarray or, if unable to allocate memory, a null pointer
     51 *
     52 * @example
     53 * #include "stdlib/ndarray/ctor.h"
     54 * #include "stdlib/ndarray/dtypes.h"
     55 * #include "stdlib/ndarray/index_modes.h"
     56 * #include "stdlib/ndarray/orders.h"
     57 * #include "stdlib/ndarray/base/bytes_per_element.h"
     58 * #include <stdlib.h>
     59 * #include <stdio.h>
     60 * #include <stdint.h>
     61 *
     62 * // Specify the underlying data type:
     63 * enum STDLIB_NDARRAY_DTYPE dtype = STDLIB_NDARRAY_FLOAT64;
     64 *
     65 * // Create an underlying byte array:
     66 * uint8_t buffer[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     67 *
     68 * // Specify the number of array dimensions:
     69 * int64_t ndims = 1;
     70 *
     71 * // Specify the array shape:
     72 * int64_t shape[] = { 3 }; // vector consisting of 3 doubles
     73 *
     74 * // Specify the array strides:
     75 * int64_t strides[] = { STDLIB_NDARRAY_FLOAT64_BYTES_PER_ELEMENT };
     76 *
     77 * // Specify the byte offset:
     78 * int64_t offset = 0;
     79 *
     80 * // Specify the array order (note: this does not matter for a 1-dimensional array):
     81 * enum STDLIB_NDARRAY_ORDER order = STDLIB_NDARRAY_ROW_MAJOR;
     82 *
     83 * // Specify the index mode:
     84 * enum STDLIB_NDARRAY_INDEX_MODE imode = STDLIB_NDARRAY_INDEX_ERROR;
     85 *
     86 * // Specify the subscript index modes:
     87 * int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR };
     88 * int64_t nsubmodes = 1;
     89 *
     90 * // Create an ndarray:
     91 * struct ndarray *x = stdlib_ndarray_allocate( dtype, buffer, ndims, shape, strides, offset, order, imode, nsubmodes, submodes );
     92 * if ( x == NULL ) {
     93 *     fprintf( stderr, "Error allocating memory.\n" );
     94 *     exit( 1 );
     95 * }
     96 *
     97 * // Free allocated memory:
     98 * stdlib_ndarray_free( x );
     99 */
    100 struct ndarray * stdlib_ndarray_allocate( int16_t dtype, uint8_t *data, int64_t ndims, int64_t *shape, int64_t *strides, int64_t offset, int8_t order, int8_t imode, int64_t nsubmodes, int8_t *submodes ) {
    101 	int64_t len;
    102 
    103 	struct ndarray *arr = malloc( sizeof( struct ndarray ) );
    104 	if ( arr == NULL ) {
    105 		return NULL;
    106 	}
    107 	arr->data = data;
    108 	arr->dtype = dtype;
    109 	arr->imode = imode;
    110 	arr->ndims = ndims;
    111 	arr->nsubmodes = nsubmodes;
    112 	arr->offset = offset;
    113 	arr->order = order;
    114 	arr->shape = shape;
    115 	arr->strides = strides;
    116 	arr->submodes = submodes;
    117 
    118 	len = stdlib_ndarray_numel( ndims, shape );
    119 	arr->length = len;
    120 
    121 	arr->BYTES_PER_ELEMENT = stdlib_ndarray_bytes_per_element( dtype );
    122 	arr->byteLength = len * (arr->BYTES_PER_ELEMENT);
    123 	arr->flags = stdlib_ndarray_flags( arr );
    124 
    125 	return arr;
    126 }
    127 
    128 /**
    129 * Returns the size of an ndarray (in bytes).
    130 *
    131 * @param arr  input ndarray
    132 * @return     array size
    133 */
    134 int64_t stdlib_ndarray_bytelength( const struct ndarray *arr ) {
    135 	return arr->byteLength;
    136 }
    137 
    138 /**
    139 * Returns a pointer to an ndarray's underlying byte array.
    140 *
    141 * @param arr  input ndarray
    142 * @return     underlying byte array
    143 */
    144 uint8_t * stdlib_ndarray_data( const struct ndarray *arr ) {
    145 	return arr->data;
    146 }
    147 
    148 /**
    149 * Returns an ndarray dimension.
    150 *
    151 * ## Notes
    152 *
    153 * -   The function does not perform any sanity checks.
    154 *
    155 * @param arr  input ndarray
    156 * @param i    dimension index
    157 * @return     dimension
    158 */
    159 int64_t stdlib_ndarray_dimension( const struct ndarray *arr, const int64_t i ) {
    160 	return arr->shape[ i ];
    161 }
    162 
    163 /**
    164 * Disables specified ndarray flags.
    165 *
    166 * ## Notes
    167 *
    168 * -   The function does not perform any sanity checks and **assumes** the user knows what s/he is doing.
    169 *
    170 * @param arr    input ndarray
    171 * @param flags  bit mask to disable flags
    172 * @return       status code
    173 */
    174 int8_t stdlib_ndarray_disable_flags( struct ndarray *arr, const int64_t flags ) {
    175 	arr->flags &= ~flags;
    176 	return 0;
    177 }
    178 
    179 /**
    180 * Returns an ndarray data type.
    181 *
    182 * @param arr  input ndarray
    183 * @return     array data type
    184 */
    185 int16_t stdlib_ndarray_dtype( const struct ndarray *arr ) {
    186 	return arr->dtype;
    187 }
    188 
    189 /**
    190 * Enables specified ndarray flags.
    191 *
    192 * ## Notes
    193 *
    194 * -   The function does not perform any sanity checks and **assumes** the user knows what s/he is doing.
    195 *
    196 * @param arr    input ndarray
    197 * @param flags  bit mask to enable flags
    198 * @return       status code
    199 */
    200 int8_t stdlib_ndarray_enable_flags( struct ndarray *arr, const int64_t flags ) {
    201 	arr->flags |= flags;
    202 	return 0;
    203 }
    204 
    205 /**
    206 * Returns ndarray flags.
    207 *
    208 * @param arr  input ndarray
    209 * @return     flags
    210 */
    211 int64_t stdlib_ndarray_flags( const struct ndarray *arr ) {
    212 	uint8_t contiguous;
    213 	int64_t *strides;
    214 	int64_t nbytes;
    215 	int64_t tmp[2];
    216 	int64_t ndims;
    217 	int64_t flags;
    218 	int64_t len;
    219 	int8_t ord;
    220 
    221 	// Cache various ndarray data:
    222 	len = arr->length;
    223 	ndims = arr->ndims;
    224 	strides = arr->strides;
    225 	nbytes = arr->BYTES_PER_ELEMENT;
    226 
    227 	// Initialize the memory for `flags`:
    228 	flags = 0;
    229 
    230 	// Determine if the array can be stored contiguously...
    231 	if ( len == 0 || stdlib_ndarray_iteration_order( ndims, strides ) == 0 ) {
    232 		// If an array does not contain any elements, then no data to store, and, if the array is unordered, adjacent array elements are not guaranteed to be stored next to each other.
    233 		contiguous = 0;
    234 	} else {
    235 		// Ensure that the array is compatible with a single memory segment:
    236 		stdlib_ndarray_minmax_view_buffer_index( ndims, arr->shape, strides, arr->offset, tmp );
    237 		if ( (len*nbytes) == ( (tmp[1]-tmp[0])+nbytes ) ) {
    238 			// Compatible:
    239 			contiguous = 1;
    240 		} else {
    241 			// Incompatible:
    242 			contiguous = 0;
    243 		}
    244 	}
    245 	// Determine if the array is row-major/column-major contiguous:
    246 	if ( contiguous == 1 ) {
    247 		// Infer the array "order" from the stride array (this is supplementary to `arr->order`):
    248 		ord = stdlib_ndarray_strides2order( ndims, strides );
    249 
    250 		if ( ord == 1 || ord == 3 ) {
    251 			flags |= STDLIB_NDARRAY_ROW_MAJOR_CONTIGUOUS_FLAG;
    252 		}
    253 		if ( ord == 2 || ord == 3 ) {
    254 			flags |= STDLIB_NDARRAY_COLUMN_MAJOR_CONTIGUOUS_FLAG;
    255 		}
    256 	}
    257 	return flags;
    258 }
    259 
    260 /**
    261 * Frees an ndarray's allocated memory.
    262 *
    263 * @param arr  input ndarray
    264 */
    265 void stdlib_ndarray_free( struct ndarray *arr ) {
    266 	free( arr );
    267 }
    268 
    269 /**
    270 * Tests whether an ndarray has specified flags enabled.
    271 *
    272 * @param arr    input ndarray
    273 * @param flags  bit mask specifying the flags to test against
    274 * @return       `1` if flags are set and `0` otherwise
    275 */
    276 int8_t stdlib_ndarray_has_flags( const struct ndarray *arr, const int64_t flags ) {
    277 	if ( ( arr->flags & flags ) == flags ) {
    278 		return 1;
    279 	}
    280 	return 0;
    281 }
    282 
    283 /**
    284 * Returns the index mode of an ndarray.
    285 *
    286 * @param arr  input ndarray
    287 * @return     index mode
    288 */
    289 int8_t stdlib_ndarray_index_mode( const struct ndarray *arr ) {
    290 	return arr->imode;
    291 }
    292 
    293 /**
    294 * Returns the number of elements in an ndarray.
    295 *
    296 * @param arr  input ndarray
    297 * @return     number of elements
    298 */
    299 int64_t stdlib_ndarray_length( const struct ndarray *arr ) {
    300 	return arr->length;
    301 }
    302 
    303 /**
    304 * Returns the number of ndarray dimensions.
    305 *
    306 * @param arr  input ndarray
    307 * @return     number of dimensions
    308 */
    309 int64_t stdlib_ndarray_ndims( const struct ndarray *arr ) {
    310 	return arr->ndims;
    311 }
    312 
    313 /**
    314 * Returns the number of ndarray subscript modes.
    315 *
    316 * @param arr  input ndarray
    317 * @return     number of subscript modes
    318 */
    319 int64_t stdlib_ndarray_nsubmodes( const struct ndarray *arr ) {
    320 	return arr->nsubmodes;
    321 }
    322 
    323 /**
    324 * Returns an ndarray index offset (in bytes).
    325 *
    326 * @param arr  input ndarray
    327 * @return     array strides
    328 */
    329 int64_t stdlib_ndarray_offset( const struct ndarray *arr ) {
    330 	return arr->offset;
    331 }
    332 
    333 /**
    334 * Returns the order of an ndarray.
    335 *
    336 * @param arr  input ndarray
    337 * @return     array order
    338 */
    339 int8_t stdlib_ndarray_order( const struct ndarray *arr ) {
    340 	return arr->order;
    341 }
    342 
    343 /**
    344 * Returns a pointer to an array containing an ndarray shape (dimensions).
    345 *
    346 * @param arr  input ndarray
    347 * @return     array shape (dimensions)
    348 */
    349 int64_t * stdlib_ndarray_shape( const struct ndarray *arr ) {
    350 	return arr->shape;
    351 }
    352 
    353 /**
    354 * Returns an ndarray stride (in bytes).
    355 *
    356 * ## Notes
    357 *
    358 * -   The function does not perform any sanity checks.
    359 *
    360 * @param arr  input ndarray
    361 * @param i    dimension index
    362 * @return     array stride
    363 */
    364 int64_t stdlib_ndarray_stride( const struct ndarray *arr, const int64_t i ) {
    365 	return arr->strides[ i ];
    366 }
    367 
    368 /**
    369 * Returns a pointer to an array containing ndarray strides (in bytes).
    370 *
    371 * @param arr  input ndarray
    372 * @return     array strides
    373 */
    374 int64_t * stdlib_ndarray_strides( const struct ndarray *arr ) {
    375 	return arr->strides;
    376 }
    377 
    378 /**
    379 * Returns an ndarray subscript mode.
    380 *
    381 * ## Notes
    382 *
    383 * -   If an ndarray has fewer subscript modes than dimensions, modes are recycled using modulo arithmetic.
    384 * -   The function does not perform any sanity checks.
    385 *
    386 * @param arr  input ndarray
    387 * @param i    dimension index
    388 * @return     subscript mode
    389 */
    390 int8_t stdlib_ndarray_submode( const struct ndarray *arr, const int64_t i ) {
    391 	return arr->submodes[ i%(arr->nsubmodes) ];
    392 }
    393 
    394 /**
    395 * Returns ndarray subscript modes.
    396 *
    397 * @param arr  input ndarray
    398 * @return     subscript modes
    399 */
    400 int8_t * stdlib_ndarray_submodes( const struct ndarray *arr ) {
    401 	return arr->submodes;
    402 }