intrinsics.h (6114B)
1 #pragma once 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <stdint.h> 6 #include <string.h> 7 8 #include "platform.h" 9 #include "platform_backtrace.h" 10 11 typedef int8_t s8; 12 typedef int16_t s16; 13 typedef int32_t s32; 14 typedef int64_t s64; 15 16 typedef uint8_t u8; 17 typedef uint16_t u16; 18 typedef uint32_t u32; 19 typedef uint64_t u64; 20 21 typedef intptr_t sptr; 22 typedef uintptr_t uptr; 23 24 #define S8_MAX s8( INT8_MAX ) 25 #define S16_MAX s16( INT16_MAX ) 26 #define S32_MAX s32( INT32_MAX ) 27 #define S64_MAX s64( INT64_MAX ) 28 #define S8_MIN s8( INT8_MIN ) 29 #define S16_MIN s16( INT16_MIN ) 30 #define S32_MIN s32( INT32_MIN ) 31 #define S64_MIN s64( INT64_MIN ) 32 33 #define U8_MAX u8( UINT8_MAX ) 34 #define U16_MAX u16( UINT16_MAX ) 35 #define U32_MAX u32( UINT32_MAX ) 36 #define U64_MAX u64( UINT64_MAX ) 37 38 #define S8 INT8_C 39 #define S16 INT16_C 40 #define S32 INT32_C 41 #define S64 INT64_C 42 #define U8 UINT8_C 43 #define U16 UINT16_C 44 #define U32 UINT32_C 45 #define U64 UINT64_C 46 47 #define PI 3.14159265359f 48 #define TAU 6.28318530717958647692f 49 50 #define STRINGIFY_HELPER( x ) #x 51 #define STRINGIFY( x ) STRINGIFY_HELPER( x ) 52 53 #define CONCAT_HELPER( a, b ) a##b 54 #define CONCAT( a, b ) CONCAT_HELPER( a, b ) 55 #define COUNTER_NAME( x ) CONCAT( x, __COUNTER__ ) 56 #define LINE_NAME( x ) CONCAT( x, __LINE__ ) 57 58 inline void assert_impl( const bool predicate, const char * message ) { 59 if( !predicate ) { 60 puts( message ); 61 print_backtrace_and_abort(); 62 } 63 } 64 65 #define ASSERT( predicate ) assert_impl( predicate, "\x1b[1;31massertion failed at " __FILE__ " line " STRINGIFY( __LINE__ ) ": \x1b[0;1m" #predicate "\x1b[0m" ) 66 67 #define STATIC_ASSERT( p ) static_assert( p, #p ) 68 69 template< typename T, size_t N > 70 char ( &ArrayCountObj( const T ( & )[ N ] ) )[ N ]; 71 #define ARRAY_COUNT( arr ) ( sizeof( ArrayCountObj( arr ) ) ) 72 73 #define is_power_of_2( n ) ( ( ( n ) & ( ( n ) - 1 ) ) == 0 ) 74 75 #define align_power_of_2( n, alignment ) ( ( ( n ) + ( alignment ) - 1 ) & ~( ( alignment ) - 1 ) ) 76 #define align2( n ) align_power_of_2( n, 2 ) 77 #define align4( n ) align_power_of_2( n, 4 ) 78 #define align8( n ) align_power_of_2( n, 8 ) 79 #define align16( n ) align_power_of_2( n, 16 ) 80 #define align_arbitrary( n, alignment ) ( ( ( n ) + ( alignment ) - 1 ) / ( alignment ) * ( alignment ) ) 81 82 #define kilobytes( kb ) ( size_t( kb ) * size_t( 1024 ) ) 83 #define megabytes( mb ) ( kilobytes( mb ) * size_t( 1024 ) ) 84 #define gigabytes( gb ) ( megabytes( gb ) * size_t( 1024 ) ) 85 86 template< typename T > 87 void swap2( T & a, T & b ) { 88 T t = a; 89 a = b; 90 b = t; 91 } 92 93 template< typename T > 94 constexpr T min( T a, T b ) { 95 return a < b ? a : b; 96 } 97 98 template< typename T > 99 constexpr T min( T a, T b, T c ) { 100 return min( min( a, b ), c ); 101 } 102 103 template< typename T > 104 constexpr T min( T a, T b, T c, T d ) { 105 return min( min( min( a, b ), c ), d ); 106 } 107 108 template< typename T > 109 constexpr T max( T a, T b ) { 110 return a > b ? a : b; 111 } 112 113 template< typename T > 114 constexpr T max( T a, T b, T c ) { 115 return max( max( a, b ), c ); 116 } 117 118 template< typename T > 119 constexpr T max( T a, T b, T c, T d ) { 120 return max( max( max( a, b ), c ), d ); 121 } 122 123 template< typename T > 124 constexpr T abs( T x ) { 125 return x > 0 ? x : -x; 126 } 127 128 template< typename T > 129 constexpr T clamp( T x, T lo, T hi ) { 130 return x < lo ? lo : ( x > hi ? hi : x ); 131 } 132 133 template< typename T > 134 constexpr T saturate( T x ) { 135 return clamp( x, T( 0 ), T( 1 ) ); 136 } 137 138 template< typename T > 139 constexpr T clamp11( T x ) { 140 return clamp( x, T( -1 ), T( 1 ) ); 141 } 142 143 #define slots_required( data_size, slot_size ) ( ( data_size ) / ( slot_size ) + ( ( data_size ) % ( slot_size ) != 0 ) ) 144 145 #define AT_STARTUP( code ) \ 146 namespace COUNTER_NAME( StartupCode ) { \ 147 static struct AtStartup { \ 148 AtStartup() { code; } \ 149 } AtStartupInstance; \ 150 } 151 152 #if !PLATFORM_RELACY 153 #define NONCOPYABLE( T ) T( const T & ) = delete; void operator=( const T & ) = delete; 154 #else 155 #define NONCOPYABLE( T ) 156 #endif 157 158 template< typename F > 159 struct ScopeExit { 160 ScopeExit( F f_ ) : f( f_ ) { } 161 ~ScopeExit() { f(); } 162 F f; 163 }; 164 165 struct DeferHelper { 166 template< typename F > 167 ScopeExit< F > operator+( F f ) { return f; } 168 }; 169 170 #define defer const auto & COUNTER_NAME( DEFER_ ) = DeferHelper() + [&]() 171 172 template< typename S, typename T > 173 struct SameType { 174 enum { value = false }; 175 }; 176 template< typename T > 177 struct SameType< T, T > { 178 enum { value = true }; 179 }; 180 181 #define SAME_TYPE( S, T ) SameType< S, T >::value 182 183 template< typename To, typename From > 184 inline To checked_cast( const From & from ) { 185 To result = To( from ); 186 ASSERT( From( result ) == from ); 187 return result; 188 } 189 190 // TODO: this sucks 191 inline u8 * file_get_contents( const char * path, size_t * out_len = NULL ) { 192 FILE * file = fopen( path, "rb" ); 193 ASSERT( file != NULL ); 194 195 fseek( file, 0, SEEK_END ); 196 size_t len = checked_cast< size_t >( ftell( file ) ); 197 ASSERT( len < SIZE_MAX ); 198 fseek( file, 0, SEEK_SET ); 199 200 u8 * contents = ( u8 * ) malloc( len + 1 ); 201 size_t bytes_read = fread( contents, 1, len, file ); 202 contents[ len ] = '\0'; 203 ASSERT( bytes_read == len ); 204 205 if( out_len ) *out_len = len; 206 207 fclose( file ); 208 209 return contents; 210 } 211 212 #define DEF_VISIT( T ) \ 213 template< typename F > inline void visit( T & x, F f ) { f( x ); } \ 214 template< typename F > inline void visit( const T & x, F f ) { f( x ); } 215 216 DEF_VISIT( u8 ) 217 DEF_VISIT( u16 ) 218 DEF_VISIT( u32 ) 219 DEF_VISIT( u64 ) 220 DEF_VISIT( s8 ) 221 DEF_VISIT( s16 ) 222 DEF_VISIT( s32 ) 223 DEF_VISIT( s64 ) 224 DEF_VISIT( float ) 225 DEF_VISIT( double ) 226 227 #undef DEF_VISIT 228 229 template< typename T > 230 inline T * malloc_array( size_t count ) { 231 ASSERT( SIZE_MAX / count >= sizeof( T ) ); 232 return ( T * ) malloc( count * sizeof( T ) ); 233 } 234 235 template< typename T > 236 inline T * realloc_array( T * old, size_t count ) { 237 ASSERT( SIZE_MAX / count >= sizeof( T ) ); 238 return ( T * ) realloc( old, count * sizeof( T ) ); 239 } 240 241 template< typename T > 242 static T lerp( T a, float t, T b ) { 243 ASSERT( t >= 0.0f && t <= 1.0f ); 244 return a * ( 1.0f - t ) + b * t; 245 } 246 247 template< typename T > 248 static T unlerp( T lo, T x, T hi ) { 249 return ( x - lo ) / ( hi - lo ); 250 } 251 252 /* 253 * these are meant to be used for breaking deep in leaf code on keypresses etc 254 * defined in breakbools.cc 255 */ 256 extern bool break1; 257 extern bool break2; 258 extern bool break3; 259 extern bool break4;