1 /** 2 * Type generic standard math functions and constants. 3 */ 4 module bettercmath.cmath; 5 6 import cmath = core.stdc.math; 7 import dmath = std.math; 8 import std.meta : AliasSeq; 9 10 import bettercmath.misc : FloatType; 11 12 private enum functions = AliasSeq!( 13 "acos", 14 "asin", 15 "atan", 16 "atan2", 17 "cos", 18 "sin", 19 "tan", 20 "acosh", 21 "asinh", 22 "atanh", 23 "cosh", 24 "sinh", 25 "tanh", 26 "exp", 27 "exp2", 28 "expm1", 29 "frexp", 30 "ilogb", 31 "ldexp", 32 "log", 33 "log10", 34 "log1p", 35 "log2", 36 "logb", 37 "modf", 38 "scalbn", 39 "scalbln", 40 "cbrt", 41 "fabs", 42 "hypot", 43 "pow", 44 "sqrt", 45 "erf", 46 "erfc", 47 "lgamma", 48 "tgamma", 49 "ceil", 50 "floor", 51 "nearbyint", 52 "rint", 53 "lrint", 54 "llrint", 55 "round", 56 "lround", 57 "llround", 58 "trunc", 59 "fmod", 60 "remainder", 61 "remquo", 62 "copysign", 63 "nan", 64 "nextafter", 65 "nexttoward", 66 "fdim", 67 "fmax", 68 "fmin", 69 "fma", 70 ); 71 72 static foreach (f; functions) 73 { 74 mixin(q{alias } ~ f ~ q{ = MathFunc!} ~ "\"" ~ f ~ "\".opCall;"); 75 } 76 77 private enum constants = AliasSeq!( 78 "E", 79 "PI", 80 "PI_2", 81 "PI_4", 82 "M_1_PI", 83 "M_2_PI", 84 "M_2_SQRTPI", 85 "LN10", 86 "LN2", 87 "LOG2", 88 "LOG2E", 89 "LOG2T", 90 "LOG10E", 91 "SQRT2", 92 "SQRT1_2", 93 ); 94 95 static foreach (c; constants) 96 { 97 mixin(q{alias } ~ c ~ q{ = MathConst!} ~ "\"" ~ c ~ "\";"); 98 } 99 100 // Private helpers for templated math function calls 101 private string cfuncname(T : double, string f)() 102 { 103 return f; 104 } 105 private string cfuncname(T : real, string f)() 106 { 107 return f ~ "l"; 108 } 109 private string cfuncname(T : float, string f)() 110 { 111 return f ~ "f"; 112 } 113 private string cfuncname(T : long, string f)() 114 { 115 return f ~ "f"; 116 } 117 118 /** 119 * Template wrapper for standard library math functions. 120 * 121 * On CTFE, calls the D runtime math (std.math) functions. 122 * On runtime, calls the right variant of the C runtime math (core.stdc.math) functions. 123 */ 124 template MathFunc(string f) 125 { 126 template opCall(T, Args...) 127 { 128 import std.traits : ReturnType; 129 private alias dfunc = __traits(getMember, dmath, f); 130 private alias cfunc = __traits(getMember, cmath, cfuncname!(T, f)()); 131 132 nothrow @nogc ReturnType!cfunc opCall(T arg1, Args args) 133 { 134 if (__ctfe) 135 { 136 // Use D functions on CTFE 137 return dfunc(cast(FloatType!T) arg1, args); 138 } 139 else 140 { 141 // Use the appropriate C function on runtime 142 return cfunc(arg1, args); 143 } 144 } 145 } 146 } 147 148 /// Template wrapper for typed versions of the standard library math constants. 149 private template MathConst(string c) 150 { 151 private alias dconst = __traits(getMember, dmath, c); 152 enum MathConst(T = real) = cast(FloatType!T) dconst; 153 }