/**************************************************************************** * * Copyright (c) 2020 Vivante Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * *****************************************************************************/ #ifndef _VSI_NN_MATH_H #define _VSI_NN_MATH_H #include #include #include "vsi_nn_types.h" #ifdef __cplusplus extern "C" { #endif #define vsi_nn_abs(x) (((x) < 0) ? -(x) : (x)) #define vsi_nn_max(a,b) (((a) > (b)) ? (a) : (b)) #define vsi_nn_min(a,b) (((a) < (b)) ? (a) : (b)) #define vsi_nn_clamp(x, min, max) (((x) < (min)) ? (min) : \ ((x) > (max)) ? (max) : (x)) #define vsi_nn_float_compare(a,b,diff) (vsi_nn_abs((a) - (b)) < (diff) ? TRUE : FALSE) #define vsi_abs(x) vsi_nn_abs(x) #define vsi_clamp(x, min, max) vsi_nn_clamp(x, min, max) #define vsi_rtne(x) vsi_rint(x) #define VSI_NN_INT32_MAX (0x7FFFFFFF) #define VSI_NN_FLOAT32_INF (0x7F800000) #define VSI_NN_FLOAT32_NAN (0x7FC00000) #define VSI_NN_FLOAT64_INF (0x7FF0000000000000) #define VSI_NN_FLOAT64_NAN (0x7FF8000000000000) #define DEFINE_ARRAY_TYPE( NAME, TYPE ) \ typedef struct { \ size_t size; \ TYPE *data; \ } vsi_##NAME##_array_t; \ static VSI_INLINE_API vsi_##NAME##_array_t * vsi_##NAME##_array_create( size_t size ) { \ vsi_##NAME##_array_t * array = NULL; \ array = (vsi_##NAME##_array_t *)malloc( sizeof(vsi_##NAME##_array_t) + sizeof(TYPE) * size ); \ if (array == NULL) return NULL; \ array->data = (TYPE *)(((TYPE**)(&(array->data))) + 1); \ array->size = size; \ return array; \ } \ static VSI_INLINE_API void vsi_##NAME##_array_release( vsi_##NAME##_array_t ** array ) \ { \ if( array && *array ) { \ free( *array ); \ *array = NULL; \ } \ } DEFINE_ARRAY_TYPE( int, int32_t ) DEFINE_ARRAY_TYPE( float, float ) DEFINE_ARRAY_TYPE( size, vsi_size_t ) #undef DEFINE_ARRAY_TYPE OVXLIB_API void vsi_nn_Transpose ( uint8_t * dst, uint8_t * data, vsi_size_t * shape, vsi_size_t dim_num, vsi_size_t * perm, vsi_nn_type_e type ); OVXLIB_API void vsi_nn_Permute ( uint8_t * dst, uint8_t * data, vsi_size_t * shape, vsi_size_t dim_num, vsi_size_t * perm, vsi_nn_type_e type ); OVXLIB_API void vsi_nn_SqueezeShape ( vsi_size_t * shape, vsi_size_t * dim_num ); OVXLIB_API vsi_size_t vsi_nn_ShapeProduct ( vsi_size_t * shape, vsi_size_t dim_num ); //shape: row first <--> column first OVXLIB_API void vsi_nn_InvertShape ( vsi_size_t * in, vsi_size_t dim_num, vsi_size_t * out ); //Permute shape: row first <--> column first OVXLIB_API void vsi_nn_InvertPermuteShape ( vsi_size_t * in, vsi_size_t dim_num, vsi_size_t * out ); OVXLIB_API double vsi_nn_Rint ( double x ); /** * Set Seeds for philox_4x32_10 algorithm * philox_4x32_10 algorithm need 2 uint32_t as seeds. * * @param[in] the low uint32_t of the seed. * @param[in] the high uint32_t of the seed. */ void vsi_nn_random_init_for_philox_4x32_10 ( uint32_t low, uint32_t high ); /** * Random Number Generator By philox_4x32_10 algorithm * Random Number(uint32_t) Generator By philox_4x32_10 algorithm * * @param[out] the buffer for RNG output. * @param[in] the number of generated random numbers. */ void vsi_nn_random_generate_by_philox_4x32_10 ( uint32_t *random_buf, uint32_t len ); /** * Uniform Transform * Transform the random uint32_t to Uniform float in [0, 1). * * @param[in] the buffer for random uint32_t. * @param[out] the buffer for uniform float in [0, 1). * @param[in] the number of random numbers. */ void vsi_nn_random_uniform_transform ( uint32_t *random_buf, float *uniform_buf, uint32_t len ); static VSI_INLINE_API double copy_sign ( double number, double sign ) { double value = vsi_nn_abs(number); return (sign > 0) ? value : (-value); } /* copy_sign() */ static VSI_INLINE_API float simple_round ( float x ) { return (float) copy_sign(floorf(fabsf(x) + 0.5f), x); } /* simple_round() */ static VSI_INLINE_API double vsi_rint ( double x ) { #define _EPSILON 1e-8 double decimal; double inter; decimal = modf((double)x, &inter); if( vsi_nn_abs((vsi_nn_abs(decimal) - 0.5f)) < _EPSILON ) { inter += (int32_t)(inter) % 2; } else { return simple_round( (float)x ); } return inter; } /* vsi_rint() */ /** * Computes an approximation of the error function. * This is the same approximation used by Eigen. * * @param[in] the value for input float. */ float vsi_nn_erf_impl(float x); #ifdef __cplusplus } #endif #endif