yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
57567778b
master
1#ifndef SLANG_CORE_MATH_H 2#define SLANG_CORE_MATH_H 3 4#include "slang.h" 5 6#include <cmath> 7 8namespace Slang 9{ 10// Some handy constants 11 12// The largest positive (or negative) number 13#define SLANG_HALF_MAX 65504.0f 14// Smallest (denormalized) value. 1 / 2^24 15#define SLANG_HALF_SUB_NORMAL_MIN (1.0f / 16777216.0f) 16 17class Math 18{ 19public : 20// Use to fix type punning issues with strict aliasing 21union FloatIntUnion 22 { 23float fvalue ; 24int ivalue ; 25 26SLANG_FORCE_INLINE static FloatIntUnion makeFromInt (int i ) 27 { 28FloatIntUnion cast ; 29cast .ivalue = i ; 30return cast ; 31 } 32SLANG_FORCE_INLINE static FloatIntUnion makeFromFloat (float f ) 33 { 34FloatIntUnion cast ; 35cast .fvalue = f ; 36return cast ; 37 } 38 }; 39union DoubleInt64Union 40 { 41double dvalue ; 42int64_t ivalue ; 43SLANG_FORCE_INLINE static DoubleInt64Union makeFromInt64 (int64_t i ) 44 { 45DoubleInt64Union cast ; 46cast .ivalue = i ; 47return cast ; 48 } 49SLANG_FORCE_INLINE static DoubleInt64Union makeFromDouble (double d ) 50 { 51DoubleInt64Union cast ; 52cast .dvalue = d ; 53return cast ; 54 } 55 }; 56 57static const float Pi ; 58 59template < typename T > 60static T Abs (T a ) 61 { 62return (a < 0 ) ?- a :a ; 63 } 64 65template < typename T > 66static T Min (const T & v1 ,const T & v2 ) 67 { 68return v1 < v2 ?v1 :v2 ; 69 } 70template < typename T > 71static T Max (const T & v1 ,const T & v2 ) 72 { 73return v1 > v2 ?v1 :v2 ; 74 } 75template < typename T > 76static T Min (const T & v1 ,const T & v2 ,const T & v3 ) 77 { 78return Min (v1 ,Min (v2 ,v3 )); 79 } 80template < typename T > 81static T Max (const T & v1 ,const T & v2 ,const T & v3 ) 82 { 83return Max (v1 ,Max (v2 ,v3 )); 84 } 85template < typename T > 86static T Clamp (const T & val ,const T & vmin ,const T & vmax ) 87 { 88if (val < vmin ) 89return vmin ; 90else if (val > vmax ) 91return vmax ; 92else 93return val ; 94 } 95 96static inline int FastFloor (float x ) 97 { 98int i = (int )x ; 99return i - (i > x ); 100 } 101 102static inline int FastFloor (double x ) 103 { 104int i = (int )x ; 105return i - (i > x ); 106 } 107 108static inline int IsNaN (float x ) {return std ::isnan (x ); } 109static inline int IsNaN (double x ) {return std ::isnan (x ); } 110 111static inline int IsInf (float x ) {return std ::isinf (x ); } 112static inline int IsInf (double x ) {return std ::isinf (x ); } 113 114static inline unsigned int Ones32 (unsigned int x ) 115 { 116/* 32-bit recursive reduction using SWAR... 117but first step is mapping 2-bit values 118into sum of 2 1-bit values in sneaky way 119*/ 120x -= ((x >>1 )& 0x55555555 ); 121x = (((x >>2 )& 0x33333333 )+ (x & 0x33333333 )); 122x = (((x >>4 )+ x )& 0x0f0f0f0f ); 123x += (x >>8 ); 124x += (x >>16 ); 125return (x & 0x0000003f ); 126 } 127 128static inline unsigned int Log2Floor (unsigned int x ) 129 { 130x |= (x >>1 ); 131x |= (x >>2 ); 132x |= (x >>4 ); 133x |= (x >>8 ); 134x |= (x >>16 ); 135return (Ones32 (x >>1 )); 136 } 137 138static inline unsigned int Log2Ceil (unsigned int x ) 139 { 140int y = (x & (x - 1 )); 141y |=- y ; 142y >>= (32 - 1 ); 143x |= (x >>1 ); 144x |= (x >>2 ); 145x |= (x >>4 ); 146x |= (x >>8 ); 147x |= (x >>16 ); 148return (Ones32 (x >>1 )- y ); 149 } 150/* 151static inline int Log2(float x) 152{ 153unsigned int ix = (unsigned int&)x; 154unsigned int exp = (ix >> 23) & 0xFF; 155int log2 = (unsigned int)(exp) - 127; 156 157return log2; 158} 159*/ 160 161static bool AreNearlyEqual (double a ,double b ,double epsilon ) 162 { 163// If they are equal then we are done 164if (a == b ) 165 { 166return true; 167 } 168 169const double absA = Abs (a ); 170const double absB = Abs (b ); 171const double diff = Abs (a - b ); 172 173// https://en.wikipedia.org/wiki/Double_precision_floating-point_format 174const double minNormal = 2.2250738585072014e-308 ; 175// Either a or b are very close to being zero, so doing relative comparison isn't really 176// appropriate 177if (a == 0.0 || b == 0.0 || (absA + absB < minNormal )) 178 { 179return diff < (epsilon * minNormal ); 180 } 181else 182 { 183// Calculate a relative relative error 184return diff < epsilon * (absA + absB ); 185 } 186 } 187 188template < typename T > 189static T getLowestBit (T val ) 190 { 191return val & (- val ); 192 } 193}; 194inline int FloatAsInt (float val ) 195{ 196return Math ::FloatIntUnion ::makeFromFloat (val ).ivalue ; 197} 198inline float IntAsFloat (int val ) 199{ 200return Math ::FloatIntUnion ::makeFromInt (val ).fvalue ; 201} 202 203SLANG_FORCE_INLINE int64_t DoubleAsInt64 (double val ) 204{ 205return Math ::DoubleInt64Union ::makeFromDouble (val ).ivalue ; 206} 207SLANG_FORCE_INLINE double Int64AsDouble (int64_t value ) 208{ 209return Math ::DoubleInt64Union ::makeFromInt64 (value ).dvalue ; 210} 211 212inline unsigned short FloatToHalf (float val ) 213{ 214const autox = FloatAsInt (val ); 215 216unsigned short bits = (x >>16 )& 0x8000 ; 217unsigned short m = (x >>12 )& 0x07ff ; 218unsigned int e = (x >>23 )& 0xff ; 219if (e < 103 ) 220return bits ; 221if (e > 142 ) 222 { 223bits |=0x7c00u ; 224bits |=e == 255 && (x & 0x007fffffu ); 225return bits ; 226 } 227if (e < 113 ) 228 { 229m |=0x0800u ; 230bits |= (m >> (114 - e ))+ ((m >> (113 - e ))& 1 ); 231return bits ; 232 } 233bits |= ((e - 112 ) <<10 ) | (m >>1 ); 234bits += m & 1 ; 235return bits ; 236} 237 238inline float HalfToFloat (unsigned short input ) 239{ 240static const automagic = Math ::FloatIntUnion ::makeFromInt ((127 + (127 - 15 )) <<23 ); 241static const autowas_infnan = Math ::FloatIntUnion ::makeFromInt ((127 + 16 ) <<23 ); 242Math ::FloatIntUnion o ; 243o .ivalue = (input & 0x7fff ) <<13 ;// exponent/mantissa bits 244o .fvalue *=magic .fvalue ;// exponent adjust 245if (o .fvalue >=was_infnan .fvalue )// make sure Inf/NaN survive 246o .ivalue |=255 <<23 ; 247o .ivalue |= (input & 0x8000 ) <<16 ;// sign bit 248return o .fvalue ; 249} 250 251class Random 252{ 253private : 254unsigned int seed ; 255 256public : 257Random (int seed ) {this -> seed = seed ; } 258int Next ()// random between 0 and RandMax (currently 0x7fff) 259 { 260return ((seed = ((seed <<12 )+ 150889L ) %714025 )& 0x7fff ); 261 } 262int Next (int min ,int max )// inclusive min, exclusive max 263 { 264unsigned int a = ((seed = ((seed <<12 )+ 150889L ) %714025 )& 0xFFFF ); 265unsigned int b = ((seed = ((seed <<12 )+ 150889L ) %714025 )& 0xFFFF ); 266unsigned int r = (a <<16 )+ b ; 267return min + r % (max - min ); 268 } 269float NextFloat () {return ((Next () <<15 )+ Next ()) / ((float )(1 <<30 )); } 270float NextFloat (float valMin ,float valMax ) {return valMin + (valMax - valMin )* NextFloat (); } 271static int RandMax () {return 0x7fff ; } 272}; 273}// namespace Slang 274 275#endif