2022-11-15 23:49:51 +00:00
/*
* Brickworks
*
2024-01-02 10:20:52 +00:00
* Copyright ( C ) 2022 - 2024 Orastron Srl unipersonale
2022-11-15 23:49:51 +00:00
*
* Brickworks is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , version 3 of the License .
*
* Brickworks is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2022-12-06 08:01:34 +00:00
* along with Brickworks . If not , see < http : //www.gnu.org/licenses/>.
2022-11-15 23:49:51 +00:00
*
* File author : Stefano D ' Angelo
*/
/*!
* module_type { { { foundation } } }
2024-04-15 10:15:54 +00:00
* version { { { 1.1 .1 } } }
2022-11-15 23:49:51 +00:00
* description { { {
* A common header to make sure that a bunch of basic definitions are
* available and consistent for all Brickworks modules .
* } } }
* changelog { { {
* < ul >
2024-04-15 10:15:54 +00:00
* < li > Version < strong > 1.1 .1 < / strong > :
* < ul >
* < li > Accomodate MSVC reporting incorrect C + + standard support . < / li >
* < / ul >
2024-01-02 10:20:52 +00:00
* < li > Version < strong > 1.1 .0 < / strong > :
* < ul >
2024-01-31 09:08:25 +00:00
* < li > Added < code > BW_NULL < / code > and relaxed < code > NULL < / code >
* definition requirement in C + + . < / li >
2024-02-02 16:42:12 +00:00
* < li > Added < code > BW_CXX_NO_ARRAY < / code > . < / li >
2024-01-31 09:08:25 +00:00
* < li > Fixed sign - related warning in < code > bw_hash_sdbm ( ) < / code > . < / li >
2024-02-02 16:48:53 +00:00
* < li > Now checking that C + + compilers support C + + 11 or later . < / li >
2024-01-02 10:20:52 +00:00
* < / ul >
* < / li >
2023-08-08 08:46:05 +00:00
* < li > Version < strong > 1.0 .0 < / strong > :
* < ul >
* < li > Removed < code > BW_SIZE_T < / code > and went for < code > size_t < / code >
* instead . < / li >
* < li > Made control over inclusion of standard library headers more
* explicit via < code > BW_NO_STDLIB < / code > ,
* < code > BW_NO_STDDEF_H < / code > , < code > BW_NO_STDINT_H < / code > , and
* < code > BW_NO_MATH_H < / code > . < / li >
* < li > Introduced < code > BW_NO_DEBUG < / code > to replace
* < code > NDEBUG < / code > and prevented useless inclusion of
* < code > assert . h < / code > . < / li >
2023-08-14 07:57:06 +00:00
* < li > Added < code > BW_RESTRICT < / code > specifiers to input
* arguments . < / li >
2023-08-11 10:49:05 +00:00
* < li > Removed usage of reserved identifiers . < / li >
* < li > Added < code > extern " C " < / code > to functions . < / li >
2023-08-08 08:46:05 +00:00
* < / ul >
* < / li >
2023-07-21 06:56:27 +00:00
* < li > Version < strong > 0.6 .0 < / strong > :
* < ul >
* < li > Added < code > BW_ASSERT < / code > , < code > bw_is_inf ( ) < / code > ,
* < code > bw_is_nan ( ) < / code > , < code > bw_is_finite ( ) < / code > ,
* < code > bw_has_inf ( ) < / code > , < code > bw_has_nan ( ) < / code > ,
* < code > bw_has_only_finite ( ) < / code > , and
* < code > bw_hash_sdbm ( ) < / code > . < / li >
* < li > Removed dependency on bw_config . < / li >
* < / ul >
* < / li >
2023-07-13 14:40:31 +00:00
* < li > Version < strong > 0.5 .0 < / strong > :
* < ul >
* < li > Fixed typo in the documentation of < code > BW_SIZE_T < / code > . < / li >
* < / ul >
* < / li >
2023-03-04 07:17:31 +00:00
* < li > Version < strong > 0.4 .0 < / strong > :
* < ul >
2023-04-19 23:46:41 +00:00
* < li > Added < code > BW_SIZE_T < / code > . < / li >
2023-03-04 07:17:31 +00:00
* < / ul >
* < / li >
2022-11-22 14:28:16 +00:00
* < li > Version < strong > 0.2 .0 < / strong > :
* < ul >
2023-04-19 23:46:41 +00:00
* < li > Removed < code > BW_MALLOC < / code > , < code > BW_REALLOC < / code > ,
* and < code > BW_FREE < / code > . < / li >
* < li > Added < code > BW_RESTRICT < / code > . < / li >
2022-11-22 14:28:16 +00:00
* < / ul >
* < / li >
2022-11-15 23:49:51 +00:00
* < li > Version < strong > 0.1 .0 < / strong > :
* < ul >
* < li > First release . < / li >
* < / ul >
* < / li >
* < / ul >
* } } }
*/
2023-08-08 08:46:05 +00:00
# ifndef BW_COMMON_H
# define BW_COMMON_H
2022-11-15 23:49:51 +00:00
2023-08-12 08:15:04 +00:00
/*** Public API ***/
2024-02-02 16:42:12 +00:00
# ifdef __cplusplus
# if __cplusplus < 201103L
2024-04-15 10:15:54 +00:00
# if _MSC_VER
# pragma message("Detected MSVC compiler reporting not to support C++11. Please use / Zc:__cplusplus if possible, or otherwise ignore this message if everything works for you. See https: //devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ for more information.")
# else
# error Detected C++ compiler that does not support C++11
# endif
2024-02-02 16:42:12 +00:00
# endif
# endif
2022-11-15 23:49:51 +00:00
/*! api {{{
2023-03-04 07:17:31 +00:00
*
2023-08-08 08:46:05 +00:00
* # # # # Basic definitions
*
* Brickworks requires definitions of :
*
2024-01-02 10:20:52 +00:00
* * ` NULL ` ( C only ) and ` size_t ` , normally supplied by ` stddef . h ` ;
2023-08-08 08:46:05 +00:00
* * ` ( u ) int { 8 , 16 , 32 , 64 } _t ` , ` INT { 8 , 16 , 32 , 64 } _ { MIN , MAX } ` , and
* ` UINT { 8 , 16 , 32 , 64 } _MAX ` , normally supplied by ` stdint . h ` ;
* * ` INFINITY ` , normally supplied by ` math . h ` .
*
* You can control whether those definitions are taken from said headers
* or you can supply them yourselves . In particular :
*
* * if ` BW_NO_STDLIB ` or ` BW_NO_STDDEF_H ` is defined , then ` stddef . h ` is not
* ` # include ` d ;
* * if ` BW_NO_STDLIB ` or ` BW_NO_STDINT_H ` is defined , then ` stdint . h ` is not
* ` # include ` d ;
* * if ` BW_NO_STDLIB ` or ` BW_NO_MATH_H ` is defined , then ` math . h ` is not
* ` # include ` d .
*
2024-01-02 10:20:52 +00:00
* A ` BW_NULL ` macro is defined whose value is either ` NULL ` ( C ) or ` nullptr `
* ( C + + ) .
2022-11-15 23:49:51 +00:00
* > > > */
2023-08-08 08:46:05 +00:00
# if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDDEF_H)
2022-11-15 23:49:51 +00:00
# include <stddef.h>
# endif
2023-08-08 08:46:05 +00:00
2024-01-02 10:20:52 +00:00
# ifdef __cplusplus
# define BW_NULL nullptr
# else
# ifndef NULL
# error NULL not defined
# endif
# define BW_NULL NULL
2023-08-08 08:46:05 +00:00
# endif
# if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDINT_H)
2022-11-15 23:49:51 +00:00
# include <stdint.h>
# endif
2023-08-08 08:46:05 +00:00
# if !defined(INT8_MIN) || !defined(INT8_MAX) \
| | ! defined ( INT16_MIN ) | | ! defined ( INT16_MAX ) \
| | ! defined ( INT32_MIN ) | | ! defined ( INT32_MAX ) \
| | ! defined ( INT64_MIN ) | | ! defined ( INT64_MAX ) \
| | ! defined ( UINT8_MAX ) | | ! defined ( UINT16_MAX ) \
| | ! defined ( UINT32_MAX ) | | ! defined ( UINT64_MAX )
# error At least one definition in INT{8,16,32,64}_{MIN,MAX} or UINT{8,16,32,64}_MAX is missing
# endif
# if !defined(BW_NO_STDLIB) && !defined(BW_NO_MATH_H)
2022-11-15 23:49:51 +00:00
# include <math.h>
# endif
2023-08-08 08:46:05 +00:00
# ifndef INFINITY
# error INFINITY not defined
# endif
2022-12-03 09:09:21 +00:00
/*! ...
2024-02-02 16:42:12 +00:00
*
* # # # # BW_CXX_NO_ARRAY
*
* C + + APIs of Brickworks modules typically include overloaded methods that
* use ` std : : array ` arguments , and thus require the ` < array > ` header file .
*
* If this is not wanted , defining ` BW_CXX_NO_ARRAY ` suppresses such methods
* and the inclusion of said header file .
2022-12-03 09:09:21 +00:00
*
* # # # # BW_RESTRICT
2023-08-08 08:46:05 +00:00
*
* ` BW_RESTRICT ` is a preprocessor definition that wraps the ` restrict `
* keyword .
*
* If it is not defined already , then it gets defined as ` restrict ` if C99 is
* supported , otherwise it has no effect ( typically when compiling C + + code ) .
*
2022-12-03 09:09:21 +00:00
* > > > */
2022-11-23 09:54:48 +00:00
# ifndef BW_RESTRICT
# if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
# define BW_RESTRICT restrict
# else
# define BW_RESTRICT
# endif
# endif
2023-07-21 06:56:27 +00:00
/*! ...
*
2023-08-05 06:58:45 +00:00
* # # # # BW_ASSERT and BW_ASSERT_DEEP
2023-08-08 08:46:05 +00:00
*
* Both macros are ` assert ( ) ` - like . ` BW_ASSERT ` is meant to perform
* rapid / basic validity checks ( e . g . , input pointer is not ` NULL ` , input
* ` float ` number is finite ) , while ` BW_ASSERT_DEEP ` should be used for
* deeper checks ( e . g . , validate data structures and internal states ) .
*
* If ` BW_NO_DEBUG ` is defined then " calls " to both ` BW_ASSERT ` and
2023-08-05 06:58:45 +00:00
* ` BW_ASSERT_DEEP ` will be stripped away by the preprocessor .
*
2023-08-08 08:46:05 +00:00
* Whether ` BW_NO_DEBUG ` is defined or not , " calls " to ` BW_ASSERT_DEEP ` will
* still be stripped anyway if ` BW_DEBUG_DEEP ` is not defined .
2023-08-05 06:58:45 +00:00
*
2023-08-08 08:46:05 +00:00
* Otherwise , ` BW_ASSERT ` and ` BW_ASSERT_DEEP ` can either be provided by you ,
* otherwise ` BW_ASSERT ` is defined as ` assert ` ( ` assert . h ` is ` # include ` d
2023-09-27 15:44:59 +00:00
* and ` BW_NO_STDLIB ` must not be defined & mdash ; please mind that ` assert . h `
2023-08-28 15:19:19 +00:00
* is still influenced by ` NDEBUG ` ) , and ` BW_ASSERT_DEEP ` is defined as
2023-08-08 08:46:05 +00:00
* ` BW_ASSERT ` .
2023-08-05 06:58:45 +00:00
*
2023-07-21 06:56:27 +00:00
* > > > */
2023-08-08 08:46:05 +00:00
# ifdef BW_NO_DEBUG
2023-08-05 06:58:45 +00:00
# undef BW_ASSERT
# undef BW_ASSERT_DEEP
2023-07-24 14:14:16 +00:00
# define BW_ASSERT(ignore) ((void)0)
# define BW_ASSERT_DEEP(ignore) ((void)0)
2023-07-21 06:56:27 +00:00
# else
2023-08-08 08:46:05 +00:00
# ifndef BW_ASSERT
# ifdef BW_NO_STDLIB
# error BW_NO_STDLIB defined but BW_ASSERT not defined
# endif
2023-07-21 06:56:27 +00:00
# include <assert.h>
2023-07-24 14:14:16 +00:00
# endif
# ifndef BW_ASSERT
2023-07-21 06:56:27 +00:00
# define BW_ASSERT assert
# endif
2023-07-24 14:14:16 +00:00
# ifdef BW_DEBUG_DEEP
# ifndef BW_ASSERT_DEEP
# define BW_ASSERT_DEEP BW_ASSERT
# endif
# else
# undef BW_ASSERT_DEEP
# define BW_ASSERT_DEEP(ignore) ((void)0)
# endif
2023-07-21 06:56:27 +00:00
# endif
2023-08-11 10:49:05 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2023-07-21 06:56:27 +00:00
/*! ...
*
* # # # # bw_is_inf ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_is_inf (
float x ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Returns non - ` 0 ` if ` x ` is positive or negative infinity , ` 0 ` otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_is_nan ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_is_nan (
float x ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Returns non - ` 0 ` if ` x ` is NaN , ` 0 ` otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_is_finite ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_is_finite (
float x ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Returns non - ` 0 ` if ` x ` is finite ( neither NaN nor positive or negative
* infinity ) , ` 0 ` otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_has_inf ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_has_inf (
const float * BW_RESTRICT x ,
size_t n_elems ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Scans the fist ` n_elems ` in buffer ` x ` and returns non - ` 0 ` if it contains
* at least one positive or negative inifinity value , ` 0 ` otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_has_nan ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_has_nan (
const float * BW_RESTRICT x ,
size_t n_elems ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Scans the fist ` n_elems ` in buffer ` x ` and returns non - ` 0 ` if it contains
* at least one NaN value , ` 0 ` otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_has_only_finite ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline char bw_has_only_finite (
const float * BW_RESTRICT x ,
size_t n_elems ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Scans the fist ` n_elems ` in buffer ` x ` and returns non - ` 0 ` if it only
* finds finite values ( neither NaN nor positive or negative infinity ) , ` 0 `
* otherwise .
2023-07-21 06:56:27 +00:00
*
* # # # # bw_hash_sdbm ( )
* ` ` ` > > > */
2023-08-28 15:19:19 +00:00
static inline uint32_t bw_hash_sdbm (
const char * BW_RESTRICT string ) ;
2023-07-21 06:56:27 +00:00
/*! <<<```
2023-08-05 06:58:45 +00:00
* Returns the sdbm hash of the given ` string ` .
2023-07-21 06:56:27 +00:00
* } } } */
2023-08-11 10:49:05 +00:00
# ifdef __cplusplus
}
# endif
2023-07-21 06:56:27 +00:00
/*** Implementation ***/
/* WARNING: This part of the file is not part of the public API. Its content may
* change at any time in future versions . Please , do not use it directly . */
2023-08-11 10:49:05 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2023-08-28 15:19:19 +00:00
static inline char bw_is_inf (
float x ) {
2023-08-10 08:17:22 +00:00
union { uint32_t u ; float f ; } v ;
2023-07-21 06:56:27 +00:00
v . f = x ;
return ( v . u & 0x7fffffff ) = = 0x7f800000 ;
}
2023-08-28 15:19:19 +00:00
static inline char bw_is_nan (
float x ) {
2023-08-10 08:17:22 +00:00
union { uint32_t u ; float f ; } v ;
2023-07-21 06:56:27 +00:00
v . f = x ;
return ( ( v . u & 0x7f800000 ) = = 0x7f800000 ) & & ( v . u & 0x7fffff ) ;
}
2023-08-28 15:19:19 +00:00
static inline char bw_is_finite (
float x ) {
2023-08-10 08:17:22 +00:00
union { uint32_t u ; float f ; } v ;
2023-07-21 06:56:27 +00:00
v . f = x ;
return ( v . u & 0x7f800000 ) ! = 0x7f800000 ;
}
2023-08-28 15:19:19 +00:00
static inline char bw_has_inf (
const float * BW_RESTRICT x ,
size_t n_elems ) {
2023-07-21 06:56:27 +00:00
char ret = 0 ;
2023-08-08 08:46:05 +00:00
for ( size_t i = 0 ; i < n_elems & & ! ret ; i + + )
2023-07-21 06:56:27 +00:00
ret = bw_is_inf ( x [ i ] ) ;
return ret ;
}
2023-08-28 15:19:19 +00:00
static inline char bw_has_nan (
const float * BW_RESTRICT x ,
size_t n_elems ) {
2023-07-21 06:56:27 +00:00
char ret = 0 ;
2023-08-08 08:46:05 +00:00
for ( size_t i = 0 ; i < n_elems & & ! ret ; i + + )
2023-07-21 06:56:27 +00:00
ret = bw_is_nan ( x [ i ] ) ;
return ret ;
}
2023-08-28 15:19:19 +00:00
static inline char bw_has_only_finite (
const float * BW_RESTRICT x ,
size_t n_elems ) {
2023-07-21 06:56:27 +00:00
char ret = 1 ;
2023-08-08 08:46:05 +00:00
for ( size_t i = 0 ; i < n_elems & & ret ; i + + )
2023-07-21 06:56:27 +00:00
ret = bw_is_finite ( x [ i ] ) ;
return ret ;
}
2023-08-28 15:19:19 +00:00
static inline uint32_t bw_hash_sdbm (
const char * BW_RESTRICT string ) {
2023-07-21 06:56:27 +00:00
uint32_t hash = 0 ;
for ( ; * string ! = ' \0 ' ; string + + )
2023-12-06 13:40:16 +00:00
hash = ( uint32_t ) * string + ( hash < < 6 ) + ( hash < < 16 ) - hash ;
2023-07-21 06:56:27 +00:00
return hash ;
}
2022-11-15 23:49:51 +00:00
2023-08-11 10:49:05 +00:00
# ifdef __cplusplus
}
# endif
2022-11-15 23:49:51 +00:00
# endif