/// Josh's 3D Math Library /// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing. /// Developed and Maintained by Josh O'Leary @ Redacted Software. /// Special Thanks to William Tomasine II and Maxine Hayes. /// (c) 2024 Redacted Software /// This work is dedicated to the public domain. /// @file J3ML.h /// @desc Core mathematical and utility functions, concrete types, and math constants. /// @edit 2024-07-05 #pragma once #include #include #include #include #include /// Swaps two elements in-place without copying their data. template void Swap(T &a, T &b) { T temp = std::move(a); a = std::move(b); b = std::move(temp); } /// Clean symbolic names for integers of specific size. namespace J3ML::SizedIntegralTypes { using u8 = uint8_t; using u16 = uint16_t; using u32 = uint32_t; using u64 = uint64_t; using s8 = int8_t; using s16 = int16_t; using s32 = int32_t; using s64 = int64_t; } namespace J3ML::SizedFloatTypes { using f32 = float; using f64 = double; using f128 = long double; } using namespace J3ML::SizedIntegralTypes; using namespace J3ML::SizedFloatTypes; namespace J3ML::Math::BitTwiddling { /// Parses a string of form "011101010" to a u32 u32 BinaryStringToValue(const char* s); /// Returns the number of 1's set in the given value. inline int CountBitsSet(u32 value); } // TODO: Implement "Wrappers" for most standard math functions. // We want to later-on implement lookup tables and SSE as conditional macros. namespace J3ML::Math::Constants { /// sqrt(2pi) ^ -1 constexpr float RecipSqrt2Pi = 0.3989422804014326779399460599343818684758586311649346576659258296706579258993018385012523339073069364; /// pi - https://www.mathsisfun.com/numbers/pi.html constexpr float Pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679; /// e - https://www.mathsisfun.com/numbers/e-eulers-number.html constexpr float EulersNumber = 2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274; /// 2pi - The ratio of a circle's circumferecne to its radius, and the number of radians in one turn. constexpr float Tau = 6.28318530717958647692; /// sqrt(2) constexpr float PythagorasConstant = 1.41421356237309504880; /// sqrt(3) constexpr float TheodorusConstant = 1.73205080756887729352; /// Golden Ratio constexpr float Phi = 1.61803398874989484820; /// ln 2 constexpr float NaturalLog2 = 0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875; /// ln 10 constexpr float NaturalLog10 = 2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983; constexpr float Infinity = INFINITY; constexpr float NegativeInfinity = INFINITY; } /// This set of functions may be set to use lookup tables or SIMD operations. /// If no options are set, they will default to using standard library implementation. #undef USE_LOOKUP_TABLES /// Pre-computed lookup tables. #undef USE_SSE /// Streaming SIMD Extensions (x86) #undef USE_NEON /// ARM Vector Processing #undef USE_AVX /// Advanced Vector Extensions (x86) namespace J3ML::Math::Functions { float Radians(float deg); /// Converts the given amount of degrees into radians. float Degrees(float rad); /// Converts the given amount of radians into degrees. float Sin(float x); /// Computes the sine of x, in radians. float Cos(float x); /// Computes the cosine of x, in radians. float Tan(float x); /// Computes the tangent of x, in radians. /// Simultaneously computes both sine and cosine of x, in radians. /// This yields a small performance increase over computing them separately. /// @see Sin(), Cos(). void SinCos(float x, float& outSin, float& outCos); float Asin(float x); /// Computes the inverse sine of x, in radians. float Acos(float x); /// Computes the inverse cosine of x, in radians. float Atan(float x); /// Computes the inverse tangent of x, in radians. float Atan2(float y, float x); /// Computes the signed (principal value) inverse tangent of y/x, in radians. float Sinh(float x); /// Computes the hyperbolic sine of x, in radians. float Cosh(float x); /// Computes the hyperbolic cosine of x, in radians. float Tanh(float x); /// Computes the hyperbolic tangent of x, in radians. bool IsPow2(u32 number); /// Returns true if the given number is a power of 2. bool IsPow2(u64 number); /// Returns true if the given number is a power of 2. float PowInt(float base, int exponent); /// Raises the given base to an integral exponent. float Pow(float base, float exponent); /// Raises the given base to a float exponent. float Exp(float exp); /// Returns e (the constant 2.71828...) raised to the given power. float Log(float base, float value); /// Computes a logarithm of the given value in the specified base. float Log2(float value); /// Computes a logarithm in base-2. float Ln(float value); /// Computes a logarithm in the natural base (using e as the base). float Log10(float value); /// Computes a logarithm in base-10; float Ceil(float f); int CeilInt(float f); float Floor(float f); int FloorInt(float f); float Round(float f); int RoundInt(float f); float Round(float f, float decimalPlaces); float Sign(float f); /// Formats larger numbers into shortened 'Truncated' string representations. /// 2241 -> 2.2k, 55421 -> 55.4k, 1000000 -> 1.0M std::string Truncate(float input); /// Clamps the given input value to the range [min, max]. /** @see Clamp01(), Min(), Max(). */ template T Clamp(const T &val, const T &floor, const T &ceil) { assert(floor <= ceil); return val <= ceil ? (val >= floor ? val : floor) : ceil; } /// Clamps the given input value to the range [0, 1]. /** @see Clamp(), Min(), Max(). */ template T Clamp01(const T &val) { return Clamp(val, T(0), T(1)); } bool EqualAbs(float a, float b, float epsilon = 1e-3f); float RecipFast(float x); struct NumberRange { float LowerBound; float UpperBound; }; float NormalizeToRange(float input, float fromLower, float fromUpper, float toLower, float toUpper); float NormalizeToRange(float input, const NumberRange& from, const NumberRange& to); // auto rotation_normalized = NormalizeToRange(inp, {0, 360}, {-1, 1}); float Lerp(float a, float b, float t); /// Linearly interpolates from a to b, under the modulus mod. /// This function takes evaluates a and b in the range [0, mod] and takes the shorter path to reach from a to b. float LerpMod(float a, float b, float mod, float t); /// Computes the lerp factor a and b have to be Lerp()ed to get x. float InverseLerp(float a, float b, float x); /// See http://msdn.microsoft.com/en-us/library/bb509665(v=VS.85).aspx float Step(float y, float x); /// See http://msdn.microsoft.com/en-us/library/bb509658(v=vs.85).aspx float Ramp(float min, float max, float x); float PingPongMod(float x, float mod); float Sqrt(float x); float FastSqrt(float x); /// Returns 1/Sqrt(x). (The reciprocal of the square root of x) float RSqrt(float x); float FastRSqrt(float x); namespace Interp { inline float SmoothStart(float t); } } namespace J3ML::Math { using namespace Math::Constants; using namespace Math::Functions; struct Rotation { public: Rotation(); Rotation(float value); float valueInRadians; float ValueInRadians() const; float ValueInDegrees() const; Rotation operator+(const Rotation& rhs); }; Rotation operator ""_rad(long double rads); Rotation operator ""_radians(long double rads); Rotation operator ""_deg(long double rads); Rotation operator ""_degrees(long double rads); }