1 // Written in the D programming language. 2 3 /** 4 * Builtin mathematical intrinsics 5 * 6 * Source: $(DRUNTIMESRC core/_math.d) 7 * Macros: 8 * TABLE_SV = <table border="1" cellpadding="4" cellspacing="0"> 9 * <caption>Special Values</caption> 10 * $0</table> 11 * 12 * NAN = $(RED NAN) 13 * SUP = <span style="vertical-align:super;font-size:smaller">$0</span> 14 * POWER = $1<sup>$2</sup> 15 * PLUSMN = ± 16 * INFIN = ∞ 17 * PLUSMNINF = ±∞ 18 * LT = < 19 * GT = > 20 * 21 * Copyright: Copyright Digital Mars 2000 - 2011. 22 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 23 * Authors: $(HTTP digitalmars.com, Walter Bright), 24 * Don Clugston 25 */ 26 module core.math; 27 28 public: 29 @nogc: 30 nothrow: 31 @safe: 32 33 /***************************************** 34 * Returns x rounded to a long value using the FE_TONEAREST rounding mode. 35 * If the integer value of x is 36 * greater than long.max, the result is 37 * indeterminate. 38 */ 39 deprecated("rndtonl is to be removed by 2.100. Please use round instead") 40 extern (C) real rndtonl(real x); 41 42 pure: 43 /*********************************** 44 * Returns cosine of x. x is in radians. 45 * 46 * $(TABLE_SV 47 * $(TR $(TH x) $(TH cos(x)) $(TH invalid?)) 48 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) ) 49 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes) ) 50 * ) 51 * Bugs: 52 * Results are undefined if |x| >= $(POWER 2,64). 53 */ 54 55 float cos(float x); /* intrinsic */ 56 double cos(double x); /* intrinsic */ /// ditto 57 real cos(real x); /* intrinsic */ /// ditto 58 59 /*********************************** 60 * Returns sine of x. x is in radians. 61 * 62 * $(TABLE_SV 63 * $(TR $(TH x) $(TH sin(x)) $(TH invalid?)) 64 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) 65 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) 66 * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD yes)) 67 * ) 68 * Bugs: 69 * Results are undefined if |x| >= $(POWER 2,64). 70 */ 71 72 float sin(float x); /* intrinsic */ 73 double sin(double x); /* intrinsic */ /// ditto 74 real sin(real x); /* intrinsic */ /// ditto 75 76 /***************************************** 77 * Returns x rounded to a long value using the current rounding mode. 78 * If the integer value of x is 79 * greater than long.max, the result is 80 * indeterminate. 81 */ 82 83 long rndtol(float x); /* intrinsic */ 84 long rndtol(double x); /* intrinsic */ /// ditto 85 long rndtol(real x); /* intrinsic */ /// ditto 86 87 /*************************************** 88 * Compute square root of x. 89 * 90 * $(TABLE_SV 91 * $(TR $(TH x) $(TH sqrt(x)) $(TH invalid?)) 92 * $(TR $(TD -0.0) $(TD -0.0) $(TD no)) 93 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD yes)) 94 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no)) 95 * ) 96 */ 97 98 float sqrt(float x); /* intrinsic */ 99 double sqrt(double x); /* intrinsic */ /// ditto 100 real sqrt(real x); /* intrinsic */ /// ditto 101 102 /******************************************* 103 * Compute n * 2$(SUPERSCRIPT exp) 104 * References: frexp 105 */ 106 107 float ldexp(float n, int exp); /* intrinsic */ 108 double ldexp(double n, int exp); /* intrinsic */ /// ditto 109 real ldexp(real n, int exp); /* intrinsic */ /// ditto 110 111 unittest { 112 static if (real.mant_dig == 113) 113 { 114 assert(ldexp(1.0L, -16384) == 0x1p-16384L); 115 assert(ldexp(1.0L, -16382) == 0x1p-16382L); 116 } 117 else static if (real.mant_dig == 106) 118 { 119 assert(ldexp(1.0L, 1023) == 0x1p1023L); 120 assert(ldexp(1.0L, -1022) == 0x1p-1022L); 121 assert(ldexp(1.0L, -1021) == 0x1p-1021L); 122 } 123 else static if (real.mant_dig == 64) 124 { 125 assert(ldexp(1.0L, -16384) == 0x1p-16384L); 126 assert(ldexp(1.0L, -16382) == 0x1p-16382L); 127 } 128 else static if (real.mant_dig == 53) 129 { 130 assert(ldexp(1.0L, 1023) == 0x1p1023L); 131 assert(ldexp(1.0L, -1022) == 0x1p-1022L); 132 assert(ldexp(1.0L, -1021) == 0x1p-1021L); 133 } 134 else 135 assert(false, "Only 128bit, 80bit and 64bit reals expected here"); 136 } 137 138 /******************************* 139 * Compute the absolute value. 140 * $(TABLE_SV 141 * $(TR $(TH x) $(TH fabs(x))) 142 * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) ) 143 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) 144 * ) 145 * It is implemented as a compiler intrinsic. 146 * Params: 147 * x = floating point value 148 * Returns: |x| 149 * References: equivalent to `std.math.fabs` 150 */ 151 @safe pure nothrow @nogc 152 { 153 float fabs(float x); 154 double fabs(double x); /// ditto 155 real fabs(real x); /// ditto 156 } 157 158 /********************************** 159 * Rounds x to the nearest integer value, using the current rounding 160 * mode. 161 * If the return value is not equal to x, the FE_INEXACT 162 * exception is raised. 163 * $(B nearbyint) performs 164 * the same operation, but does not set the FE_INEXACT exception. 165 */ 166 float rint(float x); /* intrinsic */ 167 double rint(double x); /* intrinsic */ /// ditto 168 real rint(real x); /* intrinsic */ /// ditto 169 170 /*********************************** 171 * Building block functions, they 172 * translate to a single x87 instruction. 173 */ 174 // y * log2(x) 175 float yl2x(float x, float y); /* intrinsic */ 176 double yl2x(double x, double y); /* intrinsic */ /// ditto 177 real yl2x(real x, real y); /* intrinsic */ /// ditto 178 // y * log2(x +1) 179 float yl2xp1(float x, float y); /* intrinsic */ 180 double yl2xp1(double x, double y); /* intrinsic */ /// ditto 181 real yl2xp1(real x, real y); /* intrinsic */ /// ditto 182 183 unittest 184 { 185 version (INLINE_YL2X) 186 { 187 assert(yl2x(1024.0L, 1) == 10); 188 assert(yl2xp1(1023.0L, 1) == 10); 189 } 190 } 191 192 /************************************* 193 * Round argument to a specific precision. 194 * 195 * D language types specify only a minimum precision, not a maximum. The 196 * `toPrec()` function forces rounding of the argument `f` to the precision 197 * of the specified floating point type `T`. 198 * The rounding mode used is inevitably target-dependent, but will be done in 199 * a way to maximize accuracy. In most cases, the default is round-to-nearest. 200 * 201 * Params: 202 * T = precision type to round to 203 * f = value to convert 204 * Returns: 205 * f in precision of type `T` 206 */ 207 T toPrec(T:float)(float f) { pragma(inline, false); return f; } 208 /// ditto 209 T toPrec(T:float)(double f) { pragma(inline, false); return cast(T) f; } 210 /// ditto 211 T toPrec(T:float)(real f) { pragma(inline, false); return cast(T) f; } 212 /// ditto 213 T toPrec(T:double)(float f) { pragma(inline, false); return f; } 214 /// ditto 215 T toPrec(T:double)(double f) { pragma(inline, false); return f; } 216 /// ditto 217 T toPrec(T:double)(real f) { pragma(inline, false); return cast(T) f; } 218 /// ditto 219 T toPrec(T:real)(float f) { pragma(inline, false); return f; } 220 /// ditto 221 T toPrec(T:real)(double f) { pragma(inline, false); return f; } 222 /// ditto 223 T toPrec(T:real)(real f) { pragma(inline, false); return f; } 224 225 @safe unittest 226 { 227 // Test all instantiations work with all combinations of float. 228 float f = 1.1f; 229 double d = 1.1; 230 real r = 1.1L; 231 f = toPrec!float(f + f); 232 f = toPrec!float(d + d); 233 f = toPrec!float(r + r); 234 d = toPrec!double(f + f); 235 d = toPrec!double(d + d); 236 d = toPrec!double(r + r); 237 r = toPrec!real(f + f); 238 r = toPrec!real(d + d); 239 r = toPrec!real(r + r); 240 241 // Comparison tests. 242 bool approxEqual(T)(T lhs, T rhs) 243 { 244 return fabs((lhs - rhs) / rhs) <= 1e-2 || fabs(lhs - rhs) <= 1e-5; 245 } 246 247 enum real PIR = 0xc.90fdaa22168c235p-2; 248 enum double PID = 0x1.921fb54442d18p+1; 249 enum float PIF = 0x1.921fb6p+1; 250 static assert(approxEqual(toPrec!float(PIR), PIF)); 251 static assert(approxEqual(toPrec!double(PIR), PID)); 252 static assert(approxEqual(toPrec!real(PIR), PIR)); 253 static assert(approxEqual(toPrec!float(PID), PIF)); 254 static assert(approxEqual(toPrec!double(PID), PID)); 255 static assert(approxEqual(toPrec!real(PID), PID)); 256 static assert(approxEqual(toPrec!float(PIF), PIF)); 257 static assert(approxEqual(toPrec!double(PIF), PIF)); 258 static assert(approxEqual(toPrec!real(PIF), PIF)); 259 260 assert(approxEqual(toPrec!float(PIR), PIF)); 261 assert(approxEqual(toPrec!double(PIR), PID)); 262 assert(approxEqual(toPrec!real(PIR), PIR)); 263 assert(approxEqual(toPrec!float(PID), PIF)); 264 assert(approxEqual(toPrec!double(PID), PID)); 265 assert(approxEqual(toPrec!real(PID), PID)); 266 assert(approxEqual(toPrec!float(PIF), PIF)); 267 assert(approxEqual(toPrec!double(PIF), PIF)); 268 assert(approxEqual(toPrec!real(PIF), PIF)); 269 }