1 /** 2 * Copyright: Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved 3 * Authors: $(Gabriel Gheorghe) 4 * License: $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007) 5 * Source: $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/math/functions.d, _functions.d) 6 * Documentation: 7 * Coverage: 8 */ 9 module liberty.math.functions; 10 import std.traits : isIntegral, isSigned, isFloatingPoint; 11 public import std.math; 12 //import std.math : trunc, floor, asin, acos, sin, PI; 13 version (D_InlineAsm_X86) { 14 version = AsmX86; 15 } else version (D_InlineAsm_X86_64) { 16 version = AsmX86; 17 } 18 /// Convert from radians to degrees. 19 T degrees(T)(T x) pure nothrow @safe @nogc if (!isIntegral!T) { 20 return x * (180 / PI); 21 } 22 /// Convert from degrees to radians. 23 T radians(T)(T x) pure nothrow @safe @nogc if (!isIntegral!T) { 24 return x * (PI / 180); 25 } 26 /// Linear interpolation. 27 S lerp(S, T)(S a, S b, T t) pure nothrow @safe @nogc if (is(typeof(t * b + (1 - t) * a) : S)) { 28 return t * b + (1 - t) * a; 29 } 30 /// Clamp x in [min, max]. 31 T clamp(T)(T x, T min, T max) pure nothrow @safe @nogc { 32 if (x < min) { 33 return min; 34 } else if (x > max) { 35 return max; 36 } 37 return x; 38 } 39 /// Integer truncation. 40 long ltrunc(real x) nothrow @safe @nogc { 41 return cast(long)(trunc(x)); 42 } 43 /// Integer flooring. 44 long lfloor(real x) nothrow @safe @nogc { 45 return cast(long)(floor(x)); 46 } 47 /// Returns fractional part of x. 48 T fract(T)(real x) nothrow @safe @nogc { 49 return x - lfloor(x); 50 } 51 /// Safe asin. Input clamped to [-1, 1]. 52 T safeAsin(T)(T x) pure nothrow @safe @nogc { 53 return asin(clamp!T(x, -1, 1)); 54 } 55 /// Safe acos. Input clamped to [-1, 1]. 56 T safeAcos(T)(T x) pure nothrow @safe @nogc { 57 return acos(clamp!T(x, -1, 1)); 58 } 59 60 /// If x < edge => 0.0 is returned, otherwise 1.0 is returned. 61 T step(T)(T edge, T x) pure nothrow @safe @nogc { 62 return (x < edge) ? 0 : 1; 63 } 64 /// 65 T smoothStep(T)(T a, T b, T t) pure nothrow @safe @nogc { 66 if (t <= a) { 67 return 0; 68 } else if (t >= b) { 69 return 1; 70 } 71 T x = (t - a) / (b - a); 72 return x * x * (3 - 2 * x); 73 } 74 /// Returns true of i is a power of 2. 75 bool isPowerOf2(T)(T i) pure nothrow @safe @nogc if (isIntegral!T) 76 in { 77 assert(i >= 0); 78 } do { 79 return (i != 0) && ((i & (i - 1)) == 0); 80 } 81 82 /// Integer log2. 83 int ilog2(T)(T i) nothrow @safe @nogc if (isIntegral!T) 84 in { 85 assert(i > 0); 86 assert(isPowerOf2(i)); 87 } do { 88 int result = 0; 89 while (i > 1) { 90 i = i / 2; 91 result++; 92 } 93 return result; 94 } 95 /// Computes next power of 2. 96 int nextPowerOf2(int i) pure nothrow @safe @nogc 97 out(result) { 98 assert(isPowerOf2(result)); 99 } do { 100 int v = i - 1; 101 v |= v >> 1; 102 v |= v >> 2; 103 v |= v >> 4; 104 v |= v >> 8; 105 v |= v >> 16; 106 v++; 107 return v; 108 } 109 /// Computes next power of 2. 110 long nextPowerOf2(long i) pure nothrow @safe @nogc 111 out(result) { 112 assert(isPowerOf2(result)); 113 } do { 114 long v = i - 1; 115 v |= v >> 1; 116 v |= v >> 2; 117 v |= v >> 4; 118 v |= v >> 8; 119 v |= v >> 16; 120 v |= v >> 32; 121 v++; 122 return v; 123 } 124 /// Computes sin(x)/x accurately. 125 T sinOverX(T)(T x) pure nothrow @safe @nogc { 126 if (1 + x * x == 1) { 127 return 1; 128 } 129 return sin(x) / x; 130 } 131 132 /// Signed integer modulo a/b where the remainder is guaranteed to be in [0..b], even if a is negative. 133 /// Only supports positive dividers. 134 T moduloWrap(T)(T a, T b) pure nothrow @safe @nogc if (isSigned!T) 135 in { 136 assert(b > 0); 137 } do { 138 T x; 139 if (a >= 0) { 140 a = a % b; 141 } else { 142 auto rem = a % b; 143 x = (rem == 0) ? 0 : (-rem + b); 144 } 145 assert(x >= 0 && x < b); 146 return x; 147 } 148 /// 149 pure nothrow @safe @nogc unittest { 150 assert(nextPowerOf2(3) == 4); 151 assert(nextPowerOf2(21) == 32); 152 assert(nextPowerOf2(1000) == 1024); 153 } 154 /// SSE approximation of reciprocal square root. 155 T inverseSqrt(T)(T x) pure nothrow @safe @nogc if (isFloatingPoint!T) { 156 version(AsmX86) { 157 static if (is(T == float)) { 158 float result; 159 asm pure nothrow @safe @nogc { 160 movss XMM0, x; 161 rsqrtss XMM0, XMM0; 162 movss result, XMM0; 163 } 164 return result; 165 } else { 166 return 1 / sqrt(x); 167 } 168 } else { 169 return 1 / sqrt(x); 170 } 171 } 172 /// 173 pure nothrow @safe @nogc unittest { 174 assert (abs(inverseSqrt!float(1) - 1) < 1e-3 ); 175 assert (abs(inverseSqrt!double(1) - 1) < 1e-3 ); 176 }