// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Types/BaseTypes.h" #include namespace Math { /// /// Computes the sine and cosine of a scalar double. /// /// The input angle (in radians). /// The output sine value. /// The output cosine value. FLAXENGINE_API void SinCos(double angle, double& sine, double& cosine); static FORCE_INLINE double Trunc(double value) { return trunc(value); } static FORCE_INLINE double Round(double value) { return round(value); } static FORCE_INLINE double Floor(double value) { return floor(value); } static FORCE_INLINE double Ceil(double value) { return ceil(value); } static FORCE_INLINE double Sin(double value) { return sin(value); } static FORCE_INLINE double Asin(double value) { return asin(value < -1. ? -1. : value < 1. ? value : 1.); } static FORCE_INLINE double Sinh(double value) { return sinh(value); } static FORCE_INLINE double Cos(double value) { return cos(value); } static FORCE_INLINE double Acos(double value) { return acos(value < -1. ? -1. : value < 1. ? value : 1.); } static FORCE_INLINE double Tan(double value) { return tan(value); } static FORCE_INLINE double Atan(double value) { return atan(value); } static FORCE_INLINE double Atan2(double y, double x) { return atan2(y, x); } static FORCE_INLINE double InvSqrt(double value) { return 1.0 / sqrt(value); } static FORCE_INLINE double Log(const double value) { return log(value); } static FORCE_INLINE double Log2(const double value) { return log2(value); } static FORCE_INLINE double Log10(const double value) { return log10(value); } static FORCE_INLINE double Pow(const double base, const double exponent) { return pow(base, exponent); } static FORCE_INLINE double Sqrt(const double value) { return sqrt(value); } static FORCE_INLINE double Exp(const double value) { return exp(value); } static FORCE_INLINE double Exp2(const double value) { return exp2(value); } static FORCE_INLINE double Abs(const double value) { return fabs(value); } static FORCE_INLINE double Mod(const double a, const double b) { return fmod(a, b); } static FORCE_INLINE double ModF(double a, double* b) { return modf(a, b); } static FORCE_INLINE double Frac(double value) { return value - Floor(value); } /// /// Returns signed fractional part of a double. /// /// Double point value to convert. /// A double between [0 ; 1) for nonnegative input. A double between [-1; 0) for negative input. static FORCE_INLINE double Fractional(double value) { return value - Trunc(value); } static int64 TruncToInt(double value) { return (int64)value; } static int64 FloorToInt(double value) { return TruncToInt(floor(value)); } static FORCE_INLINE int64 RoundToInt(double value) { return FloorToInt(value + 0.5); } static FORCE_INLINE int64 CeilToInt(double value) { return TruncToInt(ceil(value)); } // Performs smooth (cubic Hermite) interpolation between 0 and 1 // @param amount Value between 0 and 1 indicating interpolation amount static double SmoothStep(double amount) { return amount <= 0. ? 0. : amount >= 1. ? 1. : amount * amount * (3. - 2. * amount); } // Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints // @param amount Value between 0 and 1 indicating interpolation amount static double SmootherStep(double amount) { return amount <= 0. ? 0. : amount >= 1. ? 1. : amount * amount * amount * (amount * (amount * 6. - 15.) + 10.); } // Determines whether the specified value is close to zero (0.0) // @param a The floating value // @returns True if the specified value is close to zero (0.0). otherwise false inline bool IsZero(double a) { return Abs(a) < ZeroTolerance; } // Determines whether the specified value is close to one (1.0f) // @param a The floating value // @returns True if the specified value is close to one (1.0f). otherwise false inline bool IsOne(double a) { return IsZero(a - 1.); } // Returns a value indicating the sign of a number // @returns A number that indicates the sign of value inline double Sign(double v) { return v > 0. ? 1. : v < 0. ? -1. : 0.; } /// /// Compares the sign of two double values. /// /// The first value. /// The second value. /// True if given values have the same sign (both positive or negative); otherwise false. inline bool SameSign(const double a, const double b) { return a * b >= 0.; } /// /// Compares the sign of two double values. /// /// The first value. /// The second value. /// True if given values don't have the same sign (first is positive and second is negative or vice versa); otherwise false. inline bool NotSameSign(const double a, const double b) { return a * b < 0.; } /// /// Checks if a and b are not even almost equal, taking into account the magnitude of double numbers /// /// The left value to compare /// The right value to compare /// False if a almost equal to b, otherwise true static bool NotNearEqual(double a, double b) { return Abs(a - b) >= ZeroToleranceDouble; } /// /// Checks if a and b are almost equals, taking into account the magnitude of double precision floating point numbers /// /// The left value to compare /// The right value to compare /// True if a almost equal to b, otherwise false static bool NearEqual(double a, double b) { return Abs(a - b) < ZeroToleranceDouble; } /// /// Checks if a and b are almost equals within the given epsilon value. /// /// The left value to compare. /// The right value to compare. /// The comparision epsilon value. Should be 1e-4 or less. /// True if a almost equal to b, otherwise false static bool NearEqual(double a, double b, double eps) { return Abs(a - b) < eps; } /// /// Remaps the specified value from the specified range to another. /// /// The value to remap. /// The source range minimum. /// The source range maximum. /// The destination range minimum. /// The destination range maximum. /// The remapped value. static double Remap(double value, double fromMin, double fromMax, double toMin, double toMax) { return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin; } static double ClampAxis(double angle) { angle = Mod(angle, 360.); if (angle < 0.) angle += 360.; return angle; } static double NormalizeAxis(double angle) { angle = ClampAxis(angle); if (angle > 180.) angle -= 360.; return angle; } // Find the smallest angle between two headings (in radians). static double FindDeltaAngle(double a1, double a2) { double delta = a2 - a1; if (delta > PI) delta = delta - TWO_PI; else if (delta < -PI) delta = delta + TWO_PI; return delta; } /// /// Returns value based on comparand. The main purpose of this function is to avoid branching based on floating point comparison which can be avoided via compiler intrinsics. /// /// /// Please note that this doesn't define what happens in the case of NaNs as there might be platform specific differences. /// /// Comparand the results are based on. /// The result value if comparand >= 0. /// The result value if comparand < 0. /// the valueGEZero if comparand >= 0, valueLTZero otherwise static double DoubleSelect(double comparand, double valueGEZero, double valueLTZero) { return comparand >= 0. ? valueGEZero : valueLTZero; } /// /// Returns a smooth Hermite interpolation between 0 and 1 for the value X (where X ranges between A and B). Clamped to 0 for X <= A and 1 for X >= B. /// /// The minimum value of x. /// The maximum value of x. /// The x. /// The smoothed value between 0 and 1. static double SmoothStep(double a, double b, double x) { if (x < a) return 0.; if (x >= b) return 1.; const double fraction = (x - a) / (b - a); return fraction * fraction * (3. - 2. * fraction); } }