diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/core/slang-math.h | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff) | |
format
* format
* Minor test fixes
* enable checking cpp format in ci
Diffstat (limited to 'source/core/slang-math.h')
| -rw-r--r-- | source/core/slang-math.h | 460 |
1 files changed, 234 insertions, 226 deletions
diff --git a/source/core/slang-math.h b/source/core/slang-math.h index 51ada76a9..e977dc37d 100644 --- a/source/core/slang-math.h +++ b/source/core/slang-math.h @@ -2,264 +2,272 @@ #define SLANG_CORE_MATH_H #include "slang.h" + #include <cmath> namespace Slang { - // Some handy constants +// Some handy constants - // The largest positive (or negative) number -# define SLANG_HALF_MAX 65504.0f - // Smallest (denormalized) value. 1 / 2^24 -# define SLANG_HALF_SUB_NORMAL_MIN (1.0f / 16777216.0f) +// The largest positive (or negative) number +#define SLANG_HALF_MAX 65504.0f +// Smallest (denormalized) value. 1 / 2^24 +#define SLANG_HALF_SUB_NORMAL_MIN (1.0f / 16777216.0f) - class Math - { - public: - // Use to fix type punning issues with strict aliasing - union FloatIntUnion - { - float fvalue; - int ivalue; +class Math +{ +public: + // Use to fix type punning issues with strict aliasing + union FloatIntUnion + { + float fvalue; + int ivalue; - SLANG_FORCE_INLINE static FloatIntUnion makeFromInt(int i) { FloatIntUnion cast; cast.ivalue = i; return cast; } - SLANG_FORCE_INLINE static FloatIntUnion makeFromFloat(float f) { FloatIntUnion cast; cast.fvalue = f; return cast; } - }; - union DoubleInt64Union + SLANG_FORCE_INLINE static FloatIntUnion makeFromInt(int i) { - double dvalue; - int64_t ivalue; - SLANG_FORCE_INLINE static DoubleInt64Union makeFromInt64(int64_t i) { DoubleInt64Union cast; cast.ivalue = i; return cast; } - SLANG_FORCE_INLINE static DoubleInt64Union makeFromDouble(double d) { DoubleInt64Union cast; cast.dvalue = d; return cast; } - }; - - static const float Pi; - - template <typename T> - static T Abs(T a) + FloatIntUnion cast; + cast.ivalue = i; + return cast; + } + SLANG_FORCE_INLINE static FloatIntUnion makeFromFloat(float f) + { + FloatIntUnion cast; + cast.fvalue = f; + return cast; + } + }; + union DoubleInt64Union + { + double dvalue; + int64_t ivalue; + SLANG_FORCE_INLINE static DoubleInt64Union makeFromInt64(int64_t i) { - return (a < 0) ? -a : a; + DoubleInt64Union cast; + cast.ivalue = i; + return cast; } + SLANG_FORCE_INLINE static DoubleInt64Union makeFromDouble(double d) + { + DoubleInt64Union cast; + cast.dvalue = d; + return cast; + } + }; - template<typename T> - static T Min(const T& v1, const T&v2) - { - return v1<v2?v1:v2; - } - template<typename T> - static T Max(const T& v1, const T&v2) - { - return v1>v2?v1:v2; - } - template<typename T> - static T Min(const T& v1, const T&v2, const T&v3) - { - return Min(v1, Min(v2, v3)); - } - template<typename T> - static T Max(const T& v1, const T&v2, const T&v3) - { - return Max(v1, Max(v2, v3)); - } - template<typename T> - static T Clamp(const T& val, const T& vmin, const T&vmax) - { - if (val < vmin) return vmin; - else if (val > vmax) return vmax; - else return val; - } + static const float Pi; - static inline int FastFloor(float x) - { - int i = (int)x; - return i - (i > x); - } + template<typename T> + static T Abs(T a) + { + return (a < 0) ? -a : a; + } - static inline int FastFloor(double x) - { - int i = (int)x; - return i - (i > x); - } + template<typename T> + static T Min(const T& v1, const T& v2) + { + return v1 < v2 ? v1 : v2; + } + template<typename T> + static T Max(const T& v1, const T& v2) + { + return v1 > v2 ? v1 : v2; + } + template<typename T> + static T Min(const T& v1, const T& v2, const T& v3) + { + return Min(v1, Min(v2, v3)); + } + template<typename T> + static T Max(const T& v1, const T& v2, const T& v3) + { + return Max(v1, Max(v2, v3)); + } + template<typename T> + static T Clamp(const T& val, const T& vmin, const T& vmax) + { + if (val < vmin) + return vmin; + else if (val > vmax) + return vmax; + else + return val; + } - static inline int IsNaN(float x) - { - return std::isnan(x); - } + static inline int FastFloor(float x) + { + int i = (int)x; + return i - (i > x); + } - static inline int IsInf(float x) - { - return std::isinf(x); - } + static inline int FastFloor(double x) + { + int i = (int)x; + return i - (i > x); + } - static inline unsigned int Ones32(unsigned int x) - { - /* 32-bit recursive reduction using SWAR... - but first step is mapping 2-bit values - into sum of 2 1-bit values in sneaky way - */ - x -= ((x >> 1) & 0x55555555); - x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); - x = (((x >> 4) + x) & 0x0f0f0f0f); - x += (x >> 8); - x += (x >> 16); - return(x & 0x0000003f); - } + static inline int IsNaN(float x) { return std::isnan(x); } - static inline unsigned int Log2Floor(unsigned int x) - { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return(Ones32(x >> 1)); - } + static inline int IsInf(float x) { return std::isinf(x); } - static inline unsigned int Log2Ceil(unsigned int x) - { - int y = (x & (x - 1)); - y |= -y; - y >>= (32 - 1); - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return(Ones32(x >> 1) - y); - } - /* - static inline int Log2(float x) - { - unsigned int ix = (unsigned int&)x; - unsigned int exp = (ix >> 23) & 0xFF; - int log2 = (unsigned int)(exp) - 127; + static inline unsigned int Ones32(unsigned int x) + { + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return (x & 0x0000003f); + } - return log2; - } - */ + static inline unsigned int Log2Floor(unsigned int x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (Ones32(x >> 1)); + } - static bool AreNearlyEqual(double a, double b, double epsilon) - { - // If they are equal then we are done - if (a == b) - { - return true; - } + static inline unsigned int Log2Ceil(unsigned int x) + { + int y = (x & (x - 1)); + y |= -y; + y >>= (32 - 1); + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (Ones32(x >> 1) - y); + } + /* + static inline int Log2(float x) + { + unsigned int ix = (unsigned int&)x; + unsigned int exp = (ix >> 23) & 0xFF; + int log2 = (unsigned int)(exp) - 127; - const double absA = Abs(a); - const double absB = Abs(b); - const double diff = Abs(a - b); + return log2; + } + */ - // https://en.wikipedia.org/wiki/Double_precision_floating-point_format - const double minNormal = 2.2250738585072014e-308; - // Either a or b are very close to being zero, so doing relative comparison isn't really appropriate - if (a == 0.0 || b == 0.0 || (absA + absB < minNormal)) - { - return diff < (epsilon * minNormal); - } - else - { - // Calculate a relative relative error - return diff < epsilon * (absA + absB); - } + static bool AreNearlyEqual(double a, double b, double epsilon) + { + // If they are equal then we are done + if (a == b) + { + return true; } - template <typename T> - static T getLowestBit(T val) + const double absA = Abs(a); + const double absB = Abs(b); + const double diff = Abs(a - b); + + // https://en.wikipedia.org/wiki/Double_precision_floating-point_format + const double minNormal = 2.2250738585072014e-308; + // Either a or b are very close to being zero, so doing relative comparison isn't really + // appropriate + if (a == 0.0 || b == 0.0 || (absA + absB < minNormal)) + { + return diff < (epsilon * minNormal); + } + else { - return val & (-val); + // Calculate a relative relative error + return diff < epsilon * (absA + absB); } - }; - inline int FloatAsInt(float val) - { - return Math::FloatIntUnion::makeFromFloat(val).ivalue; - } - inline float IntAsFloat(int val) - { - return Math::FloatIntUnion::makeFromInt(val).fvalue; - } + } + + template<typename T> + static T getLowestBit(T val) + { + return val & (-val); + } +}; +inline int FloatAsInt(float val) +{ + return Math::FloatIntUnion::makeFromFloat(val).ivalue; +} +inline float IntAsFloat(int val) +{ + return Math::FloatIntUnion::makeFromInt(val).fvalue; +} - SLANG_FORCE_INLINE int64_t DoubleAsInt64(double val) +SLANG_FORCE_INLINE int64_t DoubleAsInt64(double val) +{ + return Math::DoubleInt64Union::makeFromDouble(val).ivalue; +} +SLANG_FORCE_INLINE double Int64AsDouble(int64_t value) +{ + return Math::DoubleInt64Union::makeFromInt64(value).dvalue; +} + +inline unsigned short FloatToHalf(float val) +{ + const auto x = FloatAsInt(val); + + unsigned short bits = (x >> 16) & 0x8000; + unsigned short m = (x >> 12) & 0x07ff; + unsigned int e = (x >> 23) & 0xff; + if (e < 103) + return bits; + if (e > 142) { - return Math::DoubleInt64Union::makeFromDouble(val).ivalue; + bits |= 0x7c00u; + bits |= e == 255 && (x & 0x007fffffu); + return bits; } - SLANG_FORCE_INLINE double Int64AsDouble(int64_t value) + if (e < 113) { - return Math::DoubleInt64Union::makeFromInt64(value).dvalue; + m |= 0x0800u; + bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); + return bits; } + bits |= ((e - 112) << 10) | (m >> 1); + bits += m & 1; + return bits; +} - inline unsigned short FloatToHalf(float val) - { - const auto x = FloatAsInt(val); - - unsigned short bits = (x >> 16) & 0x8000; - unsigned short m = (x >> 12) & 0x07ff; - unsigned int e = (x >> 23) & 0xff; - if (e < 103) - return bits; - if (e > 142) - { - bits |= 0x7c00u; - bits |= e == 255 && (x & 0x007fffffu); - return bits; - } - if (e < 113) - { - m |= 0x0800u; - bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); - return bits; - } - bits |= ((e - 112) << 10) | (m >> 1); - bits += m & 1; - return bits; - } +inline float HalfToFloat(unsigned short input) +{ + static const auto magic = Math::FloatIntUnion::makeFromInt((127 + (127 - 15)) << 23); + static const auto was_infnan = Math::FloatIntUnion::makeFromInt((127 + 16) << 23); + Math::FloatIntUnion o; + o.ivalue = (input & 0x7fff) << 13; // exponent/mantissa bits + o.fvalue *= magic.fvalue; // exponent adjust + if (o.fvalue >= was_infnan.fvalue) // make sure Inf/NaN survive + o.ivalue |= 255 << 23; + o.ivalue |= (input & 0x8000) << 16; // sign bit + return o.fvalue; +} - inline float HalfToFloat(unsigned short input) - { - static const auto magic = Math::FloatIntUnion::makeFromInt((127 + (127 - 15)) << 23); - static const auto was_infnan = Math::FloatIntUnion::makeFromInt((127 + 16) << 23); - Math::FloatIntUnion o; - o.ivalue = (input & 0x7fff) << 13; // exponent/mantissa bits - o.fvalue *= magic.fvalue; // exponent adjust - if (o.fvalue >= was_infnan.fvalue) // make sure Inf/NaN survive - o.ivalue |= 255 << 23; - o.ivalue |= (input & 0x8000) << 16; // sign bit - return o.fvalue; - } +class Random +{ +private: + unsigned int seed; - class Random - { - private: - unsigned int seed; - public: - Random(int seed) - { - this->seed = seed; - } - int Next() // random between 0 and RandMax (currently 0x7fff) - { - return ((seed = ((seed << 12) + 150889L) % 714025) & 0x7fff); - } - int Next(int min, int max) // inclusive min, exclusive max - { - unsigned int a = ((seed = ((seed << 12) + 150889L) % 714025) & 0xFFFF); - unsigned int b = ((seed = ((seed << 12) + 150889L) % 714025) & 0xFFFF); - unsigned int r = (a << 16) + b; - return min + r % (max - min); - } - float NextFloat() - { - return ((Next() << 15) + Next()) / ((float)(1 << 30)); - } - float NextFloat(float valMin, float valMax) - { - return valMin + (valMax - valMin) * NextFloat(); - } - static int RandMax() - { - return 0x7fff; - } - }; -} +public: + Random(int seed) { this->seed = seed; } + int Next() // random between 0 and RandMax (currently 0x7fff) + { + return ((seed = ((seed << 12) + 150889L) % 714025) & 0x7fff); + } + int Next(int min, int max) // inclusive min, exclusive max + { + unsigned int a = ((seed = ((seed << 12) + 150889L) % 714025) & 0xFFFF); + unsigned int b = ((seed = ((seed << 12) + 150889L) % 714025) & 0xFFFF); + unsigned int r = (a << 16) + b; + return min + r % (max - min); + } + float NextFloat() { return ((Next() << 15) + Next()) / ((float)(1 << 30)); } + float NextFloat(float valMin, float valMax) { return valMin + (valMax - valMin) * NextFloat(); } + static int RandMax() { return 0x7fff; } +}; +} // namespace Slang -#endif +#endif |
