1 // Written in the D programming language. 2 3 /** 4 * Contains the elementary mathematical functions (powers, roots, 5 * and trigonometric functions), and low-level floating-point operations. 6 * Mathematical special functions are available in `std.mathspecial`. 7 * 8 $(SCRIPT inhibitQuickIndex = 1;) 9 10 $(DIVC quickindex, 11 $(BOOKTABLE , 12 $(TR $(TH Category) $(TH Members) ) 13 $(TR $(TDNW Constants) $(TD 14 $(MYREF E) $(MYREF PI) $(MYREF PI_2) $(MYREF PI_4) $(MYREF M_1_PI) 15 $(MYREF M_2_PI) $(MYREF M_2_SQRTPI) $(MYREF LN10) $(MYREF LN2) 16 $(MYREF LOG2) $(MYREF LOG2E) $(MYREF LOG2T) $(MYREF LOG10E) 17 $(MYREF SQRT2) $(MYREF SQRT1_2) 18 )) 19 $(TR $(TDNW Classics) $(TD 20 $(MYREF abs) $(MYREF fabs) $(MYREF sqrt) $(MYREF cbrt) $(MYREF hypot) 21 $(MYREF poly) $(MYREF nextPow2) $(MYREF truncPow2) 22 )) 23 $(TR $(TDNW Trigonometry) $(TD 24 $(MYREF sin) $(MYREF cos) $(MYREF tan) $(MYREF asin) $(MYREF acos) 25 $(MYREF atan) $(MYREF atan2) $(MYREF sinh) $(MYREF cosh) $(MYREF tanh) 26 $(MYREF asinh) $(MYREF acosh) $(MYREF atanh) 27 )) 28 $(TR $(TDNW Rounding) $(TD 29 $(MYREF ceil) $(MYREF floor) $(MYREF round) $(MYREF lround) 30 $(MYREF trunc) $(MYREF rint) $(MYREF lrint) $(MYREF nearbyint) 31 $(MYREF rndtol) $(MYREF quantize) 32 )) 33 $(TR $(TDNW Exponentiation & Logarithms) $(TD 34 $(MYREF pow) $(MYREF exp) $(MYREF exp2) $(MYREF expm1) $(MYREF ldexp) 35 $(MYREF frexp) $(MYREF log) $(MYREF log2) $(MYREF log10) $(MYREF logb) 36 $(MYREF ilogb) $(MYREF log1p) $(MYREF scalbn) 37 )) 38 $(TR $(TDNW Modulus) $(TD 39 $(MYREF fmod) $(MYREF modf) $(MYREF remainder) 40 )) 41 $(TR $(TDNW Floating-point operations) $(TD 42 $(MYREF approxEqual) $(MYREF feqrel) $(MYREF fdim) $(MYREF fmax) 43 $(MYREF fmin) $(MYREF fma) $(MYREF isClose) $(MYREF nextDown) $(MYREF nextUp) 44 $(MYREF nextafter) $(MYREF NaN) $(MYREF getNaNPayload) 45 $(MYREF cmp) 46 )) 47 $(TR $(TDNW Introspection) $(TD 48 $(MYREF isFinite) $(MYREF isIdentical) $(MYREF isInfinity) $(MYREF isNaN) 49 $(MYREF isNormal) $(MYREF isSubnormal) $(MYREF signbit) $(MYREF sgn) 50 $(MYREF copysign) $(MYREF isPowerOf2) 51 )) 52 $(TR $(TDNW Hardware Control) $(TD 53 $(MYREF IeeeFlags) $(MYREF FloatingPointControl) 54 )) 55 ) 56 ) 57 58 * The functionality closely follows the IEEE754-2008 standard for 59 * floating-point arithmetic, including the use of camelCase names rather 60 * than C99-style lower case names. All of these functions behave correctly 61 * when presented with an infinity or NaN. 62 * 63 * The following IEEE 'real' formats are currently supported: 64 * $(UL 65 * $(LI 64 bit Big-endian 'double' (eg PowerPC)) 66 * $(LI 128 bit Big-endian 'quadruple' (eg SPARC)) 67 * $(LI 64 bit Little-endian 'double' (eg x86-SSE2)) 68 * $(LI 80 bit Little-endian, with implied bit 'real80' (eg x87, Itanium)) 69 * $(LI 128 bit Little-endian 'quadruple' (not implemented on any known processor!)) 70 * $(LI Non-IEEE 128 bit Big-endian 'doubledouble' (eg PowerPC) has partial support) 71 * ) 72 * Unlike C, there is no global 'errno' variable. Consequently, almost all of 73 * these functions are pure nothrow. 74 * 75 * Macros: 76 * TABLE_SV = <table border="1" cellpadding="4" cellspacing="0"> 77 * <caption>Special Values</caption> 78 * $0</table> 79 * SVH = $(TR $(TH $1) $(TH $2)) 80 * SV = $(TR $(TD $1) $(TD $2)) 81 * TH3 = $(TR $(TH $1) $(TH $2) $(TH $3)) 82 * TD3 = $(TR $(TD $1) $(TD $2) $(TD $3)) 83 * TABLE_DOMRG = <table border="1" cellpadding="4" cellspacing="0"> 84 * $(SVH Domain X, Range Y) 85 $(SV $1, $2) 86 * </table> 87 * DOMAIN=$1 88 * RANGE=$1 89 90 * NAN = $(RED NAN) 91 * SUP = <span style="vertical-align:super;font-size:smaller">$0</span> 92 * GAMMA = Γ 93 * THETA = θ 94 * INTEGRAL = ∫ 95 * INTEGRATE = $(BIG ∫<sub>$(SMALL $1)</sub><sup>$2</sup>) 96 * POWER = $1<sup>$2</sup> 97 * SUB = $1<sub>$2</sub> 98 * BIGSUM = $(BIG Σ <sup>$2</sup><sub>$(SMALL $1)</sub>) 99 * CHOOSE = $(BIG () <sup>$(SMALL $1)</sup><sub>$(SMALL $2)</sub> $(BIG )) 100 * PLUSMN = ± 101 * INFIN = ∞ 102 * PLUSMNINF = ±∞ 103 * PI = π 104 * LT = < 105 * GT = > 106 * SQRT = √ 107 * HALF = ½ 108 * 109 * Copyright: Copyright The D Language Foundation 2000 - 2011. 110 * D implementations of tan, atan, atan2, exp, expm1, exp2, log, log10, log1p, 111 * log2, floor, ceil and lrint functions are based on the CEPHES math library, 112 * which is Copyright (C) 2001 Stephen L. Moshier $(LT)steve@moshier.net$(GT) 113 * and are incorporated herein by permission of the author. The author 114 * reserves the right to distribute this material elsewhere under different 115 * copying permissions. These modifications are distributed here under 116 * the following terms: 117 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 118 * Authors: $(HTTP digitalmars.com, Walter Bright), Don Clugston, 119 * Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger 120 * Source: $(PHOBOSSRC std/math.d) 121 */ 122 module std.math; 123 124 version (Win64) 125 { 126 version (D_InlineAsm_X86_64) 127 version = Win64_DMD_InlineAsm; 128 } 129 130 static import core.math; 131 static import core.stdc.math; 132 static import core.stdc.fenv; 133 import std.traits : CommonType, isFloatingPoint, isIntegral, isNumeric, 134 isSigned, isUnsigned, Largest, Unqual; 135 136 // @@@DEPRECATED_2.102@@@ 137 // Note: Exposed accidentally, should be deprecated / removed 138 deprecated("std.meta.AliasSeq was unintentionally available from std.math " 139 ~ "and will be removed after 2.102. Please import std.meta instead") 140 public import std.meta : AliasSeq; 141 142 version (DigitalMars) 143 { 144 version = INLINE_YL2X; // x87 has opcodes for these 145 } 146 147 version (X86) version = X86_Any; 148 version (X86_64) version = X86_Any; 149 version (PPC) version = PPC_Any; 150 version (PPC64) version = PPC_Any; 151 version (MIPS32) version = MIPS_Any; 152 version (MIPS64) version = MIPS_Any; 153 version (AArch64) version = ARM_Any; 154 version (ARM) version = ARM_Any; 155 version (S390) version = IBMZ_Any; 156 version (SPARC) version = SPARC_Any; 157 version (SPARC64) version = SPARC_Any; 158 version (SystemZ) version = IBMZ_Any; 159 version (RISCV32) version = RISCV_Any; 160 version (RISCV64) version = RISCV_Any; 161 162 version (D_InlineAsm_X86) 163 { 164 version = InlineAsm_X86_Any; 165 } 166 else version (D_InlineAsm_X86_64) 167 { 168 version = InlineAsm_X86_Any; 169 } 170 171 version (CRuntime_Microsoft) 172 { 173 version (InlineAsm_X86_Any) 174 version = MSVC_InlineAsm; 175 } 176 177 version (X86_64) version = StaticallyHaveSSE; 178 version (X86) version (OSX) version = StaticallyHaveSSE; 179 180 version (StaticallyHaveSSE) 181 { 182 private enum bool haveSSE = true; 183 } 184 else version (X86) 185 { 186 static import core.cpuid; 187 private alias haveSSE = core.cpuid.sse; 188 } 189 190 version (D_SoftFloat) 191 { 192 // Some soft float implementations may support IEEE floating flags. 193 // The implementation here supports hardware flags only and is so currently 194 // only available for supported targets. 195 } 196 else version (X86_Any) version = IeeeFlagsSupport; 197 else version (PPC_Any) version = IeeeFlagsSupport; 198 else version (RISCV_Any) version = IeeeFlagsSupport; 199 else version (MIPS_Any) version = IeeeFlagsSupport; 200 else version (ARM_Any) version = IeeeFlagsSupport; 201 202 // Struct FloatingPointControl is only available if hardware FP units are available. 203 version (D_HardFloat) 204 { 205 // FloatingPointControl.clearExceptions() depends on version IeeeFlagsSupport 206 version (IeeeFlagsSupport) version = FloatingPointControlSupport; 207 } 208 209 version (StdUnittest) private 210 { 211 static if (real.sizeof > double.sizeof) 212 enum uint useDigits = 16; 213 else 214 enum uint useDigits = 15; 215 216 /****************************************** 217 * Compare floating point numbers to n decimal digits of precision. 218 * Returns: 219 * 1 match 220 * 0 nomatch 221 */ 222 223 private bool equalsDigit(real x, real y, uint ndigits) @safe nothrow @nogc 224 { 225 import core.stdc.stdio : sprintf; 226 227 if (signbit(x) != signbit(y)) 228 return 0; 229 230 if (isInfinity(x) && isInfinity(y)) 231 return 1; 232 if (isInfinity(x) || isInfinity(y)) 233 return 0; 234 235 if (isNaN(x) && isNaN(y)) 236 return 1; 237 if (isNaN(x) || isNaN(y)) 238 return 0; 239 240 char[30] bufx; 241 char[30] bufy; 242 assert(ndigits < bufx.length); 243 244 int ix; 245 int iy; 246 version (CRuntime_Microsoft) 247 alias real_t = double; 248 else 249 alias real_t = real; 250 251 () @trusted { 252 ix = sprintf(bufx.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) x); 253 iy = sprintf(bufy.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) y); 254 } (); 255 256 assert(ix < bufx.length && ix > 0); 257 assert(ix < bufy.length && ix > 0); 258 259 return bufx[0 .. ix] == bufy[0 .. iy]; 260 } 261 } 262 263 264 // Values obtained from Wolfram Alpha. 116 bits ought to be enough for anybody. 265 // Wolfram Alpha LLC. 2011. Wolfram|Alpha. http://www.wolframalpha.com/input/?i=e+in+base+16 (access July 6, 2011). 266 enum real E = 0x1.5bf0a8b1457695355fb8ac404e7a8p+1L; /** e = 2.718281... */ 267 enum real LOG2T = 0x1.a934f0979a3715fc9257edfe9b5fbp+1L; /** $(SUB log, 2)10 = 3.321928... */ 268 enum real LOG2E = 0x1.71547652b82fe1777d0ffda0d23a8p+0L; /** $(SUB log, 2)e = 1.442695... */ 269 enum real LOG2 = 0x1.34413509f79fef311f12b35816f92p-2L; /** $(SUB log, 10)2 = 0.301029... */ 270 enum real LOG10E = 0x1.bcb7b1526e50e32a6ab7555f5a67cp-2L; /** $(SUB log, 10)e = 0.434294... */ 271 enum real LN2 = 0x1.62e42fefa39ef35793c7673007e5fp-1L; /** ln 2 = 0.693147... */ 272 enum real LN10 = 0x1.26bb1bbb5551582dd4adac5705a61p+1L; /** ln 10 = 2.302585... */ 273 enum real PI = 0x1.921fb54442d18469898cc51701b84p+1L; /** π = 3.141592... */ 274 enum real PI_2 = PI/2; /** $(PI) / 2 = 1.570796... */ 275 enum real PI_4 = PI/4; /** $(PI) / 4 = 0.785398... */ 276 enum real M_1_PI = 0x1.45f306dc9c882a53f84eafa3ea69cp-2L; /** 1 / $(PI) = 0.318309... */ 277 enum real M_2_PI = 2*M_1_PI; /** 2 / $(PI) = 0.636619... */ 278 enum real M_2_SQRTPI = 0x1.20dd750429b6d11ae3a914fed7fd8p+0L; /** 2 / $(SQRT)$(PI) = 1.128379... */ 279 enum real SQRT2 = 0x1.6a09e667f3bcc908b2fb1366ea958p+0L; /** $(SQRT)2 = 1.414213... */ 280 enum real SQRT1_2 = SQRT2/2; /** $(SQRT)$(HALF) = 0.707106... */ 281 // Note: Make sure the magic numbers in compiler backend for x87 match these. 282 283 /*********************************** 284 * Calculates the absolute value of a number. 285 * 286 * Params: 287 * Num = (template parameter) type of number 288 * x = real number value 289 * 290 * Returns: 291 * The absolute value of the number. If floating-point or integral, 292 * the return type will be the same as the input. 293 * 294 * Limitations: 295 * Does not work correctly for signed intergal types and value `Num`.min. 296 */ 297 auto abs(Num)(Num x) @nogc pure nothrow 298 if ((is(immutable Num == immutable short) || is(immutable Num == immutable byte)) || 299 (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)))) 300 { 301 static if (isFloatingPoint!(Num)) 302 return fabs(x); 303 else 304 { 305 static if (is(immutable Num == immutable short) || is(immutable Num == immutable byte)) 306 return x >= 0 ? x : cast(Num) -int(x); 307 else 308 return x >= 0 ? x : -x; 309 } 310 } 311 312 /// ditto 313 @safe pure nothrow @nogc unittest 314 { 315 assert(isIdentical(abs(-0.0L), 0.0L)); 316 assert(isNaN(abs(real.nan))); 317 assert(abs(-real.infinity) == real.infinity); 318 assert(abs(-56) == 56); 319 assert(abs(2321312L) == 2321312L); 320 } 321 322 @safe pure nothrow @nogc unittest 323 { 324 short s = -8; 325 byte b = -8; 326 assert(abs(s) == 8); 327 assert(abs(b) == 8); 328 immutable(byte) c = -8; 329 assert(abs(c) == 8); 330 } 331 332 @safe pure nothrow @nogc unittest 333 { 334 import std.meta : AliasSeq; 335 static foreach (T; AliasSeq!(float, double, real)) 336 {{ 337 T f = 3; 338 assert(abs(f) == f); 339 assert(abs(-f) == f); 340 }} 341 } 342 343 // see https://issues.dlang.org/show_bug.cgi?id=20205 344 // to avoid falling into the trap again 345 @safe pure nothrow @nogc unittest 346 { 347 assert(50 - abs(-100) == -50); 348 } 349 350 // https://issues.dlang.org/show_bug.cgi?id=19162 351 @safe unittest 352 { 353 struct Vector(T, int size) 354 { 355 T x, y, z; 356 } 357 358 static auto abs(T, int size)(auto ref const Vector!(T, size) v) 359 { 360 return v; 361 } 362 Vector!(int, 3) v; 363 assert(abs(v) == v); 364 } 365 366 /*********************************** 367 * Returns cosine of x. x is in radians. 368 * 369 * $(TABLE_SV 370 * $(TR $(TH x) $(TH cos(x)) $(TH invalid?)) 371 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) ) 372 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes) ) 373 * ) 374 * Bugs: 375 * Results are undefined if |x| >= $(POWER 2,64). 376 */ 377 378 real cos(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.cos(x); } 379 //FIXME 380 ///ditto 381 double cos(double x) @safe pure nothrow @nogc { return cos(cast(real) x); } 382 //FIXME 383 ///ditto 384 float cos(float x) @safe pure nothrow @nogc { return cos(cast(real) x); } 385 386 /// 387 @safe unittest 388 { 389 assert(cos(0.0) == 1.0); 390 assert(cos(1.0).approxEqual(0.540)); 391 assert(cos(3.0).approxEqual(-0.989)); 392 } 393 394 @safe unittest 395 { 396 real function(real) pcos = &cos; 397 assert(pcos != null); 398 } 399 400 /*********************************** 401 * Returns $(HTTP en.wikipedia.org/wiki/Sine, sine) of x. x is in $(HTTP en.wikipedia.org/wiki/Radian, radians). 402 * 403 * $(TABLE_SV 404 * $(TH3 x , sin(x) , invalid?) 405 * $(TD3 $(NAN) , $(NAN) , yes ) 406 * $(TD3 $(PLUSMN)0.0, $(PLUSMN)0.0, no ) 407 * $(TD3 $(PLUSMNINF), $(NAN) , yes ) 408 * ) 409 * 410 * Params: 411 * x = angle in radians (not degrees) 412 * Returns: 413 * sine of x 414 * See_Also: 415 * $(MYREF cos), $(MYREF tan), $(MYREF asin) 416 * Bugs: 417 * Results are undefined if |x| >= $(POWER 2,64). 418 */ 419 420 real sin(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.sin(x); } 421 //FIXME 422 ///ditto 423 double sin(double x) @safe pure nothrow @nogc { return sin(cast(real) x); } 424 //FIXME 425 ///ditto 426 float sin(float x) @safe pure nothrow @nogc { return sin(cast(real) x); } 427 428 /// 429 @safe unittest 430 { 431 import std.math : sin, PI; 432 import std.stdio : writefln; 433 434 void someFunc() 435 { 436 real x = 30.0; 437 auto result = sin(x * (PI / 180)); // convert degrees to radians 438 writefln("The sine of %s degrees is %s", x, result); 439 } 440 } 441 442 @safe unittest 443 { 444 real function(real) psin = &sin; 445 assert(psin != null); 446 } 447 448 /**************************************************************************** 449 * Returns tangent of x. x is in radians. 450 * 451 * $(TABLE_SV 452 * $(TR $(TH x) $(TH tan(x)) $(TH invalid?)) 453 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) 454 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) 455 * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD yes)) 456 * ) 457 */ 458 real tan(real x) @trusted pure nothrow @nogc // TODO: @safe 459 { 460 version (InlineAsm_X86_Any) 461 { 462 if (!__ctfe) 463 return tanAsm(x); 464 } 465 return tanImpl(x); 466 } 467 468 /// ditto 469 double tan(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) tan(cast(real) x) : tanImpl(x); } 470 471 /// ditto 472 float tan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) tan(cast(real) x) : tanImpl(x); } 473 474 /// 475 @safe unittest 476 { 477 assert(isIdentical(tan(0.0), 0.0)); 478 assert(tan(PI).approxEqual(0)); 479 assert(tan(PI / 3).approxEqual(sqrt(3.0))); 480 } 481 482 version (InlineAsm_X86_Any) 483 private real tanAsm(real x) @trusted pure nothrow @nogc 484 { 485 version (D_InlineAsm_X86) 486 { 487 asm pure nothrow @nogc 488 { 489 fld x[EBP] ; // load theta 490 fxam ; // test for oddball values 491 fstsw AX ; 492 sahf ; 493 jc trigerr ; // x is NAN, infinity, or empty 494 // 387's can handle subnormals 495 SC18: fptan ; 496 fstsw AX ; 497 sahf ; 498 jnp Clear1 ; // C2 = 1 (x is out of range) 499 500 // Do argument reduction to bring x into range 501 fldpi ; 502 fxch ; 503 SC17: fprem1 ; 504 fstsw AX ; 505 sahf ; 506 jp SC17 ; 507 fstp ST(1) ; // remove pi from stack 508 jmp SC18 ; 509 510 trigerr: 511 jnp Lret ; // if theta is NAN, return theta 512 fstp ST(0) ; // dump theta 513 } 514 return real.nan; 515 516 Clear1: asm pure nothrow @nogc{ 517 fstp ST(0) ; // dump X, which is always 1 518 } 519 520 Lret: {} 521 } 522 else version (D_InlineAsm_X86_64) 523 { 524 version (Win64) 525 { 526 asm pure nothrow @nogc 527 { 528 fld real ptr [RCX] ; // load theta 529 } 530 } 531 else 532 { 533 asm pure nothrow @nogc 534 { 535 fld x[RBP] ; // load theta 536 } 537 } 538 asm pure nothrow @nogc 539 { 540 fxam ; // test for oddball values 541 fstsw AX ; 542 test AH,1 ; 543 jnz trigerr ; // x is NAN, infinity, or empty 544 // 387's can handle subnormals 545 SC18: fptan ; 546 fstsw AX ; 547 test AH,4 ; 548 jz Clear1 ; // C2 = 1 (x is out of range) 549 550 // Do argument reduction to bring x into range 551 fldpi ; 552 fxch ; 553 SC17: fprem1 ; 554 fstsw AX ; 555 test AH,4 ; 556 jnz SC17 ; 557 fstp ST(1) ; // remove pi from stack 558 jmp SC18 ; 559 560 trigerr: 561 test AH,4 ; 562 jz Lret ; // if theta is NAN, return theta 563 fstp ST(0) ; // dump theta 564 } 565 return real.nan; 566 567 Clear1: asm pure nothrow @nogc{ 568 fstp ST(0) ; // dump X, which is always 1 569 } 570 571 Lret: {} 572 } 573 else 574 static assert(0); 575 } 576 577 private T tanImpl(T)(T x) @safe pure nothrow @nogc 578 { 579 // Coefficients for tan(x) and PI/4 split into three parts. 580 enum realFormat = floatTraits!T.realFormat; 581 static if (realFormat == RealFormat.ieeeQuadruple) 582 { 583 static immutable T[6] P = [ 584 2.883414728874239697964612246732416606301E10L, 585 -2.307030822693734879744223131873392503321E9L, 586 5.160188250214037865511600561074819366815E7L, 587 -4.249691853501233575668486667664718192660E5L, 588 1.272297782199996882828849455156962260810E3L, 589 -9.889929415807650724957118893791829849557E-1L 590 ]; 591 static immutable T[7] Q = [ 592 8.650244186622719093893836740197250197602E10L, 593 -4.152206921457208101480801635640958361612E10L, 594 2.758476078803232151774723646710890525496E9L, 595 -5.733709132766856723608447733926138506824E7L, 596 4.529422062441341616231663543669583527923E5L, 597 -1.317243702830553658702531997959756728291E3L, 598 1.0 599 ]; 600 601 enum T P1 = 602 7.853981633974483067550664827649598009884357452392578125E-1L; 603 enum T P2 = 604 2.8605943630549158983813312792950660807511260829685741796657E-18L; 605 enum T P3 = 606 2.1679525325309452561992610065108379921905808E-35L; 607 } 608 else static if (realFormat == RealFormat.ieeeExtended || 609 realFormat == RealFormat.ieeeDouble) 610 { 611 static immutable T[3] P = [ 612 -1.7956525197648487798769E7L, 613 1.1535166483858741613983E6L, 614 -1.3093693918138377764608E4L, 615 ]; 616 static immutable T[5] Q = [ 617 -5.3869575592945462988123E7L, 618 2.5008380182335791583922E7L, 619 -1.3208923444021096744731E6L, 620 1.3681296347069295467845E4L, 621 1.0000000000000000000000E0L, 622 ]; 623 624 enum T P1 = 7.853981554508209228515625E-1L; 625 enum T P2 = 7.946627356147928367136046290398E-9L; 626 enum T P3 = 3.061616997868382943065164830688E-17L; 627 } 628 else static if (realFormat == RealFormat.ieeeSingle) 629 { 630 static immutable T[6] P = [ 631 3.33331568548E-1, 632 1.33387994085E-1, 633 5.34112807005E-2, 634 2.44301354525E-2, 635 3.11992232697E-3, 636 9.38540185543E-3, 637 ]; 638 639 enum T P1 = 0.78515625; 640 enum T P2 = 2.4187564849853515625E-4; 641 enum T P3 = 3.77489497744594108E-8; 642 } 643 else 644 static assert(0, "no coefficients for tan()"); 645 646 // Special cases. 647 if (x == cast(T) 0.0 || isNaN(x)) 648 return x; 649 if (isInfinity(x)) 650 return T.nan; 651 652 // Make argument positive but save the sign. 653 bool sign = false; 654 if (signbit(x)) 655 { 656 sign = true; 657 x = -x; 658 } 659 660 // Compute x mod PI/4. 661 static if (realFormat == RealFormat.ieeeSingle) 662 { 663 enum T FOPI = 4 / PI; 664 int j = cast(int) (FOPI * x); 665 T y = j; 666 T z; 667 } 668 else 669 { 670 T y = floor(x / cast(T) PI_4); 671 // Strip high bits of integer part. 672 enum T highBitsFactor = (realFormat == RealFormat.ieeeDouble ? 0x1p3 : 0x1p4); 673 enum T highBitsInv = 1.0 / highBitsFactor; 674 T z = y * highBitsInv; 675 // Compute y - 2^numHighBits * (y / 2^numHighBits). 676 z = y - highBitsFactor * floor(z); 677 678 // Integer and fraction part modulo one octant. 679 int j = cast(int)(z); 680 } 681 682 // Map zeros and singularities to origin. 683 if (j & 1) 684 { 685 j += 1; 686 y += cast(T) 1.0; 687 } 688 689 z = ((x - y * P1) - y * P2) - y * P3; 690 const T zz = z * z; 691 692 enum T zzThreshold = (realFormat == RealFormat.ieeeSingle ? 1.0e-4L : 693 realFormat == RealFormat.ieeeDouble ? 1.0e-14L : 1.0e-20L); 694 if (zz > zzThreshold) 695 { 696 static if (realFormat == RealFormat.ieeeSingle) 697 y = z + z * (zz * poly(zz, P)); 698 else 699 y = z + z * (zz * poly(zz, P) / poly(zz, Q)); 700 } 701 else 702 y = z; 703 704 if (j & 2) 705 y = (cast(T) -1.0) / y; 706 707 return (sign) ? -y : y; 708 } 709 710 @safe @nogc nothrow unittest 711 { 712 static void testTan(T)() 713 { 714 // ±0 715 const T zero = 0.0; 716 assert(isIdentical(tan(zero), zero)); 717 assert(isIdentical(tan(-zero), -zero)); 718 // ±∞ 719 const T inf = T.infinity; 720 assert(isNaN(tan(inf))); 721 assert(isNaN(tan(-inf))); 722 // NaN 723 const T specialNaN = NaN(0x0123L); 724 assert(isIdentical(tan(specialNaN), specialNaN)); 725 726 static immutable T[2][] vals = 727 [ 728 // angle, tan 729 [ .5, .5463024898], 730 [ 1, 1.557407725], 731 [ 1.5, 14.10141995], 732 [ 2, -2.185039863], 733 [ 2.5,-.7470222972], 734 [ 3, -.1425465431], 735 [ 3.5, .3745856402], 736 [ 4, 1.157821282], 737 [ 4.5, 4.637332055], 738 [ 5, -3.380515006], 739 [ 5.5,-.9955840522], 740 [ 6, -.2910061914], 741 [ 6.5, .2202772003], 742 [ 10, .6483608275], 743 744 // special angles 745 [ PI_4, 1], 746 //[ PI_2, T.infinity], // PI_2 is not _exactly_ pi/2. 747 [ 3*PI_4, -1], 748 [ PI, 0], 749 [ 5*PI_4, 1], 750 //[ 3*PI_2, -T.infinity], 751 [ 7*PI_4, -1], 752 [ 2*PI, 0], 753 ]; 754 755 foreach (ref val; vals) 756 { 757 T x = val[0]; 758 T r = val[1]; 759 T t = tan(x); 760 761 //printf("tan(%Lg) = %Lg, should be %Lg\n", cast(real) x, cast(real) t, cast(real) r); 762 assert(approxEqual(r, t)); 763 764 x = -x; 765 r = -r; 766 t = tan(x); 767 //printf("tan(%Lg) = %Lg, should be %Lg\n", cast(real) x, cast(real) t, cast(real) r); 768 assert(approxEqual(r, t)); 769 } 770 } 771 772 import std.meta : AliasSeq; 773 foreach (T; AliasSeq!(real, double, float)) 774 testTan!T(); 775 776 assert(equalsDigit(tan(PI / 3), std.math.sqrt(3.0L), useDigits)); 777 } 778 779 /*************** 780 * Calculates the arc cosine of x, 781 * returning a value ranging from 0 to $(PI). 782 * 783 * $(TABLE_SV 784 * $(TR $(TH x) $(TH acos(x)) $(TH invalid?)) 785 * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes)) 786 * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes)) 787 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) 788 * ) 789 */ 790 real acos(real x) @safe pure nothrow @nogc 791 { 792 return atan2(sqrt(1-x*x), x); 793 } 794 795 /// ditto 796 double acos(double x) @safe pure nothrow @nogc { return acos(cast(real) x); } 797 798 /// ditto 799 float acos(float x) @safe pure nothrow @nogc { return acos(cast(real) x); } 800 801 /// 802 @safe unittest 803 { 804 assert(acos(0.0).approxEqual(1.570)); 805 assert(acos(0.5).approxEqual(std.math.PI / 3)); 806 assert(acos(PI).isNaN); 807 } 808 809 @safe @nogc nothrow unittest 810 { 811 assert(equalsDigit(acos(0.5), std.math.PI / 3, useDigits)); 812 } 813 814 /*************** 815 * Calculates the arc sine of x, 816 * returning a value ranging from -$(PI)/2 to $(PI)/2. 817 * 818 * $(TABLE_SV 819 * $(TR $(TH x) $(TH asin(x)) $(TH invalid?)) 820 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) 821 * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes)) 822 * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes)) 823 * ) 824 */ 825 real asin(real x) @safe pure nothrow @nogc 826 { 827 return atan2(x, sqrt(1-x*x)); 828 } 829 830 /// ditto 831 double asin(double x) @safe pure nothrow @nogc { return asin(cast(real) x); } 832 833 /// ditto 834 float asin(float x) @safe pure nothrow @nogc { return asin(cast(real) x); } 835 836 /// 837 @safe unittest 838 { 839 assert(isIdentical(asin(0.0), 0.0)); 840 assert(asin(0.5).approxEqual(PI / 6)); 841 assert(asin(PI).isNaN); 842 } 843 844 @safe @nogc nothrow unittest 845 { 846 assert(equalsDigit(asin(0.5), PI / 6, useDigits)); 847 } 848 849 /*************** 850 * Calculates the arc tangent of x, 851 * returning a value ranging from -$(PI)/2 to $(PI)/2. 852 * 853 * $(TABLE_SV 854 * $(TR $(TH x) $(TH atan(x)) $(TH invalid?)) 855 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) 856 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes)) 857 * ) 858 */ 859 real atan(real x) @safe pure nothrow @nogc 860 { 861 version (InlineAsm_X86_Any) 862 { 863 if (!__ctfe) 864 return atan2Asm(x, 1.0L); 865 } 866 return atanImpl(x); 867 } 868 869 /// ditto 870 double atan(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) atan(cast(real) x) : atanImpl(x); } 871 872 /// ditto 873 float atan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) atan(cast(real) x) : atanImpl(x); } 874 875 /// 876 @safe unittest 877 { 878 assert(isIdentical(atan(0.0), 0.0)); 879 assert(atan(sqrt(3.0)).approxEqual(PI / 3)); 880 } 881 882 private T atanImpl(T)(T x) @safe pure nothrow @nogc 883 { 884 // Coefficients for atan(x) 885 enum realFormat = floatTraits!T.realFormat; 886 static if (realFormat == RealFormat.ieeeQuadruple) 887 { 888 static immutable T[9] P = [ 889 -6.880597774405940432145577545328795037141E2L, 890 -2.514829758941713674909996882101723647996E3L, 891 -3.696264445691821235400930243493001671932E3L, 892 -2.792272753241044941703278827346430350236E3L, 893 -1.148164399808514330375280133523543970854E3L, 894 -2.497759878476618348858065206895055957104E2L, 895 -2.548067867495502632615671450650071218995E1L, 896 -8.768423468036849091777415076702113400070E-1L, 897 -6.635810778635296712545011270011752799963E-4L 898 ]; 899 static immutable T[9] Q = [ 900 2.064179332321782129643673263598686441900E3L, 901 8.782996876218210302516194604424986107121E3L, 902 1.547394317752562611786521896296215170819E4L, 903 1.458510242529987155225086911411015961174E4L, 904 7.928572347062145288093560392463784743935E3L, 905 2.494680540950601626662048893678584497900E3L, 906 4.308348370818927353321556740027020068897E2L, 907 3.566239794444800849656497338030115886153E1L, 908 1.0 909 ]; 910 } 911 else static if (realFormat == RealFormat.ieeeExtended) 912 { 913 static immutable T[5] P = [ 914 -5.0894116899623603312185E1L, 915 -9.9988763777265819915721E1L, 916 -6.3976888655834347413154E1L, 917 -1.4683508633175792446076E1L, 918 -8.6863818178092187535440E-1L, 919 ]; 920 static immutable T[6] Q = [ 921 1.5268235069887081006606E2L, 922 3.9157570175111990631099E2L, 923 3.6144079386152023162701E2L, 924 1.4399096122250781605352E2L, 925 2.2981886733594175366172E1L, 926 1.0000000000000000000000E0L, 927 ]; 928 } 929 else static if (realFormat == RealFormat.ieeeDouble) 930 { 931 static immutable T[5] P = [ 932 -6.485021904942025371773E1L, 933 -1.228866684490136173410E2L, 934 -7.500855792314704667340E1L, 935 -1.615753718733365076637E1L, 936 -8.750608600031904122785E-1L, 937 ]; 938 static immutable T[6] Q = [ 939 1.945506571482613964425E2L, 940 4.853903996359136964868E2L, 941 4.328810604912902668951E2L, 942 1.650270098316988542046E2L, 943 2.485846490142306297962E1L, 944 1.000000000000000000000E0L, 945 ]; 946 947 enum T MOREBITS = 6.123233995736765886130E-17L; 948 } 949 else static if (realFormat == RealFormat.ieeeSingle) 950 { 951 static immutable T[4] P = [ 952 -3.33329491539E-1, 953 1.99777106478E-1, 954 -1.38776856032E-1, 955 8.05374449538E-2, 956 ]; 957 } 958 else 959 static assert(0, "no coefficients for atan()"); 960 961 // tan(PI/8) 962 enum T TAN_PI_8 = 0.414213562373095048801688724209698078569672L; 963 // tan(3 * PI/8) 964 enum T TAN3_PI_8 = 2.414213562373095048801688724209698078569672L; 965 966 // Special cases. 967 if (x == cast(T) 0.0) 968 return x; 969 if (isInfinity(x)) 970 return copysign(cast(T) PI_2, x); 971 972 // Make argument positive but save the sign. 973 bool sign = false; 974 if (signbit(x)) 975 { 976 sign = true; 977 x = -x; 978 } 979 980 static if (realFormat == RealFormat.ieeeDouble) // special case for double precision 981 { 982 short flag = 0; 983 T y; 984 if (x > TAN3_PI_8) 985 { 986 y = PI_2; 987 flag = 1; 988 x = -(1.0 / x); 989 } 990 else if (x <= 0.66) 991 { 992 y = 0.0; 993 } 994 else 995 { 996 y = PI_4; 997 flag = 2; 998 x = (x - 1.0)/(x + 1.0); 999 } 1000 1001 T z = x * x; 1002 z = z * poly(z, P) / poly(z, Q); 1003 z = x * z + x; 1004 if (flag == 2) 1005 z += 0.5 * MOREBITS; 1006 else if (flag == 1) 1007 z += MOREBITS; 1008 y = y + z; 1009 } 1010 else 1011 { 1012 // Range reduction. 1013 T y; 1014 if (x > TAN3_PI_8) 1015 { 1016 y = PI_2; 1017 x = -((cast(T) 1.0) / x); 1018 } 1019 else if (x > TAN_PI_8) 1020 { 1021 y = PI_4; 1022 x = (x - cast(T) 1.0)/(x + cast(T) 1.0); 1023 } 1024 else 1025 y = 0.0; 1026 1027 // Rational form in x^^2. 1028 const T z = x * x; 1029 static if (realFormat == RealFormat.ieeeSingle) 1030 y += poly(z, P) * z * x + x; 1031 else 1032 y = y + (poly(z, P) / poly(z, Q)) * z * x + x; 1033 } 1034 1035 return (sign) ? -y : y; 1036 } 1037 1038 @safe @nogc nothrow unittest 1039 { 1040 static void testAtan(T)() 1041 { 1042 // ±0 1043 const T zero = 0.0; 1044 assert(isIdentical(atan(zero), zero)); 1045 assert(isIdentical(atan(-zero), -zero)); 1046 // ±∞ 1047 const T inf = T.infinity; 1048 assert(approxEqual(atan(inf), cast(T) PI_2)); 1049 assert(approxEqual(atan(-inf), cast(T) -PI_2)); 1050 // NaN 1051 const T specialNaN = NaN(0x0123L); 1052 assert(isIdentical(atan(specialNaN), specialNaN)); 1053 1054 static immutable T[2][] vals = 1055 [ 1056 // x, atan(x) 1057 [ 0.25, 0.2449786631 ], 1058 [ 0.5, 0.4636476090 ], 1059 [ 1, PI_4 ], 1060 [ 1.5, 0.9827937232 ], 1061 [ 10, 1.4711276743 ], 1062 ]; 1063 1064 foreach (ref val; vals) 1065 { 1066 T x = val[0]; 1067 T r = val[1]; 1068 T a = atan(x); 1069 1070 //printf("atan(%Lg) = %Lg, should be %Lg\n", cast(real) x, cast(real) a, cast(real) r); 1071 assert(approxEqual(r, a)); 1072 1073 x = -x; 1074 r = -r; 1075 a = atan(x); 1076 //printf("atan(%Lg) = %Lg, should be %Lg\n", cast(real) x, cast(real) a, cast(real) r); 1077 assert(approxEqual(r, a)); 1078 } 1079 } 1080 1081 import std.meta : AliasSeq; 1082 foreach (T; AliasSeq!(real, double, float)) 1083 testAtan!T(); 1084 1085 assert(equalsDigit(atan(std.math.sqrt(3.0L)), PI / 3, useDigits)); 1086 } 1087 1088 /*************** 1089 * Calculates the arc tangent of y / x, 1090 * returning a value ranging from -$(PI) to $(PI). 1091 * 1092 * $(TABLE_SV 1093 * $(TR $(TH y) $(TH x) $(TH atan(y, x))) 1094 * $(TR $(TD $(NAN)) $(TD anything) $(TD $(NAN)) ) 1095 * $(TR $(TD anything) $(TD $(NAN)) $(TD $(NAN)) ) 1096 * $(TR $(TD $(PLUSMN)0.0) $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) ) 1097 * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) $(TD $(PLUSMN)0.0) ) 1098 * $(TR $(TD $(PLUSMN)0.0) $(TD $(LT)0.0) $(TD $(PLUSMN)$(PI))) 1099 * $(TR $(TD $(PLUSMN)0.0) $(TD -0.0) $(TD $(PLUSMN)$(PI))) 1100 * $(TR $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2) ) 1101 * $(TR $(TD $(LT)0.0) $(TD $(PLUSMN)0.0) $(TD -$(PI)/2) ) 1102 * $(TR $(TD $(GT)0.0) $(TD $(INFIN)) $(TD $(PLUSMN)0.0) ) 1103 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(PLUSMN)$(PI)/2)) 1104 * $(TR $(TD $(GT)0.0) $(TD -$(INFIN)) $(TD $(PLUSMN)$(PI)) ) 1105 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(INFIN)) $(TD $(PLUSMN)$(PI)/4)) 1106 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD -$(INFIN)) $(TD $(PLUSMN)3$(PI)/4)) 1107 * ) 1108 */ 1109 real atan2(real y, real x) @trusted pure nothrow @nogc // TODO: @safe 1110 { 1111 version (InlineAsm_X86_Any) 1112 { 1113 if (!__ctfe) 1114 return atan2Asm(y, x); 1115 } 1116 return atan2Impl(y, x); 1117 } 1118 1119 /// ditto 1120 double atan2(double y, double x) @safe pure nothrow @nogc 1121 { 1122 return __ctfe ? cast(double) atan2(cast(real) y, cast(real) x) : atan2Impl(y, x); 1123 } 1124 1125 /// ditto 1126 float atan2(float y, float x) @safe pure nothrow @nogc 1127 { 1128 return __ctfe ? cast(float) atan2(cast(real) y, cast(real) x) : atan2Impl(y, x); 1129 } 1130 1131 /// 1132 @safe unittest 1133 { 1134 assert(atan2(1.0, sqrt(3.0)).approxEqual(PI / 6)); 1135 } 1136 1137 version (InlineAsm_X86_Any) 1138 private real atan2Asm(real y, real x) @trusted pure nothrow @nogc 1139 { 1140 version (Win64) 1141 { 1142 asm pure nothrow @nogc { 1143 naked; 1144 fld real ptr [RDX]; // y 1145 fld real ptr [RCX]; // x 1146 fpatan; 1147 ret; 1148 } 1149 } 1150 else 1151 { 1152 asm pure nothrow @nogc { 1153 fld y; 1154 fld x; 1155 fpatan; 1156 } 1157 } 1158 } 1159 1160 private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc 1161 { 1162 // Special cases. 1163 if (isNaN(x) || isNaN(y)) 1164 return T.nan; 1165 if (y == cast(T) 0.0) 1166 { 1167 if (x >= 0 && !signbit(x)) 1168 return copysign(0, y); 1169 else 1170 return copysign(cast(T) PI, y); 1171 } 1172 if (x == cast(T) 0.0) 1173 return copysign(cast(T) PI_2, y); 1174 if (isInfinity(x)) 1175 { 1176 if (signbit(x)) 1177 { 1178 if (isInfinity(y)) 1179 return copysign(3 * cast(T) PI_4, y); 1180 else 1181 return copysign(cast(T) PI, y); 1182 } 1183 else 1184 { 1185 if (isInfinity(y)) 1186 return copysign(cast(T) PI_4, y); 1187 else 1188 return copysign(cast(T) 0.0, y); 1189 } 1190 } 1191 if (isInfinity(y)) 1192 return copysign(cast(T) PI_2, y); 1193 1194 // Call atan and determine the quadrant. 1195 T z = atan(y / x); 1196 1197 if (signbit(x)) 1198 { 1199 if (signbit(y)) 1200 z = z - cast(T) PI; 1201 else 1202 z = z + cast(T) PI; 1203 } 1204 1205 if (z == cast(T) 0.0) 1206 return copysign(z, y); 1207 1208 return z; 1209 } 1210 1211 @safe @nogc nothrow unittest 1212 { 1213 static void testAtan2(T)() 1214 { 1215 // NaN 1216 const T nan = T.nan; 1217 assert(isNaN(atan2(nan, cast(T) 1))); 1218 assert(isNaN(atan2(cast(T) 1, nan))); 1219 1220 const T inf = T.infinity; 1221 static immutable T[3][] vals = 1222 [ 1223 // y, x, atan2(y, x) 1224 1225 // ±0 1226 [ 0.0, 1.0, 0.0 ], 1227 [ -0.0, 1.0, -0.0 ], 1228 [ 0.0, 0.0, 0.0 ], 1229 [ -0.0, 0.0, -0.0 ], 1230 [ 0.0, -1.0, PI ], 1231 [ -0.0, -1.0, -PI ], 1232 [ 0.0, -0.0, PI ], 1233 [ -0.0, -0.0, -PI ], 1234 [ 1.0, 0.0, PI_2 ], 1235 [ 1.0, -0.0, PI_2 ], 1236 [ -1.0, 0.0, -PI_2 ], 1237 [ -1.0, -0.0, -PI_2 ], 1238 1239 // ±∞ 1240 [ 1.0, inf, 0.0 ], 1241 [ -1.0, inf, -0.0 ], 1242 [ 1.0, -inf, PI ], 1243 [ -1.0, -inf, -PI ], 1244 [ inf, 1.0, PI_2 ], 1245 [ inf, -1.0, PI_2 ], 1246 [ -inf, 1.0, -PI_2 ], 1247 [ -inf, -1.0, -PI_2 ], 1248 [ inf, inf, PI_4 ], 1249 [ -inf, inf, -PI_4 ], 1250 [ inf, -inf, 3 * PI_4 ], 1251 [ -inf, -inf, -3 * PI_4 ], 1252 1253 [ 1.0, 1.0, PI_4 ], 1254 [ -2.0, 2.0, -PI_4 ], 1255 [ 3.0, -3.0, 3 * PI_4 ], 1256 [ -4.0, -4.0, -3 * PI_4 ], 1257 1258 [ 0.75, 0.25, 1.249045772398 ], 1259 [ -0.5, 0.375, -0.927295218002 ], 1260 [ 0.5, -0.125, 1.815774989922 ], 1261 [ -0.75, -0.5, -2.158798930342 ], 1262 ]; 1263 1264 foreach (ref val; vals) 1265 { 1266 const T y = val[0]; 1267 const T x = val[1]; 1268 const T r = val[2]; 1269 const T a = atan2(y, x); 1270 1271 //printf("atan2(%Lg, %Lg) = %Lg, should be %Lg\n", cast(real) y, cast(real) x, cast(real) a, cast(real) r); 1272 if (r == 0) 1273 assert(isIdentical(r, a)); // check sign 1274 else 1275 assert(approxEqual(r, a)); 1276 } 1277 } 1278 1279 import std.meta : AliasSeq; 1280 foreach (T; AliasSeq!(real, double, float)) 1281 testAtan2!T(); 1282 1283 assert(equalsDigit(atan2(1.0L, std.math.sqrt(3.0L)), PI / 6, useDigits)); 1284 } 1285 1286 /*********************************** 1287 * Calculates the hyperbolic cosine of x. 1288 * 1289 * $(TABLE_SV 1290 * $(TR $(TH x) $(TH cosh(x)) $(TH invalid?)) 1291 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)0.0) $(TD no) ) 1292 * ) 1293 */ 1294 real cosh(real x) @safe pure nothrow @nogc 1295 { 1296 // cosh = (exp(x)+exp(-x))/2. 1297 // The naive implementation works correctly. 1298 const real y = exp(x); 1299 return (y + 1.0/y) * 0.5; 1300 } 1301 1302 /// ditto 1303 double cosh(double x) @safe pure nothrow @nogc { return cosh(cast(real) x); } 1304 1305 /// ditto 1306 float cosh(float x) @safe pure nothrow @nogc { return cosh(cast(real) x); } 1307 1308 /// 1309 @safe unittest 1310 { 1311 assert(cosh(0.0) == 1.0); 1312 assert(cosh(1.0).approxEqual((E + 1.0 / E) / 2)); 1313 } 1314 1315 @safe @nogc nothrow unittest 1316 { 1317 assert(equalsDigit(cosh(1.0), (E + 1.0 / E) / 2, useDigits)); 1318 } 1319 1320 /*********************************** 1321 * Calculates the hyperbolic sine of x. 1322 * 1323 * $(TABLE_SV 1324 * $(TR $(TH x) $(TH sinh(x)) $(TH invalid?)) 1325 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) 1326 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no)) 1327 * ) 1328 */ 1329 real sinh(real x) @safe pure nothrow @nogc 1330 { 1331 // sinh(x) = (exp(x)-exp(-x))/2; 1332 // Very large arguments could cause an overflow, but 1333 // the maximum value of x for which exp(x) + exp(-x)) != exp(x) 1334 // is x = 0.5 * (real.mant_dig) * LN2. // = 22.1807 for real80. 1335 if (fabs(x) > real.mant_dig * LN2) 1336 { 1337 return copysign(0.5 * exp(fabs(x)), x); 1338 } 1339 1340 const real y = expm1(x); 1341 return 0.5 * y / (y+1) * (y+2); 1342 } 1343 1344 /// ditto 1345 double sinh(double x) @safe pure nothrow @nogc { return sinh(cast(real) x); } 1346 1347 /// ditto 1348 float sinh(float x) @safe pure nothrow @nogc { return sinh(cast(real) x); } 1349 1350 /// 1351 @safe unittest 1352 { 1353 assert(isIdentical(sinh(0.0), 0.0)); 1354 assert(sinh(1.0).approxEqual((E - 1.0 / E) / 2)); 1355 } 1356 1357 @safe @nogc nothrow unittest 1358 { 1359 assert(equalsDigit(sinh(1.0), (E - 1.0 / E) / 2, useDigits)); 1360 } 1361 1362 /*********************************** 1363 * Calculates the hyperbolic tangent of x. 1364 * 1365 * $(TABLE_SV 1366 * $(TR $(TH x) $(TH tanh(x)) $(TH invalid?)) 1367 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) ) 1368 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)1.0) $(TD no)) 1369 * ) 1370 */ 1371 real tanh(real x) @safe pure nothrow @nogc 1372 { 1373 // tanh(x) = (exp(x) - exp(-x))/(exp(x)+exp(-x)) 1374 if (fabs(x) > real.mant_dig * LN2) 1375 { 1376 return copysign(1, x); 1377 } 1378 1379 const real y = expm1(2*x); 1380 return y / (y + 2); 1381 } 1382 1383 /// ditto 1384 double tanh(double x) @safe pure nothrow @nogc { return tanh(cast(real) x); } 1385 1386 /// ditto 1387 float tanh(float x) @safe pure nothrow @nogc { return tanh(cast(real) x); } 1388 1389 /// 1390 @safe unittest 1391 { 1392 assert(isIdentical(tanh(0.0), 0.0)); 1393 assert(tanh(1.0).approxEqual(sinh(1.0) / cosh(1.0))); 1394 } 1395 1396 @safe @nogc nothrow unittest 1397 { 1398 assert(equalsDigit(tanh(1.0), sinh(1.0) / cosh(1.0), 15)); 1399 } 1400 1401 /*********************************** 1402 * Calculates the inverse hyperbolic cosine of x. 1403 * 1404 * Mathematically, acosh(x) = log(x + sqrt( x*x - 1)) 1405 * 1406 * $(TABLE_DOMRG 1407 * $(DOMAIN 1..$(INFIN)), 1408 * $(RANGE 0..$(INFIN)) 1409 * ) 1410 * 1411 * $(TABLE_SV 1412 * $(SVH x, acosh(x) ) 1413 * $(SV $(NAN), $(NAN) ) 1414 * $(SV $(LT)1, $(NAN) ) 1415 * $(SV 1, 0 ) 1416 * $(SV +$(INFIN),+$(INFIN)) 1417 * ) 1418 */ 1419 real acosh(real x) @safe pure nothrow @nogc 1420 { 1421 if (x > 1/real.epsilon) 1422 return LN2 + log(x); 1423 else 1424 return log(x + sqrt(x*x - 1)); 1425 } 1426 1427 /// ditto 1428 double acosh(double x) @safe pure nothrow @nogc { return acosh(cast(real) x); } 1429 1430 /// ditto 1431 float acosh(float x) @safe pure nothrow @nogc { return acosh(cast(real) x); } 1432 1433 /// 1434 @safe @nogc nothrow unittest 1435 { 1436 assert(isNaN(acosh(0.9))); 1437 assert(isNaN(acosh(real.nan))); 1438 assert(isIdentical(acosh(1.0), 0.0)); 1439 assert(acosh(real.infinity) == real.infinity); 1440 assert(isNaN(acosh(0.5))); 1441 } 1442 1443 @safe @nogc nothrow unittest 1444 { 1445 assert(equalsDigit(acosh(cosh(3.0)), 3, useDigits)); 1446 } 1447 1448 /*********************************** 1449 * Calculates the inverse hyperbolic sine of x. 1450 * 1451 * Mathematically, 1452 * --------------- 1453 * asinh(x) = log( x + sqrt( x*x + 1 )) // if x >= +0 1454 * asinh(x) = -log(-x + sqrt( x*x + 1 )) // if x <= -0 1455 * ------------- 1456 * 1457 * $(TABLE_SV 1458 * $(SVH x, asinh(x) ) 1459 * $(SV $(NAN), $(NAN) ) 1460 * $(SV $(PLUSMN)0, $(PLUSMN)0 ) 1461 * $(SV $(PLUSMN)$(INFIN),$(PLUSMN)$(INFIN)) 1462 * ) 1463 */ 1464 real asinh(real x) @safe pure nothrow @nogc 1465 { 1466 return (fabs(x) > 1 / real.epsilon) 1467 // beyond this point, x*x + 1 == x*x 1468 ? copysign(LN2 + log(fabs(x)), x) 1469 // sqrt(x*x + 1) == 1 + x * x / ( 1 + sqrt(x*x + 1) ) 1470 : copysign(log1p(fabs(x) + x*x / (1 + sqrt(x*x + 1)) ), x); 1471 } 1472 1473 /// ditto 1474 double asinh(double x) @safe pure nothrow @nogc { return asinh(cast(real) x); } 1475 1476 /// ditto 1477 float asinh(float x) @safe pure nothrow @nogc { return asinh(cast(real) x); } 1478 1479 /// 1480 @safe @nogc nothrow unittest 1481 { 1482 assert(isIdentical(asinh(0.0), 0.0)); 1483 assert(isIdentical(asinh(-0.0), -0.0)); 1484 assert(asinh(real.infinity) == real.infinity); 1485 assert(asinh(-real.infinity) == -real.infinity); 1486 assert(isNaN(asinh(real.nan))); 1487 } 1488 1489 @safe unittest 1490 { 1491 assert(equalsDigit(asinh(sinh(3.0)), 3, useDigits)); 1492 } 1493 1494 /*********************************** 1495 * Calculates the inverse hyperbolic tangent of x, 1496 * returning a value from ranging from -1 to 1. 1497 * 1498 * Mathematically, atanh(x) = log( (1+x)/(1-x) ) / 2 1499 * 1500 * $(TABLE_DOMRG 1501 * $(DOMAIN -$(INFIN)..$(INFIN)), 1502 * $(RANGE -1 .. 1) 1503 * ) 1504 * $(BR) 1505 * $(TABLE_SV 1506 * $(SVH x, acosh(x) ) 1507 * $(SV $(NAN), $(NAN) ) 1508 * $(SV $(PLUSMN)0, $(PLUSMN)0) 1509 * $(SV -$(INFIN), -0) 1510 * ) 1511 */ 1512 real atanh(real x) @safe pure nothrow @nogc 1513 { 1514 // log( (1+x)/(1-x) ) == log ( 1 + (2*x)/(1-x) ) 1515 return 0.5 * log1p( 2 * x / (1 - x) ); 1516 } 1517 1518 /// ditto 1519 double atanh(double x) @safe pure nothrow @nogc { return atanh(cast(real) x); } 1520 1521 /// ditto 1522 float atanh(float x) @safe pure nothrow @nogc { return atanh(cast(real) x); } 1523 1524 /// 1525 @safe @nogc nothrow unittest 1526 { 1527 assert(isIdentical(atanh(0.0), 0.0)); 1528 assert(isIdentical(atanh(-0.0),-0.0)); 1529 assert(isNaN(atanh(real.nan))); 1530 assert(isNaN(atanh(-real.infinity))); 1531 assert(atanh(0.0) == 0); 1532 } 1533 1534 @safe unittest 1535 { 1536 assert(equalsDigit(atanh(tanh(0.5L)), 0.5, useDigits)); 1537 } 1538 1539 /***************************************** 1540 * Returns x rounded to a long value using the current rounding mode. 1541 * If the integer value of x is 1542 * greater than long.max, the result is 1543 * indeterminate. 1544 */ 1545 long rndtol(real x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.rndtol(x); } 1546 //FIXME 1547 ///ditto 1548 long rndtol(double x) @safe pure nothrow @nogc { return rndtol(cast(real) x); } 1549 //FIXME 1550 ///ditto 1551 long rndtol(float x) @safe pure nothrow @nogc { return rndtol(cast(real) x); } 1552 1553 /// 1554 @safe unittest 1555 { 1556 assert(rndtol(1.0) == 1L); 1557 assert(rndtol(1.2) == 1L); 1558 assert(rndtol(1.7) == 2L); 1559 assert(rndtol(1.0001) == 1L); 1560 } 1561 1562 @safe unittest 1563 { 1564 long function(real) prndtol = &rndtol; 1565 assert(prndtol != null); 1566 } 1567 1568 /** 1569 $(RED Deprecated. Please use $(LREF round) instead.) 1570 1571 Returns `x` rounded to a `long` value using the `FE_TONEAREST` rounding mode. 1572 If the integer value of `x` is greater than `long.max`, the result is 1573 indeterminate. 1574 1575 Only works with the Digital Mars C Runtime. 1576 1577 Params: 1578 x = the number to round 1579 Returns: 1580 `x` rounded to an integer value 1581 */ 1582 deprecated("rndtonl is to be removed by 2.089. Please use round instead") 1583 extern (C) real rndtonl(real x); 1584 1585 /// 1586 deprecated @system unittest 1587 { 1588 version (CRuntime_DigitalMars) 1589 { 1590 assert(rndtonl(1.0) is -real.nan); 1591 assert(rndtonl(1.2) is -real.nan); 1592 assert(rndtonl(1.7) is -real.nan); 1593 assert(rndtonl(1.0001) is -real.nan); 1594 } 1595 } 1596 1597 /*************************************** 1598 * Compute square root of x. 1599 * 1600 * $(TABLE_SV 1601 * $(TR $(TH x) $(TH sqrt(x)) $(TH invalid?)) 1602 * $(TR $(TD -0.0) $(TD -0.0) $(TD no)) 1603 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD yes)) 1604 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no)) 1605 * ) 1606 */ 1607 float sqrt(float x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.sqrt(x); } 1608 1609 /// ditto 1610 double sqrt(double x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.sqrt(x); } 1611 1612 /// ditto 1613 real sqrt(real x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.sqrt(x); } 1614 1615 /// 1616 @safe pure nothrow @nogc unittest 1617 { 1618 assert(sqrt(2.0).feqrel(1.4142) > 16); 1619 assert(sqrt(9.0).feqrel(3.0) > 16); 1620 1621 assert(isNaN(sqrt(-1.0f))); 1622 assert(isNaN(sqrt(-1.0))); 1623 assert(isNaN(sqrt(-1.0L))); 1624 } 1625 1626 @safe unittest 1627 { 1628 float function(float) psqrtf = &sqrt; 1629 assert(psqrtf != null); 1630 double function(double) psqrtd = &sqrt; 1631 assert(psqrtd != null); 1632 real function(real) psqrtr = &sqrt; 1633 assert(psqrtr != null); 1634 1635 //ctfe 1636 enum ZX80 = sqrt(7.0f); 1637 enum ZX81 = sqrt(7.0); 1638 enum ZX82 = sqrt(7.0L); 1639 } 1640 1641 /** 1642 * Calculates e$(SUPERSCRIPT x). 1643 * 1644 * $(TABLE_SV 1645 * $(TR $(TH x) $(TH e$(SUPERSCRIPT x)) ) 1646 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) ) 1647 * $(TR $(TD -$(INFIN)) $(TD +0.0) ) 1648 * $(TR $(TD $(NAN)) $(TD $(NAN)) ) 1649 * ) 1650 */ 1651 real exp(real x) @trusted pure nothrow @nogc // TODO: @safe 1652 { 1653 version (D_InlineAsm_X86) 1654 { 1655 // e^^x = 2^^(LOG2E*x) 1656 // (This is valid because the overflow & underflow limits for exp 1657 // and exp2 are so similar). 1658 if (!__ctfe) 1659 return exp2Asm(LOG2E*x); 1660 } 1661 else version (D_InlineAsm_X86_64) 1662 { 1663 // e^^x = 2^^(LOG2E*x) 1664 // (This is valid because the overflow & underflow limits for exp 1665 // and exp2 are so similar). 1666 if (!__ctfe) 1667 return exp2Asm(LOG2E*x); 1668 } 1669 return expImpl(x); 1670 } 1671 1672 /// ditto 1673 double exp(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) exp(cast(real) x) : expImpl(x); } 1674 1675 /// ditto 1676 float exp(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) exp(cast(real) x) : expImpl(x); } 1677 1678 /// 1679 @safe unittest 1680 { 1681 assert(exp(0.0) == 1.0); 1682 assert(exp(3.0).feqrel(E * E * E) > 16); 1683 } 1684 1685 private T expImpl(T)(T x) @safe pure nothrow @nogc 1686 { 1687 alias F = floatTraits!T; 1688 static if (F.realFormat == RealFormat.ieeeSingle) 1689 { 1690 static immutable T[6] P = [ 1691 5.0000001201E-1, 1692 1.6666665459E-1, 1693 4.1665795894E-2, 1694 8.3334519073E-3, 1695 1.3981999507E-3, 1696 1.9875691500E-4, 1697 ]; 1698 1699 enum T C1 = 0.693359375; 1700 enum T C2 = -2.12194440e-4; 1701 1702 // Overflow and Underflow limits. 1703 enum T OF = 88.72283905206835; 1704 enum T UF = -103.278929903431851103; // ln(2^-149) 1705 } 1706 else static if (F.realFormat == RealFormat.ieeeDouble) 1707 { 1708 // Coefficients for exp(x) 1709 static immutable T[3] P = [ 1710 9.99999999999999999910E-1L, 1711 3.02994407707441961300E-2L, 1712 1.26177193074810590878E-4L, 1713 ]; 1714 static immutable T[4] Q = [ 1715 2.00000000000000000009E0L, 1716 2.27265548208155028766E-1L, 1717 2.52448340349684104192E-3L, 1718 3.00198505138664455042E-6L, 1719 ]; 1720 1721 // C1 + C2 = LN2. 1722 enum T C1 = 6.93145751953125E-1; 1723 enum T C2 = 1.42860682030941723212E-6; 1724 1725 // Overflow and Underflow limits. 1726 enum T OF = 7.09782712893383996732E2; // ln((1-2^-53) * 2^1024) 1727 enum T UF = -7.451332191019412076235E2; // ln(2^-1075) 1728 } 1729 else static if (F.realFormat == RealFormat.ieeeExtended) 1730 { 1731 // Coefficients for exp(x) 1732 static immutable T[3] P = [ 1733 9.9999999999999999991025E-1L, 1734 3.0299440770744196129956E-2L, 1735 1.2617719307481059087798E-4L, 1736 ]; 1737 static immutable T[4] Q = [ 1738 2.0000000000000000000897E0L, 1739 2.2726554820815502876593E-1L, 1740 2.5244834034968410419224E-3L, 1741 3.0019850513866445504159E-6L, 1742 ]; 1743 1744 // C1 + C2 = LN2. 1745 enum T C1 = 6.9314575195312500000000E-1L; 1746 enum T C2 = 1.4286068203094172321215E-6L; 1747 1748 // Overflow and Underflow limits. 1749 enum T OF = 1.1356523406294143949492E4L; // ln((1-2^-64) * 2^16384) 1750 enum T UF = -1.13994985314888605586758E4L; // ln(2^-16446) 1751 } 1752 else static if (F.realFormat == RealFormat.ieeeQuadruple) 1753 { 1754 // Coefficients for exp(x) - 1 1755 static immutable T[5] P = [ 1756 9.999999999999999999999999999999999998502E-1L, 1757 3.508710990737834361215404761139478627390E-2L, 1758 2.708775201978218837374512615596512792224E-4L, 1759 6.141506007208645008909088812338454698548E-7L, 1760 3.279723985560247033712687707263393506266E-10L 1761 ]; 1762 static immutable T[6] Q = [ 1763 2.000000000000000000000000000000000000150E0, 1764 2.368408864814233538909747618894558968880E-1L, 1765 3.611828913847589925056132680618007270344E-3L, 1766 1.504792651814944826817779302637284053660E-5L, 1767 1.771372078166251484503904874657985291164E-8L, 1768 2.980756652081995192255342779918052538681E-12L 1769 ]; 1770 1771 // C1 + C2 = LN2. 1772 enum T C1 = 6.93145751953125E-1L; 1773 enum T C2 = 1.428606820309417232121458176568075500134E-6L; 1774 1775 // Overflow and Underflow limits. 1776 enum T OF = 1.135583025911358400418251384584930671458833e4L; 1777 enum T UF = -1.143276959615573793352782661133116431383730e4L; 1778 } 1779 else 1780 static assert(0, "Not implemented for this architecture"); 1781 1782 // Special cases. 1783 if (isNaN(x)) 1784 return x; 1785 if (x > OF) 1786 return real.infinity; 1787 if (x < UF) 1788 return 0.0; 1789 1790 // Express: e^^x = e^^g * 2^^n 1791 // = e^^g * e^^(n * LOG2E) 1792 // = e^^(g + n * LOG2E) 1793 T xx = floor((cast(T) LOG2E) * x + cast(T) 0.5); 1794 const int n = cast(int) xx; 1795 x -= xx * C1; 1796 x -= xx * C2; 1797 1798 static if (F.realFormat == RealFormat.ieeeSingle) 1799 { 1800 xx = x * x; 1801 x = poly(x, P) * xx + x + 1.0f; 1802 } 1803 else 1804 { 1805 // Rational approximation for exponential of the fractional part: 1806 // e^^x = 1 + 2x P(x^^2) / (Q(x^^2) - P(x^^2)) 1807 xx = x * x; 1808 const T px = x * poly(xx, P); 1809 x = px / (poly(xx, Q) - px); 1810 x = (cast(T) 1.0) + (cast(T) 2.0) * x; 1811 } 1812 1813 // Scale by power of 2. 1814 x = ldexp(x, n); 1815 1816 return x; 1817 } 1818 1819 @safe @nogc nothrow unittest 1820 { 1821 version (FloatingPointControlSupport) 1822 { 1823 FloatingPointControl ctrl; 1824 if (FloatingPointControl.hasExceptionTraps) 1825 ctrl.disableExceptions(FloatingPointControl.allExceptions); 1826 ctrl.rounding = FloatingPointControl.roundToNearest; 1827 } 1828 1829 static void testExp(T)() 1830 { 1831 enum realFormat = floatTraits!T.realFormat; 1832 static if (realFormat == RealFormat.ieeeQuadruple) 1833 { 1834 static immutable T[2][] exptestpoints = 1835 [ // x exp(x) 1836 [ 1.0L, E ], 1837 [ 0.5L, 0x1.a61298e1e069bc972dfefab6df34p+0L ], 1838 [ 3.0L, E*E*E ], 1839 [ 0x1.6p+13L, 0x1.6e509d45728655cdb4840542acb5p+16250L ], // near overflow 1840 [ 0x1.7p+13L, T.infinity ], // close overflow 1841 [ 0x1p+80L, T.infinity ], // far overflow 1842 [ T.infinity, T.infinity ], 1843 [-0x1.18p+13L, 0x1.5e4bf54b4807034ea97fef0059a6p-12927L ], // near underflow 1844 [-0x1.625p+13L, 0x1.a6bd68a39d11fec3a250cd97f524p-16358L ], // ditto 1845 [-0x1.62dafp+13L, 0x0.cb629e9813b80ed4d639e875be6cp-16382L ], // near underflow - subnormal 1846 [-0x1.6549p+13L, 0x0.0000000000000000000000000001p-16382L ], // ditto 1847 [-0x1.655p+13L, 0 ], // close underflow 1848 [-0x1p+30L, 0 ], // far underflow 1849 ]; 1850 } 1851 else static if (realFormat == RealFormat.ieeeExtended) 1852 { 1853 static immutable T[2][] exptestpoints = 1854 [ // x exp(x) 1855 [ 1.0L, E ], 1856 [ 0.5L, 0x1.a61298e1e069bc97p+0L ], 1857 [ 3.0L, E*E*E ], 1858 [ 0x1.1p+13L, 0x1.29aeffefc8ec645p+12557L ], // near overflow 1859 [ 0x1.7p+13L, T.infinity ], // close overflow 1860 [ 0x1p+80L, T.infinity ], // far overflow 1861 [ T.infinity, T.infinity ], 1862 [-0x1.18p+13L, 0x1.5e4bf54b4806db9p-12927L ], // near underflow 1863 [-0x1.625p+13L, 0x1.a6bd68a39d11f35cp-16358L ], // ditto 1864 [-0x1.62dafp+13L, 0x1.96c53d30277021dp-16383L ], // near underflow - subnormal 1865 [-0x1.643p+13L, 0x1p-16444L ], // ditto 1866 [-0x1.645p+13L, 0 ], // close underflow 1867 [-0x1p+30L, 0 ], // far underflow 1868 ]; 1869 } 1870 else static if (realFormat == RealFormat.ieeeDouble) 1871 { 1872 static immutable T[2][] exptestpoints = 1873 [ // x, exp(x) 1874 [ 1.0L, E ], 1875 [ 0.5L, 0x1.a61298e1e069cp+0L ], 1876 [ 3.0L, E*E*E ], 1877 [ 0x1.6p+9L, 0x1.93bf4ec282efbp+1015L ], // near overflow 1878 [ 0x1.7p+9L, T.infinity ], // close overflow 1879 [ 0x1p+80L, T.infinity ], // far overflow 1880 [ T.infinity, T.infinity ], 1881 [-0x1.6p+9L, 0x1.44a3824e5285fp-1016L ], // near underflow 1882 [-0x1.64p+9L, 0x0.06f84920bb2d4p-1022L ], // near underflow - subnormal 1883 [-0x1.743p+9L, 0x0.0000000000001p-1022L ], // ditto 1884 [-0x1.8p+9L, 0 ], // close underflow 1885 [-0x1p+30L, 0 ], // far underflow 1886 ]; 1887 } 1888 else static if (realFormat == RealFormat.ieeeSingle) 1889 { 1890 static immutable T[2][] exptestpoints = 1891 [ // x, exp(x) 1892 [ 1.0L, E ], 1893 [ 0.5L, 0x1.a61299p+0L ], 1894 [ 3.0L, E*E*E ], 1895 [ 0x1.62p+6L, 0x1.99b988p+127L ], // near overflow 1896 [ 0x1.7p+6L, T.infinity ], // close overflow 1897 [ 0x1p+80L, T.infinity ], // far overflow 1898 [ T.infinity, T.infinity ], 1899 [-0x1.5cp+6L, 0x1.666d0ep-126L ], // near underflow 1900 [-0x1.7p+6L, 0x0.026a42p-126L ], // near underflow - subnormal 1901 [-0x1.9cp+6L, 0x0.000002p-126L ], // ditto 1902 [-0x1.ap+6L, 0 ], // close underflow 1903 [-0x1p+30L, 0 ], // far underflow 1904 ]; 1905 } 1906 else 1907 static assert(0, "No exp() tests for real type!"); 1908 1909 const minEqualMantissaBits = T.mant_dig - 2; 1910 T x; 1911 version (IeeeFlagsSupport) IeeeFlags f; 1912 foreach (ref pair; exptestpoints) 1913 { 1914 version (IeeeFlagsSupport) resetIeeeFlags(); 1915 x = exp(pair[0]); 1916 //printf("exp(%La) = %La, should be %La\n", cast(real) pair[0], cast(real) x, cast(real) pair[1]); 1917 assert(feqrel(x, pair[1]) >= minEqualMantissaBits); 1918 } 1919 1920 // Ideally, exp(0) would not set the inexact flag. 1921 // Unfortunately, fldl2e sets it! 1922 // So it's not realistic to avoid setting it. 1923 assert(exp(cast(T) 0.0) == 1.0); 1924 1925 // NaN propagation. Doesn't set flags, bcos was already NaN. 1926 version (IeeeFlagsSupport) 1927 { 1928 resetIeeeFlags(); 1929 x = exp(T.nan); 1930 f = ieeeFlags; 1931 assert(isIdentical(abs(x), T.nan)); 1932 assert(f.flags == 0); 1933 1934 resetIeeeFlags(); 1935 x = exp(-T.nan); 1936 f = ieeeFlags; 1937 assert(isIdentical(abs(x), T.nan)); 1938 assert(f.flags == 0); 1939 } 1940 else 1941 { 1942 x = exp(T.nan); 1943 assert(isIdentical(abs(x), T.nan)); 1944 1945 x = exp(-T.nan); 1946 assert(isIdentical(abs(x), T.nan)); 1947 } 1948 1949 x = exp(NaN(0x123)); 1950 assert(isIdentical(x, NaN(0x123))); 1951 } 1952 1953 import std.meta : AliasSeq; 1954 foreach (T; AliasSeq!(real, double, float)) 1955 testExp!T(); 1956 1957 // High resolution test (verified against GNU MPFR/Mathematica). 1958 assert(exp(0.5L) == 0x1.A612_98E1_E069_BC97_2DFE_FAB6_DF34p+0L); 1959 1960 assert(equalsDigit(exp(3.0L), E * E * E, useDigits)); 1961 } 1962 1963 /** 1964 * Calculates the value of the natural logarithm base (e) 1965 * raised to the power of x, minus 1. 1966 * 1967 * For very small x, expm1(x) is more accurate 1968 * than exp(x)-1. 1969 * 1970 * $(TABLE_SV 1971 * $(TR $(TH x) $(TH e$(SUPERSCRIPT x)-1) ) 1972 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) ) 1973 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) ) 1974 * $(TR $(TD -$(INFIN)) $(TD -1.0) ) 1975 * $(TR $(TD $(NAN)) $(TD $(NAN)) ) 1976 * ) 1977 */ 1978 real expm1(real x) @trusted pure nothrow @nogc // TODO: @safe 1979 { 1980 version (InlineAsm_X86_Any) 1981 { 1982 if (!__ctfe) 1983 return expm1Asm(x); 1984 } 1985 return expm1Impl(x); 1986 } 1987 1988 /// ditto 1989 double expm1(double x) @safe pure nothrow @nogc 1990 { 1991 return __ctfe ? cast(double) expm1(cast(real) x) : expm1Impl(x); 1992 } 1993 1994 /// ditto 1995 float expm1(float x) @safe pure nothrow @nogc 1996 { 1997 // no single-precision version in Cephes => use double precision 1998 return __ctfe ? cast(float) expm1(cast(real) x) : cast(float) expm1Impl(cast(double) x); 1999 } 2000 2001 /// 2002 @safe unittest 2003 { 2004 assert(isIdentical(expm1(0.0), 0.0)); 2005 assert(expm1(1.0).feqrel(1.71828) > 16); 2006 assert(expm1(2.0).feqrel(6.3890) > 16); 2007 } 2008 2009 version (InlineAsm_X86_Any) 2010 private real expm1Asm(real x) @trusted pure nothrow @nogc 2011 { 2012 version (D_InlineAsm_X86) 2013 { 2014 enum PARAMSIZE = (real.sizeof+3)&(0xFFFF_FFFC); // always a multiple of 4 2015 asm pure nothrow @nogc 2016 { 2017 /* expm1() for x87 80-bit reals, IEEE754-2008 conformant. 2018 * Author: Don Clugston. 2019 * 2020 * expm1(x) = 2^^(rndint(y))* 2^^(y-rndint(y)) - 1 where y = LN2*x. 2021 * = 2rndy * 2ym1 + 2rndy - 1, where 2rndy = 2^^(rndint(y)) 2022 * and 2ym1 = (2^^(y-rndint(y))-1). 2023 * If 2rndy < 0.5*real.epsilon, result is -1. 2024 * Implementation is otherwise the same as for exp2() 2025 */ 2026 naked; 2027 fld real ptr [ESP+4] ; // x 2028 mov AX, [ESP+4+8]; // AX = exponent and sign 2029 sub ESP, 12+8; // Create scratch space on the stack 2030 // [ESP,ESP+2] = scratchint 2031 // [ESP+4..+6, +8..+10, +10] = scratchreal 2032 // set scratchreal mantissa = 1.0 2033 mov dword ptr [ESP+8], 0; 2034 mov dword ptr [ESP+8+4], 0x80000000; 2035 and AX, 0x7FFF; // drop sign bit 2036 cmp AX, 0x401D; // avoid InvalidException in fist 2037 jae L_extreme; 2038 fldl2e; 2039 fmulp ST(1), ST; // y = x*log2(e) 2040 fist dword ptr [ESP]; // scratchint = rndint(y) 2041 fisub dword ptr [ESP]; // y - rndint(y) 2042 // and now set scratchreal exponent 2043 mov EAX, [ESP]; 2044 add EAX, 0x3fff; 2045 jle short L_largenegative; 2046 cmp EAX,0x8000; 2047 jge short L_largepositive; 2048 mov [ESP+8+8],AX; 2049 f2xm1; // 2ym1 = 2^^(y-rndint(y)) -1 2050 fld real ptr [ESP+8] ; // 2rndy = 2^^rndint(y) 2051 fmul ST(1), ST; // ST=2rndy, ST(1)=2rndy*2ym1 2052 fld1; 2053 fsubp ST(1), ST; // ST = 2rndy-1, ST(1) = 2rndy * 2ym1 - 1 2054 faddp ST(1), ST; // ST = 2rndy * 2ym1 + 2rndy - 1 2055 add ESP,12+8; 2056 ret PARAMSIZE; 2057 2058 L_extreme: // Extreme exponent. X is very large positive, very 2059 // large negative, infinity, or NaN. 2060 fxam; 2061 fstsw AX; 2062 test AX, 0x0400; // NaN_or_zero, but we already know x != 0 2063 jz L_was_nan; // if x is NaN, returns x 2064 test AX, 0x0200; 2065 jnz L_largenegative; 2066 L_largepositive: 2067 // Set scratchreal = real.max. 2068 // squaring it will create infinity, and set overflow flag. 2069 mov word ptr [ESP+8+8], 0x7FFE; 2070 fstp ST(0); 2071 fld real ptr [ESP+8]; // load scratchreal 2072 fmul ST(0), ST; // square it, to create havoc! 2073 L_was_nan: 2074 add ESP,12+8; 2075 ret PARAMSIZE; 2076 L_largenegative: 2077 fstp ST(0); 2078 fld1; 2079 fchs; // return -1. Underflow flag is not set. 2080 add ESP,12+8; 2081 ret PARAMSIZE; 2082 } 2083 } 2084 else version (D_InlineAsm_X86_64) 2085 { 2086 asm pure nothrow @nogc 2087 { 2088 naked; 2089 } 2090 version (Win64) 2091 { 2092 asm pure nothrow @nogc 2093 { 2094 fld real ptr [RCX]; // x 2095 mov AX,[RCX+8]; // AX = exponent and sign 2096 } 2097 } 2098 else 2099 { 2100 asm pure nothrow @nogc 2101 { 2102 fld real ptr [RSP+8]; // x 2103 mov AX,[RSP+8+8]; // AX = exponent and sign 2104 } 2105 } 2106 asm pure nothrow @nogc 2107 { 2108 /* expm1() for x87 80-bit reals, IEEE754-2008 conformant. 2109 * Author: Don Clugston. 2110 * 2111 * expm1(x) = 2^(rndint(y))* 2^(y-rndint(y)) - 1 where y = LN2*x. 2112 * = 2rndy * 2ym1 + 2rndy - 1, where 2rndy = 2^(rndint(y)) 2113 * and 2ym1 = (2^(y-rndint(y))-1). 2114 * If 2rndy < 0.5*real.epsilon, result is -1. 2115 * Implementation is otherwise the same as for exp2() 2116 */ 2117 sub RSP, 24; // Create scratch space on the stack 2118 // [RSP,RSP+2] = scratchint 2119 // [RSP+4..+6, +8..+10, +10] = scratchreal 2120 // set scratchreal mantissa = 1.0 2121 mov dword ptr [RSP+8], 0; 2122 mov dword ptr [RSP+8+4], 0x80000000; 2123 and AX, 0x7FFF; // drop sign bit 2124 cmp AX, 0x401D; // avoid InvalidException in fist 2125 jae L_extreme; 2126 fldl2e; 2127 fmul ; // y = x*log2(e) 2128 fist dword ptr [RSP]; // scratchint = rndint(y) 2129 fisub dword ptr [RSP]; // y - rndint(y) 2130 // and now set scratchreal exponent 2131 mov EAX, [RSP]; 2132 add EAX, 0x3fff; 2133 jle short L_largenegative; 2134 cmp EAX,0x8000; 2135 jge short L_largepositive; 2136 mov [RSP+8+8],AX; 2137 f2xm1; // 2^(y-rndint(y)) -1 2138 fld real ptr [RSP+8] ; // 2^rndint(y) 2139 fmul ST(1), ST; 2140 fld1; 2141 fsubp ST(1), ST; 2142 fadd; 2143 add RSP,24; 2144 ret; 2145 2146 L_extreme: // Extreme exponent. X is very large positive, very 2147 // large negative, infinity, or NaN. 2148 fxam; 2149 fstsw AX; 2150 test AX, 0x0400; // NaN_or_zero, but we already know x != 0 2151 jz L_was_nan; // if x is NaN, returns x 2152 test AX, 0x0200; 2153 jnz L_largenegative; 2154 L_largepositive: 2155 // Set scratchreal = real.max. 2156 // squaring it will create infinity, and set overflow flag. 2157 mov word ptr [RSP+8+8], 0x7FFE; 2158 fstp ST(0); 2159 fld real ptr [RSP+8]; // load scratchreal 2160 fmul ST(0), ST; // square it, to create havoc! 2161 L_was_nan: 2162 add RSP,24; 2163 ret; 2164 2165 L_largenegative: 2166 fstp ST(0); 2167 fld1; 2168 fchs; // return -1. Underflow flag is not set. 2169 add RSP,24; 2170 ret; 2171 } 2172 } 2173 else 2174 static assert(0); 2175 } 2176 2177 private T expm1Impl(T)(T x) @safe pure nothrow @nogc 2178 { 2179 // Coefficients for exp(x) - 1 and overflow/underflow limits. 2180 enum realFormat = floatTraits!T.realFormat; 2181 static if (realFormat == RealFormat.ieeeQuadruple) 2182 { 2183 static immutable T[8] P = [ 2184 2.943520915569954073888921213330863757240E8L, 2185 -5.722847283900608941516165725053359168840E7L, 2186 8.944630806357575461578107295909719817253E6L, 2187 -7.212432713558031519943281748462837065308E5L, 2188 4.578962475841642634225390068461943438441E4L, 2189 -1.716772506388927649032068540558788106762E3L, 2190 4.401308817383362136048032038528753151144E1L, 2191 -4.888737542888633647784737721812546636240E-1L 2192 ]; 2193 2194 static immutable T[9] Q = [ 2195 1.766112549341972444333352727998584753865E9L, 2196 -7.848989743695296475743081255027098295771E8L, 2197 1.615869009634292424463780387327037251069E8L, 2198 -2.019684072836541751428967854947019415698E7L, 2199 1.682912729190313538934190635536631941751E6L, 2200 -9.615511549171441430850103489315371768998E4L, 2201 3.697714952261803935521187272204485251835E3L, 2202 -8.802340681794263968892934703309274564037E1L, 2203 1.0 2204 ]; 2205 2206 enum T OF = 1.1356523406294143949491931077970764891253E4L; 2207 enum T UF = -1.143276959615573793352782661133116431383730e4L; 2208 } 2209 else static if (realFormat == RealFormat.ieeeExtended) 2210 { 2211 static immutable T[5] P = [ 2212 -1.586135578666346600772998894928250240826E4L, 2213 2.642771505685952966904660652518429479531E3L, 2214 -3.423199068835684263987132888286791620673E2L, 2215 1.800826371455042224581246202420972737840E1L, 2216 -5.238523121205561042771939008061958820811E-1L, 2217 ]; 2218 static immutable T[6] Q = [ 2219 -9.516813471998079611319047060563358064497E4L, 2220 3.964866271411091674556850458227710004570E4L, 2221 -7.207678383830091850230366618190187434796E3L, 2222 7.206038318724600171970199625081491823079E2L, 2223 -4.002027679107076077238836622982900945173E1L, 2224 1.0 2225 ]; 2226 2227 enum T OF = 1.1356523406294143949492E4L; 2228 enum T UF = -4.5054566736396445112120088E1L; 2229 } 2230 else static if (realFormat == RealFormat.ieeeDouble) 2231 { 2232 static immutable T[3] P = [ 2233 9.9999999999999999991025E-1, 2234 3.0299440770744196129956E-2, 2235 1.2617719307481059087798E-4, 2236 ]; 2237 static immutable T[4] Q = [ 2238 2.0000000000000000000897E0, 2239 2.2726554820815502876593E-1, 2240 2.5244834034968410419224E-3, 2241 3.0019850513866445504159E-6, 2242 ]; 2243 } 2244 else 2245 static assert(0, "no coefficients for expm1()"); 2246 2247 static if (realFormat == RealFormat.ieeeDouble) // special case for double precision 2248 { 2249 if (x < -0.5 || x > 0.5) 2250 return exp(x) - 1.0; 2251 if (x == 0.0) 2252 return x; 2253 2254 const T xx = x * x; 2255 x = x * poly(xx, P); 2256 x = x / (poly(xx, Q) - x); 2257 return x + x; 2258 } 2259 else 2260 { 2261 // C1 + C2 = LN2. 2262 enum T C1 = 6.9314575195312500000000E-1L; 2263 enum T C2 = 1.428606820309417232121458176568075500134E-6L; 2264 2265 // Special cases. 2266 if (x > OF) 2267 return real.infinity; 2268 if (x == cast(T) 0.0) 2269 return x; 2270 if (x < UF) 2271 return -1.0; 2272 2273 // Express x = LN2 (n + remainder), remainder not exceeding 1/2. 2274 int n = cast(int) floor((cast(T) 0.5) + x / cast(T) LN2); 2275 x -= n * C1; 2276 x -= n * C2; 2277 2278 // Rational approximation: 2279 // exp(x) - 1 = x + 0.5 x^^2 + x^^3 P(x) / Q(x) 2280 T px = x * poly(x, P); 2281 T qx = poly(x, Q); 2282 const T xx = x * x; 2283 qx = x + ((cast(T) 0.5) * xx + xx * px / qx); 2284 2285 // We have qx = exp(remainder LN2) - 1, so: 2286 // exp(x) - 1 = 2^^n (qx + 1) - 1 = 2^^n qx + 2^^n - 1. 2287 px = ldexp(cast(T) 1.0, n); 2288 x = px * qx + (px - cast(T) 1.0); 2289 2290 return x; 2291 } 2292 } 2293 2294 @safe @nogc nothrow unittest 2295 { 2296 static void testExpm1(T)() 2297 { 2298 // NaN 2299 assert(isNaN(expm1(cast(T) T.nan))); 2300 2301 static immutable T[] xs = [ -2, -0.75, -0.3, 0.0, 0.1, 0.2, 0.5, 1.0 ]; 2302 foreach (x; xs) 2303 { 2304 const T e = expm1(x); 2305 const T r = exp(x) - 1; 2306 2307 //printf("expm1(%Lg) = %Lg, should approximately be %Lg\n", cast(real) x, cast(real) e, cast(real) r); 2308 assert(approxEqual(r, e)); 2309 } 2310 } 2311 2312 import std.meta : AliasSeq; 2313 foreach (T; AliasSeq!(real, double)) 2314 testExpm1!T(); 2315 } 2316 2317 /** 2318 * Calculates 2$(SUPERSCRIPT x). 2319 * 2320 * $(TABLE_SV 2321 * $(TR $(TH x) $(TH exp2(x)) ) 2322 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) ) 2323 * $(TR $(TD -$(INFIN)) $(TD +0.0) ) 2324 * $(TR $(TD $(NAN)) $(TD $(NAN)) ) 2325 * ) 2326 */ 2327 real exp2(real x) @nogc @trusted pure nothrow // TODO: @safe 2328 { 2329 version (InlineAsm_X86_Any) 2330 { 2331 if (!__ctfe) 2332 return exp2Asm(x); 2333 } 2334 return exp2Impl(x); 2335 } 2336 2337 /// ditto 2338 double exp2(double x) @nogc @safe pure nothrow { return __ctfe ? cast(double) exp2(cast(real) x) : exp2Impl(x); } 2339 2340 /// ditto 2341 float exp2(float x) @nogc @safe pure nothrow { return __ctfe ? cast(float) exp2(cast(real) x) : exp2Impl(x); } 2342 2343 /// 2344 @safe unittest 2345 { 2346 assert(isIdentical(exp2(0.0), 1.0)); 2347 assert(exp2(2.0).feqrel(4.0) > 16); 2348 assert(exp2(8.0).feqrel(256.0) > 16); 2349 } 2350 2351 @safe unittest 2352 { 2353 version (CRuntime_Microsoft) {} else // aexp2/exp2f/exp2l not implemented 2354 { 2355 assert( core.stdc.math.exp2f(0.0f) == 1 ); 2356 assert( core.stdc.math.exp2 (0.0) == 1 ); 2357 assert( core.stdc.math.exp2l(0.0L) == 1 ); 2358 } 2359 } 2360 2361 version (InlineAsm_X86_Any) 2362 private real exp2Asm(real x) @nogc @trusted pure nothrow 2363 { 2364 version (D_InlineAsm_X86) 2365 { 2366 enum PARAMSIZE = (real.sizeof+3)&(0xFFFF_FFFC); // always a multiple of 4 2367 2368 asm pure nothrow @nogc 2369 { 2370 /* exp2() for x87 80-bit reals, IEEE754-2008 conformant. 2371 * Author: Don Clugston. 2372 * 2373 * exp2(x) = 2^^(rndint(x))* 2^^(y-rndint(x)) 2374 * The trick for high performance is to avoid the fscale(28cycles on core2), 2375 * frndint(19 cycles), leaving f2xm1(19 cycles) as the only slow instruction. 2376 * 2377 * We can do frndint by using fist. BUT we can't use it for huge numbers, 2378 * because it will set the Invalid Operation flag if overflow or NaN occurs. 2379 * Fortunately, whenever this happens the result would be zero or infinity. 2380 * 2381 * We can perform fscale by directly poking into the exponent. BUT this doesn't 2382 * work for the (very rare) cases where the result is subnormal. So we fall back 2383 * to the slow method in that case. 2384 */ 2385 naked; 2386 fld real ptr [ESP+4] ; // x 2387 mov AX, [ESP+4+8]; // AX = exponent and sign 2388 sub ESP, 12+8; // Create scratch space on the stack 2389 // [ESP,ESP+2] = scratchint 2390 // [ESP+4..+6, +8..+10, +10] = scratchreal 2391 // set scratchreal mantissa = 1.0 2392 mov dword ptr [ESP+8], 0; 2393 mov dword ptr [ESP+8+4], 0x80000000; 2394 and AX, 0x7FFF; // drop sign bit 2395 cmp AX, 0x401D; // avoid InvalidException in fist 2396 jae L_extreme; 2397 fist dword ptr [ESP]; // scratchint = rndint(x) 2398 fisub dword ptr [ESP]; // x - rndint(x) 2399 // and now set scratchreal exponent 2400 mov EAX, [ESP]; 2401 add EAX, 0x3fff; 2402 jle short L_subnormal; 2403 cmp EAX,0x8000; 2404 jge short L_overflow; 2405 mov [ESP+8+8],AX; 2406 L_normal: 2407 f2xm1; 2408 fld1; 2409 faddp ST(1), ST; // 2^^(x-rndint(x)) 2410 fld real ptr [ESP+8] ; // 2^^rndint(x) 2411 add ESP,12+8; 2412 fmulp ST(1), ST; 2413 ret PARAMSIZE; 2414 2415 L_subnormal: 2416 // Result will be subnormal. 2417 // In this rare case, the simple poking method doesn't work. 2418 // The speed doesn't matter, so use the slow fscale method. 2419 fild dword ptr [ESP]; // scratchint 2420 fld1; 2421 fscale; 2422 fstp real ptr [ESP+8]; // scratchreal = 2^^scratchint 2423 fstp ST(0); // drop scratchint 2424 jmp L_normal; 2425 2426 L_extreme: // Extreme exponent. X is very large positive, very 2427 // large negative, infinity, or NaN. 2428 fxam; 2429 fstsw AX; 2430 test AX, 0x0400; // NaN_or_zero, but we already know x != 0 2431 jz L_was_nan; // if x is NaN, returns x 2432 // set scratchreal = real.min_normal 2433 // squaring it will return 0, setting underflow flag 2434 mov word ptr [ESP+8+8], 1; 2435 test AX, 0x0200; 2436 jnz L_waslargenegative; 2437 L_overflow: 2438 // Set scratchreal = real.max. 2439 // squaring it will create infinity, and set overflow flag. 2440 mov word ptr [ESP+8+8], 0x7FFE; 2441 L_waslargenegative: 2442 fstp ST(0); 2443 fld real ptr [ESP+8]; // load scratchreal 2444 fmul ST(0), ST; // square it, to create havoc! 2445 L_was_nan: 2446 add ESP,12+8; 2447 ret PARAMSIZE; 2448 } 2449 } 2450 else version (D_InlineAsm_X86_64) 2451 { 2452 asm pure nothrow @nogc 2453 { 2454 naked; 2455 } 2456 version (Win64) 2457 { 2458 asm pure nothrow @nogc 2459 { 2460 fld real ptr [RCX]; // x 2461 mov AX,[RCX+8]; // AX = exponent and sign 2462 } 2463 } 2464 else 2465 { 2466 asm pure nothrow @nogc 2467 { 2468 fld real ptr [RSP+8]; // x 2469 mov AX,[RSP+8+8]; // AX = exponent and sign 2470 } 2471 } 2472 asm pure nothrow @nogc 2473 { 2474 /* exp2() for x87 80-bit reals, IEEE754-2008 conformant. 2475 * Author: Don Clugston. 2476 * 2477 * exp2(x) = 2^(rndint(x))* 2^(y-rndint(x)) 2478 * The trick for high performance is to avoid the fscale(28cycles on core2), 2479 * frndint(19 cycles), leaving f2xm1(19 cycles) as the only slow instruction. 2480 * 2481 * We can do frndint by using fist. BUT we can't use it for huge numbers, 2482 * because it will set the Invalid Operation flag is overflow or NaN occurs. 2483 * Fortunately, whenever this happens the result would be zero or infinity. 2484 * 2485 * We can perform fscale by directly poking into the exponent. BUT this doesn't 2486 * work for the (very rare) cases where the result is subnormal. So we fall back 2487 * to the slow method in that case. 2488 */ 2489 sub RSP, 24; // Create scratch space on the stack 2490 // [RSP,RSP+2] = scratchint 2491 // [RSP+4..+6, +8..+10, +10] = scratchreal 2492 // set scratchreal mantissa = 1.0 2493 mov dword ptr [RSP+8], 0; 2494 mov dword ptr [RSP+8+4], 0x80000000; 2495 and AX, 0x7FFF; // drop sign bit 2496 cmp AX, 0x401D; // avoid InvalidException in fist 2497 jae L_extreme; 2498 fist dword ptr [RSP]; // scratchint = rndint(x) 2499 fisub dword ptr [RSP]; // x - rndint(x) 2500 // and now set scratchreal exponent 2501 mov EAX, [RSP]; 2502 add EAX, 0x3fff; 2503 jle short L_subnormal; 2504 cmp EAX,0x8000; 2505 jge short L_overflow; 2506 mov [RSP+8+8],AX; 2507 L_normal: 2508 f2xm1; 2509 fld1; 2510 fadd; // 2^(x-rndint(x)) 2511 fld real ptr [RSP+8] ; // 2^rndint(x) 2512 add RSP,24; 2513 fmulp ST(1), ST; 2514 ret; 2515 2516 L_subnormal: 2517 // Result will be subnormal. 2518 // In this rare case, the simple poking method doesn't work. 2519 // The speed doesn't matter, so use the slow fscale method. 2520 fild dword ptr [RSP]; // scratchint 2521 fld1; 2522 fscale; 2523 fstp real ptr [RSP+8]; // scratchreal = 2^scratchint 2524 fstp ST(0); // drop scratchint 2525 jmp L_normal; 2526 2527 L_extreme: // Extreme exponent. X is very large positive, very 2528 // large negative, infinity, or NaN. 2529 fxam; 2530 fstsw AX; 2531 test AX, 0x0400; // NaN_or_zero, but we already know x != 0 2532 jz L_was_nan; // if x is NaN, returns x 2533 // set scratchreal = real.min 2534 // squaring it will return 0, setting underflow flag 2535 mov word ptr [RSP+8+8], 1; 2536 test AX, 0x0200; 2537 jnz L_waslargenegative; 2538 L_overflow: 2539 // Set scratchreal = real.max. 2540 // squaring it will create infinity, and set overflow flag. 2541 mov word ptr [RSP+8+8], 0x7FFE; 2542 L_waslargenegative: 2543 fstp ST(0); 2544 fld real ptr [RSP+8]; // load scratchreal 2545 fmul ST(0), ST; // square it, to create havoc! 2546 L_was_nan: 2547 add RSP,24; 2548 ret; 2549 } 2550 } 2551 else 2552 static assert(0); 2553 } 2554 2555 private T exp2Impl(T)(T x) @nogc @safe pure nothrow 2556 { 2557 // Coefficients for exp2(x) 2558 enum realFormat = floatTraits!T.realFormat; 2559 static if (realFormat == RealFormat.ieeeQuadruple) 2560 { 2561 static immutable T[5] P = [ 2562 9.079594442980146270952372234833529694788E12L, 2563 1.530625323728429161131811299626419117557E11L, 2564 5.677513871931844661829755443994214173883E8L, 2565 6.185032670011643762127954396427045467506E5L, 2566 1.587171580015525194694938306936721666031E2L 2567 ]; 2568 2569 static immutable T[6] Q = [ 2570 2.619817175234089411411070339065679229869E13L, 2571 1.490560994263653042761789432690793026977E12L, 2572 1.092141473886177435056423606755843616331E10L, 2573 2.186249607051644894762167991800811827835E7L, 2574 1.236602014442099053716561665053645270207E4L, 2575 1.0 2576 ]; 2577 } 2578 else static if (realFormat == RealFormat.ieeeExtended) 2579 { 2580 static immutable T[3] P = [ 2581 2.0803843631901852422887E6L, 2582 3.0286971917562792508623E4L, 2583 6.0614853552242266094567E1L, 2584 ]; 2585 static immutable T[4] Q = [ 2586 6.0027204078348487957118E6L, 2587 3.2772515434906797273099E5L, 2588 1.7492876999891839021063E3L, 2589 1.0000000000000000000000E0L, 2590 ]; 2591 } 2592 else static if (realFormat == RealFormat.ieeeDouble) 2593 { 2594 static immutable T[3] P = [ 2595 1.51390680115615096133E3L, 2596 2.02020656693165307700E1L, 2597 2.30933477057345225087E-2L, 2598 ]; 2599 static immutable T[3] Q = [ 2600 4.36821166879210612817E3L, 2601 2.33184211722314911771E2L, 2602 1.00000000000000000000E0L, 2603 ]; 2604 } 2605 else static if (realFormat == RealFormat.ieeeSingle) 2606 { 2607 static immutable T[6] P = [ 2608 6.931472028550421E-001L, 2609 2.402264791363012E-001L, 2610 5.550332471162809E-002L, 2611 9.618437357674640E-003L, 2612 1.339887440266574E-003L, 2613 1.535336188319500E-004L, 2614 ]; 2615 } 2616 else 2617 static assert(0, "no coefficients for exp2()"); 2618 2619 // Overflow and Underflow limits. 2620 enum T OF = T.max_exp; 2621 enum T UF = T.min_exp - 1; 2622 2623 // Special cases. 2624 if (isNaN(x)) 2625 return x; 2626 if (x > OF) 2627 return real.infinity; 2628 if (x < UF) 2629 return 0.0; 2630 2631 static if (realFormat == RealFormat.ieeeSingle) // special case for single precision 2632 { 2633 // The following is necessary because range reduction blows up. 2634 if (x == 0.0f) 2635 return 1.0f; 2636 2637 // Separate into integer and fractional parts. 2638 const T i = floor(x); 2639 int n = cast(int) i; 2640 x -= i; 2641 if (x > 0.5f) 2642 { 2643 n += 1; 2644 x -= 1.0f; 2645 } 2646 2647 // Rational approximation: 2648 // exp2(x) = 1.0 + x P(x) 2649 x = 1.0f + x * poly(x, P); 2650 } 2651 else 2652 { 2653 // Separate into integer and fractional parts. 2654 const T i = floor(x + cast(T) 0.5); 2655 int n = cast(int) i; 2656 x -= i; 2657 2658 // Rational approximation: 2659 // exp2(x) = 1.0 + 2x P(x^^2) / (Q(x^^2) - P(x^^2)) 2660 const T xx = x * x; 2661 const T px = x * poly(xx, P); 2662 x = px / (poly(xx, Q) - px); 2663 x = (cast(T) 1.0) + (cast(T) 2.0) * x; 2664 } 2665 2666 // Scale by power of 2. 2667 x = ldexp(x, n); 2668 2669 return x; 2670 } 2671 2672 @safe @nogc nothrow unittest 2673 { 2674 assert(feqrel(exp2(0.5L), SQRT2) >= real.mant_dig -1); 2675 assert(exp2(8.0L) == 256.0); 2676 assert(exp2(-9.0L)== 1.0L/512.0); 2677 2678 static void testExp2(T)() 2679 { 2680 // NaN 2681 const T specialNaN = NaN(0x0123L); 2682 assert(isIdentical(exp2(specialNaN), specialNaN)); 2683 2684 // over-/underflow 2685 enum T OF = T.max_exp; 2686 enum T UF = T.min_exp - T.mant_dig; 2687 assert(isIdentical(exp2(OF + 1), cast(T) T.infinity)); 2688 assert(isIdentical(exp2(UF - 1), cast(T) 0.0)); 2689 2690 static immutable T[2][] vals = 2691 [ 2692 // x, exp2(x) 2693 [ 0.0, 1.0 ], 2694 [ -0.0, 1.0 ], 2695 [ 0.5, SQRT2 ], 2696 [ 8.0, 256.0 ], 2697 [ -9.0, 1.0 / 512 ], 2698 ]; 2699 2700 foreach (ref val; vals) 2701 { 2702 const T x = val[0]; 2703 const T r = val[1]; 2704 const T e = exp2(x); 2705 2706 //printf("exp2(%Lg) = %Lg, should be %Lg\n", cast(real) x, cast(real) e, cast(real) r); 2707 assert(approxEqual(r, e)); 2708 } 2709 } 2710 2711 import std.meta : AliasSeq; 2712 foreach (T; AliasSeq!(real, double, float)) 2713 testExp2!T(); 2714 } 2715 2716 /********************************************************************* 2717 * Separate floating point value into significand and exponent. 2718 * 2719 * Returns: 2720 * Calculate and return $(I x) and $(I exp) such that 2721 * value =$(I x)*2$(SUPERSCRIPT exp) and 2722 * .5 $(LT)= |$(I x)| $(LT) 1.0 2723 * 2724 * $(I x) has same sign as value. 2725 * 2726 * $(TABLE_SV 2727 * $(TR $(TH value) $(TH returns) $(TH exp)) 2728 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD 0)) 2729 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD int.max)) 2730 * $(TR $(TD -$(INFIN)) $(TD -$(INFIN)) $(TD int.min)) 2731 * $(TR $(TD $(PLUSMN)$(NAN)) $(TD $(PLUSMN)$(NAN)) $(TD int.min)) 2732 * ) 2733 */ 2734 T frexp(T)(const T value, out int exp) @trusted pure nothrow @nogc 2735 if (isFloatingPoint!T) 2736 { 2737 if (__ctfe) 2738 { 2739 // Handle special cases. 2740 if (value == 0) { exp = 0; return value; } 2741 if (value == T.infinity) { exp = int.max; return value; } 2742 if (value == -T.infinity || value != value) { exp = int.min; return value; } 2743 // Handle ordinary cases. 2744 // In CTFE there is no performance advantage for having separate 2745 // paths for different floating point types. 2746 T absValue = value < 0 ? -value : value; 2747 int expCount; 2748 static if (T.mant_dig > double.mant_dig) 2749 { 2750 for (; absValue >= 0x1.0p+1024L; absValue *= 0x1.0p-1024L) 2751 expCount += 1024; 2752 for (; absValue < 0x1.0p-1021L; absValue *= 0x1.0p+1021L) 2753 expCount -= 1021; 2754 } 2755 const double dval = cast(double) absValue; 2756 int dexp = cast(int) (((*cast(const long*) &dval) >>> 52) & 0x7FF) + double.min_exp - 2; 2757 dexp++; 2758 expCount += dexp; 2759 absValue *= 2.0 ^^ -dexp; 2760 // If the original value was subnormal or if it was a real 2761 // then absValue can still be outside the [0.5, 1.0) range. 2762 if (absValue < 0.5) 2763 { 2764 assert(T.mant_dig > double.mant_dig || isSubnormal(value)); 2765 do 2766 { 2767 absValue += absValue; 2768 expCount--; 2769 } while (absValue < 0.5); 2770 } 2771 else 2772 { 2773 assert(absValue < 1 || T.mant_dig > double.mant_dig); 2774 for (; absValue >= 1; absValue *= T(0.5)) 2775 expCount++; 2776 } 2777 exp = expCount; 2778 return value < 0 ? -absValue : absValue; 2779 } 2780 2781 Unqual!T vf = value; 2782 ushort* vu = cast(ushort*)&vf; 2783 static if (is(immutable T == immutable float)) 2784 int* vi = cast(int*)&vf; 2785 else 2786 long* vl = cast(long*)&vf; 2787 int ex; 2788 alias F = floatTraits!T; 2789 2790 ex = vu[F.EXPPOS_SHORT] & F.EXPMASK; 2791 static if (F.realFormat == RealFormat.ieeeExtended) 2792 { 2793 if (ex) 2794 { // If exponent is non-zero 2795 if (ex == F.EXPMASK) // infinity or NaN 2796 { 2797 if (*vl & 0x7FFF_FFFF_FFFF_FFFF) // NaN 2798 { 2799 *vl |= 0xC000_0000_0000_0000; // convert NaNS to NaNQ 2800 exp = int.min; 2801 } 2802 else if (vu[F.EXPPOS_SHORT] & 0x8000) // negative infinity 2803 exp = int.min; 2804 else // positive infinity 2805 exp = int.max; 2806 2807 } 2808 else 2809 { 2810 exp = ex - F.EXPBIAS; 2811 vu[F.EXPPOS_SHORT] = (0x8000 & vu[F.EXPPOS_SHORT]) | 0x3FFE; 2812 } 2813 } 2814 else if (!*vl) 2815 { 2816 // vf is +-0.0 2817 exp = 0; 2818 } 2819 else 2820 { 2821 // subnormal 2822 2823 vf *= F.RECIP_EPSILON; 2824 ex = vu[F.EXPPOS_SHORT] & F.EXPMASK; 2825 exp = ex - F.EXPBIAS - T.mant_dig + 1; 2826 vu[F.EXPPOS_SHORT] = ((-1 - F.EXPMASK) & vu[F.EXPPOS_SHORT]) | 0x3FFE; 2827 } 2828 return vf; 2829 } 2830 else static if (F.realFormat == RealFormat.ieeeQuadruple) 2831 { 2832 if (ex) // If exponent is non-zero 2833 { 2834 if (ex == F.EXPMASK) 2835 { 2836 // infinity or NaN 2837 if (vl[MANTISSA_LSB] | 2838 (vl[MANTISSA_MSB] & 0x0000_FFFF_FFFF_FFFF)) // NaN 2839 { 2840 // convert NaNS to NaNQ 2841 vl[MANTISSA_MSB] |= 0x0000_8000_0000_0000; 2842 exp = int.min; 2843 } 2844 else if (vu[F.EXPPOS_SHORT] & 0x8000) // negative infinity 2845 exp = int.min; 2846 else // positive infinity 2847 exp = int.max; 2848 } 2849 else 2850 { 2851 exp = ex - F.EXPBIAS; 2852 vu[F.EXPPOS_SHORT] = F.EXPBIAS | (0x8000 & vu[F.EXPPOS_SHORT]); 2853 } 2854 } 2855 else if ((vl[MANTISSA_LSB] | 2856 (vl[MANTISSA_MSB] & 0x0000_FFFF_FFFF_FFFF)) == 0) 2857 { 2858 // vf is +-0.0 2859 exp = 0; 2860 } 2861 else 2862 { 2863 // subnormal 2864 vf *= F.RECIP_EPSILON; 2865 ex = vu[F.EXPPOS_SHORT] & F.EXPMASK; 2866 exp = ex - F.EXPBIAS - T.mant_dig + 1; 2867 vu[F.EXPPOS_SHORT] = F.EXPBIAS | (0x8000 & vu[F.EXPPOS_SHORT]); 2868 } 2869 return vf; 2870 } 2871 else static if (F.realFormat == RealFormat.ieeeDouble) 2872 { 2873 if (ex) // If exponent is non-zero 2874 { 2875 if (ex == F.EXPMASK) // infinity or NaN 2876 { 2877 if (*vl == 0x7FF0_0000_0000_0000) // positive infinity 2878 { 2879 exp = int.max; 2880 } 2881 else if (*vl == 0xFFF0_0000_0000_0000) // negative infinity 2882 exp = int.min; 2883 else 2884 { // NaN 2885 *vl |= 0x0008_0000_0000_0000; // convert NaNS to NaNQ 2886 exp = int.min; 2887 } 2888 } 2889 else 2890 { 2891 exp = (ex - F.EXPBIAS) >> 4; 2892 vu[F.EXPPOS_SHORT] = cast(ushort)((0x800F & vu[F.EXPPOS_SHORT]) | 0x3FE0); 2893 } 2894 } 2895 else if (!(*vl & 0x7FFF_FFFF_FFFF_FFFF)) 2896 { 2897 // vf is +-0.0 2898 exp = 0; 2899 } 2900 else 2901 { 2902 // subnormal 2903 vf *= F.RECIP_EPSILON; 2904 ex = vu[F.EXPPOS_SHORT] & F.EXPMASK; 2905 exp = ((ex - F.EXPBIAS) >> 4) - T.mant_dig + 1; 2906 vu[F.EXPPOS_SHORT] = 2907 cast(ushort)(((-1 - F.EXPMASK) & vu[F.EXPPOS_SHORT]) | 0x3FE0); 2908 } 2909 return vf; 2910 } 2911 else static if (F.realFormat == RealFormat.ieeeSingle) 2912 { 2913 if (ex) // If exponent is non-zero 2914 { 2915 if (ex == F.EXPMASK) // infinity or NaN 2916 { 2917 if (*vi == 0x7F80_0000) // positive infinity 2918 { 2919 exp = int.max; 2920 } 2921 else if (*vi == 0xFF80_0000) // negative infinity 2922 exp = int.min; 2923 else 2924 { // NaN 2925 *vi |= 0x0040_0000; // convert NaNS to NaNQ 2926 exp = int.min; 2927 } 2928 } 2929 else 2930 { 2931 exp = (ex - F.EXPBIAS) >> 7; 2932 vu[F.EXPPOS_SHORT] = cast(ushort)((0x807F & vu[F.EXPPOS_SHORT]) | 0x3F00); 2933 } 2934 } 2935 else if (!(*vi & 0x7FFF_FFFF)) 2936 { 2937 // vf is +-0.0 2938 exp = 0; 2939 } 2940 else 2941 { 2942 // subnormal 2943 vf *= F.RECIP_EPSILON; 2944 ex = vu[F.EXPPOS_SHORT] & F.EXPMASK; 2945 exp = ((ex - F.EXPBIAS) >> 7) - T.mant_dig + 1; 2946 vu[F.EXPPOS_SHORT] = 2947 cast(ushort)(((-1 - F.EXPMASK) & vu[F.EXPPOS_SHORT]) | 0x3F00); 2948 } 2949 return vf; 2950 } 2951 else // static if (F.realFormat == RealFormat.ibmExtended) 2952 { 2953 assert(0, "frexp not implemented"); 2954 } 2955 } 2956 2957 /// 2958 @safe unittest 2959 { 2960 int exp; 2961 real mantissa = frexp(123.456L, exp); 2962 2963 assert(approxEqual(mantissa * pow(2.0L, cast(real) exp), 123.456L)); 2964 2965 assert(frexp(-real.nan, exp) && exp == int.min); 2966 assert(frexp(real.nan, exp) && exp == int.min); 2967 assert(frexp(-real.infinity, exp) == -real.infinity && exp == int.min); 2968 assert(frexp(real.infinity, exp) == real.infinity && exp == int.max); 2969 assert(frexp(-0.0, exp) == -0.0 && exp == 0); 2970 assert(frexp(0.0, exp) == 0.0 && exp == 0); 2971 } 2972 2973 @safe @nogc nothrow unittest 2974 { 2975 int exp; 2976 real mantissa = frexp(123.456L, exp); 2977 2978 // check if values are equal to 19 decimal digits of precision 2979 assert(equalsDigit(mantissa * pow(2.0L, cast(real) exp), 123.456L, 19)); 2980 } 2981 2982 @safe unittest 2983 { 2984 import std.meta : AliasSeq; 2985 import std.typecons : tuple, Tuple; 2986 2987 static foreach (T; AliasSeq!(real, double, float)) 2988 {{ 2989 Tuple!(T, T, int)[] vals = // x,frexp,exp 2990 [ 2991 tuple(T(0.0), T( 0.0 ), 0), 2992 tuple(T(-0.0), T( -0.0), 0), 2993 tuple(T(1.0), T( .5 ), 1), 2994 tuple(T(-1.0), T( -.5 ), 1), 2995 tuple(T(2.0), T( .5 ), 2), 2996 tuple(T(float.min_normal/2.0f), T(.5), -126), 2997 tuple(T.infinity, T.infinity, int.max), 2998 tuple(-T.infinity, -T.infinity, int.min), 2999 tuple(T.nan, T.nan, int.min), 3000 tuple(-T.nan, -T.nan, int.min), 3001 3002 // https://issues.dlang.org/show_bug.cgi?id=16026: 3003 tuple(3 * (T.min_normal * T.epsilon), T( .75), (T.min_exp - T.mant_dig) + 2) 3004 ]; 3005 3006 foreach (elem; vals) 3007 { 3008 T x = elem[0]; 3009 T e = elem[1]; 3010 int exp = elem[2]; 3011 int eptr; 3012 T v = frexp(x, eptr); 3013 assert(isIdentical(e, v)); 3014 assert(exp == eptr); 3015 3016 } 3017 3018 static if (floatTraits!(T).realFormat == RealFormat.ieeeExtended) 3019 { 3020 static T[3][] extendedvals = [ // x,frexp,exp 3021 [0x1.a5f1c2eb3fe4efp+73L, 0x1.A5F1C2EB3FE4EFp-1L, 74], // normal 3022 [0x1.fa01712e8f0471ap-1064L, 0x1.fa01712e8f0471ap-1L, -1063], 3023 [T.min_normal, .5, -16381], 3024 [T.min_normal/2.0L, .5, -16382] // subnormal 3025 ]; 3026 foreach (elem; extendedvals) 3027 { 3028 T x = elem[0]; 3029 T e = elem[1]; 3030 int exp = cast(int) elem[2]; 3031 int eptr; 3032 T v = frexp(x, eptr); 3033 assert(isIdentical(e, v)); 3034 assert(exp == eptr); 3035 3036 } 3037 } 3038 }} 3039 3040 // CTFE 3041 alias CtfeFrexpResult= Tuple!(real, int); 3042 static CtfeFrexpResult ctfeFrexp(T)(const T value) 3043 { 3044 int exp; 3045 auto significand = frexp(value, exp); 3046 return CtfeFrexpResult(significand, exp); 3047 } 3048 static foreach (T; AliasSeq!(real, double, float)) 3049 {{ 3050 enum Tuple!(T, T, int)[] vals = // x,frexp,exp 3051 [ 3052 tuple(T(0.0), T( 0.0 ), 0), 3053 tuple(T(-0.0), T( -0.0), 0), 3054 tuple(T(1.0), T( .5 ), 1), 3055 tuple(T(-1.0), T( -.5 ), 1), 3056 tuple(T(2.0), T( .5 ), 2), 3057 tuple(T(float.min_normal/2.0f), T(.5), -126), 3058 tuple(T.infinity, T.infinity, int.max), 3059 tuple(-T.infinity, -T.infinity, int.min), 3060 tuple(T.nan, T.nan, int.min), 3061 tuple(-T.nan, -T.nan, int.min), 3062 3063 // https://issues.dlang.org/show_bug.cgi?id=16026: 3064 tuple(3 * (T.min_normal * T.epsilon), T( .75), (T.min_exp - T.mant_dig) + 2) 3065 ]; 3066 3067 static foreach (elem; vals) 3068 { 3069 static assert(ctfeFrexp(elem[0]) is CtfeFrexpResult(elem[1], elem[2])); 3070 } 3071 3072 static if (floatTraits!(T).realFormat == RealFormat.ieeeExtended) 3073 { 3074 enum T[3][] extendedvals = [ // x,frexp,exp 3075 [0x1.a5f1c2eb3fe4efp+73L, 0x1.A5F1C2EB3FE4EFp-1L, 74], // normal 3076 [0x1.fa01712e8f0471ap-1064L, 0x1.fa01712e8f0471ap-1L, -1063], 3077 [T.min_normal, .5, -16381], 3078 [T.min_normal/2.0L, .5, -16382] // subnormal 3079 ]; 3080 static foreach (elem; extendedvals) 3081 { 3082 static assert(ctfeFrexp(elem[0]) is CtfeFrexpResult(elem[1], cast(int) elem[2])); 3083 } 3084 } 3085 }} 3086 } 3087 3088 @safe unittest 3089 { 3090 import std.meta : AliasSeq; 3091 void foo() { 3092 static foreach (T; AliasSeq!(real, double, float)) 3093 {{ 3094 int exp; 3095 const T a = 1; 3096 immutable T b = 2; 3097 auto c = frexp(a, exp); 3098 auto d = frexp(b, exp); 3099 }} 3100 } 3101 } 3102 3103 /****************************************** 3104 * Extracts the exponent of x as a signed integral value. 3105 * 3106 * If x is not a special value, the result is the same as 3107 * $(D cast(int) logb(x)). 3108 * 3109 * $(TABLE_SV 3110 * $(TR $(TH x) $(TH ilogb(x)) $(TH Range error?)) 3111 * $(TR $(TD 0) $(TD FP_ILOGB0) $(TD yes)) 3112 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD int.max) $(TD no)) 3113 * $(TR $(TD $(NAN)) $(TD FP_ILOGBNAN) $(TD no)) 3114 * ) 3115 */ 3116 int ilogb(T)(const T x) @trusted pure nothrow @nogc 3117 if (isFloatingPoint!T) 3118 { 3119 import core.bitop : bsr; 3120 alias F = floatTraits!T; 3121 3122 union floatBits 3123 { 3124 T rv; 3125 ushort[T.sizeof/2] vu; 3126 uint[T.sizeof/4] vui; 3127 static if (T.sizeof >= 8) 3128 ulong[T.sizeof/8] vul; 3129 } 3130 floatBits y = void; 3131 y.rv = x; 3132 3133 int ex = y.vu[F.EXPPOS_SHORT] & F.EXPMASK; 3134 static if (F.realFormat == RealFormat.ieeeExtended) 3135 { 3136 if (ex) 3137 { 3138 // If exponent is non-zero 3139 if (ex == F.EXPMASK) // infinity or NaN 3140 { 3141 if (y.vul[0] & 0x7FFF_FFFF_FFFF_FFFF) // NaN 3142 return FP_ILOGBNAN; 3143 else // +-infinity 3144 return int.max; 3145 } 3146 else 3147 { 3148 return ex - F.EXPBIAS - 1; 3149 } 3150 } 3151 else if (!y.vul[0]) 3152 { 3153 // vf is +-0.0 3154 return FP_ILOGB0; 3155 } 3156 else 3157 { 3158 // subnormal 3159 return ex - F.EXPBIAS - T.mant_dig + 1 + bsr(y.vul[0]); 3160 } 3161 } 3162 else static if (F.realFormat == RealFormat.ieeeQuadruple) 3163 { 3164 if (ex) // If exponent is non-zero 3165 { 3166 if (ex == F.EXPMASK) 3167 { 3168 // infinity or NaN 3169 if (y.vul[MANTISSA_LSB] | ( y.vul[MANTISSA_MSB] & 0x0000_FFFF_FFFF_FFFF)) // NaN 3170 return FP_ILOGBNAN; 3171 else // +- infinity 3172 return int.max; 3173 } 3174 else 3175 { 3176 return ex - F.EXPBIAS - 1; 3177 } 3178 } 3179 else if ((y.vul[MANTISSA_LSB] | (y.vul[MANTISSA_MSB] & 0x0000_FFFF_FFFF_FFFF)) == 0) 3180 { 3181 // vf is +-0.0 3182 return FP_ILOGB0; 3183 } 3184 else 3185 { 3186 // subnormal 3187 const ulong msb = y.vul[MANTISSA_MSB] & 0x0000_FFFF_FFFF_FFFF; 3188 const ulong lsb = y.vul[MANTISSA_LSB]; 3189 if (msb) 3190 return ex - F.EXPBIAS - T.mant_dig + 1 + bsr(msb) + 64; 3191 else 3192 return ex - F.EXPBIAS - T.mant_dig + 1 + bsr(lsb); 3193 } 3194 } 3195 else static if (F.realFormat == RealFormat.ieeeDouble) 3196 { 3197 if (ex) // If exponent is non-zero 3198 { 3199 if (ex == F.EXPMASK) // infinity or NaN 3200 { 3201 if ((y.vul[0] & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FF0_0000_0000_0000) // +- infinity 3202 return int.max; 3203 else // NaN 3204 return FP_ILOGBNAN; 3205 } 3206 else 3207 { 3208 return ((ex - F.EXPBIAS) >> 4) - 1; 3209 } 3210 } 3211 else if (!(y.vul[0] & 0x7FFF_FFFF_FFFF_FFFF)) 3212 { 3213 // vf is +-0.0 3214 return FP_ILOGB0; 3215 } 3216 else 3217 { 3218 // subnormal 3219 enum MANTISSAMASK_64 = ((cast(ulong) F.MANTISSAMASK_INT) << 32) | 0xFFFF_FFFF; 3220 return ((ex - F.EXPBIAS) >> 4) - T.mant_dig + 1 + bsr(y.vul[0] & MANTISSAMASK_64); 3221 } 3222 } 3223 else static if (F.realFormat == RealFormat.ieeeSingle) 3224 { 3225 if (ex) // If exponent is non-zero 3226 { 3227 if (ex == F.EXPMASK) // infinity or NaN 3228 { 3229 if ((y.vui[0] & 0x7FFF_FFFF) == 0x7F80_0000) // +- infinity 3230 return int.max; 3231 else // NaN 3232 return FP_ILOGBNAN; 3233 } 3234 else 3235 { 3236 return ((ex - F.EXPBIAS) >> 7) - 1; 3237 } 3238 } 3239 else if (!(y.vui[0] & 0x7FFF_FFFF)) 3240 { 3241 // vf is +-0.0 3242 return FP_ILOGB0; 3243 } 3244 else 3245 { 3246 // subnormal 3247 const uint mantissa = y.vui[0] & F.MANTISSAMASK_INT; 3248 return ((ex - F.EXPBIAS) >> 7) - T.mant_dig + 1 + bsr(mantissa); 3249 } 3250 } 3251 else // static if (F.realFormat == RealFormat.ibmExtended) 3252 { 3253 assert(0, "ilogb not implemented"); 3254 } 3255 } 3256 /// ditto 3257 int ilogb(T)(const T x) @safe pure nothrow @nogc 3258 if (isIntegral!T && isUnsigned!T) 3259 { 3260 import core.bitop : bsr; 3261 if (x == 0) 3262 return FP_ILOGB0; 3263 else 3264 { 3265 static assert(T.sizeof <= ulong.sizeof, "integer size too large for the current ilogb implementation"); 3266 return bsr(x); 3267 } 3268 } 3269 /// ditto 3270 int ilogb(T)(const T x) @safe pure nothrow @nogc 3271 if (isIntegral!T && isSigned!T) 3272 { 3273 import std.traits : Unsigned; 3274 // Note: abs(x) can not be used because the return type is not Unsigned and 3275 // the return value would be wrong for x == int.min 3276 Unsigned!T absx = x >= 0 ? x : -x; 3277 return ilogb(absx); 3278 } 3279 3280 /// 3281 @safe pure unittest 3282 { 3283 assert(ilogb(1) == 0); 3284 assert(ilogb(3) == 1); 3285 assert(ilogb(3.0) == 1); 3286 assert(ilogb(100_000_000) == 26); 3287 3288 assert(ilogb(0) == FP_ILOGB0); 3289 assert(ilogb(0.0) == FP_ILOGB0); 3290 assert(ilogb(double.nan) == FP_ILOGBNAN); 3291 assert(ilogb(double.infinity) == int.max); 3292 } 3293 3294 /** 3295 Special return values of $(LREF ilogb). 3296 */ 3297 alias FP_ILOGB0 = core.stdc.math.FP_ILOGB0; 3298 /// ditto 3299 alias FP_ILOGBNAN = core.stdc.math.FP_ILOGBNAN; 3300 3301 /// 3302 @safe pure unittest 3303 { 3304 assert(ilogb(0) == FP_ILOGB0); 3305 assert(ilogb(0.0) == FP_ILOGB0); 3306 assert(ilogb(double.nan) == FP_ILOGBNAN); 3307 } 3308 3309 @safe nothrow @nogc unittest 3310 { 3311 import std.meta : AliasSeq; 3312 import std.typecons : Tuple; 3313 static foreach (F; AliasSeq!(float, double, real)) 3314 {{ 3315 alias T = Tuple!(F, int); 3316 T[13] vals = // x, ilogb(x) 3317 [ 3318 T( F.nan , FP_ILOGBNAN ), 3319 T( -F.nan , FP_ILOGBNAN ), 3320 T( F.infinity, int.max ), 3321 T( -F.infinity, int.max ), 3322 T( 0.0 , FP_ILOGB0 ), 3323 T( -0.0 , FP_ILOGB0 ), 3324 T( 2.0 , 1 ), 3325 T( 2.0001 , 1 ), 3326 T( 1.9999 , 0 ), 3327 T( 0.5 , -1 ), 3328 T( 123.123 , 6 ), 3329 T( -123.123 , 6 ), 3330 T( 0.123 , -4 ), 3331 ]; 3332 3333 foreach (elem; vals) 3334 { 3335 assert(ilogb(elem[0]) == elem[1]); 3336 } 3337 }} 3338 3339 // min_normal and subnormals 3340 assert(ilogb(-float.min_normal) == -126); 3341 assert(ilogb(nextUp(-float.min_normal)) == -127); 3342 assert(ilogb(nextUp(-float(0.0))) == -149); 3343 assert(ilogb(-double.min_normal) == -1022); 3344 assert(ilogb(nextUp(-double.min_normal)) == -1023); 3345 assert(ilogb(nextUp(-double(0.0))) == -1074); 3346 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended) 3347 { 3348 assert(ilogb(-real.min_normal) == -16382); 3349 assert(ilogb(nextUp(-real.min_normal)) == -16383); 3350 assert(ilogb(nextUp(-real(0.0))) == -16445); 3351 } 3352 else static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) 3353 { 3354 assert(ilogb(-real.min_normal) == -1022); 3355 assert(ilogb(nextUp(-real.min_normal)) == -1023); 3356 assert(ilogb(nextUp(-real(0.0))) == -1074); 3357 } 3358 3359 // test integer types 3360 assert(ilogb(0) == FP_ILOGB0); 3361 assert(ilogb(int.max) == 30); 3362 assert(ilogb(int.min) == 31); 3363 assert(ilogb(uint.max) == 31); 3364 assert(ilogb(long.max) == 62); 3365 assert(ilogb(long.min) == 63); 3366 assert(ilogb(ulong.max) == 63); 3367 } 3368 3369 /******************************************* 3370 * Compute n * 2$(SUPERSCRIPT exp) 3371 * References: frexp 3372 */ 3373 3374 pragma(inline, true) 3375 real ldexp(real n, int exp) @safe pure nothrow @nogc { return core.math.ldexp(n, exp); } 3376 ///ditto 3377 pragma(inline, true) 3378 double ldexp(double n, int exp) @safe pure nothrow @nogc { return core.math.ldexp(n, exp); } 3379 ///ditto 3380 pragma(inline, true) 3381 float ldexp(float n, int exp) @safe pure nothrow @nogc { return core.math.ldexp(n, exp); } 3382 3383 /// 3384 @nogc @safe pure nothrow unittest 3385 { 3386 import std.meta : AliasSeq; 3387 static foreach (T; AliasSeq!(float, double, real)) 3388 {{ 3389 T r; 3390 3391 r = ldexp(3.0L, 3); 3392 assert(r == 24); 3393 3394 r = ldexp(cast(T) 3.0, cast(int) 3); 3395 assert(r == 24); 3396 3397 T n = 3.0; 3398 int exp = 3; 3399 r = ldexp(n, exp); 3400 assert(r == 24); 3401 }} 3402 } 3403 3404 @safe pure nothrow @nogc unittest 3405 { 3406 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended || 3407 floatTraits!(real).realFormat == RealFormat.ieeeQuadruple) 3408 { 3409 assert(ldexp(1.0L, -16384) == 0x1p-16384L); 3410 assert(ldexp(1.0L, -16382) == 0x1p-16382L); 3411 int x; 3412 real n = frexp(0x1p-16384L, x); 3413 assert(n == 0.5L); 3414 assert(x==-16383); 3415 assert(ldexp(n, x)==0x1p-16384L); 3416 } 3417 else static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) 3418 { 3419 assert(ldexp(1.0L, -1024) == 0x1p-1024L); 3420 assert(ldexp(1.0L, -1022) == 0x1p-1022L); 3421 int x; 3422 real n = frexp(0x1p-1024L, x); 3423 assert(n == 0.5L); 3424 assert(x==-1023); 3425 assert(ldexp(n, x)==0x1p-1024L); 3426 } 3427 else static assert(false, "Floating point type real not supported"); 3428 } 3429 3430 /* workaround https://issues.dlang.org/show_bug.cgi?id=14718 3431 float parsing depends on platform strtold 3432 @safe pure nothrow @nogc unittest 3433 { 3434 assert(ldexp(1.0, -1024) == 0x1p-1024); 3435 assert(ldexp(1.0, -1022) == 0x1p-1022); 3436 int x; 3437 double n = frexp(0x1p-1024, x); 3438 assert(n == 0.5); 3439 assert(x==-1023); 3440 assert(ldexp(n, x)==0x1p-1024); 3441 } 3442 3443 @safe pure nothrow @nogc unittest 3444 { 3445 assert(ldexp(1.0f, -128) == 0x1p-128f); 3446 assert(ldexp(1.0f, -126) == 0x1p-126f); 3447 int x; 3448 float n = frexp(0x1p-128f, x); 3449 assert(n == 0.5f); 3450 assert(x==-127); 3451 assert(ldexp(n, x)==0x1p-128f); 3452 } 3453 */ 3454 3455 @safe @nogc nothrow unittest 3456 { 3457 static real[3][] vals = // value,exp,ldexp 3458 [ 3459 [ 0, 0, 0], 3460 [ 1, 0, 1], 3461 [ -1, 0, -1], 3462 [ 1, 1, 2], 3463 [ 123, 10, 125952], 3464 [ real.max, int.max, real.infinity], 3465 [ real.max, -int.max, 0], 3466 [ real.min_normal, -int.max, 0], 3467 ]; 3468 int i; 3469 3470 for (i = 0; i < vals.length; i++) 3471 { 3472 real x = vals[i][0]; 3473 int exp = cast(int) vals[i][1]; 3474 real z = vals[i][2]; 3475 real l = ldexp(x, exp); 3476 3477 assert(equalsDigit(z, l, 7)); 3478 } 3479 3480 real function(real, int) pldexp = &ldexp; 3481 assert(pldexp != null); 3482 } 3483 3484 private 3485 { 3486 version (INLINE_YL2X) {} else 3487 { 3488 static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple) 3489 { 3490 // Coefficients for log(1 + x) = x - x**2/2 + x**3 P(x)/Q(x) 3491 static immutable real[13] logCoeffsP = [ 3492 1.313572404063446165910279910527789794488E4L, 3493 7.771154681358524243729929227226708890930E4L, 3494 2.014652742082537582487669938141683759923E5L, 3495 3.007007295140399532324943111654767187848E5L, 3496 2.854829159639697837788887080758954924001E5L, 3497 1.797628303815655343403735250238293741397E5L, 3498 7.594356839258970405033155585486712125861E4L, 3499 2.128857716871515081352991964243375186031E4L, 3500 3.824952356185897735160588078446136783779E3L, 3501 4.114517881637811823002128927449878962058E2L, 3502 2.321125933898420063925789532045674660756E1L, 3503 4.998469661968096229986658302195402690910E-1L, 3504 1.538612243596254322971797716843006400388E-6L 3505 ]; 3506 static immutable real[13] logCoeffsQ = [ 3507 3.940717212190338497730839731583397586124E4L, 3508 2.626900195321832660448791748036714883242E5L, 3509 7.777690340007566932935753241556479363645E5L, 3510 1.347518538384329112529391120390701166528E6L, 3511 1.514882452993549494932585972882995548426E6L, 3512 1.158019977462989115839826904108208787040E6L, 3513 6.132189329546557743179177159925690841200E5L, 3514 2.248234257620569139969141618556349415120E5L, 3515 5.605842085972455027590989944010492125825E4L, 3516 9.147150349299596453976674231612674085381E3L, 3517 9.104928120962988414618126155557301584078E2L, 3518 4.839208193348159620282142911143429644326E1L, 3519 1.0 3520 ]; 3521 3522 // Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2) 3523 // where z = 2(x-1)/(x+1) 3524 static immutable real[6] logCoeffsR = [ 3525 -8.828896441624934385266096344596648080902E-1L, 3526 8.057002716646055371965756206836056074715E1L, 3527 -2.024301798136027039250415126250455056397E3L, 3528 2.048819892795278657810231591630928516206E4L, 3529 -8.977257995689735303686582344659576526998E4L, 3530 1.418134209872192732479751274970992665513E5L 3531 ]; 3532 static immutable real[6] logCoeffsS = [ 3533 1.701761051846631278975701529965589676574E6L 3534 -1.332535117259762928288745111081235577029E6L, 3535 4.001557694070773974936904547424676279307E5L, 3536 -5.748542087379434595104154610899551484314E4L, 3537 3.998526750980007367835804959888064681098E3L, 3538 -1.186359407982897997337150403816839480438E2L, 3539 1.0 3540 ]; 3541 } 3542 else 3543 { 3544 // Coefficients for log(1 + x) = x - x**2/2 + x**3 P(x)/Q(x) 3545 static immutable real[7] logCoeffsP = [ 3546 2.0039553499201281259648E1L, 3547 5.7112963590585538103336E1L, 3548 6.0949667980987787057556E1L, 3549 2.9911919328553073277375E1L, 3550 6.5787325942061044846969E0L, 3551 4.9854102823193375972212E-1L, 3552 4.5270000862445199635215E-5L, 3553 ]; 3554 static immutable real[7] logCoeffsQ = [ 3555 6.0118660497603843919306E1L, 3556 2.1642788614495947685003E2L, 3557 3.0909872225312059774938E2L, 3558 2.2176239823732856465394E2L, 3559 8.3047565967967209469434E1L, 3560 1.5062909083469192043167E1L, 3561 1.0000000000000000000000E0L, 3562 ]; 3563 3564 // Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2) 3565 // where z = 2(x-1)/(x+1) 3566 static immutable real[4] logCoeffsR = [ 3567 -3.5717684488096787370998E1L, 3568 1.0777257190312272158094E1L, 3569 -7.1990767473014147232598E-1L, 3570 1.9757429581415468984296E-3L, 3571 ]; 3572 static immutable real[4] logCoeffsS = [ 3573 -4.2861221385716144629696E2L, 3574 1.9361891836232102174846E2L, 3575 -2.6201045551331104417768E1L, 3576 1.0000000000000000000000E0L, 3577 ]; 3578 } 3579 } 3580 } 3581 3582 /************************************** 3583 * Calculate the natural logarithm of x. 3584 * 3585 * $(TABLE_SV 3586 * $(TR $(TH x) $(TH log(x)) $(TH divide by 0?) $(TH invalid?)) 3587 * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) 3588 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes)) 3589 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no)) 3590 * ) 3591 */ 3592 real log(real x) @safe pure nothrow @nogc 3593 { 3594 version (INLINE_YL2X) 3595 return core.math.yl2x(x, LN2); 3596 else 3597 { 3598 // C1 + C2 = LN2. 3599 enum real C1 = 6.93145751953125E-1L; 3600 enum real C2 = 1.428606820309417232121458176568075500134E-6L; 3601 3602 // Special cases. 3603 if (isNaN(x)) 3604 return x; 3605 if (isInfinity(x) && !signbit(x)) 3606 return x; 3607 if (x == 0.0) 3608 return -real.infinity; 3609 if (x < 0.0) 3610 return real.nan; 3611 3612 // Separate mantissa from exponent. 3613 // Note, frexp is used so that denormal numbers will be handled properly. 3614 real y, z; 3615 int exp; 3616 3617 x = frexp(x, exp); 3618 3619 // Logarithm using log(x) = z + z^^3 R(z) / S(z), 3620 // where z = 2(x - 1)/(x + 1) 3621 if ((exp > 2) || (exp < -2)) 3622 { 3623 if (x < SQRT1_2) 3624 { // 2(2x - 1)/(2x + 1) 3625 exp -= 1; 3626 z = x - 0.5; 3627 y = 0.5 * z + 0.5; 3628 } 3629 else 3630 { // 2(x - 1)/(x + 1) 3631 z = x - 0.5; 3632 z -= 0.5; 3633 y = 0.5 * x + 0.5; 3634 } 3635 x = z / y; 3636 z = x * x; 3637 z = x * (z * poly(z, logCoeffsR) / poly(z, logCoeffsS)); 3638 z += exp * C2; 3639 z += x; 3640 z += exp * C1; 3641 3642 return z; 3643 } 3644 3645 // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x) 3646 if (x < SQRT1_2) 3647 { 3648 exp -= 1; 3649 x = 2.0 * x - 1.0; 3650 } 3651 else 3652 { 3653 x = x - 1.0; 3654 } 3655 z = x * x; 3656 y = x * (z * poly(x, logCoeffsP) / poly(x, logCoeffsQ)); 3657 y += exp * C2; 3658 z = y - 0.5 * z; 3659 3660 // Note, the sum of above terms does not exceed x/4, 3661 // so it contributes at most about 1/4 lsb to the error. 3662 z += x; 3663 z += exp * C1; 3664 3665 return z; 3666 } 3667 } 3668 3669 /// 3670 @safe pure nothrow @nogc unittest 3671 { 3672 assert(feqrel(log(E), 1) >= real.mant_dig - 1); 3673 } 3674 3675 /************************************** 3676 * Calculate the base-10 logarithm of x. 3677 * 3678 * $(TABLE_SV 3679 * $(TR $(TH x) $(TH log10(x)) $(TH divide by 0?) $(TH invalid?)) 3680 * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) 3681 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes)) 3682 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no)) 3683 * ) 3684 */ 3685 real log10(real x) @safe pure nothrow @nogc 3686 { 3687 version (INLINE_YL2X) 3688 return core.math.yl2x(x, LOG2); 3689 else 3690 { 3691 // log10(2) split into two parts. 3692 enum real L102A = 0.3125L; 3693 enum real L102B = -1.14700043360188047862611052755069732318101185E-2L; 3694 3695 // log10(e) split into two parts. 3696 enum real L10EA = 0.5L; 3697 enum real L10EB = -6.570551809674817234887108108339491770560299E-2L; 3698 3699 // Special cases are the same as for log. 3700 if (isNaN(x)) 3701 return x; 3702 if (isInfinity(x) && !signbit(x)) 3703 return x; 3704 if (x == 0.0) 3705 return -real.infinity; 3706 if (x < 0.0) 3707 return real.nan; 3708 3709 // Separate mantissa from exponent. 3710 // Note, frexp is used so that denormal numbers will be handled properly. 3711 real y, z; 3712 int exp; 3713 3714 x = frexp(x, exp); 3715 3716 // Logarithm using log(x) = z + z^^3 R(z) / S(z), 3717 // where z = 2(x - 1)/(x + 1) 3718 if ((exp > 2) || (exp < -2)) 3719 { 3720 if (x < SQRT1_2) 3721 { // 2(2x - 1)/(2x + 1) 3722 exp -= 1; 3723 z = x - 0.5; 3724 y = 0.5 * z + 0.5; 3725 } 3726 else 3727 { // 2(x - 1)/(x + 1) 3728 z = x - 0.5; 3729 z -= 0.5; 3730 y = 0.5 * x + 0.5; 3731 } 3732 x = z / y; 3733 z = x * x; 3734 y = x * (z * poly(z, logCoeffsR) / poly(z, logCoeffsS)); 3735 goto Ldone; 3736 } 3737 3738 // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x) 3739 if (x < SQRT1_2) 3740 { 3741 exp -= 1; 3742 x = 2.0 * x - 1.0; 3743 } 3744 else 3745 x = x - 1.0; 3746 3747 z = x * x; 3748 y = x * (z * poly(x, logCoeffsP) / poly(x, logCoeffsQ)); 3749 y = y - 0.5 * z; 3750 3751 // Multiply log of fraction by log10(e) and base 2 exponent by log10(2). 3752 // This sequence of operations is critical and it may be horribly 3753 // defeated by some compiler optimizers. 3754 Ldone: 3755 z = y * L10EB; 3756 z += x * L10EB; 3757 z += exp * L102B; 3758 z += y * L10EA; 3759 z += x * L10EA; 3760 z += exp * L102A; 3761 3762 return z; 3763 } 3764 } 3765 3766 /// 3767 @safe pure nothrow @nogc unittest 3768 { 3769 assert(fabs(log10(1000) - 3) < .000001); 3770 } 3771 3772 /** 3773 * Calculates the natural logarithm of 1 + x. 3774 * 3775 * For very small x, log1p(x) will be more accurate than 3776 * log(1 + x). 3777 * 3778 * $(TABLE_SV 3779 * $(TR $(TH x) $(TH log1p(x)) $(TH divide by 0?) $(TH invalid?)) 3780 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) $(TD no)) 3781 * $(TR $(TD -1.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) 3782 * $(TR $(TD $(LT)-1.0) $(TD -$(NAN)) $(TD no) $(TD yes)) 3783 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no)) 3784 * ) 3785 */ 3786 real log1p(real x) @safe pure nothrow @nogc 3787 { 3788 version (INLINE_YL2X) 3789 { 3790 // On x87, yl2xp1 is valid if and only if -0.5 <= lg(x) <= 0.5, 3791 // ie if -0.29 <= x <= 0.414 3792 return (fabs(x) <= 0.25) ? core.math.yl2xp1(x, LN2) : core.math.yl2x(x+1, LN2); 3793 } 3794 else 3795 { 3796 // Special cases. 3797 if (isNaN(x) || x == 0.0) 3798 return x; 3799 if (isInfinity(x) && !signbit(x)) 3800 return x; 3801 if (x == -1.0) 3802 return -real.infinity; 3803 if (x < -1.0) 3804 return real.nan; 3805 3806 return log(x + 1.0); 3807 } 3808 } 3809 3810 /// 3811 @safe pure unittest 3812 { 3813 assert(isIdentical(log1p(0.0), 0.0)); 3814 assert(log1p(1.0).feqrel(0.69314) > 16); 3815 3816 assert(log1p(-1.0) == -real.infinity); 3817 assert(isNaN(log1p(-2.0))); 3818 assert(log1p(real.nan) is real.nan); 3819 assert(log1p(-real.nan) is -real.nan); 3820 assert(log1p(real.infinity) == real.infinity); 3821 } 3822 3823 /*************************************** 3824 * Calculates the base-2 logarithm of x: 3825 * $(SUB log, 2)x 3826 * 3827 * $(TABLE_SV 3828 * $(TR $(TH x) $(TH log2(x)) $(TH divide by 0?) $(TH invalid?)) 3829 * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no) ) 3830 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes) ) 3831 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no) ) 3832 * ) 3833 */ 3834 real log2(real x) @safe pure nothrow @nogc 3835 { 3836 version (INLINE_YL2X) 3837 return core.math.yl2x(x, 1.0L); 3838 else 3839 { 3840 // Special cases are the same as for log. 3841 if (isNaN(x)) 3842 return x; 3843 if (isInfinity(x) && !signbit(x)) 3844 return x; 3845 if (x == 0.0) 3846 return -real.infinity; 3847 if (x < 0.0) 3848 return real.nan; 3849 3850 // Separate mantissa from exponent. 3851 // Note, frexp is used so that denormal numbers will be handled properly. 3852 real y, z; 3853 int exp; 3854 3855 x = frexp(x, exp); 3856 3857 // Logarithm using log(x) = z + z^^3 R(z) / S(z), 3858 // where z = 2(x - 1)/(x + 1) 3859 if ((exp > 2) || (exp < -2)) 3860 { 3861 if (x < SQRT1_2) 3862 { // 2(2x - 1)/(2x + 1) 3863 exp -= 1; 3864 z = x - 0.5; 3865 y = 0.5 * z + 0.5; 3866 } 3867 else 3868 { // 2(x - 1)/(x + 1) 3869 z = x - 0.5; 3870 z -= 0.5; 3871 y = 0.5 * x + 0.5; 3872 } 3873 x = z / y; 3874 z = x * x; 3875 y = x * (z * poly(z, logCoeffsR) / poly(z, logCoeffsS)); 3876 goto Ldone; 3877 } 3878 3879 // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x) 3880 if (x < SQRT1_2) 3881 { 3882 exp -= 1; 3883 x = 2.0 * x - 1.0; 3884 } 3885 else 3886 x = x - 1.0; 3887 3888 z = x * x; 3889 y = x * (z * poly(x, logCoeffsP) / poly(x, logCoeffsQ)); 3890 y = y - 0.5 * z; 3891 3892 // Multiply log of fraction by log10(e) and base 2 exponent by log10(2). 3893 // This sequence of operations is critical and it may be horribly 3894 // defeated by some compiler optimizers. 3895 Ldone: 3896 z = y * (LOG2E - 1.0); 3897 z += x * (LOG2E - 1.0); 3898 z += y; 3899 z += x; 3900 z += exp; 3901 3902 return z; 3903 } 3904 } 3905 3906 /// 3907 @safe unittest 3908 { 3909 assert(approxEqual(log2(1024.0L), 10)); 3910 } 3911 3912 @safe @nogc nothrow unittest 3913 { 3914 // check if values are equal to 19 decimal digits of precision 3915 assert(equalsDigit(log2(1024.0L), 10, 19)); 3916 } 3917 3918 /***************************************** 3919 * Extracts the exponent of x as a signed integral value. 3920 * 3921 * If x is subnormal, it is treated as if it were normalized. 3922 * For a positive, finite x: 3923 * 3924 * 1 $(LT)= $(I x) * FLT_RADIX$(SUPERSCRIPT -logb(x)) $(LT) FLT_RADIX 3925 * 3926 * $(TABLE_SV 3927 * $(TR $(TH x) $(TH logb(x)) $(TH divide by 0?) ) 3928 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) $(TD no)) 3929 * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) ) 3930 * ) 3931 */ 3932 real logb(real x) @trusted nothrow @nogc 3933 { 3934 version (Win64_DMD_InlineAsm) 3935 { 3936 asm pure nothrow @nogc 3937 { 3938 naked ; 3939 fld real ptr [RCX] ; 3940 fxtract ; 3941 fstp ST(0) ; 3942 ret ; 3943 } 3944 } 3945 else version (MSVC_InlineAsm) 3946 { 3947 asm pure nothrow @nogc 3948 { 3949 fld x ; 3950 fxtract ; 3951 fstp ST(0) ; 3952 } 3953 } 3954 else 3955 return core.stdc.math.logbl(x); 3956 } 3957 3958 /// 3959 @safe @nogc nothrow unittest 3960 { 3961 assert(logb(1.0) == 0); 3962 assert(logb(100.0) == 6); 3963 3964 assert(logb(0.0) == -real.infinity); 3965 assert(logb(real.infinity) == real.infinity); 3966 assert(logb(-real.infinity) == real.infinity); 3967 } 3968 3969 /************************************ 3970 * Calculates the remainder from the calculation x/y. 3971 * Returns: 3972 * The value of x - i * y, where i is the number of times that y can 3973 * be completely subtracted from x. The result has the same sign as x. 3974 * 3975 * $(TABLE_SV 3976 * $(TR $(TH x) $(TH y) $(TH fmod(x, y)) $(TH invalid?)) 3977 * $(TR $(TD $(PLUSMN)0.0) $(TD not 0.0) $(TD $(PLUSMN)0.0) $(TD no)) 3978 * $(TR $(TD $(PLUSMNINF)) $(TD anything) $(TD $(NAN)) $(TD yes)) 3979 * $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(NAN)) $(TD yes)) 3980 * $(TR $(TD !=$(PLUSMNINF)) $(TD $(PLUSMNINF)) $(TD x) $(TD no)) 3981 * ) 3982 */ 3983 real fmod(real x, real y) @trusted nothrow @nogc 3984 { 3985 version (CRuntime_Microsoft) 3986 { 3987 return x % y; 3988 } 3989 else 3990 return core.stdc.math.fmodl(x, y); 3991 } 3992 3993 /// 3994 @safe unittest 3995 { 3996 assert(isIdentical(fmod(0.0, 1.0), 0.0)); 3997 assert(fmod(5.0, 3.0).feqrel(2.0) > 16); 3998 assert(isNaN(fmod(5.0, 0.0))); 3999 } 4000 4001 /************************************ 4002 * Breaks x into an integral part and a fractional part, each of which has 4003 * the same sign as x. The integral part is stored in i. 4004 * Returns: 4005 * The fractional part of x. 4006 * 4007 * $(TABLE_SV 4008 * $(TR $(TH x) $(TH i (on input)) $(TH modf(x, i)) $(TH i (on return))) 4009 * $(TR $(TD $(PLUSMNINF)) $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(PLUSMNINF))) 4010 * ) 4011 */ 4012 real modf(real x, ref real i) @trusted nothrow @nogc 4013 { 4014 version (CRuntime_Microsoft) 4015 { 4016 i = trunc(x); 4017 return copysign(isInfinity(x) ? 0.0 : x - i, x); 4018 } 4019 else 4020 return core.stdc.math.modfl(x,&i); 4021 } 4022 4023 /// 4024 @safe unittest 4025 { 4026 real frac; 4027 real intpart; 4028 4029 frac = modf(3.14159, intpart); 4030 assert(intpart.feqrel(3.0) > 16); 4031 assert(frac.feqrel(0.14159) > 16); 4032 } 4033 4034 /************************************* 4035 * Efficiently calculates x * 2$(SUPERSCRIPT n). 4036 * 4037 * scalbn handles underflow and overflow in 4038 * the same fashion as the basic arithmetic operators. 4039 * 4040 * $(TABLE_SV 4041 * $(TR $(TH x) $(TH scalb(x))) 4042 * $(TR $(TD $(PLUSMNINF)) $(TD $(PLUSMNINF)) ) 4043 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) ) 4044 * ) 4045 */ 4046 real scalbn(real x, int n) @safe pure nothrow @nogc 4047 { 4048 if (__ctfe) 4049 { 4050 // Handle special cases. 4051 if (x == 0.0 || isInfinity(x)) 4052 return x; 4053 } 4054 return core.math.ldexp(x, n); 4055 } 4056 4057 /// 4058 @safe pure nothrow @nogc unittest 4059 { 4060 assert(scalbn(0x1.2345678abcdefp0, 999) == 0x1.2345678abcdefp999); 4061 assert(scalbn(-real.infinity, 5) == -real.infinity); 4062 } 4063 4064 @safe pure nothrow @nogc unittest 4065 { 4066 // CTFE-able test 4067 static assert(scalbn(0x1.2345678abcdefp0, 999) == 0x1.2345678abcdefp999); 4068 static assert(scalbn(-real.infinity, 5) == -real.infinity); 4069 // Test with large exponent delta n where the result is in bounds but 2.0L ^^ n is not. 4070 enum initialExponent = real.min_exp + 2, resultExponent = real.max_exp - 2; 4071 enum int n = resultExponent - initialExponent; 4072 enum real x = 0x1.2345678abcdefp0 * (2.0L ^^ initialExponent); 4073 enum staticResult = scalbn(x, n); 4074 static assert(staticResult == 0x1.2345678abcdefp0 * (2.0L ^^ resultExponent)); 4075 assert(scalbn(x, n) == staticResult); 4076 } 4077 4078 /*************** 4079 * Calculates the cube root of x. 4080 * 4081 * $(TABLE_SV 4082 * $(TR $(TH $(I x)) $(TH cbrt(x)) $(TH invalid?)) 4083 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) ) 4084 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) ) 4085 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no) ) 4086 * ) 4087 */ 4088 real cbrt(real x) @trusted nothrow @nogc 4089 { 4090 version (CRuntime_Microsoft) 4091 { 4092 version (INLINE_YL2X) 4093 return copysign(exp2(core.math.yl2x(fabs(x), 1.0L/3.0L)), x); 4094 else 4095 return core.stdc.math.cbrtl(x); 4096 } 4097 else 4098 return core.stdc.math.cbrtl(x); 4099 } 4100 4101 /// 4102 @safe unittest 4103 { 4104 assert(cbrt(1.0).feqrel(1.0) > 16); 4105 assert(cbrt(27.0).feqrel(3.0) > 16); 4106 assert(cbrt(15.625).feqrel(2.5) > 16); 4107 } 4108 4109 /******************************* 4110 * Returns |x| 4111 * 4112 * $(TABLE_SV 4113 * $(TR $(TH x) $(TH fabs(x))) 4114 * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) ) 4115 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) 4116 * ) 4117 */ 4118 real fabs(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.fabs(x); } 4119 4120 ///ditto 4121 pragma(inline, true) 4122 double fabs(double d) @trusted pure nothrow @nogc 4123 { 4124 ulong tmp = *cast(ulong*)&d & 0x7FFF_FFFF_FFFF_FFFF; 4125 return *cast(double*)&tmp; 4126 } 4127 4128 ///ditto 4129 pragma(inline, true) 4130 float fabs(float f) @trusted pure nothrow @nogc 4131 { 4132 uint tmp = *cast(uint*)&f & 0x7FFF_FFFF; 4133 return *cast(float*)&tmp; 4134 } 4135 4136 /// 4137 @safe unittest 4138 { 4139 4140 assert(isIdentical(fabs(0.0f), 0.0f)); 4141 assert(isIdentical(fabs(-0.0f), 0.0f)); 4142 assert(fabs(-10.0f) == 10.0f); 4143 4144 assert(isIdentical(fabs(0.0), 0.0)); 4145 assert(isIdentical(fabs(-0.0), 0.0)); 4146 assert(fabs(-10.0) == 10.0); 4147 4148 assert(isIdentical(fabs(0.0L), 0.0L)); 4149 assert(isIdentical(fabs(-0.0L), 0.0L)); 4150 assert(fabs(-10.0L) == 10.0L); 4151 } 4152 4153 @safe unittest 4154 { 4155 real function(real) pfabs = &fabs; 4156 assert(pfabs != null); 4157 } 4158 4159 /*********************************************************************** 4160 * Calculates the length of the 4161 * hypotenuse of a right-angled triangle with sides of length x and y. 4162 * The hypotenuse is the value of the square root of 4163 * the sums of the squares of x and y: 4164 * 4165 * sqrt($(POWER x, 2) + $(POWER y, 2)) 4166 * 4167 * Note that hypot(x, y), hypot(y, x) and 4168 * hypot(x, -y) are equivalent. 4169 * 4170 * $(TABLE_SV 4171 * $(TR $(TH x) $(TH y) $(TH hypot(x, y)) $(TH invalid?)) 4172 * $(TR $(TD x) $(TD $(PLUSMN)0.0) $(TD |x|) $(TD no)) 4173 * $(TR $(TD $(PLUSMNINF)) $(TD y) $(TD +$(INFIN)) $(TD no)) 4174 * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD +$(INFIN)) $(TD no)) 4175 * ) 4176 */ 4177 4178 real hypot(real x, real y) @safe pure nothrow @nogc 4179 { 4180 // Scale x and y to avoid underflow and overflow. 4181 // If one is huge and the other tiny, return the larger. 4182 // If both are huge, avoid overflow by scaling by 1/sqrt(real.max/2). 4183 // If both are tiny, avoid underflow by scaling by sqrt(real.min_normal*real.epsilon). 4184 4185 enum real SQRTMIN = 0.5 * sqrt(real.min_normal); // This is a power of 2. 4186 enum real SQRTMAX = 1.0L / SQRTMIN; // 2^^((max_exp)/2) = nextUp(sqrt(real.max)) 4187 4188 static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max); 4189 4190 // Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal) 4191 static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4); 4192 4193 real u = fabs(x); 4194 real v = fabs(y); 4195 if (!(u >= v)) // check for NaN as well. 4196 { 4197 v = u; 4198 u = fabs(y); 4199 if (u == real.infinity) return u; // hypot(inf, nan) == inf 4200 if (v == real.infinity) return v; // hypot(nan, inf) == inf 4201 } 4202 4203 // Now u >= v, or else one is NaN. 4204 if (v >= SQRTMAX*0.5) 4205 { 4206 // hypot(huge, huge) -- avoid overflow 4207 u *= SQRTMIN*0.5; 4208 v *= SQRTMIN*0.5; 4209 return sqrt(u*u + v*v) * SQRTMAX * 2.0; 4210 } 4211 4212 if (u <= SQRTMIN) 4213 { 4214 // hypot (tiny, tiny) -- avoid underflow 4215 // This is only necessary to avoid setting the underflow 4216 // flag. 4217 u *= SQRTMAX / real.epsilon; 4218 v *= SQRTMAX / real.epsilon; 4219 return sqrt(u*u + v*v) * SQRTMIN * real.epsilon; 4220 } 4221 4222 if (u * real.epsilon > v) 4223 { 4224 // hypot (huge, tiny) = huge 4225 return u; 4226 } 4227 4228 // both are in the normal range 4229 return sqrt(u*u + v*v); 4230 } 4231 4232 /// 4233 @safe unittest 4234 { 4235 assert(hypot(1.0, 1.0).feqrel(1.4142) > 16); 4236 assert(hypot(3.0, 4.0).feqrel(5.0) > 16); 4237 assert(hypot(real.infinity, 1.0) == real.infinity); 4238 assert(hypot(real.infinity, real.nan) == real.infinity); 4239 } 4240 4241 @safe unittest 4242 { 4243 static real[3][] vals = // x,y,hypot 4244 [ 4245 [ 0.0, 0.0, 0.0], 4246 [ 0.0, -0.0, 0.0], 4247 [ -0.0, -0.0, 0.0], 4248 [ 3.0, 4.0, 5.0], 4249 [ -300, -400, 500], 4250 [0.0, 7.0, 7.0], 4251 [9.0, 9*real.epsilon, 9.0], 4252 [88/(64*sqrt(real.min_normal)), 105/(64*sqrt(real.min_normal)), 137/(64*sqrt(real.min_normal))], 4253 [88/(128*sqrt(real.min_normal)), 105/(128*sqrt(real.min_normal)), 137/(128*sqrt(real.min_normal))], 4254 [3*real.min_normal*real.epsilon, 4*real.min_normal*real.epsilon, 5*real.min_normal*real.epsilon], 4255 [ real.min_normal, real.min_normal, sqrt(2.0L)*real.min_normal], 4256 [ real.max/sqrt(2.0L), real.max/sqrt(2.0L), real.max], 4257 [ real.infinity, real.nan, real.infinity], 4258 [ real.nan, real.infinity, real.infinity], 4259 [ real.nan, real.nan, real.nan], 4260 [ real.nan, real.max, real.nan], 4261 [ real.max, real.nan, real.nan], 4262 ]; 4263 for (int i = 0; i < vals.length; i++) 4264 { 4265 real x = vals[i][0]; 4266 real y = vals[i][1]; 4267 real z = vals[i][2]; 4268 real h = hypot(x, y); 4269 assert(isIdentical(z,h) || feqrel(z, h) >= real.mant_dig - 1); 4270 } 4271 } 4272 4273 /************************************** 4274 * Returns the value of x rounded upward to the next integer 4275 * (toward positive infinity). 4276 */ 4277 real ceil(real x) @trusted pure nothrow @nogc 4278 { 4279 version (Win64_DMD_InlineAsm) 4280 { 4281 asm pure nothrow @nogc 4282 { 4283 naked ; 4284 fld real ptr [RCX] ; 4285 fstcw 8[RSP] ; 4286 mov AL,9[RSP] ; 4287 mov DL,AL ; 4288 and AL,0xC3 ; 4289 or AL,0x08 ; // round to +infinity 4290 mov 9[RSP],AL ; 4291 fldcw 8[RSP] ; 4292 frndint ; 4293 mov 9[RSP],DL ; 4294 fldcw 8[RSP] ; 4295 ret ; 4296 } 4297 } 4298 else version (MSVC_InlineAsm) 4299 { 4300 short cw; 4301 asm pure nothrow @nogc 4302 { 4303 fld x ; 4304 fstcw cw ; 4305 mov AL,byte ptr cw+1 ; 4306 mov DL,AL ; 4307 and AL,0xC3 ; 4308 or AL,0x08 ; // round to +infinity 4309 mov byte ptr cw+1,AL ; 4310 fldcw cw ; 4311 frndint ; 4312 mov byte ptr cw+1,DL ; 4313 fldcw cw ; 4314 } 4315 } 4316 else 4317 { 4318 // Special cases. 4319 if (isNaN(x) || isInfinity(x)) 4320 return x; 4321 4322 real y = floorImpl(x); 4323 if (y < x) 4324 y += 1.0; 4325 4326 return y; 4327 } 4328 } 4329 4330 /// 4331 @safe pure nothrow @nogc unittest 4332 { 4333 assert(ceil(+123.456L) == +124); 4334 assert(ceil(-123.456L) == -123); 4335 assert(ceil(-1.234L) == -1); 4336 assert(ceil(-0.123L) == 0); 4337 assert(ceil(0.0L) == 0); 4338 assert(ceil(+0.123L) == 1); 4339 assert(ceil(+1.234L) == 2); 4340 assert(ceil(real.infinity) == real.infinity); 4341 assert(isNaN(ceil(real.nan))); 4342 assert(isNaN(ceil(real.init))); 4343 } 4344 4345 /// ditto 4346 double ceil(double x) @trusted pure nothrow @nogc 4347 { 4348 // Special cases. 4349 if (isNaN(x) || isInfinity(x)) 4350 return x; 4351 4352 double y = floorImpl(x); 4353 if (y < x) 4354 y += 1.0; 4355 4356 return y; 4357 } 4358 4359 @safe pure nothrow @nogc unittest 4360 { 4361 assert(ceil(+123.456) == +124); 4362 assert(ceil(-123.456) == -123); 4363 assert(ceil(-1.234) == -1); 4364 assert(ceil(-0.123) == 0); 4365 assert(ceil(0.0) == 0); 4366 assert(ceil(+0.123) == 1); 4367 assert(ceil(+1.234) == 2); 4368 assert(ceil(double.infinity) == double.infinity); 4369 assert(isNaN(ceil(double.nan))); 4370 assert(isNaN(ceil(double.init))); 4371 } 4372 4373 /// ditto 4374 float ceil(float x) @trusted pure nothrow @nogc 4375 { 4376 // Special cases. 4377 if (isNaN(x) || isInfinity(x)) 4378 return x; 4379 4380 float y = floorImpl(x); 4381 if (y < x) 4382 y += 1.0; 4383 4384 return y; 4385 } 4386 4387 @safe pure nothrow @nogc unittest 4388 { 4389 assert(ceil(+123.456f) == +124); 4390 assert(ceil(-123.456f) == -123); 4391 assert(ceil(-1.234f) == -1); 4392 assert(ceil(-0.123f) == 0); 4393 assert(ceil(0.0f) == 0); 4394 assert(ceil(+0.123f) == 1); 4395 assert(ceil(+1.234f) == 2); 4396 assert(ceil(float.infinity) == float.infinity); 4397 assert(isNaN(ceil(float.nan))); 4398 assert(isNaN(ceil(float.init))); 4399 } 4400 4401 /************************************** 4402 * Returns the value of x rounded downward to the next integer 4403 * (toward negative infinity). 4404 */ 4405 real floor(real x) @trusted pure nothrow @nogc 4406 { 4407 version (Win64_DMD_InlineAsm) 4408 { 4409 asm pure nothrow @nogc 4410 { 4411 naked ; 4412 fld real ptr [RCX] ; 4413 fstcw 8[RSP] ; 4414 mov AL,9[RSP] ; 4415 mov DL,AL ; 4416 and AL,0xC3 ; 4417 or AL,0x04 ; // round to -infinity 4418 mov 9[RSP],AL ; 4419 fldcw 8[RSP] ; 4420 frndint ; 4421 mov 9[RSP],DL ; 4422 fldcw 8[RSP] ; 4423 ret ; 4424 } 4425 } 4426 else version (MSVC_InlineAsm) 4427 { 4428 short cw; 4429 asm pure nothrow @nogc 4430 { 4431 fld x ; 4432 fstcw cw ; 4433 mov AL,byte ptr cw+1 ; 4434 mov DL,AL ; 4435 and AL,0xC3 ; 4436 or AL,0x04 ; // round to -infinity 4437 mov byte ptr cw+1,AL ; 4438 fldcw cw ; 4439 frndint ; 4440 mov byte ptr cw+1,DL ; 4441 fldcw cw ; 4442 } 4443 } 4444 else 4445 { 4446 // Special cases. 4447 if (isNaN(x) || isInfinity(x) || x == 0.0) 4448 return x; 4449 4450 return floorImpl(x); 4451 } 4452 } 4453 4454 /// 4455 @safe pure nothrow @nogc unittest 4456 { 4457 assert(floor(+123.456L) == +123); 4458 assert(floor(-123.456L) == -124); 4459 assert(floor(+123.0L) == +123); 4460 assert(floor(-124.0L) == -124); 4461 assert(floor(-1.234L) == -2); 4462 assert(floor(-0.123L) == -1); 4463 assert(floor(0.0L) == 0); 4464 assert(floor(+0.123L) == 0); 4465 assert(floor(+1.234L) == 1); 4466 assert(floor(real.infinity) == real.infinity); 4467 assert(isNaN(floor(real.nan))); 4468 assert(isNaN(floor(real.init))); 4469 } 4470 4471 /// ditto 4472 double floor(double x) @trusted pure nothrow @nogc 4473 { 4474 // Special cases. 4475 if (isNaN(x) || isInfinity(x) || x == 0.0) 4476 return x; 4477 4478 return floorImpl(x); 4479 } 4480 4481 @safe pure nothrow @nogc unittest 4482 { 4483 assert(floor(+123.456) == +123); 4484 assert(floor(-123.456) == -124); 4485 assert(floor(+123.0) == +123); 4486 assert(floor(-124.0) == -124); 4487 assert(floor(-1.234) == -2); 4488 assert(floor(-0.123) == -1); 4489 assert(floor(0.0) == 0); 4490 assert(floor(+0.123) == 0); 4491 assert(floor(+1.234) == 1); 4492 assert(floor(double.infinity) == double.infinity); 4493 assert(isNaN(floor(double.nan))); 4494 assert(isNaN(floor(double.init))); 4495 } 4496 4497 /// ditto 4498 float floor(float x) @trusted pure nothrow @nogc 4499 { 4500 // Special cases. 4501 if (isNaN(x) || isInfinity(x) || x == 0.0) 4502 return x; 4503 4504 return floorImpl(x); 4505 } 4506 4507 @safe pure nothrow @nogc unittest 4508 { 4509 assert(floor(+123.456f) == +123); 4510 assert(floor(-123.456f) == -124); 4511 assert(floor(+123.0f) == +123); 4512 assert(floor(-124.0f) == -124); 4513 assert(floor(-1.234f) == -2); 4514 assert(floor(-0.123f) == -1); 4515 assert(floor(0.0f) == 0); 4516 assert(floor(+0.123f) == 0); 4517 assert(floor(+1.234f) == 1); 4518 assert(floor(float.infinity) == float.infinity); 4519 assert(isNaN(floor(float.nan))); 4520 assert(isNaN(floor(float.init))); 4521 } 4522 4523 /** 4524 * Round `val` to a multiple of `unit`. `rfunc` specifies the rounding 4525 * function to use; by default this is `rint`, which uses the current 4526 * rounding mode. 4527 */ 4528 Unqual!F quantize(alias rfunc = rint, F)(const F val, const F unit) 4529 if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F) 4530 { 4531 typeof(return) ret = val; 4532 if (unit != 0) 4533 { 4534 const scaled = val / unit; 4535 if (!scaled.isInfinity) 4536 ret = rfunc(scaled) * unit; 4537 } 4538 return ret; 4539 } 4540 4541 /// 4542 @safe pure nothrow @nogc unittest 4543 { 4544 assert(12345.6789L.quantize(0.01L) == 12345.68L); 4545 assert(12345.6789L.quantize!floor(0.01L) == 12345.67L); 4546 assert(12345.6789L.quantize(22.0L) == 12342.0L); 4547 } 4548 4549 /// 4550 @safe pure nothrow @nogc unittest 4551 { 4552 assert(12345.6789L.quantize(0) == 12345.6789L); 4553 assert(12345.6789L.quantize(real.infinity).isNaN); 4554 assert(12345.6789L.quantize(real.nan).isNaN); 4555 assert(real.infinity.quantize(0.01L) == real.infinity); 4556 assert(real.infinity.quantize(real.nan).isNaN); 4557 assert(real.nan.quantize(0.01L).isNaN); 4558 assert(real.nan.quantize(real.infinity).isNaN); 4559 assert(real.nan.quantize(real.nan).isNaN); 4560 } 4561 4562 /** 4563 * Round `val` to a multiple of `pow(base, exp)`. `rfunc` specifies the 4564 * rounding function to use; by default this is `rint`, which uses the 4565 * current rounding mode. 4566 */ 4567 Unqual!F quantize(real base, alias rfunc = rint, F, E)(const F val, const E exp) 4568 if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F && isIntegral!E) 4569 { 4570 // TODO: Compile-time optimization for power-of-two bases? 4571 return quantize!rfunc(val, pow(cast(F) base, exp)); 4572 } 4573 4574 /// ditto 4575 Unqual!F quantize(real base, long exp = 1, alias rfunc = rint, F)(const F val) 4576 if (is(typeof(rfunc(F.init)) : F) && isFloatingPoint!F) 4577 { 4578 enum unit = cast(F) pow(base, exp); 4579 return quantize!rfunc(val, unit); 4580 } 4581 4582 /// 4583 @safe pure nothrow @nogc unittest 4584 { 4585 assert(12345.6789L.quantize!10(-2) == 12345.68L); 4586 assert(12345.6789L.quantize!(10, -2) == 12345.68L); 4587 assert(12345.6789L.quantize!(10, floor)(-2) == 12345.67L); 4588 assert(12345.6789L.quantize!(10, -2, floor) == 12345.67L); 4589 4590 assert(12345.6789L.quantize!22(1) == 12342.0L); 4591 assert(12345.6789L.quantize!22 == 12342.0L); 4592 } 4593 4594 @safe pure nothrow @nogc unittest 4595 { 4596 import std.meta : AliasSeq; 4597 4598 static foreach (F; AliasSeq!(real, double, float)) 4599 {{ 4600 const maxL10 = cast(int) F.max.log10.floor; 4601 const maxR10 = pow(cast(F) 10, maxL10); 4602 assert((cast(F) 0.9L * maxR10).quantize!10(maxL10) == maxR10); 4603 assert((cast(F)-0.9L * maxR10).quantize!10(maxL10) == -maxR10); 4604 4605 assert(F.max.quantize(F.min_normal) == F.max); 4606 assert((-F.max).quantize(F.min_normal) == -F.max); 4607 assert(F.min_normal.quantize(F.max) == 0); 4608 assert((-F.min_normal).quantize(F.max) == 0); 4609 assert(F.min_normal.quantize(F.min_normal) == F.min_normal); 4610 assert((-F.min_normal).quantize(F.min_normal) == -F.min_normal); 4611 }} 4612 } 4613 4614 /****************************************** 4615 * Rounds x to the nearest integer value, using the current rounding 4616 * mode. 4617 * 4618 * Unlike the rint functions, nearbyint does not raise the 4619 * FE_INEXACT exception. 4620 */ 4621 real nearbyint(real x) @safe pure nothrow @nogc 4622 { 4623 return core.stdc.math.nearbyintl(x); 4624 } 4625 4626 /// 4627 @safe pure unittest 4628 { 4629 assert(nearbyint(0.4) == 0); 4630 assert(nearbyint(0.5) == 0); 4631 assert(nearbyint(0.6) == 1); 4632 assert(nearbyint(100.0) == 100); 4633 4634 assert(isNaN(nearbyint(real.nan))); 4635 assert(nearbyint(real.infinity) == real.infinity); 4636 assert(nearbyint(-real.infinity) == -real.infinity); 4637 } 4638 4639 /********************************** 4640 * Rounds x to the nearest integer value, using the current rounding 4641 * mode. 4642 * 4643 * If the return value is not equal to x, the FE_INEXACT 4644 * exception is raised. 4645 * 4646 * $(LREF nearbyint) performs the same operation, but does 4647 * not set the FE_INEXACT exception. 4648 */ 4649 real rint(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.rint(x); } 4650 //FIXME 4651 ///ditto 4652 double rint(double x) @safe pure nothrow @nogc { return rint(cast(real) x); } 4653 //FIXME 4654 ///ditto 4655 float rint(float x) @safe pure nothrow @nogc { return rint(cast(real) x); } 4656 4657 /// 4658 @safe unittest 4659 { 4660 version (IeeeFlagsSupport) resetIeeeFlags(); 4661 assert(rint(0.4) == 0); 4662 version (IeeeFlagsSupport) assert(ieeeFlags.inexact); 4663 4664 assert(rint(0.5) == 0); 4665 assert(rint(0.6) == 1); 4666 assert(rint(100.0) == 100); 4667 4668 assert(isNaN(rint(real.nan))); 4669 assert(rint(real.infinity) == real.infinity); 4670 assert(rint(-real.infinity) == -real.infinity); 4671 } 4672 4673 @safe unittest 4674 { 4675 real function(real) print = &rint; 4676 assert(print != null); 4677 } 4678 4679 /*************************************** 4680 * Rounds x to the nearest integer value, using the current rounding 4681 * mode. 4682 * 4683 * This is generally the fastest method to convert a floating-point number 4684 * to an integer. Note that the results from this function 4685 * depend on the rounding mode, if the fractional part of x is exactly 0.5. 4686 * If using the default rounding mode (ties round to even integers) 4687 * lrint(4.5) == 4, lrint(5.5)==6. 4688 */ 4689 long lrint(real x) @trusted pure nothrow @nogc 4690 { 4691 version (InlineAsm_X86_Any) 4692 { 4693 version (Win64) 4694 { 4695 asm pure nothrow @nogc 4696 { 4697 naked; 4698 fld real ptr [RCX]; 4699 fistp qword ptr 8[RSP]; 4700 mov RAX,8[RSP]; 4701 ret; 4702 } 4703 } 4704 else 4705 { 4706 long n; 4707 asm pure nothrow @nogc 4708 { 4709 fld x; 4710 fistp n; 4711 } 4712 return n; 4713 } 4714 } 4715 else 4716 { 4717 alias F = floatTraits!(real); 4718 static if (F.realFormat == RealFormat.ieeeDouble) 4719 { 4720 long result; 4721 4722 // Rounding limit when casting from real(double) to ulong. 4723 enum real OF = 4.50359962737049600000E15L; 4724 4725 uint* vi = cast(uint*)(&x); 4726 4727 // Find the exponent and sign 4728 uint msb = vi[MANTISSA_MSB]; 4729 uint lsb = vi[MANTISSA_LSB]; 4730 int exp = ((msb >> 20) & 0x7ff) - 0x3ff; 4731 const int sign = msb >> 31; 4732 msb &= 0xfffff; 4733 msb |= 0x100000; 4734 4735 if (exp < 63) 4736 { 4737 if (exp >= 52) 4738 result = (cast(long) msb << (exp - 20)) | (lsb << (exp - 52)); 4739 else 4740 { 4741 // Adjust x and check result. 4742 const real j = sign ? -OF : OF; 4743 x = (j + x) - j; 4744 msb = vi[MANTISSA_MSB]; 4745 lsb = vi[MANTISSA_LSB]; 4746 exp = ((msb >> 20) & 0x7ff) - 0x3ff; 4747 msb &= 0xfffff; 4748 msb |= 0x100000; 4749 4750 if (exp < 0) 4751 result = 0; 4752 else if (exp < 20) 4753 result = cast(long) msb >> (20 - exp); 4754 else if (exp == 20) 4755 result = cast(long) msb; 4756 else 4757 result = (cast(long) msb << (exp - 20)) | (lsb >> (52 - exp)); 4758 } 4759 } 4760 else 4761 { 4762 // It is left implementation defined when the number is too large. 4763 return cast(long) x; 4764 } 4765 4766 return sign ? -result : result; 4767 } 4768 else static if (F.realFormat == RealFormat.ieeeExtended) 4769 { 4770 long result; 4771 4772 // Rounding limit when casting from real(80-bit) to ulong. 4773 enum real OF = 9.22337203685477580800E18L; 4774 4775 ushort* vu = cast(ushort*)(&x); 4776 uint* vi = cast(uint*)(&x); 4777 4778 // Find the exponent and sign 4779 int exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff; 4780 const int sign = (vu[F.EXPPOS_SHORT] >> 15) & 1; 4781 4782 if (exp < 63) 4783 { 4784 // Adjust x and check result. 4785 const real j = sign ? -OF : OF; 4786 x = (j + x) - j; 4787 exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff; 4788 4789 version (LittleEndian) 4790 { 4791 if (exp < 0) 4792 result = 0; 4793 else if (exp <= 31) 4794 result = vi[1] >> (31 - exp); 4795 else 4796 result = (cast(long) vi[1] << (exp - 31)) | (vi[0] >> (63 - exp)); 4797 } 4798 else 4799 { 4800 if (exp < 0) 4801 result = 0; 4802 else if (exp <= 31) 4803 result = vi[1] >> (31 - exp); 4804 else 4805 result = (cast(long) vi[1] << (exp - 31)) | (vi[2] >> (63 - exp)); 4806 } 4807 } 4808 else 4809 { 4810 // It is left implementation defined when the number is too large 4811 // to fit in a 64bit long. 4812 return cast(long) x; 4813 } 4814 4815 return sign ? -result : result; 4816 } 4817 else static if (F.realFormat == RealFormat.ieeeQuadruple) 4818 { 4819 const vu = cast(ushort*)(&x); 4820 4821 // Find the exponent and sign 4822 const sign = (vu[F.EXPPOS_SHORT] >> 15) & 1; 4823 if ((vu[F.EXPPOS_SHORT] & F.EXPMASK) - (F.EXPBIAS + 1) > 63) 4824 { 4825 // The result is left implementation defined when the number is 4826 // too large to fit in a 64 bit long. 4827 return cast(long) x; 4828 } 4829 4830 // Force rounding of lower bits according to current rounding 4831 // mode by adding ±2^-112 and subtracting it again. 4832 enum OF = 5.19229685853482762853049632922009600E33L; 4833 const j = sign ? -OF : OF; 4834 x = (j + x) - j; 4835 4836 const exp = (vu[F.EXPPOS_SHORT] & F.EXPMASK) - (F.EXPBIAS + 1); 4837 const implicitOne = 1UL << 48; 4838 auto vl = cast(ulong*)(&x); 4839 vl[MANTISSA_MSB] &= implicitOne - 1; 4840 vl[MANTISSA_MSB] |= implicitOne; 4841 4842 long result; 4843 4844 if (exp < 0) 4845 result = 0; 4846 else if (exp <= 48) 4847 result = vl[MANTISSA_MSB] >> (48 - exp); 4848 else 4849 result = (vl[MANTISSA_MSB] << (exp - 48)) | (vl[MANTISSA_LSB] >> (112 - exp)); 4850 4851 return sign ? -result : result; 4852 } 4853 else 4854 { 4855 static assert(false, "real type not supported by lrint()"); 4856 } 4857 } 4858 } 4859 4860 /// 4861 @safe pure nothrow @nogc unittest 4862 { 4863 assert(lrint(4.5) == 4); 4864 assert(lrint(5.5) == 6); 4865 assert(lrint(-4.5) == -4); 4866 assert(lrint(-5.5) == -6); 4867 4868 assert(lrint(int.max - 0.5) == 2147483646L); 4869 assert(lrint(int.max + 0.5) == 2147483648L); 4870 assert(lrint(int.min - 0.5) == -2147483648L); 4871 assert(lrint(int.min + 0.5) == -2147483648L); 4872 } 4873 4874 static if (real.mant_dig >= long.sizeof * 8) 4875 { 4876 @safe pure nothrow @nogc unittest 4877 { 4878 assert(lrint(long.max - 1.5L) == long.max - 1); 4879 assert(lrint(long.max - 0.5L) == long.max - 1); 4880 assert(lrint(long.min + 0.5L) == long.min); 4881 assert(lrint(long.min + 1.5L) == long.min + 2); 4882 } 4883 } 4884 4885 /******************************************* 4886 * Return the value of x rounded to the nearest integer. 4887 * If the fractional part of x is exactly 0.5, the return value is 4888 * rounded away from zero. 4889 * 4890 * Returns: 4891 * A `real`. 4892 */ 4893 auto round(real x) @trusted nothrow @nogc 4894 { 4895 version (CRuntime_Microsoft) 4896 { 4897 auto old = FloatingPointControl.getControlState(); 4898 FloatingPointControl.setControlState( 4899 (old & (-1 - FloatingPointControl.roundingMask)) | FloatingPointControl.roundToZero 4900 ); 4901 x = rint((x >= 0) ? x + 0.5 : x - 0.5); 4902 FloatingPointControl.setControlState(old); 4903 return x; 4904 } 4905 else 4906 return core.stdc.math.roundl(x); 4907 } 4908 4909 /// 4910 @safe nothrow @nogc unittest 4911 { 4912 assert(round(4.5) == 5); 4913 assert(round(5.4) == 5); 4914 assert(round(-4.5) == -5); 4915 assert(round(-5.1) == -5); 4916 } 4917 4918 // assure purity on Posix 4919 version (Posix) 4920 { 4921 @safe pure nothrow @nogc unittest 4922 { 4923 assert(round(4.5) == 5); 4924 } 4925 } 4926 4927 /********************************************** 4928 * Return the value of x rounded to the nearest integer. 4929 * 4930 * If the fractional part of x is exactly 0.5, the return value is rounded 4931 * away from zero. 4932 * 4933 * $(BLUE This function is not implemented for Digital Mars C runtime.) 4934 */ 4935 long lround(real x) @trusted nothrow @nogc 4936 { 4937 version (CRuntime_DigitalMars) 4938 assert(0, "lround not implemented"); 4939 else 4940 return core.stdc.math.llroundl(x); 4941 } 4942 4943 /// 4944 @safe nothrow @nogc unittest 4945 { 4946 version (CRuntime_DigitalMars) {} 4947 else 4948 { 4949 assert(lround(0.49) == 0); 4950 assert(lround(0.5) == 1); 4951 assert(lround(1.5) == 2); 4952 } 4953 } 4954 4955 /** 4956 Returns the integer portion of x, dropping the fractional portion. 4957 This is also known as "chop" rounding. 4958 `pure` on all platforms. 4959 */ 4960 real trunc(real x) @trusted nothrow @nogc pure 4961 { 4962 version (Win64_DMD_InlineAsm) 4963 { 4964 asm pure nothrow @nogc 4965 { 4966 naked ; 4967 fld real ptr [RCX] ; 4968 fstcw 8[RSP] ; 4969 mov AL,9[RSP] ; 4970 mov DL,AL ; 4971 and AL,0xC3 ; 4972 or AL,0x0C ; // round to 0 4973 mov 9[RSP],AL ; 4974 fldcw 8[RSP] ; 4975 frndint ; 4976 mov 9[RSP],DL ; 4977 fldcw 8[RSP] ; 4978 ret ; 4979 } 4980 } 4981 else version (MSVC_InlineAsm) 4982 { 4983 short cw; 4984 asm pure nothrow @nogc 4985 { 4986 fld x ; 4987 fstcw cw ; 4988 mov AL,byte ptr cw+1 ; 4989 mov DL,AL ; 4990 and AL,0xC3 ; 4991 or AL,0x0C ; // round to 0 4992 mov byte ptr cw+1,AL ; 4993 fldcw cw ; 4994 frndint ; 4995 mov byte ptr cw+1,DL ; 4996 fldcw cw ; 4997 } 4998 } 4999 else 5000 return core.stdc.math.truncl(x); 5001 } 5002 5003 /// 5004 @safe pure unittest 5005 { 5006 assert(trunc(0.01) == 0); 5007 assert(trunc(0.49) == 0); 5008 assert(trunc(0.5) == 0); 5009 assert(trunc(1.5) == 1); 5010 } 5011 5012 /**************************************************** 5013 * Calculate the remainder x REM y, following IEC 60559. 5014 * 5015 * REM is the value of x - y * n, where n is the integer nearest the exact 5016 * value of x / y. 5017 * If |n - x / y| == 0.5, n is even. 5018 * If the result is zero, it has the same sign as x. 5019 * Otherwise, the sign of the result is the sign of x / y. 5020 * Precision mode has no effect on the remainder functions. 5021 * 5022 * remquo returns `n` in the parameter `n`. 5023 * 5024 * $(TABLE_SV 5025 * $(TR $(TH x) $(TH y) $(TH remainder(x, y)) $(TH n) $(TH invalid?)) 5026 * $(TR $(TD $(PLUSMN)0.0) $(TD not 0.0) $(TD $(PLUSMN)0.0) $(TD 0.0) $(TD no)) 5027 * $(TR $(TD $(PLUSMNINF)) $(TD anything) $(TD -$(NAN)) $(TD ?) $(TD yes)) 5028 * $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)$(NAN)) $(TD ?) $(TD yes)) 5029 * $(TR $(TD != $(PLUSMNINF)) $(TD $(PLUSMNINF)) $(TD x) $(TD ?) $(TD no)) 5030 * ) 5031 */ 5032 real remainder(real x, real y) @trusted nothrow @nogc 5033 { 5034 return core.stdc.math.remainderl(x, y); 5035 } 5036 5037 /// ditto 5038 real remquo(real x, real y, out int n) @trusted nothrow @nogc /// ditto 5039 { 5040 return core.stdc.math.remquol(x, y, &n); 5041 } 5042 5043 /// 5044 @safe @nogc nothrow unittest 5045 { 5046 assert(remainder(5.1, 3.0).feqrel(-0.9) > 16); 5047 assert(remainder(-5.1, 3.0).feqrel(0.9) > 16); 5048 assert(remainder(0.0, 3.0) == 0.0); 5049 5050 assert(isNaN(remainder(1.0, 0.0))); 5051 assert(isNaN(remainder(-1.0, 0.0))); 5052 } 5053 5054 /// 5055 @safe @nogc nothrow unittest 5056 { 5057 int n; 5058 5059 assert(remquo(5.1, 3.0, n).feqrel(-0.9) > 16 && n == 2); 5060 assert(remquo(-5.1, 3.0, n).feqrel(0.9) > 16 && n == -2); 5061 assert(remquo(0.0, 3.0, n) == 0.0 && n == 0); 5062 } 5063 5064 5065 version (IeeeFlagsSupport) 5066 { 5067 5068 /** IEEE exception status flags ('sticky bits') 5069 5070 These flags indicate that an exceptional floating-point condition has occurred. 5071 They indicate that a NaN or an infinity has been generated, that a result 5072 is inexact, or that a signalling NaN has been encountered. If floating-point 5073 exceptions are enabled (unmasked), a hardware exception will be generated 5074 instead of setting these flags. 5075 */ 5076 struct IeeeFlags 5077 { 5078 nothrow @nogc: 5079 5080 private: 5081 // The x87 FPU status register is 16 bits. 5082 // The Pentium SSE2 status register is 32 bits. 5083 // The ARM and PowerPC FPSCR is a 32-bit register. 5084 // The SPARC FSR is a 32bit register (64 bits for SPARC 7 & 8, but high bits are uninteresting). 5085 // The RISC-V (32 & 64 bit) fcsr is 32-bit register. 5086 uint flags; 5087 5088 version (CRuntime_Microsoft) 5089 { 5090 // Microsoft uses hardware-incompatible custom constants in fenv.h (core.stdc.fenv). 5091 // Applies to both x87 status word (16 bits) and SSE2 status word(32 bits). 5092 enum : int 5093 { 5094 INEXACT_MASK = 0x20, 5095 UNDERFLOW_MASK = 0x10, 5096 OVERFLOW_MASK = 0x08, 5097 DIVBYZERO_MASK = 0x04, 5098 INVALID_MASK = 0x01, 5099 5100 EXCEPTIONS_MASK = 0b11_1111 5101 } 5102 // Don't bother about subnormals, they are not supported on most CPUs. 5103 // SUBNORMAL_MASK = 0x02; 5104 } 5105 else 5106 { 5107 enum : int 5108 { 5109 INEXACT_MASK = core.stdc.fenv.FE_INEXACT, 5110 UNDERFLOW_MASK = core.stdc.fenv.FE_UNDERFLOW, 5111 OVERFLOW_MASK = core.stdc.fenv.FE_OVERFLOW, 5112 DIVBYZERO_MASK = core.stdc.fenv.FE_DIVBYZERO, 5113 INVALID_MASK = core.stdc.fenv.FE_INVALID, 5114 EXCEPTIONS_MASK = core.stdc.fenv.FE_ALL_EXCEPT, 5115 } 5116 } 5117 5118 static uint getIeeeFlags() @trusted pure 5119 { 5120 version (InlineAsm_X86_Any) 5121 { 5122 ushort sw; 5123 asm pure nothrow @nogc { fstsw sw; } 5124 5125 // OR the result with the SSE2 status register (MXCSR). 5126 if (haveSSE) 5127 { 5128 uint mxcsr; 5129 asm pure nothrow @nogc { stmxcsr mxcsr; } 5130 return (sw | mxcsr) & EXCEPTIONS_MASK; 5131 } 5132 else return sw & EXCEPTIONS_MASK; 5133 } 5134 else version (SPARC) 5135 { 5136 /* 5137 int retval; 5138 asm pure nothrow @nogc { st %fsr, retval; } 5139 return retval; 5140 */ 5141 assert(0, "Not yet supported"); 5142 } 5143 else version (ARM) 5144 { 5145 assert(false, "Not yet supported."); 5146 } 5147 else version (RISCV_Any) 5148 { 5149 mixin(` 5150 uint result = void; 5151 asm pure nothrow @nogc 5152 { 5153 "frflags %0" : "=r" (result); 5154 } 5155 return result; 5156 `); 5157 } 5158 else 5159 assert(0, "Not yet supported"); 5160 } 5161 5162 static void resetIeeeFlags() @trusted 5163 { 5164 version (InlineAsm_X86_Any) 5165 { 5166 asm nothrow @nogc 5167 { 5168 fnclex; 5169 } 5170 5171 // Also clear exception flags in MXCSR, SSE's control register. 5172 if (haveSSE) 5173 { 5174 uint mxcsr; 5175 asm nothrow @nogc { stmxcsr mxcsr; } 5176 mxcsr &= ~EXCEPTIONS_MASK; 5177 asm nothrow @nogc { ldmxcsr mxcsr; } 5178 } 5179 } 5180 else version (RISCV_Any) 5181 { 5182 mixin(` 5183 uint newValues = 0x0; 5184 asm pure nothrow @nogc 5185 { 5186 "fsflags %0" : : "r" (newValues); 5187 } 5188 `); 5189 } 5190 else 5191 { 5192 /* SPARC: 5193 int tmpval; 5194 asm pure nothrow @nogc { st %fsr, tmpval; } 5195 tmpval &=0xFFFF_FC00; 5196 asm pure nothrow @nogc { ld tmpval, %fsr; } 5197 */ 5198 assert(0, "Not yet supported"); 5199 } 5200 } 5201 5202 public: 5203 /** 5204 * The result cannot be represented exactly, so rounding occurred. 5205 * Example: `x = sin(0.1);` 5206 */ 5207 @property bool inexact() @safe const { return (flags & INEXACT_MASK) != 0; } 5208 5209 /** 5210 * A zero was generated by underflow 5211 * Example: `x = real.min*real.epsilon/2;` 5212 */ 5213 @property bool underflow() @safe const { return (flags & UNDERFLOW_MASK) != 0; } 5214 5215 /** 5216 * An infinity was generated by overflow 5217 * Example: `x = real.max*2;` 5218 */ 5219 @property bool overflow() @safe const { return (flags & OVERFLOW_MASK) != 0; } 5220 5221 /** 5222 * An infinity was generated by division by zero 5223 * Example: `x = 3/0.0;` 5224 */ 5225 @property bool divByZero() @safe const { return (flags & DIVBYZERO_MASK) != 0; } 5226 5227 /** 5228 * A machine NaN was generated. 5229 * Example: `x = real.infinity * 0.0;` 5230 */ 5231 @property bool invalid() @safe const { return (flags & INVALID_MASK) != 0; } 5232 } 5233 5234 /// 5235 @safe unittest 5236 { 5237 static void func() { 5238 int a = 10 * 10; 5239 } 5240 pragma(inline, false) static void blockopt(ref real x) {} 5241 real a = 3.5; 5242 // Set all the flags to zero 5243 resetIeeeFlags(); 5244 assert(!ieeeFlags.divByZero); 5245 blockopt(a); // avoid constant propagation by the optimizer 5246 // Perform a division by zero. 5247 a /= 0.0L; 5248 assert(a == real.infinity); 5249 assert(ieeeFlags.divByZero); 5250 blockopt(a); // avoid constant propagation by the optimizer 5251 // Create a NaN 5252 a *= 0.0L; 5253 assert(ieeeFlags.invalid); 5254 assert(isNaN(a)); 5255 5256 // Check that calling func() has no effect on the 5257 // status flags. 5258 IeeeFlags f = ieeeFlags; 5259 func(); 5260 assert(ieeeFlags == f); 5261 } 5262 5263 @safe unittest 5264 { 5265 import std.meta : AliasSeq; 5266 5267 static struct Test 5268 { 5269 void delegate() @trusted action; 5270 bool function() @trusted ieeeCheck; 5271 } 5272 5273 static foreach (T; AliasSeq!(float, double, real)) 5274 {{ 5275 T x; /* Needs to be here to trick -O. It would optimize away the 5276 calculations if x were local to the function literals. */ 5277 auto tests = [ 5278 Test( 5279 () { x = 1; x += 0.1L; }, 5280 () => ieeeFlags.inexact 5281 ), 5282 Test( 5283 () { x = T.min_normal; x /= T.max; }, 5284 () => ieeeFlags.underflow 5285 ), 5286 Test( 5287 () { x = T.max; x += T.max; }, 5288 () => ieeeFlags.overflow 5289 ), 5290 Test( 5291 () { x = 1; x /= 0; }, 5292 () => ieeeFlags.divByZero 5293 ), 5294 Test( 5295 () { x = 0; x /= 0; }, 5296 () => ieeeFlags.invalid 5297 ) 5298 ]; 5299 foreach (test; tests) 5300 { 5301 resetIeeeFlags(); 5302 assert(!test.ieeeCheck()); 5303 test.action(); 5304 assert(test.ieeeCheck()); 5305 } 5306 }} 5307 } 5308 5309 /// Set all of the floating-point status flags to false. 5310 void resetIeeeFlags() @trusted nothrow @nogc 5311 { 5312 IeeeFlags.resetIeeeFlags(); 5313 } 5314 5315 /// 5316 @safe unittest 5317 { 5318 pragma(inline, false) static void blockopt(ref real x) {} 5319 resetIeeeFlags(); 5320 real a = 3.5; 5321 blockopt(a); // avoid constant propagation by the optimizer 5322 a /= 0.0L; 5323 blockopt(a); // avoid constant propagation by the optimizer 5324 assert(a == real.infinity); 5325 assert(ieeeFlags.divByZero); 5326 5327 resetIeeeFlags(); 5328 assert(!ieeeFlags.divByZero); 5329 } 5330 5331 /// Returns: snapshot of the current state of the floating-point status flags 5332 @property IeeeFlags ieeeFlags() @trusted pure nothrow @nogc 5333 { 5334 return IeeeFlags(IeeeFlags.getIeeeFlags()); 5335 } 5336 5337 /// 5338 @safe nothrow unittest 5339 { 5340 pragma(inline, false) static void blockopt(ref real x) {} 5341 resetIeeeFlags(); 5342 real a = 3.5; 5343 blockopt(a); // avoid constant propagation by the optimizer 5344 5345 a /= 0.0L; 5346 assert(a == real.infinity); 5347 assert(ieeeFlags.divByZero); 5348 blockopt(a); // avoid constant propagation by the optimizer 5349 5350 a *= 0.0L; 5351 assert(isNaN(a)); 5352 assert(ieeeFlags.invalid); 5353 } 5354 5355 } // IeeeFlagsSupport 5356 5357 5358 version (FloatingPointControlSupport) 5359 { 5360 5361 /** Control the Floating point hardware 5362 5363 Change the IEEE754 floating-point rounding mode and the floating-point 5364 hardware exceptions. 5365 5366 By default, the rounding mode is roundToNearest and all hardware exceptions 5367 are disabled. For most applications, debugging is easier if the $(I division 5368 by zero), $(I overflow), and $(I invalid operation) exceptions are enabled. 5369 These three are combined into a $(I severeExceptions) value for convenience. 5370 Note in particular that if $(I invalidException) is enabled, a hardware trap 5371 will be generated whenever an uninitialized floating-point variable is used. 5372 5373 All changes are temporary. The previous state is restored at the 5374 end of the scope. 5375 5376 5377 Example: 5378 ---- 5379 { 5380 FloatingPointControl fpctrl; 5381 5382 // Enable hardware exceptions for division by zero, overflow to infinity, 5383 // invalid operations, and uninitialized floating-point variables. 5384 fpctrl.enableExceptions(FloatingPointControl.severeExceptions); 5385 5386 // This will generate a hardware exception, if x is a 5387 // default-initialized floating point variable: 5388 real x; // Add `= 0` or even `= real.nan` to not throw the exception. 5389 real y = x * 3.0; 5390 5391 // The exception is only thrown for default-uninitialized NaN-s. 5392 // NaN-s with other payload are valid: 5393 real z = y * real.nan; // ok 5394 5395 // The set hardware exceptions and rounding modes will be disabled when 5396 // leaving this scope. 5397 } 5398 ---- 5399 5400 */ 5401 struct FloatingPointControl 5402 { 5403 nothrow @nogc: 5404 5405 alias RoundingMode = uint; /// 5406 5407 version (StdDdoc) 5408 { 5409 enum : RoundingMode 5410 { 5411 /** IEEE rounding modes. 5412 * The default mode is roundToNearest. 5413 * 5414 * roundingMask = A mask of all rounding modes. 5415 */ 5416 roundToNearest, 5417 roundDown, /// ditto 5418 roundUp, /// ditto 5419 roundToZero, /// ditto 5420 roundingMask, /// ditto 5421 } 5422 } 5423 else version (CRuntime_Microsoft) 5424 { 5425 // Microsoft uses hardware-incompatible custom constants in fenv.h (core.stdc.fenv). 5426 enum : RoundingMode 5427 { 5428 roundToNearest = 0x0000, 5429 roundDown = 0x0400, 5430 roundUp = 0x0800, 5431 roundToZero = 0x0C00, 5432 roundingMask = roundToNearest | roundDown 5433 | roundUp | roundToZero, 5434 } 5435 } 5436 else 5437 { 5438 enum : RoundingMode 5439 { 5440 roundToNearest = core.stdc.fenv.FE_TONEAREST, 5441 roundDown = core.stdc.fenv.FE_DOWNWARD, 5442 roundUp = core.stdc.fenv.FE_UPWARD, 5443 roundToZero = core.stdc.fenv.FE_TOWARDZERO, 5444 roundingMask = roundToNearest | roundDown 5445 | roundUp | roundToZero, 5446 } 5447 } 5448 5449 /*** 5450 * Change the floating-point hardware rounding mode 5451 * 5452 * Changing the rounding mode in the middle of a function can interfere 5453 * with optimizations of floating point expressions, as the optimizer assumes 5454 * that the rounding mode does not change. 5455 * It is best to change the rounding mode only at the 5456 * beginning of the function, and keep it until the function returns. 5457 * It is also best to add the line: 5458 * --- 5459 * pragma(inline, false); 5460 * --- 5461 * as the first line of the function so it will not get inlined. 5462 * Params: 5463 * newMode = the new rounding mode 5464 */ 5465 @property void rounding(RoundingMode newMode) @trusted 5466 { 5467 initialize(); 5468 setControlState((getControlState() & (-1 - roundingMask)) | (newMode & roundingMask)); 5469 } 5470 5471 /// Returns: the currently active rounding mode 5472 @property static RoundingMode rounding() @trusted pure 5473 { 5474 return cast(RoundingMode)(getControlState() & roundingMask); 5475 } 5476 5477 alias ExceptionMask = uint; /// 5478 5479 version (StdDdoc) 5480 { 5481 enum : ExceptionMask 5482 { 5483 /** IEEE hardware exceptions. 5484 * By default, all exceptions are masked (disabled). 5485 * 5486 * severeExceptions = The overflow, division by zero, and invalid 5487 * exceptions. 5488 */ 5489 subnormalException, 5490 inexactException, /// ditto 5491 underflowException, /// ditto 5492 overflowException, /// ditto 5493 divByZeroException, /// ditto 5494 invalidException, /// ditto 5495 severeExceptions, /// ditto 5496 allExceptions, /// ditto 5497 } 5498 } 5499 else version (ARM_Any) 5500 { 5501 enum : ExceptionMask 5502 { 5503 subnormalException = 0x8000, 5504 inexactException = 0x1000, 5505 underflowException = 0x0800, 5506 overflowException = 0x0400, 5507 divByZeroException = 0x0200, 5508 invalidException = 0x0100, 5509 severeExceptions = overflowException | divByZeroException 5510 | invalidException, 5511 allExceptions = severeExceptions | underflowException 5512 | inexactException | subnormalException, 5513 } 5514 } 5515 else version (PPC_Any) 5516 { 5517 enum : ExceptionMask 5518 { 5519 inexactException = 0x0008, 5520 divByZeroException = 0x0010, 5521 underflowException = 0x0020, 5522 overflowException = 0x0040, 5523 invalidException = 0x0080, 5524 severeExceptions = overflowException | divByZeroException 5525 | invalidException, 5526 allExceptions = severeExceptions | underflowException 5527 | inexactException, 5528 } 5529 } 5530 else version (RISCV_Any) 5531 { 5532 enum : ExceptionMask 5533 { 5534 inexactException = 0x01, 5535 divByZeroException = 0x02, 5536 underflowException = 0x04, 5537 overflowException = 0x08, 5538 invalidException = 0x10, 5539 severeExceptions = overflowException | divByZeroException 5540 | invalidException, 5541 allExceptions = severeExceptions | underflowException 5542 | inexactException, 5543 } 5544 } 5545 else version (HPPA) 5546 { 5547 enum : ExceptionMask 5548 { 5549 inexactException = 0x01, 5550 underflowException = 0x02, 5551 overflowException = 0x04, 5552 divByZeroException = 0x08, 5553 invalidException = 0x10, 5554 severeExceptions = overflowException | divByZeroException 5555 | invalidException, 5556 allExceptions = severeExceptions | underflowException 5557 | inexactException, 5558 } 5559 } 5560 else version (MIPS_Any) 5561 { 5562 enum : ExceptionMask 5563 { 5564 inexactException = 0x0080, 5565 divByZeroException = 0x0400, 5566 overflowException = 0x0200, 5567 underflowException = 0x0100, 5568 invalidException = 0x0800, 5569 severeExceptions = overflowException | divByZeroException 5570 | invalidException, 5571 allExceptions = severeExceptions | underflowException 5572 | inexactException, 5573 } 5574 } 5575 else version (SPARC_Any) 5576 { 5577 enum : ExceptionMask 5578 { 5579 inexactException = 0x0800000, 5580 divByZeroException = 0x1000000, 5581 overflowException = 0x4000000, 5582 underflowException = 0x2000000, 5583 invalidException = 0x8000000, 5584 severeExceptions = overflowException | divByZeroException 5585 | invalidException, 5586 allExceptions = severeExceptions | underflowException 5587 | inexactException, 5588 } 5589 } 5590 else version (IBMZ_Any) 5591 { 5592 enum : ExceptionMask 5593 { 5594 inexactException = 0x08000000, 5595 divByZeroException = 0x40000000, 5596 overflowException = 0x20000000, 5597 underflowException = 0x10000000, 5598 invalidException = 0x80000000, 5599 severeExceptions = overflowException | divByZeroException 5600 | invalidException, 5601 allExceptions = severeExceptions | underflowException 5602 | inexactException, 5603 } 5604 } 5605 else version (X86_Any) 5606 { 5607 enum : ExceptionMask 5608 { 5609 inexactException = 0x20, 5610 underflowException = 0x10, 5611 overflowException = 0x08, 5612 divByZeroException = 0x04, 5613 subnormalException = 0x02, 5614 invalidException = 0x01, 5615 severeExceptions = overflowException | divByZeroException 5616 | invalidException, 5617 allExceptions = severeExceptions | underflowException 5618 | inexactException | subnormalException, 5619 } 5620 } 5621 else 5622 static assert(false, "Not implemented for this architecture"); 5623 5624 version (ARM_Any) 5625 { 5626 static bool hasExceptionTraps_impl() @safe 5627 { 5628 auto oldState = getControlState(); 5629 // If exceptions are not supported, we set the bit but read it back as zero 5630 // https://sourceware.org/ml/libc-ports/2012-06/msg00091.html 5631 setControlState(oldState | divByZeroException); 5632 immutable result = (getControlState() & allExceptions) != 0; 5633 setControlState(oldState); 5634 return result; 5635 } 5636 } 5637 5638 /// Returns: true if the current FPU supports exception trapping 5639 @property static bool hasExceptionTraps() @safe pure 5640 { 5641 version (X86_Any) 5642 return true; 5643 else version (PPC_Any) 5644 return true; 5645 else version (MIPS_Any) 5646 return true; 5647 else version (ARM_Any) 5648 { 5649 // The hasExceptionTraps_impl function is basically pure, 5650 // as it restores all global state 5651 auto fptr = ( () @trusted => cast(bool function() @safe 5652 pure nothrow @nogc)&hasExceptionTraps_impl)(); 5653 return fptr(); 5654 } 5655 else 5656 assert(0, "Not yet supported"); 5657 } 5658 5659 /// Enable (unmask) specific hardware exceptions. Multiple exceptions may be ORed together. 5660 void enableExceptions(ExceptionMask exceptions) @trusted 5661 { 5662 assert(hasExceptionTraps); 5663 initialize(); 5664 version (X86_Any) 5665 setControlState(getControlState() & ~(exceptions & allExceptions)); 5666 else 5667 setControlState(getControlState() | (exceptions & allExceptions)); 5668 } 5669 5670 /// Disable (mask) specific hardware exceptions. Multiple exceptions may be ORed together. 5671 void disableExceptions(ExceptionMask exceptions) @trusted 5672 { 5673 assert(hasExceptionTraps); 5674 initialize(); 5675 version (X86_Any) 5676 setControlState(getControlState() | (exceptions & allExceptions)); 5677 else 5678 setControlState(getControlState() & ~(exceptions & allExceptions)); 5679 } 5680 5681 /// Returns: the exceptions which are currently enabled (unmasked) 5682 @property static ExceptionMask enabledExceptions() @trusted pure 5683 { 5684 assert(hasExceptionTraps); 5685 version (X86_Any) 5686 return (getControlState() & allExceptions) ^ allExceptions; 5687 else 5688 return (getControlState() & allExceptions); 5689 } 5690 5691 /// Clear all pending exceptions, then restore the original exception state and rounding mode. 5692 ~this() @trusted 5693 { 5694 clearExceptions(); 5695 if (initialized) 5696 setControlState(savedState); 5697 } 5698 5699 private: 5700 ControlState savedState; 5701 5702 bool initialized = false; 5703 5704 version (ARM_Any) 5705 { 5706 alias ControlState = uint; 5707 } 5708 else version (HPPA) 5709 { 5710 alias ControlState = uint; 5711 } 5712 else version (PPC_Any) 5713 { 5714 alias ControlState = uint; 5715 } 5716 else version (RISCV_Any) 5717 { 5718 alias ControlState = uint; 5719 } 5720 else version (MIPS_Any) 5721 { 5722 alias ControlState = uint; 5723 } 5724 else version (SPARC_Any) 5725 { 5726 alias ControlState = ulong; 5727 } 5728 else version (IBMZ_Any) 5729 { 5730 alias ControlState = uint; 5731 } 5732 else version (X86_Any) 5733 { 5734 alias ControlState = ushort; 5735 } 5736 else 5737 static assert(false, "Not implemented for this architecture"); 5738 5739 void initialize() @safe 5740 { 5741 // BUG: This works around the absence of this() constructors. 5742 if (initialized) return; 5743 clearExceptions(); 5744 savedState = getControlState(); 5745 initialized = true; 5746 } 5747 5748 // Clear all pending exceptions 5749 static void clearExceptions() @safe 5750 { 5751 version (IeeeFlagsSupport) 5752 resetIeeeFlags(); 5753 else 5754 static assert(false, "Not implemented for this architecture"); 5755 } 5756 5757 // Read from the control register 5758 static ControlState getControlState() @trusted pure 5759 { 5760 version (D_InlineAsm_X86) 5761 { 5762 short cont; 5763 asm pure nothrow @nogc 5764 { 5765 xor EAX, EAX; 5766 fstcw cont; 5767 } 5768 return cont; 5769 } 5770 else 5771 version (D_InlineAsm_X86_64) 5772 { 5773 short cont; 5774 asm pure nothrow @nogc 5775 { 5776 xor RAX, RAX; 5777 fstcw cont; 5778 } 5779 return cont; 5780 } 5781 else version (RISCV_Any) 5782 { 5783 mixin(` 5784 ControlState cont; 5785 asm pure nothrow @nogc 5786 { 5787 "frcsr %0" : "=r" (cont); 5788 } 5789 return cont; 5790 `); 5791 } 5792 else 5793 assert(0, "Not yet supported"); 5794 } 5795 5796 // Set the control register 5797 static void setControlState(ControlState newState) @trusted 5798 { 5799 version (InlineAsm_X86_Any) 5800 { 5801 asm nothrow @nogc 5802 { 5803 fclex; 5804 fldcw newState; 5805 } 5806 5807 // Also update MXCSR, SSE's control register. 5808 if (haveSSE) 5809 { 5810 uint mxcsr; 5811 asm nothrow @nogc { stmxcsr mxcsr; } 5812 5813 /* In the FPU control register, rounding mode is in bits 10 and 5814 11. In MXCSR it's in bits 13 and 14. */ 5815 mxcsr &= ~(roundingMask << 3); // delete old rounding mode 5816 mxcsr |= (newState & roundingMask) << 3; // write new rounding mode 5817 5818 /* In the FPU control register, masks are bits 0 through 5. 5819 In MXCSR they're 7 through 12. */ 5820 mxcsr &= ~(allExceptions << 7); // delete old masks 5821 mxcsr |= (newState & allExceptions) << 7; // write new exception masks 5822 5823 asm nothrow @nogc { ldmxcsr mxcsr; } 5824 } 5825 } 5826 else version (RISCV_Any) 5827 { 5828 mixin(` 5829 asm pure nothrow @nogc 5830 { 5831 "fscsr %0" : : "r" (newState); 5832 } 5833 `); 5834 } 5835 else 5836 assert(0, "Not yet supported"); 5837 } 5838 } 5839 5840 /// 5841 @safe unittest 5842 { 5843 FloatingPointControl fpctrl; 5844 5845 fpctrl.rounding = FloatingPointControl.roundDown; 5846 assert(lrint(1.5) == 1.0); 5847 5848 fpctrl.rounding = FloatingPointControl.roundUp; 5849 assert(lrint(1.4) == 2.0); 5850 5851 fpctrl.rounding = FloatingPointControl.roundToNearest; 5852 assert(lrint(1.5) == 2.0); 5853 } 5854 5855 @safe unittest 5856 { 5857 void ensureDefaults() 5858 { 5859 assert(FloatingPointControl.rounding 5860 == FloatingPointControl.roundToNearest); 5861 if (FloatingPointControl.hasExceptionTraps) 5862 assert(FloatingPointControl.enabledExceptions == 0); 5863 } 5864 5865 { 5866 FloatingPointControl ctrl; 5867 } 5868 ensureDefaults(); 5869 5870 { 5871 FloatingPointControl ctrl; 5872 ctrl.rounding = FloatingPointControl.roundDown; 5873 assert(FloatingPointControl.rounding == FloatingPointControl.roundDown); 5874 } 5875 ensureDefaults(); 5876 5877 if (FloatingPointControl.hasExceptionTraps) 5878 { 5879 FloatingPointControl ctrl; 5880 ctrl.enableExceptions(FloatingPointControl.divByZeroException 5881 | FloatingPointControl.overflowException); 5882 assert(ctrl.enabledExceptions == 5883 (FloatingPointControl.divByZeroException 5884 | FloatingPointControl.overflowException)); 5885 5886 ctrl.rounding = FloatingPointControl.roundUp; 5887 assert(FloatingPointControl.rounding == FloatingPointControl.roundUp); 5888 } 5889 ensureDefaults(); 5890 } 5891 5892 @safe unittest // rounding 5893 { 5894 import std.meta : AliasSeq; 5895 5896 static foreach (T; AliasSeq!(float, double, real)) 5897 {{ 5898 /* Be careful with changing the rounding mode, it interferes 5899 * with common subexpressions. Changing rounding modes should 5900 * be done with separate functions that are not inlined. 5901 */ 5902 5903 { 5904 static T addRound(T)(uint rm) 5905 { 5906 pragma(inline, false) static void blockopt(ref T x) {} 5907 pragma(inline, false); 5908 FloatingPointControl fpctrl; 5909 fpctrl.rounding = rm; 5910 T x = 1; 5911 blockopt(x); // avoid constant propagation by the optimizer 5912 x += 0.1L; 5913 return x; 5914 } 5915 5916 T u = addRound!(T)(FloatingPointControl.roundUp); 5917 T d = addRound!(T)(FloatingPointControl.roundDown); 5918 T z = addRound!(T)(FloatingPointControl.roundToZero); 5919 5920 assert(u > d); 5921 assert(z == d); 5922 } 5923 5924 { 5925 static T subRound(T)(uint rm) 5926 { 5927 pragma(inline, false) static void blockopt(ref T x) {} 5928 pragma(inline, false); 5929 FloatingPointControl fpctrl; 5930 fpctrl.rounding = rm; 5931 T x = -1; 5932 blockopt(x); // avoid constant propagation by the optimizer 5933 x -= 0.1L; 5934 return x; 5935 } 5936 5937 T u = subRound!(T)(FloatingPointControl.roundUp); 5938 T d = subRound!(T)(FloatingPointControl.roundDown); 5939 T z = subRound!(T)(FloatingPointControl.roundToZero); 5940 5941 assert(u > d); 5942 assert(z == u); 5943 } 5944 }} 5945 } 5946 5947 } // FloatingPointControlSupport 5948 5949 5950 /********************************* 5951 * Determines if $(D_PARAM x) is NaN. 5952 * Params: 5953 * x = a floating point number. 5954 * Returns: 5955 * `true` if $(D_PARAM x) is Nan. 5956 */ 5957 bool isNaN(X)(X x) @nogc @trusted pure nothrow 5958 if (isFloatingPoint!(X)) 5959 { 5960 version (all) 5961 { 5962 return x != x; 5963 } 5964 else 5965 { 5966 /* 5967 Code kept for historical context. At least on Intel, the simple test 5968 x != x uses one dedicated instruction (ucomiss/ucomisd) that runs in one 5969 cycle. Code for 80- and 128-bits is larger but still smaller than the 5970 integrals-based solutions below. Future revisions may enable the code 5971 below conditionally depending on hardware. 5972 */ 5973 alias F = floatTraits!(X); 5974 static if (F.realFormat == RealFormat.ieeeSingle) 5975 { 5976 const uint p = *cast(uint *)&x; 5977 // Sign bit (MSB) is irrelevant so mask it out. 5978 // Next 8 bits should be all set. 5979 // At least one bit among the least significant 23 bits should be set. 5980 return (p & 0x7FFF_FFFF) > 0x7F80_0000; 5981 } 5982 else static if (F.realFormat == RealFormat.ieeeDouble) 5983 { 5984 const ulong p = *cast(ulong *)&x; 5985 // Sign bit (MSB) is irrelevant so mask it out. 5986 // Next 11 bits should be all set. 5987 // At least one bit among the least significant 52 bits should be set. 5988 return (p & 0x7FFF_FFFF_FFFF_FFFF) > 0x7FF0_0000_0000_0000; 5989 } 5990 else static if (F.realFormat == RealFormat.ieeeExtended) 5991 { 5992 const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 5993 const ulong ps = *cast(ulong *)&x; 5994 return e == F.EXPMASK && 5995 ps & 0x7FFF_FFFF_FFFF_FFFF; // not infinity 5996 } 5997 else static if (F.realFormat == RealFormat.ieeeQuadruple) 5998 { 5999 const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 6000 const ulong psLsb = (cast(ulong *)&x)[MANTISSA_LSB]; 6001 const ulong psMsb = (cast(ulong *)&x)[MANTISSA_MSB]; 6002 return e == F.EXPMASK && 6003 (psLsb | (psMsb& 0x0000_FFFF_FFFF_FFFF)) != 0; 6004 } 6005 else 6006 { 6007 return x != x; 6008 } 6009 } 6010 } 6011 6012 /// 6013 @safe pure nothrow @nogc unittest 6014 { 6015 assert( isNaN(float.init)); 6016 assert( isNaN(-double.init)); 6017 assert( isNaN(real.nan)); 6018 assert( isNaN(-real.nan)); 6019 assert(!isNaN(cast(float) 53.6)); 6020 assert(!isNaN(cast(real)-53.6)); 6021 } 6022 6023 @safe pure nothrow @nogc unittest 6024 { 6025 import std.meta : AliasSeq; 6026 6027 static foreach (T; AliasSeq!(float, double, real)) 6028 {{ 6029 // CTFE-able tests 6030 assert(isNaN(T.init)); 6031 assert(isNaN(-T.init)); 6032 assert(isNaN(T.nan)); 6033 assert(isNaN(-T.nan)); 6034 assert(!isNaN(T.infinity)); 6035 assert(!isNaN(-T.infinity)); 6036 assert(!isNaN(cast(T) 53.6)); 6037 assert(!isNaN(cast(T)-53.6)); 6038 6039 // Runtime tests 6040 shared T f; 6041 f = T.init; 6042 assert(isNaN(f)); 6043 assert(isNaN(-f)); 6044 f = T.nan; 6045 assert(isNaN(f)); 6046 assert(isNaN(-f)); 6047 f = T.infinity; 6048 assert(!isNaN(f)); 6049 assert(!isNaN(-f)); 6050 f = cast(T) 53.6; 6051 assert(!isNaN(f)); 6052 assert(!isNaN(-f)); 6053 }} 6054 } 6055 6056 /********************************* 6057 * Determines if $(D_PARAM x) is finite. 6058 * Params: 6059 * x = a floating point number. 6060 * Returns: 6061 * `true` if $(D_PARAM x) is finite. 6062 */ 6063 bool isFinite(X)(X x) @trusted pure nothrow @nogc 6064 { 6065 static if (__traits(isFloating, X)) 6066 if (__ctfe) 6067 return x == x && x != X.infinity && x != -X.infinity; 6068 alias F = floatTraits!(X); 6069 ushort* pe = cast(ushort *)&x; 6070 return (pe[F.EXPPOS_SHORT] & F.EXPMASK) != F.EXPMASK; 6071 } 6072 6073 /// 6074 @safe pure nothrow @nogc unittest 6075 { 6076 assert( isFinite(1.23f)); 6077 assert( isFinite(float.max)); 6078 assert( isFinite(float.min_normal)); 6079 assert(!isFinite(float.nan)); 6080 assert(!isFinite(float.infinity)); 6081 } 6082 6083 @safe pure nothrow @nogc unittest 6084 { 6085 assert(isFinite(1.23)); 6086 assert(isFinite(double.max)); 6087 assert(isFinite(double.min_normal)); 6088 assert(!isFinite(double.nan)); 6089 assert(!isFinite(double.infinity)); 6090 6091 assert(isFinite(1.23L)); 6092 assert(isFinite(real.max)); 6093 assert(isFinite(real.min_normal)); 6094 assert(!isFinite(real.nan)); 6095 assert(!isFinite(real.infinity)); 6096 6097 //CTFE 6098 static assert(isFinite(1.23)); 6099 static assert(isFinite(double.max)); 6100 static assert(isFinite(double.min_normal)); 6101 static assert(!isFinite(double.nan)); 6102 static assert(!isFinite(double.infinity)); 6103 6104 static assert(isFinite(1.23L)); 6105 static assert(isFinite(real.max)); 6106 static assert(isFinite(real.min_normal)); 6107 static assert(!isFinite(real.nan)); 6108 static assert(!isFinite(real.infinity)); 6109 } 6110 6111 6112 /********************************* 6113 * Determines if $(D_PARAM x) is normalized. 6114 * 6115 * A normalized number must not be zero, subnormal, infinite nor $(NAN). 6116 * 6117 * Params: 6118 * x = a floating point number. 6119 * Returns: 6120 * `true` if $(D_PARAM x) is normalized. 6121 */ 6122 6123 /* Need one for each format because subnormal floats might 6124 * be converted to normal reals. 6125 */ 6126 bool isNormal(X)(X x) @trusted pure nothrow @nogc 6127 { 6128 static if (__traits(isFloating, X)) 6129 if (__ctfe) 6130 return (x <= -X.min_normal && x != -X.infinity) || (x >= X.min_normal && x != X.infinity); 6131 alias F = floatTraits!(X); 6132 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 6133 return (e != F.EXPMASK && e != 0); 6134 } 6135 6136 /// 6137 @safe pure nothrow @nogc unittest 6138 { 6139 float f = 3; 6140 double d = 500; 6141 real e = 10e+48; 6142 6143 assert(isNormal(f)); 6144 assert(isNormal(d)); 6145 assert(isNormal(e)); 6146 f = d = e = 0; 6147 assert(!isNormal(f)); 6148 assert(!isNormal(d)); 6149 assert(!isNormal(e)); 6150 assert(!isNormal(real.infinity)); 6151 assert(isNormal(-real.max)); 6152 assert(!isNormal(real.min_normal/4)); 6153 6154 } 6155 6156 @safe pure nothrow @nogc unittest 6157 { 6158 // CTFE 6159 enum float f = 3; 6160 enum double d = 500; 6161 enum real e = 10e+48; 6162 6163 static assert(isNormal(f)); 6164 static assert(isNormal(d)); 6165 static assert(isNormal(e)); 6166 6167 static assert(!isNormal(0.0f)); 6168 static assert(!isNormal(0.0)); 6169 static assert(!isNormal(0.0L)); 6170 static assert(!isNormal(real.infinity)); 6171 static assert(isNormal(-real.max)); 6172 static assert(!isNormal(real.min_normal/4)); 6173 } 6174 6175 /********************************* 6176 * Determines if $(D_PARAM x) is subnormal. 6177 * 6178 * Subnormals (also known as "denormal number"), have a 0 exponent 6179 * and a 0 most significant mantissa bit. 6180 * 6181 * Params: 6182 * x = a floating point number. 6183 * Returns: 6184 * `true` if $(D_PARAM x) is a denormal number. 6185 */ 6186 bool isSubnormal(X)(X x) @trusted pure nothrow @nogc 6187 { 6188 static if (__traits(isFloating, X)) 6189 if (__ctfe) 6190 return -X.min_normal < x && x < X.min_normal; 6191 /* 6192 Need one for each format because subnormal floats might 6193 be converted to normal reals. 6194 */ 6195 alias F = floatTraits!(X); 6196 static if (F.realFormat == RealFormat.ieeeSingle) 6197 { 6198 uint *p = cast(uint *)&x; 6199 return (*p & F.EXPMASK_INT) == 0 && *p & F.MANTISSAMASK_INT; 6200 } 6201 else static if (F.realFormat == RealFormat.ieeeDouble) 6202 { 6203 uint *p = cast(uint *)&x; 6204 return (p[MANTISSA_MSB] & F.EXPMASK_INT) == 0 6205 && (p[MANTISSA_LSB] || p[MANTISSA_MSB] & F.MANTISSAMASK_INT); 6206 } 6207 else static if (F.realFormat == RealFormat.ieeeQuadruple) 6208 { 6209 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 6210 long* ps = cast(long *)&x; 6211 return (e == 0 && 6212 ((ps[MANTISSA_LSB]|(ps[MANTISSA_MSB]& 0x0000_FFFF_FFFF_FFFF)) != 0)); 6213 } 6214 else static if (F.realFormat == RealFormat.ieeeExtended) 6215 { 6216 ushort* pe = cast(ushort *)&x; 6217 long* ps = cast(long *)&x; 6218 6219 return (pe[F.EXPPOS_SHORT] & F.EXPMASK) == 0 && *ps > 0; 6220 } 6221 else 6222 { 6223 static assert(false, "Not implemented for this architecture"); 6224 } 6225 } 6226 6227 /// 6228 @safe pure nothrow @nogc unittest 6229 { 6230 import std.meta : AliasSeq; 6231 6232 static foreach (T; AliasSeq!(float, double, real)) 6233 {{ 6234 T f; 6235 for (f = 1.0; !isSubnormal(f); f /= 2) 6236 assert(f != 0); 6237 }} 6238 } 6239 6240 @safe pure nothrow @nogc unittest 6241 { 6242 static bool subnormalTest(T)() 6243 { 6244 T f; 6245 for (f = 1.0; !isSubnormal(f); f /= 2) 6246 if (f == 0) 6247 return false; 6248 return true; 6249 } 6250 static assert(subnormalTest!float()); 6251 static assert(subnormalTest!double()); 6252 static assert(subnormalTest!real()); 6253 } 6254 6255 /********************************* 6256 * Determines if $(D_PARAM x) is $(PLUSMN)$(INFIN). 6257 * Params: 6258 * x = a floating point number. 6259 * Returns: 6260 * `true` if $(D_PARAM x) is $(PLUSMN)$(INFIN). 6261 */ 6262 bool isInfinity(X)(X x) @nogc @trusted pure nothrow 6263 if (isFloatingPoint!(X)) 6264 { 6265 alias F = floatTraits!(X); 6266 static if (F.realFormat == RealFormat.ieeeSingle) 6267 { 6268 return ((*cast(uint *)&x) & 0x7FFF_FFFF) == 0x7F80_0000; 6269 } 6270 else static if (F.realFormat == RealFormat.ieeeDouble) 6271 { 6272 return ((*cast(ulong *)&x) & 0x7FFF_FFFF_FFFF_FFFF) 6273 == 0x7FF0_0000_0000_0000; 6274 } 6275 else static if (F.realFormat == RealFormat.ieeeExtended) 6276 { 6277 const ushort e = cast(ushort)(F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]); 6278 const ulong ps = *cast(ulong *)&x; 6279 6280 // On Motorola 68K, infinity can have hidden bit = 1 or 0. On x86, it is always 1. 6281 return e == F.EXPMASK && (ps & 0x7FFF_FFFF_FFFF_FFFF) == 0; 6282 } 6283 else static if (F.realFormat == RealFormat.ieeeQuadruple) 6284 { 6285 const long psLsb = (cast(long *)&x)[MANTISSA_LSB]; 6286 const long psMsb = (cast(long *)&x)[MANTISSA_MSB]; 6287 return (psLsb == 0) 6288 && (psMsb & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FFF_0000_0000_0000; 6289 } 6290 else 6291 { 6292 return (x < -X.max) || (X.max < x); 6293 } 6294 } 6295 6296 /// 6297 @nogc @safe pure nothrow unittest 6298 { 6299 assert(!isInfinity(float.init)); 6300 assert(!isInfinity(-float.init)); 6301 assert(!isInfinity(float.nan)); 6302 assert(!isInfinity(-float.nan)); 6303 assert(isInfinity(float.infinity)); 6304 assert(isInfinity(-float.infinity)); 6305 assert(isInfinity(-1.0f / 0.0f)); 6306 } 6307 6308 @safe pure nothrow @nogc unittest 6309 { 6310 // CTFE-able tests 6311 assert(!isInfinity(double.init)); 6312 assert(!isInfinity(-double.init)); 6313 assert(!isInfinity(double.nan)); 6314 assert(!isInfinity(-double.nan)); 6315 assert(isInfinity(double.infinity)); 6316 assert(isInfinity(-double.infinity)); 6317 assert(isInfinity(-1.0 / 0.0)); 6318 6319 assert(!isInfinity(real.init)); 6320 assert(!isInfinity(-real.init)); 6321 assert(!isInfinity(real.nan)); 6322 assert(!isInfinity(-real.nan)); 6323 assert(isInfinity(real.infinity)); 6324 assert(isInfinity(-real.infinity)); 6325 assert(isInfinity(-1.0L / 0.0L)); 6326 6327 // Runtime tests 6328 shared float f; 6329 f = float.init; 6330 assert(!isInfinity(f)); 6331 assert(!isInfinity(-f)); 6332 f = float.nan; 6333 assert(!isInfinity(f)); 6334 assert(!isInfinity(-f)); 6335 f = float.infinity; 6336 assert(isInfinity(f)); 6337 assert(isInfinity(-f)); 6338 f = (-1.0f / 0.0f); 6339 assert(isInfinity(f)); 6340 6341 shared double d; 6342 d = double.init; 6343 assert(!isInfinity(d)); 6344 assert(!isInfinity(-d)); 6345 d = double.nan; 6346 assert(!isInfinity(d)); 6347 assert(!isInfinity(-d)); 6348 d = double.infinity; 6349 assert(isInfinity(d)); 6350 assert(isInfinity(-d)); 6351 d = (-1.0 / 0.0); 6352 assert(isInfinity(d)); 6353 6354 shared real e; 6355 e = real.init; 6356 assert(!isInfinity(e)); 6357 assert(!isInfinity(-e)); 6358 e = real.nan; 6359 assert(!isInfinity(e)); 6360 assert(!isInfinity(-e)); 6361 e = real.infinity; 6362 assert(isInfinity(e)); 6363 assert(isInfinity(-e)); 6364 e = (-1.0L / 0.0L); 6365 assert(isInfinity(e)); 6366 } 6367 6368 @nogc @safe pure nothrow unittest 6369 { 6370 import std.meta : AliasSeq; 6371 static bool foo(T)(inout T x) { return isInfinity(x); } 6372 foreach (T; AliasSeq!(float, double, real)) 6373 { 6374 assert(!foo(T(3.14f))); 6375 assert(foo(T.infinity)); 6376 } 6377 } 6378 6379 /********************************* 6380 * Is the binary representation of x identical to y? 6381 */ 6382 bool isIdentical(real x, real y) @trusted pure nothrow @nogc 6383 { 6384 // We're doing a bitwise comparison so the endianness is irrelevant. 6385 long* pxs = cast(long *)&x; 6386 long* pys = cast(long *)&y; 6387 alias F = floatTraits!(real); 6388 static if (F.realFormat == RealFormat.ieeeDouble) 6389 { 6390 return pxs[0] == pys[0]; 6391 } 6392 else static if (F.realFormat == RealFormat.ieeeQuadruple) 6393 { 6394 return pxs[0] == pys[0] && pxs[1] == pys[1]; 6395 } 6396 else static if (F.realFormat == RealFormat.ieeeExtended) 6397 { 6398 ushort* pxe = cast(ushort *)&x; 6399 ushort* pye = cast(ushort *)&y; 6400 return pxe[4] == pye[4] && pxs[0] == pys[0]; 6401 } 6402 else 6403 { 6404 assert(0, "isIdentical not implemented"); 6405 } 6406 } 6407 6408 /// 6409 @safe @nogc pure nothrow unittest 6410 { 6411 assert( isIdentical(0.0, 0.0)); 6412 assert( isIdentical(1.0, 1.0)); 6413 assert( isIdentical(real.infinity, real.infinity)); 6414 assert( isIdentical(-real.infinity, -real.infinity)); 6415 6416 assert(!isIdentical(0.0, -0.0)); 6417 assert(!isIdentical(real.nan, -real.nan)); 6418 assert(!isIdentical(real.infinity, -real.infinity)); 6419 } 6420 6421 /********************************* 6422 * Return 1 if sign bit of e is set, 0 if not. 6423 */ 6424 int signbit(X)(X x) @nogc @trusted pure nothrow 6425 { 6426 if (__ctfe) 6427 { 6428 double dval = cast(double) x; // Precision can increase or decrease but sign won't change (even NaN). 6429 return 0 > *cast(long*) &dval; 6430 } 6431 6432 alias F = floatTraits!(X); 6433 return ((cast(ubyte *)&x)[F.SIGNPOS_BYTE] & 0x80) != 0; 6434 } 6435 6436 /// 6437 @nogc @safe pure nothrow unittest 6438 { 6439 assert(!signbit(float.nan)); 6440 assert(signbit(-float.nan)); 6441 assert(!signbit(168.1234f)); 6442 assert(signbit(-168.1234f)); 6443 assert(!signbit(0.0f)); 6444 assert(signbit(-0.0f)); 6445 assert(signbit(-float.max)); 6446 assert(!signbit(float.max)); 6447 6448 assert(!signbit(double.nan)); 6449 assert(signbit(-double.nan)); 6450 assert(!signbit(168.1234)); 6451 assert(signbit(-168.1234)); 6452 assert(!signbit(0.0)); 6453 assert(signbit(-0.0)); 6454 assert(signbit(-double.max)); 6455 assert(!signbit(double.max)); 6456 6457 assert(!signbit(real.nan)); 6458 assert(signbit(-real.nan)); 6459 assert(!signbit(168.1234L)); 6460 assert(signbit(-168.1234L)); 6461 assert(!signbit(0.0L)); 6462 assert(signbit(-0.0L)); 6463 assert(signbit(-real.max)); 6464 assert(!signbit(real.max)); 6465 } 6466 6467 @nogc @safe pure nothrow unittest 6468 { 6469 // CTFE 6470 static assert(!signbit(float.nan)); 6471 static assert(signbit(-float.nan)); 6472 static assert(!signbit(168.1234f)); 6473 static assert(signbit(-168.1234f)); 6474 static assert(!signbit(0.0f)); 6475 static assert(signbit(-0.0f)); 6476 static assert(signbit(-float.max)); 6477 static assert(!signbit(float.max)); 6478 6479 static assert(!signbit(double.nan)); 6480 static assert(signbit(-double.nan)); 6481 static assert(!signbit(168.1234)); 6482 static assert(signbit(-168.1234)); 6483 static assert(!signbit(0.0)); 6484 static assert(signbit(-0.0)); 6485 static assert(signbit(-double.max)); 6486 static assert(!signbit(double.max)); 6487 6488 static assert(!signbit(real.nan)); 6489 static assert(signbit(-real.nan)); 6490 static assert(!signbit(168.1234L)); 6491 static assert(signbit(-168.1234L)); 6492 static assert(!signbit(0.0L)); 6493 static assert(signbit(-0.0L)); 6494 static assert(signbit(-real.max)); 6495 static assert(!signbit(real.max)); 6496 } 6497 6498 /** 6499 Params: 6500 to = the numeric value to use 6501 from = the sign value to use 6502 Returns: 6503 a value composed of to with from's sign bit. 6504 */ 6505 R copysign(R, X)(R to, X from) @trusted pure nothrow @nogc 6506 if (isFloatingPoint!(R) && isFloatingPoint!(X)) 6507 { 6508 if (__ctfe) 6509 { 6510 return signbit(to) == signbit(from) ? to : -to; 6511 } 6512 ubyte* pto = cast(ubyte *)&to; 6513 const ubyte* pfrom = cast(ubyte *)&from; 6514 6515 alias T = floatTraits!(R); 6516 alias F = floatTraits!(X); 6517 pto[T.SIGNPOS_BYTE] &= 0x7F; 6518 pto[T.SIGNPOS_BYTE] |= pfrom[F.SIGNPOS_BYTE] & 0x80; 6519 return to; 6520 } 6521 6522 /// ditto 6523 R copysign(R, X)(X to, R from) @trusted pure nothrow @nogc 6524 if (isIntegral!(X) && isFloatingPoint!(R)) 6525 { 6526 return copysign(cast(R) to, from); 6527 } 6528 6529 /// 6530 @safe pure nothrow @nogc unittest 6531 { 6532 assert(copysign(1.0, 1.0) == 1.0); 6533 assert(copysign(1.0, -0.0) == -1.0); 6534 assert(copysign(1UL, -1.0) == -1.0); 6535 assert(copysign(-1.0, -1.0) == -1.0); 6536 6537 assert(copysign(real.infinity, -1.0) == -real.infinity); 6538 assert(copysign(real.nan, 1.0) is real.nan); 6539 assert(copysign(-real.nan, 1.0) is real.nan); 6540 assert(copysign(real.nan, -1.0) is -real.nan); 6541 } 6542 6543 @safe pure nothrow @nogc unittest 6544 { 6545 import std.meta : AliasSeq; 6546 6547 static foreach (X; AliasSeq!(float, double, real, int, long)) 6548 { 6549 static foreach (Y; AliasSeq!(float, double, real)) 6550 {{ 6551 X x = 21; 6552 Y y = 23.8; 6553 Y e = void; 6554 6555 e = copysign(x, y); 6556 assert(e == 21.0); 6557 6558 e = copysign(-x, y); 6559 assert(e == 21.0); 6560 6561 e = copysign(x, -y); 6562 assert(e == -21.0); 6563 6564 e = copysign(-x, -y); 6565 assert(e == -21.0); 6566 6567 static if (isFloatingPoint!X) 6568 { 6569 e = copysign(X.nan, y); 6570 assert(isNaN(e) && !signbit(e)); 6571 6572 e = copysign(X.nan, -y); 6573 assert(isNaN(e) && signbit(e)); 6574 } 6575 }} 6576 } 6577 // CTFE 6578 static foreach (X; AliasSeq!(float, double, real, int, long)) 6579 { 6580 static foreach (Y; AliasSeq!(float, double, real)) 6581 {{ 6582 enum X x = 21; 6583 enum Y y = 23.8; 6584 6585 assert(21.0 == copysign(x, y)); 6586 assert(21.0 == copysign(-x, y)); 6587 assert(-21.0 == copysign(x, -y)); 6588 assert(-21.0 == copysign(-x, -y)); 6589 6590 static if (isFloatingPoint!X) 6591 { 6592 static assert(isNaN(copysign(X.nan, y)) && !signbit(copysign(X.nan, y))); 6593 assert(isNaN(copysign(X.nan, -y)) && signbit(copysign(X.nan, -y))); 6594 } 6595 }} 6596 } 6597 } 6598 6599 /********************************* 6600 Returns `-1` if $(D x < 0), `x` if $(D x == 0), `1` if 6601 $(D x > 0), and $(NAN) if x==$(NAN). 6602 */ 6603 F sgn(F)(F x) @safe pure nothrow @nogc 6604 if (isFloatingPoint!F || isIntegral!F) 6605 { 6606 // @@@TODO@@@: make this faster 6607 return x > 0 ? 1 : x < 0 ? -1 : x; 6608 } 6609 6610 /// 6611 @safe pure nothrow @nogc unittest 6612 { 6613 assert(sgn(168.1234) == 1); 6614 assert(sgn(-168.1234) == -1); 6615 assert(sgn(0.0) == 0); 6616 assert(sgn(-0.0) == 0); 6617 } 6618 6619 // Functions for NaN payloads 6620 /* 6621 * A 'payload' can be stored in the significand of a $(NAN). One bit is required 6622 * to distinguish between a quiet and a signalling $(NAN). This leaves 22 bits 6623 * of payload for a float; 51 bits for a double; 62 bits for an 80-bit real; 6624 * and 111 bits for a 128-bit quad. 6625 */ 6626 /** 6627 * Create a quiet $(NAN), storing an integer inside the payload. 6628 * 6629 * For floats, the largest possible payload is 0x3F_FFFF. 6630 * For doubles, it is 0x3_FFFF_FFFF_FFFF. 6631 * For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF. 6632 */ 6633 real NaN(ulong payload) @trusted pure nothrow @nogc 6634 { 6635 alias F = floatTraits!(real); 6636 static if (F.realFormat == RealFormat.ieeeExtended) 6637 { 6638 // real80 (in x86 real format, the implied bit is actually 6639 // not implied but a real bit which is stored in the real) 6640 ulong v = 3; // implied bit = 1, quiet bit = 1 6641 } 6642 else 6643 { 6644 ulong v = 1; // no implied bit. quiet bit = 1 6645 } 6646 6647 ulong a = payload; 6648 6649 // 22 Float bits 6650 ulong w = a & 0x3F_FFFF; 6651 a -= w; 6652 6653 v <<=22; 6654 v |= w; 6655 a >>=22; 6656 6657 // 29 Double bits 6658 v <<=29; 6659 w = a & 0xFFF_FFFF; 6660 v |= w; 6661 a -= w; 6662 a >>=29; 6663 6664 static if (F.realFormat == RealFormat.ieeeDouble) 6665 { 6666 v |= 0x7FF0_0000_0000_0000; 6667 real x; 6668 * cast(ulong *)(&x) = v; 6669 return x; 6670 } 6671 else 6672 { 6673 v <<=11; 6674 a &= 0x7FF; 6675 v |= a; 6676 real x = real.nan; 6677 6678 // Extended real bits 6679 static if (F.realFormat == RealFormat.ieeeQuadruple) 6680 { 6681 v <<= 1; // there's no implicit bit 6682 6683 version (LittleEndian) 6684 { 6685 *cast(ulong*)(6+cast(ubyte*)(&x)) = v; 6686 } 6687 else 6688 { 6689 *cast(ulong*)(2+cast(ubyte*)(&x)) = v; 6690 } 6691 } 6692 else 6693 { 6694 *cast(ulong *)(&x) = v; 6695 } 6696 return x; 6697 } 6698 } 6699 6700 /// 6701 @safe @nogc pure nothrow unittest 6702 { 6703 real a = NaN(1_000_000); 6704 assert(isNaN(a)); 6705 assert(getNaNPayload(a) == 1_000_000); 6706 } 6707 6708 @system pure nothrow @nogc unittest // not @safe because taking address of local. 6709 { 6710 static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) 6711 { 6712 auto x = NaN(1); 6713 auto xl = *cast(ulong*)&x; 6714 assert(xl & 0x8_0000_0000_0000UL); //non-signaling bit, bit 52 6715 assert((xl & 0x7FF0_0000_0000_0000UL) == 0x7FF0_0000_0000_0000UL); //all exp bits set 6716 } 6717 } 6718 6719 /** 6720 * Extract an integral payload from a $(NAN). 6721 * 6722 * Returns: 6723 * the integer payload as a ulong. 6724 * 6725 * For floats, the largest possible payload is 0x3F_FFFF. 6726 * For doubles, it is 0x3_FFFF_FFFF_FFFF. 6727 * For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF. 6728 */ 6729 ulong getNaNPayload(real x) @trusted pure nothrow @nogc 6730 { 6731 // assert(isNaN(x)); 6732 alias F = floatTraits!(real); 6733 static if (F.realFormat == RealFormat.ieeeDouble) 6734 { 6735 ulong m = *cast(ulong *)(&x); 6736 // Make it look like an 80-bit significand. 6737 // Skip exponent, and quiet bit 6738 m &= 0x0007_FFFF_FFFF_FFFF; 6739 m <<= 11; 6740 } 6741 else static if (F.realFormat == RealFormat.ieeeQuadruple) 6742 { 6743 version (LittleEndian) 6744 { 6745 ulong m = *cast(ulong*)(6+cast(ubyte*)(&x)); 6746 } 6747 else 6748 { 6749 ulong m = *cast(ulong*)(2+cast(ubyte*)(&x)); 6750 } 6751 6752 m >>= 1; // there's no implicit bit 6753 } 6754 else 6755 { 6756 ulong m = *cast(ulong *)(&x); 6757 } 6758 6759 // ignore implicit bit and quiet bit 6760 6761 const ulong f = m & 0x3FFF_FF00_0000_0000L; 6762 6763 ulong w = f >>> 40; 6764 w |= (m & 0x00FF_FFFF_F800L) << (22 - 11); 6765 w |= (m & 0x7FF) << 51; 6766 return w; 6767 } 6768 6769 /// 6770 @safe @nogc pure nothrow unittest 6771 { 6772 real a = NaN(1_000_000); 6773 assert(isNaN(a)); 6774 assert(getNaNPayload(a) == 1_000_000); 6775 } 6776 6777 debug(UnitTest) 6778 { 6779 @safe pure nothrow @nogc unittest 6780 { 6781 real nan4 = NaN(0x789_ABCD_EF12_3456); 6782 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended 6783 || floatTraits!(real).realFormat == RealFormat.ieeeQuadruple) 6784 { 6785 assert(getNaNPayload(nan4) == 0x789_ABCD_EF12_3456); 6786 } 6787 else 6788 { 6789 assert(getNaNPayload(nan4) == 0x1_ABCD_EF12_3456); 6790 } 6791 double nan5 = nan4; 6792 assert(getNaNPayload(nan5) == 0x1_ABCD_EF12_3456); 6793 float nan6 = nan4; 6794 assert(getNaNPayload(nan6) == 0x12_3456); 6795 nan4 = NaN(0xFABCD); 6796 assert(getNaNPayload(nan4) == 0xFABCD); 6797 nan6 = nan4; 6798 assert(getNaNPayload(nan6) == 0xFABCD); 6799 nan5 = NaN(0x100_0000_0000_3456); 6800 assert(getNaNPayload(nan5) == 0x0000_0000_3456); 6801 } 6802 } 6803 6804 /** 6805 * Calculate the next largest floating point value after x. 6806 * 6807 * Return the least number greater than x that is representable as a real; 6808 * thus, it gives the next point on the IEEE number line. 6809 * 6810 * $(TABLE_SV 6811 * $(SVH x, nextUp(x) ) 6812 * $(SV -$(INFIN), -real.max ) 6813 * $(SV $(PLUSMN)0.0, real.min_normal*real.epsilon ) 6814 * $(SV real.max, $(INFIN) ) 6815 * $(SV $(INFIN), $(INFIN) ) 6816 * $(SV $(NAN), $(NAN) ) 6817 * ) 6818 */ 6819 real nextUp(real x) @trusted pure nothrow @nogc 6820 { 6821 alias F = floatTraits!(real); 6822 static if (F.realFormat == RealFormat.ieeeDouble) 6823 { 6824 return nextUp(cast(double) x); 6825 } 6826 else static if (F.realFormat == RealFormat.ieeeQuadruple) 6827 { 6828 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 6829 if (e == F.EXPMASK) 6830 { 6831 // NaN or Infinity 6832 if (x == -real.infinity) return -real.max; 6833 return x; // +Inf and NaN are unchanged. 6834 } 6835 6836 auto ps = cast(ulong *)&x; 6837 if (ps[MANTISSA_MSB] & 0x8000_0000_0000_0000) 6838 { 6839 // Negative number 6840 if (ps[MANTISSA_LSB] == 0 && ps[MANTISSA_MSB] == 0x8000_0000_0000_0000) 6841 { 6842 // it was negative zero, change to smallest subnormal 6843 ps[MANTISSA_LSB] = 1; 6844 ps[MANTISSA_MSB] = 0; 6845 return x; 6846 } 6847 if (ps[MANTISSA_LSB] == 0) --ps[MANTISSA_MSB]; 6848 --ps[MANTISSA_LSB]; 6849 } 6850 else 6851 { 6852 // Positive number 6853 ++ps[MANTISSA_LSB]; 6854 if (ps[MANTISSA_LSB] == 0) ++ps[MANTISSA_MSB]; 6855 } 6856 return x; 6857 } 6858 else static if (F.realFormat == RealFormat.ieeeExtended) 6859 { 6860 // For 80-bit reals, the "implied bit" is a nuisance... 6861 ushort *pe = cast(ushort *)&x; 6862 ulong *ps = cast(ulong *)&x; 6863 6864 if ((pe[F.EXPPOS_SHORT] & F.EXPMASK) == F.EXPMASK) 6865 { 6866 // First, deal with NANs and infinity 6867 if (x == -real.infinity) return -real.max; 6868 return x; // +Inf and NaN are unchanged. 6869 } 6870 if (pe[F.EXPPOS_SHORT] & 0x8000) 6871 { 6872 // Negative number -- need to decrease the significand 6873 --*ps; 6874 // Need to mask with 0x7FFF... so subnormals are treated correctly. 6875 if ((*ps & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FFF_FFFF_FFFF_FFFF) 6876 { 6877 if (pe[F.EXPPOS_SHORT] == 0x8000) // it was negative zero 6878 { 6879 *ps = 1; 6880 pe[F.EXPPOS_SHORT] = 0; // smallest subnormal. 6881 return x; 6882 } 6883 6884 --pe[F.EXPPOS_SHORT]; 6885 6886 if (pe[F.EXPPOS_SHORT] == 0x8000) 6887 return x; // it's become a subnormal, implied bit stays low. 6888 6889 *ps = 0xFFFF_FFFF_FFFF_FFFF; // set the implied bit 6890 return x; 6891 } 6892 return x; 6893 } 6894 else 6895 { 6896 // Positive number -- need to increase the significand. 6897 // Works automatically for positive zero. 6898 ++*ps; 6899 if ((*ps & 0x7FFF_FFFF_FFFF_FFFF) == 0) 6900 { 6901 // change in exponent 6902 ++pe[F.EXPPOS_SHORT]; 6903 *ps = 0x8000_0000_0000_0000; // set the high bit 6904 } 6905 } 6906 return x; 6907 } 6908 else // static if (F.realFormat == RealFormat.ibmExtended) 6909 { 6910 assert(0, "nextUp not implemented"); 6911 } 6912 } 6913 6914 /** ditto */ 6915 double nextUp(double x) @trusted pure nothrow @nogc 6916 { 6917 ulong s = *cast(ulong *)&x; 6918 6919 if ((s & 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) 6920 { 6921 // First, deal with NANs and infinity 6922 if (x == -x.infinity) return -x.max; 6923 return x; // +INF and NAN are unchanged. 6924 } 6925 if (s & 0x8000_0000_0000_0000) // Negative number 6926 { 6927 if (s == 0x8000_0000_0000_0000) // it was negative zero 6928 { 6929 s = 0x0000_0000_0000_0001; // change to smallest subnormal 6930 return *cast(double*) &s; 6931 } 6932 --s; 6933 } 6934 else 6935 { // Positive number 6936 ++s; 6937 } 6938 return *cast(double*) &s; 6939 } 6940 6941 /** ditto */ 6942 float nextUp(float x) @trusted pure nothrow @nogc 6943 { 6944 uint s = *cast(uint *)&x; 6945 6946 if ((s & 0x7F80_0000) == 0x7F80_0000) 6947 { 6948 // First, deal with NANs and infinity 6949 if (x == -x.infinity) return -x.max; 6950 6951 return x; // +INF and NAN are unchanged. 6952 } 6953 if (s & 0x8000_0000) // Negative number 6954 { 6955 if (s == 0x8000_0000) // it was negative zero 6956 { 6957 s = 0x0000_0001; // change to smallest subnormal 6958 return *cast(float*) &s; 6959 } 6960 6961 --s; 6962 } 6963 else 6964 { 6965 // Positive number 6966 ++s; 6967 } 6968 return *cast(float*) &s; 6969 } 6970 6971 /// 6972 @safe @nogc pure nothrow unittest 6973 { 6974 assert(nextUp(1.0 - 1.0e-6).feqrel(0.999999) > 16); 6975 assert(nextUp(1.0 - real.epsilon).feqrel(1.0) > 16); 6976 } 6977 6978 /** 6979 * Calculate the next smallest floating point value before x. 6980 * 6981 * Return the greatest number less than x that is representable as a real; 6982 * thus, it gives the previous point on the IEEE number line. 6983 * 6984 * $(TABLE_SV 6985 * $(SVH x, nextDown(x) ) 6986 * $(SV $(INFIN), real.max ) 6987 * $(SV $(PLUSMN)0.0, -real.min_normal*real.epsilon ) 6988 * $(SV -real.max, -$(INFIN) ) 6989 * $(SV -$(INFIN), -$(INFIN) ) 6990 * $(SV $(NAN), $(NAN) ) 6991 * ) 6992 */ 6993 real nextDown(real x) @safe pure nothrow @nogc 6994 { 6995 return -nextUp(-x); 6996 } 6997 6998 /** ditto */ 6999 double nextDown(double x) @safe pure nothrow @nogc 7000 { 7001 return -nextUp(-x); 7002 } 7003 7004 /** ditto */ 7005 float nextDown(float x) @safe pure nothrow @nogc 7006 { 7007 return -nextUp(-x); 7008 } 7009 7010 /// 7011 @safe pure nothrow @nogc unittest 7012 { 7013 assert( nextDown(1.0 + real.epsilon) == 1.0); 7014 } 7015 7016 @safe pure nothrow @nogc unittest 7017 { 7018 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended) 7019 { 7020 7021 // Tests for 80-bit reals 7022 assert(isIdentical(nextUp(NaN(0xABC)), NaN(0xABC))); 7023 // negative numbers 7024 assert( nextUp(-real.infinity) == -real.max ); 7025 assert( nextUp(-1.0L-real.epsilon) == -1.0 ); 7026 assert( nextUp(-2.0L) == -2.0 + real.epsilon); 7027 // subnormals and zero 7028 assert( nextUp(-real.min_normal) == -real.min_normal*(1-real.epsilon) ); 7029 assert( nextUp(-real.min_normal*(1-real.epsilon)) == -real.min_normal*(1-2*real.epsilon) ); 7030 assert( isIdentical(-0.0L, nextUp(-real.min_normal*real.epsilon)) ); 7031 assert( nextUp(-0.0L) == real.min_normal*real.epsilon ); 7032 assert( nextUp(0.0L) == real.min_normal*real.epsilon ); 7033 assert( nextUp(real.min_normal*(1-real.epsilon)) == real.min_normal ); 7034 assert( nextUp(real.min_normal) == real.min_normal*(1+real.epsilon) ); 7035 // positive numbers 7036 assert( nextUp(1.0L) == 1.0 + real.epsilon ); 7037 assert( nextUp(2.0L-real.epsilon) == 2.0 ); 7038 assert( nextUp(real.max) == real.infinity ); 7039 assert( nextUp(real.infinity)==real.infinity ); 7040 } 7041 7042 double n = NaN(0xABC); 7043 assert(isIdentical(nextUp(n), n)); 7044 // negative numbers 7045 assert( nextUp(-double.infinity) == -double.max ); 7046 assert( nextUp(-1-double.epsilon) == -1.0 ); 7047 assert( nextUp(-2.0) == -2.0 + double.epsilon); 7048 // subnormals and zero 7049 7050 assert( nextUp(-double.min_normal) == -double.min_normal*(1-double.epsilon) ); 7051 assert( nextUp(-double.min_normal*(1-double.epsilon)) == -double.min_normal*(1-2*double.epsilon) ); 7052 assert( isIdentical(-0.0, nextUp(-double.min_normal*double.epsilon)) ); 7053 assert( nextUp(0.0) == double.min_normal*double.epsilon ); 7054 assert( nextUp(-0.0) == double.min_normal*double.epsilon ); 7055 assert( nextUp(double.min_normal*(1-double.epsilon)) == double.min_normal ); 7056 assert( nextUp(double.min_normal) == double.min_normal*(1+double.epsilon) ); 7057 // positive numbers 7058 assert( nextUp(1.0) == 1.0 + double.epsilon ); 7059 assert( nextUp(2.0-double.epsilon) == 2.0 ); 7060 assert( nextUp(double.max) == double.infinity ); 7061 7062 float fn = NaN(0xABC); 7063 assert(isIdentical(nextUp(fn), fn)); 7064 float f = -float.min_normal*(1-float.epsilon); 7065 float f1 = -float.min_normal; 7066 assert( nextUp(f1) == f); 7067 f = 1.0f+float.epsilon; 7068 f1 = 1.0f; 7069 assert( nextUp(f1) == f ); 7070 f1 = -0.0f; 7071 assert( nextUp(f1) == float.min_normal*float.epsilon); 7072 assert( nextUp(float.infinity)==float.infinity ); 7073 7074 assert(nextDown(1.0L+real.epsilon)==1.0); 7075 assert(nextDown(1.0+double.epsilon)==1.0); 7076 f = 1.0f+float.epsilon; 7077 assert(nextDown(f)==1.0); 7078 assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0); 7079 7080 // CTFE 7081 7082 //enum double n = NaN(0xABC); // FIXME: Cannot set NaN payload in CTFE. 7083 //static assert(isIdentical(nextUp(n), n)); // FIXME: https://issues.dlang.org/show_bug.cgi?id=20197 7084 static assert(nextUp(double.nan) is double.nan); 7085 // negative numbers 7086 static assert( nextUp(-double.infinity) == -double.max ); 7087 static assert( nextUp(-1-double.epsilon) == -1.0 ); 7088 static assert( nextUp(-2.0) == -2.0 + double.epsilon); 7089 // subnormals and zero 7090 7091 static assert( nextUp(-double.min_normal) == -double.min_normal*(1-double.epsilon) ); 7092 static assert( nextUp(-double.min_normal*(1-double.epsilon)) == -double.min_normal*(1-2*double.epsilon) ); 7093 static assert( -0.0 is nextUp(-double.min_normal*double.epsilon) ); 7094 static assert( nextUp(0.0) == double.min_normal*double.epsilon ); 7095 static assert( nextUp(-0.0) == double.min_normal*double.epsilon ); 7096 static assert( nextUp(double.min_normal*(1-double.epsilon)) == double.min_normal ); 7097 static assert( nextUp(double.min_normal) == double.min_normal*(1+double.epsilon) ); 7098 // positive numbers 7099 static assert( nextUp(1.0) == 1.0 + double.epsilon ); 7100 static assert( nextUp(2.0-double.epsilon) == 2.0 ); 7101 static assert( nextUp(double.max) == double.infinity ); 7102 7103 //enum float fn = NaN(0xABC); // FIXME: Cannot set NaN payload in CTFE. 7104 //static assert(isIdentical(nextUp(fn), fn)); // FIXME: https://issues.dlang.org/show_bug.cgi?id=20197 7105 static assert(nextUp(float.nan) is float.nan); 7106 static assert(nextUp(-float.min_normal) == -float.min_normal*(1-float.epsilon)); 7107 static assert(nextUp(1.0f) == 1.0f+float.epsilon); 7108 static assert(nextUp(-0.0f) == float.min_normal*float.epsilon); 7109 static assert(nextUp(float.infinity)==float.infinity); 7110 //static assert(nextDown(1.0L+real.epsilon)==1.0); 7111 static assert(nextDown(1.0+double.epsilon)==1.0); 7112 static assert(nextDown(1.0f+float.epsilon)==1.0); 7113 //static assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0); 7114 } 7115 7116 7117 7118 /****************************************** 7119 * Calculates the next representable value after x in the direction of y. 7120 * 7121 * If y > x, the result will be the next largest floating-point value; 7122 * if y < x, the result will be the next smallest value. 7123 * If x == y, the result is y. 7124 * If x or y is a NaN, the result is a NaN. 7125 * 7126 * Remarks: 7127 * This function is not generally very useful; it's almost always better to use 7128 * the faster functions nextUp() or nextDown() instead. 7129 * 7130 * The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and 7131 * the function result is infinite. The FE_INEXACT and FE_UNDERFLOW 7132 * exceptions will be raised if the function value is subnormal, and x is 7133 * not equal to y. 7134 */ 7135 T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc 7136 { 7137 if (x == y || isNaN(y)) 7138 { 7139 return y; 7140 } 7141 7142 if (isNaN(x)) 7143 { 7144 return x; 7145 } 7146 7147 return ((y>x) ? nextUp(x) : nextDown(x)); 7148 } 7149 7150 /// 7151 @safe pure nothrow @nogc unittest 7152 { 7153 float a = 1; 7154 assert(is(typeof(nextafter(a, a)) == float)); 7155 assert(nextafter(a, a.infinity) > a); 7156 assert(isNaN(nextafter(a, a.nan))); 7157 assert(isNaN(nextafter(a.nan, a))); 7158 7159 double b = 2; 7160 assert(is(typeof(nextafter(b, b)) == double)); 7161 assert(nextafter(b, b.infinity) > b); 7162 assert(isNaN(nextafter(b, b.nan))); 7163 assert(isNaN(nextafter(b.nan, b))); 7164 7165 real c = 3; 7166 assert(is(typeof(nextafter(c, c)) == real)); 7167 assert(nextafter(c, c.infinity) > c); 7168 assert(isNaN(nextafter(c, c.nan))); 7169 assert(isNaN(nextafter(c.nan, c))); 7170 } 7171 7172 @safe pure nothrow @nogc unittest 7173 { 7174 // CTFE 7175 enum float a = 1; 7176 static assert(is(typeof(nextafter(a, a)) == float)); 7177 static assert(nextafter(a, a.infinity) > a); 7178 static assert(isNaN(nextafter(a, a.nan))); 7179 static assert(isNaN(nextafter(a.nan, a))); 7180 7181 enum double b = 2; 7182 static assert(is(typeof(nextafter(b, b)) == double)); 7183 static assert(nextafter(b, b.infinity) > b); 7184 static assert(isNaN(nextafter(b, b.nan))); 7185 static assert(isNaN(nextafter(b.nan, b))); 7186 7187 enum real c = 3; 7188 static assert(is(typeof(nextafter(c, c)) == real)); 7189 //static assert(nextafter(c, c.infinity) > c); 7190 7191 enum real negZero = nextafter(+0.0L, -0.0L); // specially CTFEable 7192 static assert(negZero == -0.0L); 7193 static assert(signbit(negZero)); 7194 7195 static assert(nextafter(c, c) == c); // ditto 7196 static assert(isNaN(nextafter(c, c.nan))); // ditto 7197 static assert(isNaN(nextafter(c.nan, c))); // ditto 7198 } 7199 7200 //real nexttoward(real x, real y) { return core.stdc.math.nexttowardl(x, y); } 7201 7202 /** 7203 * Returns the positive difference between x and y. 7204 * 7205 * Equivalent to `fmax(x-y, 0)`. 7206 * 7207 * Returns: 7208 * $(TABLE_SV 7209 * $(TR $(TH x, y) $(TH fdim(x, y))) 7210 * $(TR $(TD x $(GT) y) $(TD x - y)) 7211 * $(TR $(TD x $(LT)= y) $(TD +0.0)) 7212 * ) 7213 */ 7214 real fdim(real x, real y) @safe pure nothrow @nogc 7215 { 7216 return (x < y) ? +0.0 : x - y; 7217 } 7218 7219 /// 7220 @safe pure nothrow @nogc unittest 7221 { 7222 assert(fdim(2.0, 0.0) == 2.0); 7223 assert(fdim(-2.0, 0.0) == 0.0); 7224 assert(fdim(real.infinity, 2.0) == real.infinity); 7225 assert(isNaN(fdim(real.nan, 2.0))); 7226 assert(isNaN(fdim(2.0, real.nan))); 7227 assert(isNaN(fdim(real.nan, real.nan))); 7228 } 7229 7230 /** 7231 * Returns the larger of x and y. 7232 * 7233 * If one of the arguments is a NaN, the other is returned. 7234 */ 7235 real fmax(real x, real y) @safe pure nothrow @nogc 7236 { 7237 return (y > x || isNaN(x)) ? y : x; 7238 } 7239 7240 /// 7241 @safe pure nothrow @nogc unittest 7242 { 7243 assert(fmax(0.0, 2.0) == 2.0); 7244 assert(fmax(-2.0, 0.0) == 0.0); 7245 assert(fmax(real.infinity, 2.0) == real.infinity); 7246 assert(fmax(real.nan, 2.0) == 2.0); 7247 assert(fmax(2.0, real.nan) == 2.0); 7248 } 7249 7250 /** 7251 * Returns the smaller of x and y. 7252 * 7253 * If one of the arguments is a NaN, the other is returned. 7254 */ 7255 real fmin(real x, real y) @safe pure nothrow @nogc 7256 { 7257 return (y < x || isNaN(x)) ? y : x; 7258 } 7259 7260 /// 7261 @safe pure nothrow @nogc unittest 7262 { 7263 assert(fmin(0.0, 2.0) == 0.0); 7264 assert(fmin(-2.0, 0.0) == -2.0); 7265 assert(fmin(real.infinity, 2.0) == 2.0); 7266 assert(fmin(real.nan, 2.0) == 2.0); 7267 assert(fmin(2.0, real.nan) == 2.0); 7268 } 7269 7270 /************************************** 7271 * Returns (x * y) + z, rounding only once according to the 7272 * current rounding mode. 7273 * 7274 * BUGS: Not currently implemented - rounds twice. 7275 */ 7276 real fma(real x, real y, real z) @safe pure nothrow @nogc { return (x * y) + z; } 7277 7278 /// 7279 @safe pure nothrow @nogc unittest 7280 { 7281 assert(fma(0.0, 2.0, 2.0) == 2.0); 7282 assert(fma(2.0, 2.0, 2.0) == 6.0); 7283 assert(fma(real.infinity, 2.0, 2.0) == real.infinity); 7284 assert(fma(real.nan, 2.0, 2.0) is real.nan); 7285 assert(fma(2.0, 2.0, real.nan) is real.nan); 7286 } 7287 7288 /** 7289 * Compute the value of x $(SUPERSCRIPT n), where n is an integer 7290 */ 7291 Unqual!F pow(F, G)(F x, G n) @nogc @trusted pure nothrow 7292 if (isFloatingPoint!(F) && isIntegral!(G)) 7293 { 7294 import std.traits : Unsigned, isSigned; 7295 real p = 1.0, v = void; 7296 Unsigned!(Unqual!G) m = n; 7297 7298 static if (G.sizeof < 4 && !isSigned!G) 7299 { 7300 import std.conv : to; 7301 const int n2 = n.to!int; 7302 } 7303 else alias n2 = n; 7304 7305 if (n < 0) 7306 { 7307 switch (n2) 7308 { 7309 case -1: 7310 return 1 / x; 7311 case -2: 7312 return 1 / (x * x); 7313 default: 7314 } 7315 7316 m = cast(typeof(m))(0 - n); 7317 v = p / x; 7318 } 7319 else 7320 { 7321 switch (n) 7322 { 7323 case 0: 7324 return 1.0; 7325 case 1: 7326 return x; 7327 case 2: 7328 return x * x; 7329 default: 7330 } 7331 7332 v = x; 7333 } 7334 7335 while (1) 7336 { 7337 if (m & 1) 7338 p *= v; 7339 m >>= 1; 7340 if (!m) 7341 break; 7342 v *= v; 7343 } 7344 return p; 7345 } 7346 7347 /// 7348 @safe pure nothrow @nogc unittest 7349 { 7350 assert(pow(2.0, 5) == 32.0); 7351 assert(pow(1.5, 9).feqrel(38.4433) > 16); 7352 assert(pow(real.nan, 2) is real.nan); 7353 assert(pow(real.infinity, 2) == real.infinity); 7354 } 7355 7356 @safe pure nothrow @nogc unittest 7357 { 7358 // Make sure it instantiates and works properly on immutable values and 7359 // with various integer and float types. 7360 immutable real x = 46; 7361 immutable float xf = x; 7362 immutable double xd = x; 7363 immutable uint one = 1; 7364 immutable ushort two = 2; 7365 immutable ubyte three = 3; 7366 immutable ulong eight = 8; 7367 7368 immutable int neg1 = -1; 7369 immutable short neg2 = -2; 7370 immutable byte neg3 = -3; 7371 immutable long neg8 = -8; 7372 7373 7374 assert(pow(x,0) == 1.0); 7375 assert(pow(xd,one) == x); 7376 assert(pow(xf,two) == x * x); 7377 assert(pow(x,three) == x * x * x); 7378 assert(pow(x,eight) == (x * x) * (x * x) * (x * x) * (x * x)); 7379 7380 assert(pow(x, neg1) == 1 / x); 7381 7382 assert(approxEqual(pow(xd, neg2), cast(double) (1 / (x * x)), 1e-25, 0.0)); 7383 assert(approxEqual(pow(xf, neg8), cast(float) (1 / ((x * x) * (x * x) * (x * x) * (x * x))), 1e-15, 0.0)); 7384 7385 assert(feqrel(pow(x, neg3), 1 / (x * x * x)) >= real.mant_dig - 1); 7386 } 7387 7388 @safe @nogc nothrow unittest 7389 { 7390 assert(equalsDigit(pow(2.0L, 10.0L), 1024, 19)); 7391 } 7392 7393 /** 7394 * Compute the power of two integral numbers. 7395 * 7396 * Params: 7397 * x = base 7398 * n = exponent 7399 * 7400 * Returns: 7401 * x raised to the power of n. If n is negative the result is 1 / pow(x, -n), 7402 * which is calculated as integer division with remainder. This may result in 7403 * a division by zero error. 7404 * 7405 * If both x and n are 0, the result is 1. 7406 * 7407 * Throws: 7408 * If x is 0 and n is negative, the result is the same as the result of a 7409 * division by zero. 7410 */ 7411 typeof(Unqual!(F).init * Unqual!(G).init) pow(F, G)(F x, G n) @nogc @trusted pure nothrow 7412 if (isIntegral!(F) && isIntegral!(G)) 7413 { 7414 typeof(return) p, v = void; 7415 Unqual!G m = n; 7416 7417 static if (isSigned!(F)) 7418 { 7419 if (x == -1) return cast(typeof(return)) (m & 1 ? -1 : 1); 7420 } 7421 static if (isSigned!(G)) 7422 { 7423 if (x == 0 && m <= -1) return x / 0; 7424 } 7425 if (x == 1) return 1; 7426 static if (isSigned!(G)) 7427 { 7428 if (m < 0) return 0; 7429 } 7430 7431 switch (m) 7432 { 7433 case 0: 7434 p = 1; 7435 break; 7436 7437 case 1: 7438 p = x; 7439 break; 7440 7441 case 2: 7442 p = x * x; 7443 break; 7444 7445 default: 7446 v = x; 7447 p = 1; 7448 while (1) 7449 { 7450 if (m & 1) 7451 p *= v; 7452 m >>= 1; 7453 if (!m) 7454 break; 7455 v *= v; 7456 } 7457 break; 7458 } 7459 return p; 7460 } 7461 7462 /// 7463 @safe pure nothrow @nogc unittest 7464 { 7465 assert(pow(2, 3) == 8); 7466 assert(pow(3, 2) == 9); 7467 7468 assert(pow(2, 10) == 1_024); 7469 assert(pow(2, 20) == 1_048_576); 7470 assert(pow(2, 30) == 1_073_741_824); 7471 7472 assert(pow(0, 0) == 1); 7473 7474 assert(pow(1, -5) == 1); 7475 assert(pow(1, -6) == 1); 7476 assert(pow(-1, -5) == -1); 7477 assert(pow(-1, -6) == 1); 7478 7479 assert(pow(-2, 5) == -32); 7480 assert(pow(-2, -5) == 0); 7481 assert(pow(cast(double) -2, -5) == -0.03125); 7482 } 7483 7484 @safe pure nothrow @nogc unittest 7485 { 7486 immutable int one = 1; 7487 immutable byte two = 2; 7488 immutable ubyte three = 3; 7489 immutable short four = 4; 7490 immutable long ten = 10; 7491 7492 assert(pow(two, three) == 8); 7493 assert(pow(two, ten) == 1024); 7494 assert(pow(one, ten) == 1); 7495 assert(pow(ten, four) == 10_000); 7496 assert(pow(four, 10) == 1_048_576); 7497 assert(pow(three, four) == 81); 7498 } 7499 7500 // https://issues.dlang.org/show_bug.cgi?id=7006 7501 @safe pure nothrow @nogc unittest 7502 { 7503 assert(pow(5, -1) == 0); 7504 assert(pow(-5, -1) == 0); 7505 assert(pow(5, -2) == 0); 7506 assert(pow(-5, -2) == 0); 7507 assert(pow(-1, int.min) == 1); 7508 assert(pow(-2, int.min) == 0); 7509 7510 assert(pow(4294967290UL,2) == 18446744022169944100UL); 7511 assert(pow(0,uint.max) == 0); 7512 } 7513 7514 /**Computes integer to floating point powers.*/ 7515 real pow(I, F)(I x, F y) @nogc @trusted pure nothrow 7516 if (isIntegral!I && isFloatingPoint!F) 7517 { 7518 return pow(cast(real) x, cast(Unqual!F) y); 7519 } 7520 7521 /// 7522 @safe pure nothrow @nogc unittest 7523 { 7524 assert(pow(2, 5.0) == 32.0); 7525 assert(pow(7, 3.0) == 343.0); 7526 assert(pow(2, real.nan) is real.nan); 7527 assert(pow(2, real.infinity) == real.infinity); 7528 } 7529 7530 /** 7531 * Calculates x$(SUPERSCRIPT y). 7532 * 7533 * $(TABLE_SV 7534 * $(TR $(TH x) $(TH y) $(TH pow(x, y)) 7535 * $(TH div 0) $(TH invalid?)) 7536 * $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD 1.0) 7537 * $(TD no) $(TD no) ) 7538 * $(TR $(TD |x| $(GT) 1) $(TD +$(INFIN)) $(TD +$(INFIN)) 7539 * $(TD no) $(TD no) ) 7540 * $(TR $(TD |x| $(LT) 1) $(TD +$(INFIN)) $(TD +0.0) 7541 * $(TD no) $(TD no) ) 7542 * $(TR $(TD |x| $(GT) 1) $(TD -$(INFIN)) $(TD +0.0) 7543 * $(TD no) $(TD no) ) 7544 * $(TR $(TD |x| $(LT) 1) $(TD -$(INFIN)) $(TD +$(INFIN)) 7545 * $(TD no) $(TD no) ) 7546 * $(TR $(TD +$(INFIN)) $(TD $(GT) 0.0) $(TD +$(INFIN)) 7547 * $(TD no) $(TD no) ) 7548 * $(TR $(TD +$(INFIN)) $(TD $(LT) 0.0) $(TD +0.0) 7549 * $(TD no) $(TD no) ) 7550 * $(TR $(TD -$(INFIN)) $(TD odd integer $(GT) 0.0) $(TD -$(INFIN)) 7551 * $(TD no) $(TD no) ) 7552 * $(TR $(TD -$(INFIN)) $(TD $(GT) 0.0, not odd integer) $(TD +$(INFIN)) 7553 * $(TD no) $(TD no)) 7554 * $(TR $(TD -$(INFIN)) $(TD odd integer $(LT) 0.0) $(TD -0.0) 7555 * $(TD no) $(TD no) ) 7556 * $(TR $(TD -$(INFIN)) $(TD $(LT) 0.0, not odd integer) $(TD +0.0) 7557 * $(TD no) $(TD no) ) 7558 * $(TR $(TD $(PLUSMN)1.0) $(TD $(PLUSMN)$(INFIN)) $(TD -$(NAN)) 7559 * $(TD no) $(TD yes) ) 7560 * $(TR $(TD $(LT) 0.0) $(TD finite, nonintegral) $(TD $(NAN)) 7561 * $(TD no) $(TD yes)) 7562 * $(TR $(TD $(PLUSMN)0.0) $(TD odd integer $(LT) 0.0) $(TD $(PLUSMNINF)) 7563 * $(TD yes) $(TD no) ) 7564 * $(TR $(TD $(PLUSMN)0.0) $(TD $(LT) 0.0, not odd integer) $(TD +$(INFIN)) 7565 * $(TD yes) $(TD no)) 7566 * $(TR $(TD $(PLUSMN)0.0) $(TD odd integer $(GT) 0.0) $(TD $(PLUSMN)0.0) 7567 * $(TD no) $(TD no) ) 7568 * $(TR $(TD $(PLUSMN)0.0) $(TD $(GT) 0.0, not odd integer) $(TD +0.0) 7569 * $(TD no) $(TD no) ) 7570 * ) 7571 */ 7572 Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow 7573 if (isFloatingPoint!(F) && isFloatingPoint!(G)) 7574 { 7575 alias Float = typeof(return); 7576 7577 static real impl(real x, real y) @nogc pure nothrow 7578 { 7579 // Special cases. 7580 if (isNaN(y)) 7581 return y; 7582 if (isNaN(x) && y != 0.0) 7583 return x; 7584 7585 // Even if x is NaN. 7586 if (y == 0.0) 7587 return 1.0; 7588 if (y == 1.0) 7589 return x; 7590 7591 if (isInfinity(y)) 7592 { 7593 if (fabs(x) > 1) 7594 { 7595 if (signbit(y)) 7596 return +0.0; 7597 else 7598 return F.infinity; 7599 } 7600 else if (fabs(x) == 1) 7601 { 7602 return y * 0; // generate NaN. 7603 } 7604 else // < 1 7605 { 7606 if (signbit(y)) 7607 return F.infinity; 7608 else 7609 return +0.0; 7610 } 7611 } 7612 if (isInfinity(x)) 7613 { 7614 if (signbit(x)) 7615 { 7616 long i = cast(long) y; 7617 if (y > 0.0) 7618 { 7619 if (i == y && i & 1) 7620 return -F.infinity; 7621 else 7622 return F.infinity; 7623 } 7624 else if (y < 0.0) 7625 { 7626 if (i == y && i & 1) 7627 return -0.0; 7628 else 7629 return +0.0; 7630 } 7631 } 7632 else 7633 { 7634 if (y > 0.0) 7635 return F.infinity; 7636 else if (y < 0.0) 7637 return +0.0; 7638 } 7639 } 7640 7641 if (x == 0.0) 7642 { 7643 if (signbit(x)) 7644 { 7645 long i = cast(long) y; 7646 if (y > 0.0) 7647 { 7648 if (i == y && i & 1) 7649 return -0.0; 7650 else 7651 return +0.0; 7652 } 7653 else if (y < 0.0) 7654 { 7655 if (i == y && i & 1) 7656 return -F.infinity; 7657 else 7658 return F.infinity; 7659 } 7660 } 7661 else 7662 { 7663 if (y > 0.0) 7664 return +0.0; 7665 else if (y < 0.0) 7666 return F.infinity; 7667 } 7668 } 7669 if (x == 1.0) 7670 return 1.0; 7671 7672 if (y >= F.max) 7673 { 7674 if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0)) 7675 return 0.0; 7676 if (x > 1.0 || x < -1.0) 7677 return F.infinity; 7678 } 7679 if (y <= -F.max) 7680 { 7681 if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0)) 7682 return F.infinity; 7683 if (x > 1.0 || x < -1.0) 7684 return 0.0; 7685 } 7686 7687 if (x >= F.max) 7688 { 7689 if (y > 0.0) 7690 return F.infinity; 7691 else 7692 return 0.0; 7693 } 7694 if (x <= -F.max) 7695 { 7696 long i = cast(long) y; 7697 if (y > 0.0) 7698 { 7699 if (i == y && i & 1) 7700 return -F.infinity; 7701 else 7702 return F.infinity; 7703 } 7704 else if (y < 0.0) 7705 { 7706 if (i == y && i & 1) 7707 return -0.0; 7708 else 7709 return +0.0; 7710 } 7711 } 7712 7713 // Integer power of x. 7714 long iy = cast(long) y; 7715 if (iy == y && fabs(y) < 32_768.0) 7716 return pow(x, iy); 7717 7718 real sign = 1.0; 7719 if (x < 0) 7720 { 7721 // Result is real only if y is an integer 7722 // Check for a non-zero fractional part 7723 enum maxOdd = pow(2.0L, real.mant_dig) - 1.0L; 7724 static if (maxOdd > ulong.max) 7725 { 7726 // Generic method, for any FP type 7727 if (floor(y) != y) 7728 return sqrt(x); // Complex result -- create a NaN 7729 7730 const hy = 0.5 * y; 7731 if (floor(hy) != hy) 7732 sign = -1.0; 7733 } 7734 else 7735 { 7736 // Much faster, if ulong has enough precision 7737 const absY = fabs(y); 7738 if (absY <= maxOdd) 7739 { 7740 const uy = cast(ulong) absY; 7741 if (uy != absY) 7742 return sqrt(x); // Complex result -- create a NaN 7743 7744 if (uy & 1) 7745 sign = -1.0; 7746 } 7747 } 7748 x = -x; 7749 } 7750 version (INLINE_YL2X) 7751 { 7752 // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) ) 7753 // TODO: This is not accurate in practice. A fast and accurate 7754 // (though complicated) method is described in: 7755 // "An efficient rounding boundary test for pow(x, y) 7756 // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007). 7757 return sign * exp2( core.math.yl2x(x, y) ); 7758 } 7759 else 7760 { 7761 // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) ) 7762 // TODO: This is not accurate in practice. A fast and accurate 7763 // (though complicated) method is described in: 7764 // "An efficient rounding boundary test for pow(x, y) 7765 // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007). 7766 Float w = exp2(y * log2(x)); 7767 return sign * w; 7768 } 7769 } 7770 return impl(x, y); 7771 } 7772 7773 /// 7774 @safe pure nothrow @nogc unittest 7775 { 7776 assert(pow(1.0, 2.0) == 1.0); 7777 assert(pow(0.0, 0.0) == 1.0); 7778 assert(pow(1.5, 10.0).feqrel(57.665) > 16); 7779 7780 // special values 7781 assert(pow(1.5, real.infinity) == real.infinity); 7782 assert(pow(0.5, real.infinity) == 0.0); 7783 assert(pow(1.5, -real.infinity) == 0.0); 7784 assert(pow(0.5, -real.infinity) == real.infinity); 7785 assert(pow(real.infinity, 1.0) == real.infinity); 7786 assert(pow(real.infinity, -1.0) == 0.0); 7787 assert(pow(-real.infinity, 1.0) == -real.infinity); 7788 assert(pow(-real.infinity, 2.0) == real.infinity); 7789 assert(pow(-real.infinity, -1.0) == -0.0); 7790 assert(pow(-real.infinity, -2.0) == 0.0); 7791 assert(pow(1.0, real.infinity) is -real.nan); 7792 assert(pow(0.0, -1.0) == real.infinity); 7793 assert(pow(real.nan, 0.0) == 1.0); 7794 } 7795 7796 @safe pure nothrow @nogc unittest 7797 { 7798 // Test all the special values. These unittests can be run on Windows 7799 // by temporarily changing the version (linux) to version (all). 7800 immutable float zero = 0; 7801 immutable real one = 1; 7802 immutable double two = 2; 7803 immutable float three = 3; 7804 immutable float fnan = float.nan; 7805 immutable double dnan = double.nan; 7806 immutable real rnan = real.nan; 7807 immutable dinf = double.infinity; 7808 immutable rninf = -real.infinity; 7809 7810 assert(pow(fnan, zero) == 1); 7811 assert(pow(dnan, zero) == 1); 7812 assert(pow(rnan, zero) == 1); 7813 7814 assert(pow(two, dinf) == double.infinity); 7815 assert(isIdentical(pow(0.2f, dinf), +0.0)); 7816 assert(pow(0.99999999L, rninf) == real.infinity); 7817 assert(isIdentical(pow(1.000000001, rninf), +0.0)); 7818 assert(pow(dinf, 0.001) == dinf); 7819 assert(isIdentical(pow(dinf, -0.001), +0.0)); 7820 assert(pow(rninf, 3.0L) == rninf); 7821 assert(pow(rninf, 2.0L) == real.infinity); 7822 assert(isIdentical(pow(rninf, -3.0), -0.0)); 7823 assert(isIdentical(pow(rninf, -2.0), +0.0)); 7824 7825 // @@@BUG@@@ somewhere 7826 version (OSX) {} else assert(isNaN(pow(one, dinf))); 7827 version (OSX) {} else assert(isNaN(pow(-one, dinf))); 7828 assert(isNaN(pow(-0.2, PI))); 7829 // boundary cases. Note that epsilon == 2^^-n for some n, 7830 // so 1/epsilon == 2^^n is always even. 7831 assert(pow(-1.0L, 1/real.epsilon - 1.0L) == -1.0L); 7832 assert(pow(-1.0L, 1/real.epsilon) == 1.0L); 7833 assert(isNaN(pow(-1.0L, 1/real.epsilon-0.5L))); 7834 assert(isNaN(pow(-1.0L, -1/real.epsilon+0.5L))); 7835 7836 assert(pow(0.0, -3.0) == double.infinity); 7837 assert(pow(-0.0, -3.0) == -double.infinity); 7838 assert(pow(0.0, -PI) == double.infinity); 7839 assert(pow(-0.0, -PI) == double.infinity); 7840 assert(isIdentical(pow(0.0, 5.0), 0.0)); 7841 assert(isIdentical(pow(-0.0, 5.0), -0.0)); 7842 assert(isIdentical(pow(0.0, 6.0), 0.0)); 7843 assert(isIdentical(pow(-0.0, 6.0), 0.0)); 7844 7845 // https://issues.dlang.org/show_bug.cgi?id=14786 fixed 7846 immutable real maxOdd = pow(2.0L, real.mant_dig) - 1.0L; 7847 assert(pow(-1.0L, maxOdd) == -1.0L); 7848 assert(pow(-1.0L, -maxOdd) == -1.0L); 7849 assert(pow(-1.0L, maxOdd + 1.0L) == 1.0L); 7850 assert(pow(-1.0L, -maxOdd + 1.0L) == 1.0L); 7851 assert(pow(-1.0L, maxOdd - 1.0L) == 1.0L); 7852 assert(pow(-1.0L, -maxOdd - 1.0L) == 1.0L); 7853 7854 // Now, actual numbers. 7855 assert(approxEqual(pow(two, three), 8.0)); 7856 assert(approxEqual(pow(two, -2.5), 0.1767767)); 7857 7858 // Test integer to float power. 7859 immutable uint twoI = 2; 7860 assert(approxEqual(pow(twoI, three), 8.0)); 7861 } 7862 7863 /** Computes the value of a positive integer `x`, raised to the power `n`, modulo `m`. 7864 * 7865 * Params: 7866 * x = base 7867 * n = exponent 7868 * m = modulus 7869 * 7870 * Returns: 7871 * `x` to the power `n`, modulo `m`. 7872 * The return type is the largest of `x`'s and `m`'s type. 7873 * 7874 * The function requires that all values have unsigned types. 7875 */ 7876 Unqual!(Largest!(F, H)) powmod(F, G, H)(F x, G n, H m) 7877 if (isUnsigned!F && isUnsigned!G && isUnsigned!H) 7878 { 7879 import std.meta : AliasSeq; 7880 7881 alias T = Unqual!(Largest!(F, H)); 7882 static if (T.sizeof <= 4) 7883 { 7884 alias DoubleT = AliasSeq!(void, ushort, uint, void, ulong)[T.sizeof]; 7885 } 7886 7887 static T mulmod(T a, T b, T c) 7888 { 7889 static if (T.sizeof == 8) 7890 { 7891 static T addmod(T a, T b, T c) 7892 { 7893 b = c - b; 7894 if (a >= b) 7895 return a - b; 7896 else 7897 return c - b + a; 7898 } 7899 7900 T result = 0, tmp; 7901 7902 b %= c; 7903 while (a > 0) 7904 { 7905 if (a & 1) 7906 result = addmod(result, b, c); 7907 7908 a >>= 1; 7909 b = addmod(b, b, c); 7910 } 7911 7912 return result; 7913 } 7914 else 7915 { 7916 DoubleT result = cast(DoubleT) (cast(DoubleT) a * cast(DoubleT) b); 7917 return result % c; 7918 } 7919 } 7920 7921 T base = x, result = 1, modulus = m; 7922 Unqual!G exponent = n; 7923 7924 while (exponent > 0) 7925 { 7926 if (exponent & 1) 7927 result = mulmod(result, base, modulus); 7928 7929 base = mulmod(base, base, modulus); 7930 exponent >>= 1; 7931 } 7932 7933 return result; 7934 } 7935 7936 /// 7937 @safe pure nothrow @nogc unittest 7938 { 7939 assert(powmod(1U, 10U, 3U) == 1); 7940 assert(powmod(3U, 2U, 6U) == 3); 7941 assert(powmod(5U, 5U, 15U) == 5); 7942 assert(powmod(2U, 3U, 5U) == 3); 7943 assert(powmod(2U, 4U, 5U) == 1); 7944 assert(powmod(2U, 5U, 5U) == 2); 7945 } 7946 7947 @safe pure nothrow @nogc unittest 7948 { 7949 ulong a = 18446744073709551615u, b = 20u, c = 18446744073709551610u; 7950 assert(powmod(a, b, c) == 95367431640625u); 7951 a = 100; b = 7919; c = 18446744073709551557u; 7952 assert(powmod(a, b, c) == 18223853583554725198u); 7953 a = 117; b = 7919; c = 18446744073709551557u; 7954 assert(powmod(a, b, c) == 11493139548346411394u); 7955 a = 134; b = 7919; c = 18446744073709551557u; 7956 assert(powmod(a, b, c) == 10979163786734356774u); 7957 a = 151; b = 7919; c = 18446744073709551557u; 7958 assert(powmod(a, b, c) == 7023018419737782840u); 7959 a = 168; b = 7919; c = 18446744073709551557u; 7960 assert(powmod(a, b, c) == 58082701842386811u); 7961 a = 185; b = 7919; c = 18446744073709551557u; 7962 assert(powmod(a, b, c) == 17423478386299876798u); 7963 a = 202; b = 7919; c = 18446744073709551557u; 7964 assert(powmod(a, b, c) == 5522733478579799075u); 7965 a = 219; b = 7919; c = 18446744073709551557u; 7966 assert(powmod(a, b, c) == 15230218982491623487u); 7967 a = 236; b = 7919; c = 18446744073709551557u; 7968 assert(powmod(a, b, c) == 5198328724976436000u); 7969 7970 a = 0; b = 7919; c = 18446744073709551557u; 7971 assert(powmod(a, b, c) == 0); 7972 a = 123; b = 0; c = 18446744073709551557u; 7973 assert(powmod(a, b, c) == 1); 7974 7975 immutable ulong a1 = 253, b1 = 7919, c1 = 18446744073709551557u; 7976 assert(powmod(a1, b1, c1) == 3883707345459248860u); 7977 7978 uint x = 100 ,y = 7919, z = 1844674407u; 7979 assert(powmod(x, y, z) == 1613100340u); 7980 x = 134; y = 7919; z = 1844674407u; 7981 assert(powmod(x, y, z) == 734956622u); 7982 x = 151; y = 7919; z = 1844674407u; 7983 assert(powmod(x, y, z) == 1738696945u); 7984 x = 168; y = 7919; z = 1844674407u; 7985 assert(powmod(x, y, z) == 1247580927u); 7986 x = 185; y = 7919; z = 1844674407u; 7987 assert(powmod(x, y, z) == 1293855176u); 7988 x = 202; y = 7919; z = 1844674407u; 7989 assert(powmod(x, y, z) == 1566963682u); 7990 x = 219; y = 7919; z = 1844674407u; 7991 assert(powmod(x, y, z) == 181227807u); 7992 x = 236; y = 7919; z = 1844674407u; 7993 assert(powmod(x, y, z) == 217988321u); 7994 x = 253; y = 7919; z = 1844674407u; 7995 assert(powmod(x, y, z) == 1588843243u); 7996 7997 x = 0; y = 7919; z = 184467u; 7998 assert(powmod(x, y, z) == 0); 7999 x = 123; y = 0; z = 1844674u; 8000 assert(powmod(x, y, z) == 1); 8001 8002 immutable ubyte x1 = 117; 8003 immutable uint y1 = 7919; 8004 immutable uint z1 = 1844674407u; 8005 auto res = powmod(x1, y1, z1); 8006 assert(is(typeof(res) == uint)); 8007 assert(res == 9479781u); 8008 8009 immutable ushort x2 = 123; 8010 immutable uint y2 = 203; 8011 immutable ubyte z2 = 113; 8012 auto res2 = powmod(x2, y2, z2); 8013 assert(is(typeof(res2) == ushort)); 8014 assert(res2 == 42u); 8015 } 8016 8017 /************************************** 8018 * To what precision is x equal to y? 8019 * 8020 * Returns: the number of mantissa bits which are equal in x and y. 8021 * eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision. 8022 * 8023 * $(TABLE_SV 8024 * $(TR $(TH x) $(TH y) $(TH feqrel(x, y))) 8025 * $(TR $(TD x) $(TD x) $(TD real.mant_dig)) 8026 * $(TR $(TD x) $(TD $(GT)= 2*x) $(TD 0)) 8027 * $(TR $(TD x) $(TD $(LT)= x/2) $(TD 0)) 8028 * $(TR $(TD $(NAN)) $(TD any) $(TD 0)) 8029 * $(TR $(TD any) $(TD $(NAN)) $(TD 0)) 8030 * ) 8031 */ 8032 int feqrel(X)(const X x, const X y) @trusted pure nothrow @nogc 8033 if (isFloatingPoint!(X)) 8034 { 8035 /* Public Domain. Author: Don Clugston, 18 Aug 2005. 8036 */ 8037 alias F = floatTraits!(X); 8038 static if (F.realFormat == RealFormat.ieeeSingle 8039 || F.realFormat == RealFormat.ieeeDouble 8040 || F.realFormat == RealFormat.ieeeExtended 8041 || F.realFormat == RealFormat.ieeeQuadruple) 8042 { 8043 if (x == y) 8044 return X.mant_dig; // ensure diff != 0, cope with INF. 8045 8046 Unqual!X diff = fabs(x - y); 8047 8048 ushort *pa = cast(ushort *)(&x); 8049 ushort *pb = cast(ushort *)(&y); 8050 ushort *pd = cast(ushort *)(&diff); 8051 8052 8053 // The difference in abs(exponent) between x or y and abs(x-y) 8054 // is equal to the number of significand bits of x which are 8055 // equal to y. If negative, x and y have different exponents. 8056 // If positive, x and y are equal to 'bitsdiff' bits. 8057 // AND with 0x7FFF to form the absolute value. 8058 // To avoid out-by-1 errors, we subtract 1 so it rounds down 8059 // if the exponents were different. This means 'bitsdiff' is 8060 // always 1 lower than we want, except that if bitsdiff == 0, 8061 // they could have 0 or 1 bits in common. 8062 8063 int bitsdiff = ((( (pa[F.EXPPOS_SHORT] & F.EXPMASK) 8064 + (pb[F.EXPPOS_SHORT] & F.EXPMASK) 8065 - (1 << F.EXPSHIFT)) >> 1) 8066 - (pd[F.EXPPOS_SHORT] & F.EXPMASK)) >> F.EXPSHIFT; 8067 if ( (pd[F.EXPPOS_SHORT] & F.EXPMASK) == 0) 8068 { // Difference is subnormal 8069 // For subnormals, we need to add the number of zeros that 8070 // lie at the start of diff's significand. 8071 // We do this by multiplying by 2^^real.mant_dig 8072 diff *= F.RECIP_EPSILON; 8073 return bitsdiff + X.mant_dig - ((pd[F.EXPPOS_SHORT] & F.EXPMASK) >> F.EXPSHIFT); 8074 } 8075 8076 if (bitsdiff > 0) 8077 return bitsdiff + 1; // add the 1 we subtracted before 8078 8079 // Avoid out-by-1 errors when factor is almost 2. 8080 if (bitsdiff == 0 8081 && ((pa[F.EXPPOS_SHORT] ^ pb[F.EXPPOS_SHORT]) & F.EXPMASK) == 0) 8082 { 8083 return 1; 8084 } else return 0; 8085 } 8086 else 8087 { 8088 static assert(false, "Not implemented for this architecture"); 8089 } 8090 } 8091 8092 /// 8093 @safe pure unittest 8094 { 8095 assert(feqrel(2.0, 2.0) == 53); 8096 assert(feqrel(2.0f, 2.0f) == 24); 8097 assert(feqrel(2.0, double.nan) == 0); 8098 8099 // Test that numbers are within n digits of each 8100 // other by testing if feqrel > n * log2(10) 8101 8102 // five digits 8103 assert(feqrel(2.0, 2.00001) > 16); 8104 // ten digits 8105 assert(feqrel(2.0, 2.00000000001) > 33); 8106 } 8107 8108 @safe pure nothrow @nogc unittest 8109 { 8110 void testFeqrel(F)() 8111 { 8112 // Exact equality 8113 assert(feqrel(F.max, F.max) == F.mant_dig); 8114 assert(feqrel!(F)(0.0, 0.0) == F.mant_dig); 8115 assert(feqrel(F.infinity, F.infinity) == F.mant_dig); 8116 8117 // a few bits away from exact equality 8118 F w=1; 8119 for (int i = 1; i < F.mant_dig - 1; ++i) 8120 { 8121 assert(feqrel!(F)(1.0 + w * F.epsilon, 1.0) == F.mant_dig-i); 8122 assert(feqrel!(F)(1.0 - w * F.epsilon, 1.0) == F.mant_dig-i); 8123 assert(feqrel!(F)(1.0, 1 + (w-1) * F.epsilon) == F.mant_dig - i + 1); 8124 w*=2; 8125 } 8126 8127 assert(feqrel!(F)(1.5+F.epsilon, 1.5) == F.mant_dig-1); 8128 assert(feqrel!(F)(1.5-F.epsilon, 1.5) == F.mant_dig-1); 8129 assert(feqrel!(F)(1.5-F.epsilon, 1.5+F.epsilon) == F.mant_dig-2); 8130 8131 8132 // Numbers that are close 8133 assert(feqrel!(F)(0x1.Bp+84, 0x1.B8p+84) == 5); 8134 assert(feqrel!(F)(0x1.8p+10, 0x1.Cp+10) == 2); 8135 assert(feqrel!(F)(1.5 * (1 - F.epsilon), 1.0L) == 2); 8136 assert(feqrel!(F)(1.5, 1.0) == 1); 8137 assert(feqrel!(F)(2 * (1 - F.epsilon), 1.0L) == 1); 8138 8139 // Factors of 2 8140 assert(feqrel(F.max, F.infinity) == 0); 8141 assert(feqrel!(F)(2 * (1 - F.epsilon), 1.0L) == 1); 8142 assert(feqrel!(F)(1.0, 2.0) == 0); 8143 assert(feqrel!(F)(4.0, 1.0) == 0); 8144 8145 // Extreme inequality 8146 assert(feqrel(F.nan, F.nan) == 0); 8147 assert(feqrel!(F)(0.0L, -F.nan) == 0); 8148 assert(feqrel(F.nan, F.infinity) == 0); 8149 assert(feqrel(F.infinity, -F.infinity) == 0); 8150 assert(feqrel(F.max, -F.max) == 0); 8151 8152 assert(feqrel(F.min_normal / 8, F.min_normal / 17) == 3); 8153 8154 const F Const = 2; 8155 immutable F Immutable = 2; 8156 auto Compiles = feqrel(Const, Immutable); 8157 } 8158 8159 assert(feqrel(7.1824L, 7.1824L) == real.mant_dig); 8160 8161 testFeqrel!(real)(); 8162 testFeqrel!(double)(); 8163 testFeqrel!(float)(); 8164 } 8165 8166 8167 /*********************************** 8168 * Evaluate polynomial A(x) = $(SUB a, 0) + $(SUB a, 1)x + $(SUB a, 2)$(POWER x,2) + 8169 * $(SUB a,3)$(POWER x,3); ... 8170 * 8171 * Uses Horner's rule A(x) = $(SUB a, 0) + x($(SUB a, 1) + x($(SUB a, 2) + 8172 * x($(SUB a, 3) + ...))) 8173 * Params: 8174 * x = the value to evaluate. 8175 * A = array of coefficients $(SUB a, 0), $(SUB a, 1), etc. 8176 */ 8177 Unqual!(CommonType!(T1, T2)) poly(T1, T2)(T1 x, in T2[] A) @trusted pure nothrow @nogc 8178 if (isFloatingPoint!T1 && isFloatingPoint!T2) 8179 in 8180 { 8181 assert(A.length > 0); 8182 } 8183 do 8184 { 8185 static if (is(immutable T2 == immutable real)) 8186 { 8187 return polyImpl(x, A); 8188 } 8189 else 8190 { 8191 return polyImplBase(x, A); 8192 } 8193 } 8194 8195 /// ditto 8196 Unqual!(CommonType!(T1, T2)) poly(T1, T2, int N)(T1 x, ref const T2[N] A) @safe pure nothrow @nogc 8197 if (isFloatingPoint!T1 && isFloatingPoint!T2 && N > 0 && N <= 10) 8198 { 8199 // statically unrolled version for up to 10 coefficients 8200 typeof(return) r = A[N - 1]; 8201 static foreach (i; 1 .. N) 8202 { 8203 r *= x; 8204 r += A[N - 1 - i]; 8205 } 8206 return r; 8207 } 8208 8209 /// 8210 @safe nothrow @nogc unittest 8211 { 8212 real x = 3.1L; 8213 static real[] pp = [56.1L, 32.7L, 6]; 8214 8215 assert(poly(x, pp) == (56.1L + (32.7L + 6.0L * x) * x)); 8216 } 8217 8218 @safe nothrow @nogc unittest 8219 { 8220 double x = 3.1; 8221 static double[] pp = [56.1, 32.7, 6]; 8222 double y = x; 8223 y *= 6.0; 8224 y += 32.7; 8225 y *= x; 8226 y += 56.1; 8227 assert(poly(x, pp) == y); 8228 } 8229 8230 @safe unittest 8231 { 8232 static assert(poly(3.0, [1.0, 2.0, 3.0]) == 34); 8233 } 8234 8235 private Unqual!(CommonType!(T1, T2)) polyImplBase(T1, T2)(T1 x, in T2[] A) @trusted pure nothrow @nogc 8236 if (isFloatingPoint!T1 && isFloatingPoint!T2) 8237 { 8238 ptrdiff_t i = A.length - 1; 8239 typeof(return) r = A[i]; 8240 while (--i >= 0) 8241 { 8242 r *= x; 8243 r += A[i]; 8244 } 8245 return r; 8246 } 8247 8248 private real polyImpl(real x, in real[] A) @trusted pure nothrow @nogc 8249 { 8250 version (D_InlineAsm_X86) 8251 { 8252 if (__ctfe) 8253 { 8254 return polyImplBase(x, A); 8255 } 8256 version (Windows) 8257 { 8258 // BUG: This code assumes a frame pointer in EBP. 8259 asm pure nothrow @nogc // assembler by W. Bright 8260 { 8261 // EDX = (A.length - 1) * real.sizeof 8262 mov ECX,A[EBP] ; // ECX = A.length 8263 dec ECX ; 8264 lea EDX,[ECX][ECX*8] ; 8265 add EDX,ECX ; 8266 add EDX,A+4[EBP] ; 8267 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8268 jecxz return_ST ; 8269 fld x[EBP] ; // ST0 = x 8270 fxch ST(1) ; // ST1 = x, ST0 = r 8271 align 4 ; 8272 L2: fmul ST,ST(1) ; // r *= x 8273 fld real ptr -10[EDX] ; 8274 sub EDX,10 ; // deg-- 8275 faddp ST(1),ST ; 8276 dec ECX ; 8277 jne L2 ; 8278 fxch ST(1) ; // ST1 = r, ST0 = x 8279 fstp ST(0) ; // dump x 8280 align 4 ; 8281 return_ST: ; 8282 } 8283 } 8284 else version (linux) 8285 { 8286 asm pure nothrow @nogc // assembler by W. Bright 8287 { 8288 // EDX = (A.length - 1) * real.sizeof 8289 mov ECX,A[EBP] ; // ECX = A.length 8290 dec ECX ; 8291 lea EDX,[ECX*8] ; 8292 lea EDX,[EDX][ECX*4] ; 8293 add EDX,A+4[EBP] ; 8294 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8295 jecxz return_ST ; 8296 fld x[EBP] ; // ST0 = x 8297 fxch ST(1) ; // ST1 = x, ST0 = r 8298 align 4 ; 8299 L2: fmul ST,ST(1) ; // r *= x 8300 fld real ptr -12[EDX] ; 8301 sub EDX,12 ; // deg-- 8302 faddp ST(1),ST ; 8303 dec ECX ; 8304 jne L2 ; 8305 fxch ST(1) ; // ST1 = r, ST0 = x 8306 fstp ST(0) ; // dump x 8307 align 4 ; 8308 return_ST: ; 8309 } 8310 } 8311 else version (OSX) 8312 { 8313 asm pure nothrow @nogc // assembler by W. Bright 8314 { 8315 // EDX = (A.length - 1) * real.sizeof 8316 mov ECX,A[EBP] ; // ECX = A.length 8317 dec ECX ; 8318 lea EDX,[ECX*8] ; 8319 add EDX,EDX ; 8320 add EDX,A+4[EBP] ; 8321 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8322 jecxz return_ST ; 8323 fld x[EBP] ; // ST0 = x 8324 fxch ST(1) ; // ST1 = x, ST0 = r 8325 align 4 ; 8326 L2: fmul ST,ST(1) ; // r *= x 8327 fld real ptr -16[EDX] ; 8328 sub EDX,16 ; // deg-- 8329 faddp ST(1),ST ; 8330 dec ECX ; 8331 jne L2 ; 8332 fxch ST(1) ; // ST1 = r, ST0 = x 8333 fstp ST(0) ; // dump x 8334 align 4 ; 8335 return_ST: ; 8336 } 8337 } 8338 else version (FreeBSD) 8339 { 8340 asm pure nothrow @nogc // assembler by W. Bright 8341 { 8342 // EDX = (A.length - 1) * real.sizeof 8343 mov ECX,A[EBP] ; // ECX = A.length 8344 dec ECX ; 8345 lea EDX,[ECX*8] ; 8346 lea EDX,[EDX][ECX*4] ; 8347 add EDX,A+4[EBP] ; 8348 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8349 jecxz return_ST ; 8350 fld x[EBP] ; // ST0 = x 8351 fxch ST(1) ; // ST1 = x, ST0 = r 8352 align 4 ; 8353 L2: fmul ST,ST(1) ; // r *= x 8354 fld real ptr -12[EDX] ; 8355 sub EDX,12 ; // deg-- 8356 faddp ST(1),ST ; 8357 dec ECX ; 8358 jne L2 ; 8359 fxch ST(1) ; // ST1 = r, ST0 = x 8360 fstp ST(0) ; // dump x 8361 align 4 ; 8362 return_ST: ; 8363 } 8364 } 8365 else version (Solaris) 8366 { 8367 asm pure nothrow @nogc // assembler by W. Bright 8368 { 8369 // EDX = (A.length - 1) * real.sizeof 8370 mov ECX,A[EBP] ; // ECX = A.length 8371 dec ECX ; 8372 lea EDX,[ECX*8] ; 8373 lea EDX,[EDX][ECX*4] ; 8374 add EDX,A+4[EBP] ; 8375 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8376 jecxz return_ST ; 8377 fld x[EBP] ; // ST0 = x 8378 fxch ST(1) ; // ST1 = x, ST0 = r 8379 align 4 ; 8380 L2: fmul ST,ST(1) ; // r *= x 8381 fld real ptr -12[EDX] ; 8382 sub EDX,12 ; // deg-- 8383 faddp ST(1),ST ; 8384 dec ECX ; 8385 jne L2 ; 8386 fxch ST(1) ; // ST1 = r, ST0 = x 8387 fstp ST(0) ; // dump x 8388 align 4 ; 8389 return_ST: ; 8390 } 8391 } 8392 else version (DragonFlyBSD) 8393 { 8394 asm pure nothrow @nogc // assembler by W. Bright 8395 { 8396 // EDX = (A.length - 1) * real.sizeof 8397 mov ECX,A[EBP] ; // ECX = A.length 8398 dec ECX ; 8399 lea EDX,[ECX*8] ; 8400 lea EDX,[EDX][ECX*4] ; 8401 add EDX,A+4[EBP] ; 8402 fld real ptr [EDX] ; // ST0 = coeff[ECX] 8403 jecxz return_ST ; 8404 fld x[EBP] ; // ST0 = x 8405 fxch ST(1) ; // ST1 = x, ST0 = r 8406 align 4 ; 8407 L2: fmul ST,ST(1) ; // r *= x 8408 fld real ptr -12[EDX] ; 8409 sub EDX,12 ; // deg-- 8410 faddp ST(1),ST ; 8411 dec ECX ; 8412 jne L2 ; 8413 fxch ST(1) ; // ST1 = r, ST0 = x 8414 fstp ST(0) ; // dump x 8415 align 4 ; 8416 return_ST: ; 8417 } 8418 } 8419 else 8420 { 8421 static assert(0); 8422 } 8423 } 8424 else 8425 { 8426 return polyImplBase(x, A); 8427 } 8428 } 8429 8430 8431 /** 8432 Computes whether a values is approximately equal to a reference value, 8433 admitting a maximum relative difference, and a maximum absolute difference. 8434 8435 Params: 8436 value = Value to compare. 8437 reference = Reference value. 8438 maxRelDiff = Maximum allowable difference relative to `reference`. 8439 Setting to 0.0 disables this check. Defaults to `1e-2`. 8440 maxAbsDiff = Maximum absolute difference. This is mainly usefull 8441 for comparing values to zero. Setting to 0.0 disables this check. 8442 Defaults to `1e-5`. 8443 8444 Returns: 8445 `true` if `value` is approximately equal to `reference` under 8446 either criterium. It is sufficient, when `value ` satisfies 8447 one of the two criteria. 8448 8449 If one item is a range, and the other is a single value, then 8450 the result is the logical and-ing of calling `approxEqual` on 8451 each element of the ranged item against the single item. If 8452 both items are ranges, then `approxEqual` returns `true` if 8453 and only if the ranges have the same number of elements and if 8454 `approxEqual` evaluates to `true` for each pair of elements. 8455 8456 See_Also: 8457 Use $(LREF feqrel) to get the number of equal bits in the mantissa. 8458 */ 8459 bool approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 1e-2, V maxAbsDiff = 1e-5) 8460 { 8461 import std.range.primitives : empty, front, isInputRange, popFront; 8462 static if (isInputRange!T) 8463 { 8464 static if (isInputRange!U) 8465 { 8466 // Two ranges 8467 for (;; value.popFront(), reference.popFront()) 8468 { 8469 if (value.empty) return reference.empty; 8470 if (reference.empty) return value.empty; 8471 if (!approxEqual(value.front, reference.front, maxRelDiff, maxAbsDiff)) 8472 return false; 8473 } 8474 } 8475 else static if (isIntegral!U) 8476 { 8477 // convert reference to real 8478 return approxEqual(value, real(reference), maxRelDiff, maxAbsDiff); 8479 } 8480 else 8481 { 8482 // value is range, reference is number 8483 for (; !value.empty; value.popFront()) 8484 { 8485 if (!approxEqual(value.front, reference, maxRelDiff, maxAbsDiff)) 8486 return false; 8487 } 8488 return true; 8489 } 8490 } 8491 else 8492 { 8493 static if (isInputRange!U) 8494 { 8495 // value is number, reference is range 8496 for (; !reference.empty; reference.popFront()) 8497 { 8498 if (!approxEqual(value, reference.front, maxRelDiff, maxAbsDiff)) 8499 return false; 8500 } 8501 return true; 8502 } 8503 else static if (isIntegral!T || isIntegral!U) 8504 { 8505 // convert both value and reference to real 8506 return approxEqual(real(value), real(reference), maxRelDiff, maxAbsDiff); 8507 } 8508 else 8509 { 8510 // two numbers 8511 //static assert(is(T : real) && is(U : real)); 8512 if (reference == 0) 8513 { 8514 return fabs(value) <= maxAbsDiff; 8515 } 8516 static if (is(typeof(value.infinity)) && is(typeof(reference.infinity))) 8517 { 8518 if (value == value.infinity && reference == reference.infinity || 8519 value == -value.infinity && reference == -reference.infinity) return true; 8520 } 8521 return fabs((value - reference) / reference) <= maxRelDiff 8522 || maxAbsDiff != 0 && fabs(value - reference) <= maxAbsDiff; 8523 } 8524 } 8525 } 8526 8527 /// 8528 @safe pure nothrow unittest 8529 { 8530 assert(approxEqual(1.0, 1.0099)); 8531 assert(!approxEqual(1.0, 1.011)); 8532 assert(approxEqual(0.00001, 0.0)); 8533 assert(!approxEqual(0.00002, 0.0)); 8534 8535 assert(approxEqual(3.0, [3, 3.01, 2.99])); // several reference values is strange 8536 assert(approxEqual([3, 3.01, 2.99], 3.0)); // better 8537 8538 float[] arr1 = [ 1.0, 2.0, 3.0 ]; 8539 double[] arr2 = [ 1.001, 1.999, 3 ]; 8540 assert(approxEqual(arr1, arr2)); 8541 } 8542 8543 /// 8544 @safe pure nothrow unittest 8545 { 8546 // relative comparison depends on reference, make sure proper 8547 // side is used when comparing range to single value. Based on 8548 // https://issues.dlang.org/show_bug.cgi?id=15763 8549 auto a = [2e-3 - 1e-5]; 8550 auto b = 2e-3 + 1e-5; 8551 assert(a[0].approxEqual(b)); 8552 assert(!b.approxEqual(a[0])); 8553 assert(a.approxEqual(b)); 8554 assert(!b.approxEqual(a)); 8555 } 8556 8557 /// 8558 @safe pure nothrow @nogc unittest 8559 { 8560 assert(!approxEqual(0.0,1e-15,1e-9,0.0)); 8561 assert(approxEqual(0.0,1e-15,1e-9,1e-9)); 8562 assert(!approxEqual(1.0,3.0,0.0,1.0)); 8563 8564 assert(approxEqual(1.00000000099,1.0,1e-9,0.0)); 8565 assert(!approxEqual(1.0000000011,1.0,1e-9,0.0)); 8566 } 8567 8568 /// 8569 @safe pure nothrow @nogc unittest 8570 { 8571 // maybe unintuitive behavior 8572 assert(approxEqual(1000.0,1010.0)); 8573 assert(approxEqual(9_090_000_000.0,9_000_000_000.0)); 8574 assert(approxEqual(0.0,1e30,1.0)); 8575 assert(approxEqual(0.00001,1e-30)); 8576 assert(!approxEqual(-1e-30,1e-30,1e-2,0.0)); 8577 } 8578 8579 @safe pure nothrow @nogc unittest 8580 { 8581 int a = 10; 8582 assert(approxEqual(10, a)); 8583 8584 assert(!approxEqual(3, 0)); 8585 assert(approxEqual(3, 3)); 8586 assert(approxEqual(3.0, 3)); 8587 assert(approxEqual(3, 3.0)); 8588 8589 assert(approxEqual(0.0,0.0)); 8590 assert(approxEqual(-0.0,0.0)); 8591 assert(approxEqual(0.0f,0.0)); 8592 } 8593 8594 @safe pure nothrow @nogc unittest 8595 { 8596 real num = real.infinity; 8597 assert(num == real.infinity); 8598 assert(approxEqual(num, real.infinity)); 8599 num = -real.infinity; 8600 assert(num == -real.infinity); 8601 assert(approxEqual(num, -real.infinity)); 8602 8603 assert(!approxEqual(1,real.nan)); 8604 assert(!approxEqual(real.nan,real.max)); 8605 assert(!approxEqual(real.nan,real.nan)); 8606 } 8607 8608 @safe pure nothrow unittest 8609 { 8610 assert(!approxEqual([1.0,2.0,3.0],[1.0,2.0])); 8611 assert(!approxEqual([1.0,2.0],[1.0,2.0,3.0])); 8612 8613 // assert(approxEqual([],[])); //FIXME: does not work yet 8614 assert(approxEqual(cast(real[])[],cast(real[])[])); 8615 } 8616 8617 8618 /** 8619 Computes whether two values are approximately equal, admitting a maximum 8620 relative difference, and a maximum absolute difference. 8621 8622 Params: 8623 lhs = First item to compare. 8624 rhs = Second item to compare. 8625 maxRelDiff = Maximum allowable relative difference. 8626 Setting to 0.0 disables this check. Default depends on the type of 8627 `lhs` and `rhs`: It is approximately half the number of decimal digits of 8628 precision of the smaller type. 8629 maxAbsDiff = Maximum absolute difference. This is mainly usefull 8630 for comparing values to zero. Setting to 0.0 disables this check. 8631 Defaults to `0.0`. 8632 8633 Returns: 8634 `true` if the two items are approximately equal under either criterium. 8635 It is sufficient, when `value ` satisfies one of the two criteria. 8636 8637 If one item is a range, and the other is a single value, then 8638 the result is the logical and-ing of calling `isClose` on 8639 each element of the ranged item against the single item. If 8640 both items are ranges, then `isClose` returns `true` if 8641 and only if the ranges have the same number of elements and if 8642 `isClose` evaluates to `true` for each pair of elements. 8643 8644 See_Also: 8645 Use $(LREF feqrel) to get the number of equal bits in the mantissa. 8646 */ 8647 bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType!U)) 8648 (T lhs, U rhs, V maxRelDiff = CommonDefaultFor!(T,U), V maxAbsDiff = 0.0) 8649 { 8650 import std.range.primitives : empty, front, isInputRange, popFront; 8651 import std.complex : Complex; 8652 static if (isInputRange!T) 8653 { 8654 static if (isInputRange!U) 8655 { 8656 // Two ranges 8657 for (;; lhs.popFront(), rhs.popFront()) 8658 { 8659 if (lhs.empty) return rhs.empty; 8660 if (rhs.empty) return lhs.empty; 8661 if (!isClose(lhs.front, rhs.front, maxRelDiff, maxAbsDiff)) 8662 return false; 8663 } 8664 } 8665 else 8666 { 8667 // lhs is range, rhs is number 8668 for (; !lhs.empty; lhs.popFront()) 8669 { 8670 if (!isClose(lhs.front, rhs, maxRelDiff, maxAbsDiff)) 8671 return false; 8672 } 8673 return true; 8674 } 8675 } 8676 else static if (isInputRange!U) 8677 { 8678 // lhs is number, rhs is range 8679 for (; !rhs.empty; rhs.popFront()) 8680 { 8681 if (!isClose(lhs, rhs.front, maxRelDiff, maxAbsDiff)) 8682 return false; 8683 } 8684 return true; 8685 } 8686 else static if (is(T TE == Complex!TE)) 8687 { 8688 static if (is(U UE == Complex!UE)) 8689 { 8690 // Two complex numbers 8691 return isClose(lhs.re, rhs.re, maxRelDiff, maxAbsDiff) 8692 && isClose(lhs.im, rhs.im, maxRelDiff, maxAbsDiff); 8693 } 8694 else 8695 { 8696 // lhs is complex, rhs is number 8697 return isClose(lhs.re, rhs, maxRelDiff, maxAbsDiff) 8698 && isClose(lhs.im, 0.0, maxRelDiff, maxAbsDiff); 8699 } 8700 } 8701 else static if (is(U UE == Complex!UE)) 8702 { 8703 // lhs is number, rhs is complex 8704 return isClose(lhs, rhs.re, maxRelDiff, maxAbsDiff) 8705 && isClose(0.0, rhs.im, maxRelDiff, maxAbsDiff); 8706 } 8707 else 8708 { 8709 // two numbers 8710 if (lhs == rhs) return true; 8711 8712 static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity))) 8713 { 8714 if (lhs == lhs.infinity || rhs == rhs.infinity || 8715 lhs == -lhs.infinity || rhs == -rhs.infinity) return false; 8716 } 8717 8718 auto diff = abs(lhs - rhs); 8719 8720 return diff <= maxRelDiff*abs(lhs) 8721 || diff <= maxRelDiff*abs(rhs) 8722 || diff <= maxAbsDiff; 8723 } 8724 } 8725 8726 /// 8727 @safe pure nothrow @nogc unittest 8728 { 8729 assert(isClose(1.0,0.999_999_999)); 8730 assert(isClose(0.001, 0.000_999_999_999)); 8731 assert(isClose(1_000_000_000.0,999_999_999.0)); 8732 8733 assert(isClose(17.123_456_789, 17.123_456_78)); 8734 assert(!isClose(17.123_456_789, 17.123_45)); 8735 8736 // use explicit 3rd parameter for less (or more) accuracy 8737 assert(isClose(17.123_456_789, 17.123_45, 1e-6)); 8738 assert(!isClose(17.123_456_789, 17.123_45, 1e-7)); 8739 8740 // use 4th parameter when comparing close to zero 8741 assert(!isClose(1e-100, 0.0)); 8742 assert(isClose(1e-100, 0.0, 0.0, 1e-90)); 8743 assert(!isClose(1e-10, -1e-10)); 8744 assert(isClose(1e-10, -1e-10, 0.0, 1e-9)); 8745 assert(!isClose(1e-300, 1e-298)); 8746 assert(isClose(1e-300, 1e-298, 0.0, 1e-200)); 8747 8748 // different default limits for different floating point types 8749 assert(isClose(1.0f, 0.999_99f)); 8750 assert(!isClose(1.0, 0.999_99)); 8751 static if (real.sizeof > double.sizeof) 8752 assert(!isClose(1.0L, 0.999_999_999L)); 8753 } 8754 8755 /// 8756 @safe pure nothrow unittest 8757 { 8758 assert(isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001, 3.0])); 8759 assert(!isClose([1.0, 2.0], [0.999_999_999, 2.000_000_001, 3.0])); 8760 assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001])); 8761 8762 assert(isClose([2.0, 1.999_999_999, 2.000_000_001], 2.0)); 8763 assert(isClose(2.0, [2.0, 1.999_999_999, 2.000_000_001])); 8764 } 8765 8766 @safe pure nothrow unittest 8767 { 8768 assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 3.0, 3.0])); 8769 assert(!isClose([2.0, 1.999_999, 2.000_000_001], 2.0)); 8770 assert(!isClose(2.0, [2.0, 1.999_999_999, 2.000_000_999])); 8771 } 8772 8773 @safe pure nothrow @nogc unittest 8774 { 8775 immutable a = 1.00001f; 8776 const b = 1.000019; 8777 assert(isClose(a,b)); 8778 8779 assert(isClose(1.00001f,1.000019f)); 8780 assert(isClose(1.00001f,1.000019)); 8781 assert(isClose(1.00001,1.000019f)); 8782 assert(!isClose(1.00001,1.000019)); 8783 8784 real a1 = 1e-300L; 8785 real a2 = a1.nextUp; 8786 assert(isClose(a1,a2)); 8787 } 8788 8789 @safe pure nothrow unittest 8790 { 8791 float[] arr1 = [ 1.0, 2.0, 3.0 ]; 8792 double[] arr2 = [ 1.00001, 1.99999, 3 ]; 8793 assert(isClose(arr1, arr2)); 8794 } 8795 8796 @safe pure nothrow @nogc unittest 8797 { 8798 assert(!isClose(1000.0,1010.0)); 8799 assert(!isClose(9_090_000_000.0,9_000_000_000.0)); 8800 assert(isClose(0.0,1e30,1.0)); 8801 assert(!isClose(0.00001,1e-30)); 8802 assert(!isClose(-1e-30,1e-30,1e-2,0.0)); 8803 } 8804 8805 @safe pure nothrow @nogc unittest 8806 { 8807 assert(!isClose(3, 0)); 8808 assert(isClose(3, 3)); 8809 assert(isClose(3.0, 3)); 8810 assert(isClose(3, 3.0)); 8811 8812 assert(isClose(0.0,0.0)); 8813 assert(isClose(-0.0,0.0)); 8814 assert(isClose(0.0f,0.0)); 8815 } 8816 8817 @safe pure nothrow @nogc unittest 8818 { 8819 real num = real.infinity; 8820 assert(num == real.infinity); 8821 assert(isClose(num, real.infinity)); 8822 num = -real.infinity; 8823 assert(num == -real.infinity); 8824 assert(isClose(num, -real.infinity)); 8825 8826 assert(!isClose(1,real.nan)); 8827 assert(!isClose(real.nan,real.max)); 8828 assert(!isClose(real.nan,real.nan)); 8829 } 8830 8831 @safe pure nothrow @nogc unittest 8832 { 8833 assert(isClose!(real[],real[],real)([],[])); 8834 assert(isClose(cast(real[])[],cast(real[])[])); 8835 } 8836 8837 @safe pure nothrow @nogc unittest 8838 { 8839 import std.conv : to; 8840 8841 float f = 31.79f; 8842 double d = 31.79; 8843 double f2d = f.to!double; 8844 8845 assert(isClose(f,f2d)); 8846 assert(!isClose(d,f2d)); 8847 } 8848 8849 @safe pure nothrow @nogc unittest 8850 { 8851 import std.conv : to; 8852 8853 double d = 31.79; 8854 float f = d.to!float; 8855 double f2d = f.to!double; 8856 8857 assert(isClose(f,f2d)); 8858 assert(!isClose(d,f2d)); 8859 assert(isClose(d,f2d,1e-4)); 8860 } 8861 8862 private template CommonDefaultFor(T,U) 8863 { 8864 import std.algorithm.comparison : min; 8865 8866 alias baseT = FloatingPointBaseType!T; 8867 alias baseU = FloatingPointBaseType!U; 8868 8869 enum CommonType!(baseT, baseU) CommonDefaultFor = 10.0L ^^ -((min(baseT.dig, baseU.dig) + 1) / 2 + 1); 8870 } 8871 8872 private template FloatingPointBaseType(T) 8873 { 8874 import std.range.primitives : ElementType; 8875 static if (isFloatingPoint!T) 8876 { 8877 alias FloatingPointBaseType = Unqual!T; 8878 } 8879 else static if (isFloatingPoint!(ElementType!(Unqual!T))) 8880 { 8881 alias FloatingPointBaseType = Unqual!(ElementType!(Unqual!T)); 8882 } 8883 else 8884 { 8885 alias FloatingPointBaseType = real; 8886 } 8887 } 8888 8889 8890 @safe pure nothrow @nogc unittest 8891 { 8892 float f = sqrt(2.0f); 8893 assert(fabs(f * f - 2.0f) < .00001); 8894 8895 double d = sqrt(2.0); 8896 assert(fabs(d * d - 2.0) < .00001); 8897 8898 real r = sqrt(2.0L); 8899 assert(fabs(r * r - 2.0) < .00001); 8900 } 8901 8902 @safe pure nothrow @nogc unittest 8903 { 8904 float f = fabs(-2.0f); 8905 assert(f == 2); 8906 8907 double d = fabs(-2.0); 8908 assert(d == 2); 8909 8910 real r = fabs(-2.0L); 8911 assert(r == 2); 8912 } 8913 8914 @safe pure nothrow @nogc unittest 8915 { 8916 float f = sin(-2.0f); 8917 assert(fabs(f - -0.909297f) < .00001); 8918 8919 double d = sin(-2.0); 8920 assert(fabs(d - -0.909297f) < .00001); 8921 8922 real r = sin(-2.0L); 8923 assert(fabs(r - -0.909297f) < .00001); 8924 } 8925 8926 @safe pure nothrow @nogc unittest 8927 { 8928 float f = cos(-2.0f); 8929 assert(fabs(f - -0.416147f) < .00001); 8930 8931 double d = cos(-2.0); 8932 assert(fabs(d - -0.416147f) < .00001); 8933 8934 real r = cos(-2.0L); 8935 assert(fabs(r - -0.416147f) < .00001); 8936 } 8937 8938 @safe pure nothrow @nogc unittest 8939 { 8940 float f = tan(-2.0f); 8941 assert(fabs(f - 2.18504f) < .00001); 8942 8943 double d = tan(-2.0); 8944 assert(fabs(d - 2.18504f) < .00001); 8945 8946 real r = tan(-2.0L); 8947 assert(fabs(r - 2.18504f) < .00001); 8948 8949 // Verify correct behavior for large inputs 8950 assert(!isNaN(tan(0x1p63))); 8951 assert(!isNaN(tan(-0x1p63))); 8952 static if (real.mant_dig >= 64) 8953 { 8954 assert(!isNaN(tan(0x1p300L))); 8955 assert(!isNaN(tan(-0x1p300L))); 8956 } 8957 } 8958 8959 // https://issues.dlang.org/show_bug.cgi?id=6381 8960 // floor/ceil should be usable in pure function. 8961 @safe pure nothrow unittest 8962 { 8963 auto x = floor(1.2); 8964 auto y = ceil(1.2); 8965 } 8966 8967 /*********************************** 8968 * Defines a total order on all floating-point numbers. 8969 * 8970 * The order is defined as follows: 8971 * $(UL 8972 * $(LI All numbers in [-$(INFIN), +$(INFIN)] are ordered 8973 * the same way as by built-in comparison, with the exception of 8974 * -0.0, which is less than +0.0;) 8975 * $(LI If the sign bit is set (that is, it's 'negative'), $(NAN) is less 8976 * than any number; if the sign bit is not set (it is 'positive'), 8977 * $(NAN) is greater than any number;) 8978 * $(LI $(NAN)s of the same sign are ordered by the payload ('negative' 8979 * ones - in reverse order).) 8980 * ) 8981 * 8982 * Returns: 8983 * negative value if `x` precedes `y` in the order specified above; 8984 * 0 if `x` and `y` are identical, and positive value otherwise. 8985 * 8986 * See_Also: 8987 * $(MYREF isIdentical) 8988 * Standards: Conforms to IEEE 754-2008 8989 */ 8990 int cmp(T)(const(T) x, const(T) y) @nogc @trusted pure nothrow 8991 if (isFloatingPoint!T) 8992 { 8993 alias F = floatTraits!T; 8994 8995 static if (F.realFormat == RealFormat.ieeeSingle 8996 || F.realFormat == RealFormat.ieeeDouble) 8997 { 8998 static if (T.sizeof == 4) 8999 alias UInt = uint; 9000 else 9001 alias UInt = ulong; 9002 9003 union Repainter 9004 { 9005 T number; 9006 UInt bits; 9007 } 9008 9009 enum msb = ~(UInt.max >>> 1); 9010 9011 import std.typecons : Tuple; 9012 Tuple!(Repainter, Repainter) vars = void; 9013 vars[0].number = x; 9014 vars[1].number = y; 9015 9016 foreach (ref var; vars) 9017 if (var.bits & msb) 9018 var.bits = ~var.bits; 9019 else 9020 var.bits |= msb; 9021 9022 if (vars[0].bits < vars[1].bits) 9023 return -1; 9024 else if (vars[0].bits > vars[1].bits) 9025 return 1; 9026 else 9027 return 0; 9028 } 9029 else static if (F.realFormat == RealFormat.ieeeExtended53 9030 || F.realFormat == RealFormat.ieeeExtended 9031 || F.realFormat == RealFormat.ieeeQuadruple) 9032 { 9033 static if (F.realFormat == RealFormat.ieeeQuadruple) 9034 alias RemT = ulong; 9035 else 9036 alias RemT = ushort; 9037 9038 struct Bits 9039 { 9040 ulong bulk; 9041 RemT rem; 9042 } 9043 9044 union Repainter 9045 { 9046 T number; 9047 Bits bits; 9048 ubyte[T.sizeof] bytes; 9049 } 9050 9051 import std.typecons : Tuple; 9052 Tuple!(Repainter, Repainter) vars = void; 9053 vars[0].number = x; 9054 vars[1].number = y; 9055 9056 foreach (ref var; vars) 9057 if (var.bytes[F.SIGNPOS_BYTE] & 0x80) 9058 { 9059 var.bits.bulk = ~var.bits.bulk; 9060 var.bits.rem = cast(typeof(var.bits.rem))(-1 - var.bits.rem); // ~var.bits.rem 9061 } 9062 else 9063 { 9064 var.bytes[F.SIGNPOS_BYTE] |= 0x80; 9065 } 9066 9067 version (LittleEndian) 9068 { 9069 if (vars[0].bits.rem < vars[1].bits.rem) 9070 return -1; 9071 else if (vars[0].bits.rem > vars[1].bits.rem) 9072 return 1; 9073 else if (vars[0].bits.bulk < vars[1].bits.bulk) 9074 return -1; 9075 else if (vars[0].bits.bulk > vars[1].bits.bulk) 9076 return 1; 9077 else 9078 return 0; 9079 } 9080 else 9081 { 9082 if (vars[0].bits.bulk < vars[1].bits.bulk) 9083 return -1; 9084 else if (vars[0].bits.bulk > vars[1].bits.bulk) 9085 return 1; 9086 else if (vars[0].bits.rem < vars[1].bits.rem) 9087 return -1; 9088 else if (vars[0].bits.rem > vars[1].bits.rem) 9089 return 1; 9090 else 9091 return 0; 9092 } 9093 } 9094 else 9095 { 9096 // IBM Extended doubledouble does not follow the general 9097 // sign-exponent-significand layout, so has to be handled generically 9098 9099 const int xSign = signbit(x), 9100 ySign = signbit(y); 9101 9102 if (xSign == 1 && ySign == 1) 9103 return cmp(-y, -x); 9104 else if (xSign == 1) 9105 return -1; 9106 else if (ySign == 1) 9107 return 1; 9108 else if (x < y) 9109 return -1; 9110 else if (x == y) 9111 return 0; 9112 else if (x > y) 9113 return 1; 9114 else if (isNaN(x) && !isNaN(y)) 9115 return 1; 9116 else if (isNaN(y) && !isNaN(x)) 9117 return -1; 9118 else if (getNaNPayload(x) < getNaNPayload(y)) 9119 return -1; 9120 else if (getNaNPayload(x) > getNaNPayload(y)) 9121 return 1; 9122 else 9123 return 0; 9124 } 9125 } 9126 9127 /// Most numbers are ordered naturally. 9128 @safe unittest 9129 { 9130 assert(cmp(-double.infinity, -double.max) < 0); 9131 assert(cmp(-double.max, -100.0) < 0); 9132 assert(cmp(-100.0, -0.5) < 0); 9133 assert(cmp(-0.5, 0.0) < 0); 9134 assert(cmp(0.0, 0.5) < 0); 9135 assert(cmp(0.5, 100.0) < 0); 9136 assert(cmp(100.0, double.max) < 0); 9137 assert(cmp(double.max, double.infinity) < 0); 9138 9139 assert(cmp(1.0, 1.0) == 0); 9140 } 9141 9142 /// Positive and negative zeroes are distinct. 9143 @safe unittest 9144 { 9145 assert(cmp(-0.0, +0.0) < 0); 9146 assert(cmp(+0.0, -0.0) > 0); 9147 } 9148 9149 /// Depending on the sign, $(NAN)s go to either end of the spectrum. 9150 @safe unittest 9151 { 9152 assert(cmp(-double.nan, -double.infinity) < 0); 9153 assert(cmp(double.infinity, double.nan) < 0); 9154 assert(cmp(-double.nan, double.nan) < 0); 9155 } 9156 9157 /// $(NAN)s of the same sign are ordered by the payload. 9158 @safe unittest 9159 { 9160 assert(cmp(NaN(10), NaN(20)) < 0); 9161 assert(cmp(-NaN(20), -NaN(10)) < 0); 9162 } 9163 9164 @safe unittest 9165 { 9166 import std.meta : AliasSeq; 9167 static foreach (T; AliasSeq!(float, double, real)) 9168 {{ 9169 T[] values = [-cast(T) NaN(20), -cast(T) NaN(10), -T.nan, -T.infinity, 9170 -T.max, -T.max / 2, T(-16.0), T(-1.0).nextDown, 9171 T(-1.0), T(-1.0).nextUp, 9172 T(-0.5), -T.min_normal, (-T.min_normal).nextUp, 9173 -2 * T.min_normal * T.epsilon, 9174 -T.min_normal * T.epsilon, 9175 T(-0.0), T(0.0), 9176 T.min_normal * T.epsilon, 9177 2 * T.min_normal * T.epsilon, 9178 T.min_normal.nextDown, T.min_normal, T(0.5), 9179 T(1.0).nextDown, T(1.0), 9180 T(1.0).nextUp, T(16.0), T.max / 2, T.max, 9181 T.infinity, T.nan, cast(T) NaN(10), cast(T) NaN(20)]; 9182 9183 foreach (i, x; values) 9184 { 9185 foreach (y; values[i + 1 .. $]) 9186 { 9187 assert(cmp(x, y) < 0); 9188 assert(cmp(y, x) > 0); 9189 } 9190 assert(cmp(x, x) == 0); 9191 } 9192 }} 9193 } 9194 9195 private enum PowType 9196 { 9197 floor, 9198 ceil 9199 } 9200 9201 pragma(inline, true) 9202 private T powIntegralImpl(PowType type, T)(T val) 9203 { 9204 import core.bitop : bsr; 9205 9206 if (val == 0 || (type == PowType.ceil && (val > T.max / 2 || val == T.min))) 9207 return 0; 9208 else 9209 { 9210 static if (isSigned!T) 9211 return cast(Unqual!T) (val < 0 ? -(T(1) << bsr(0 - val) + type) : T(1) << bsr(val) + type); 9212 else 9213 return cast(Unqual!T) (T(1) << bsr(val) + type); 9214 } 9215 } 9216 9217 private T powFloatingPointImpl(PowType type, T)(T x) 9218 { 9219 if (!x.isFinite) 9220 return x; 9221 9222 if (!x) 9223 return x; 9224 9225 int exp; 9226 auto y = frexp(x, exp); 9227 9228 static if (type == PowType.ceil) 9229 y = ldexp(cast(T) 0.5, exp + 1); 9230 else 9231 y = ldexp(cast(T) 0.5, exp); 9232 9233 if (!y.isFinite) 9234 return cast(T) 0.0; 9235 9236 y = copysign(y, x); 9237 9238 return y; 9239 } 9240 9241 /** 9242 * Gives the next power of two after `val`. `T` can be any built-in 9243 * numerical type. 9244 * 9245 * If the operation would lead to an over/underflow, this function will 9246 * return `0`. 9247 * 9248 * Params: 9249 * val = any number 9250 * 9251 * Returns: 9252 * the next power of two after `val` 9253 */ 9254 T nextPow2(T)(const T val) 9255 if (isIntegral!T) 9256 { 9257 return powIntegralImpl!(PowType.ceil)(val); 9258 } 9259 9260 /// ditto 9261 T nextPow2(T)(const T val) 9262 if (isFloatingPoint!T) 9263 { 9264 return powFloatingPointImpl!(PowType.ceil)(val); 9265 } 9266 9267 /// 9268 @safe @nogc pure nothrow unittest 9269 { 9270 assert(nextPow2(2) == 4); 9271 assert(nextPow2(10) == 16); 9272 assert(nextPow2(4000) == 4096); 9273 9274 assert(nextPow2(-2) == -4); 9275 assert(nextPow2(-10) == -16); 9276 9277 assert(nextPow2(uint.max) == 0); 9278 assert(nextPow2(uint.min) == 0); 9279 assert(nextPow2(size_t.max) == 0); 9280 assert(nextPow2(size_t.min) == 0); 9281 9282 assert(nextPow2(int.max) == 0); 9283 assert(nextPow2(int.min) == 0); 9284 assert(nextPow2(long.max) == 0); 9285 assert(nextPow2(long.min) == 0); 9286 } 9287 9288 /// 9289 @safe @nogc pure nothrow unittest 9290 { 9291 assert(nextPow2(2.1) == 4.0); 9292 assert(nextPow2(-2.0) == -4.0); 9293 assert(nextPow2(0.25) == 0.5); 9294 assert(nextPow2(-4.0) == -8.0); 9295 9296 assert(nextPow2(double.max) == 0.0); 9297 assert(nextPow2(double.infinity) == double.infinity); 9298 } 9299 9300 @safe @nogc pure nothrow unittest 9301 { 9302 assert(nextPow2(ubyte(2)) == 4); 9303 assert(nextPow2(ubyte(10)) == 16); 9304 9305 assert(nextPow2(byte(2)) == 4); 9306 assert(nextPow2(byte(10)) == 16); 9307 9308 assert(nextPow2(short(2)) == 4); 9309 assert(nextPow2(short(10)) == 16); 9310 assert(nextPow2(short(4000)) == 4096); 9311 9312 assert(nextPow2(ushort(2)) == 4); 9313 assert(nextPow2(ushort(10)) == 16); 9314 assert(nextPow2(ushort(4000)) == 4096); 9315 } 9316 9317 @safe @nogc pure nothrow unittest 9318 { 9319 foreach (ulong i; 1 .. 62) 9320 { 9321 assert(nextPow2(1UL << i) == 2UL << i); 9322 assert(nextPow2((1UL << i) - 1) == 1UL << i); 9323 assert(nextPow2((1UL << i) + 1) == 2UL << i); 9324 assert(nextPow2((1UL << i) + (1UL<<(i-1))) == 2UL << i); 9325 } 9326 } 9327 9328 @safe @nogc pure nothrow unittest 9329 { 9330 import std.meta : AliasSeq; 9331 9332 static foreach (T; AliasSeq!(float, double, real)) 9333 {{ 9334 enum T subNormal = T.min_normal / 2; 9335 9336 static if (subNormal) assert(nextPow2(subNormal) == T.min_normal); 9337 9338 assert(nextPow2(T(0.0)) == 0.0); 9339 9340 assert(nextPow2(T(2.0)) == 4.0); 9341 assert(nextPow2(T(2.1)) == 4.0); 9342 assert(nextPow2(T(3.1)) == 4.0); 9343 assert(nextPow2(T(4.0)) == 8.0); 9344 assert(nextPow2(T(0.25)) == 0.5); 9345 9346 assert(nextPow2(T(-2.0)) == -4.0); 9347 assert(nextPow2(T(-2.1)) == -4.0); 9348 assert(nextPow2(T(-3.1)) == -4.0); 9349 assert(nextPow2(T(-4.0)) == -8.0); 9350 assert(nextPow2(T(-0.25)) == -0.5); 9351 9352 assert(nextPow2(T.max) == 0); 9353 assert(nextPow2(-T.max) == 0); 9354 9355 assert(nextPow2(T.infinity) == T.infinity); 9356 assert(nextPow2(T.init).isNaN); 9357 }} 9358 } 9359 9360 // https://issues.dlang.org/show_bug.cgi?id=15973 9361 @safe @nogc pure nothrow unittest 9362 { 9363 assert(nextPow2(uint.max / 2) == uint.max / 2 + 1); 9364 assert(nextPow2(uint.max / 2 + 2) == 0); 9365 assert(nextPow2(int.max / 2) == int.max / 2 + 1); 9366 assert(nextPow2(int.max / 2 + 2) == 0); 9367 assert(nextPow2(int.min + 1) == int.min); 9368 } 9369 9370 /** 9371 * Gives the last power of two before `val`. $(T) can be any built-in 9372 * numerical type. 9373 * 9374 * Params: 9375 * val = any number 9376 * 9377 * Returns: 9378 * the last power of two before `val` 9379 */ 9380 T truncPow2(T)(const T val) 9381 if (isIntegral!T) 9382 { 9383 return powIntegralImpl!(PowType.floor)(val); 9384 } 9385 9386 /// ditto 9387 T truncPow2(T)(const T val) 9388 if (isFloatingPoint!T) 9389 { 9390 return powFloatingPointImpl!(PowType.floor)(val); 9391 } 9392 9393 /// 9394 @safe @nogc pure nothrow unittest 9395 { 9396 assert(truncPow2(3) == 2); 9397 assert(truncPow2(4) == 4); 9398 assert(truncPow2(10) == 8); 9399 assert(truncPow2(4000) == 2048); 9400 9401 assert(truncPow2(-5) == -4); 9402 assert(truncPow2(-20) == -16); 9403 9404 assert(truncPow2(uint.max) == int.max + 1); 9405 assert(truncPow2(uint.min) == 0); 9406 assert(truncPow2(ulong.max) == long.max + 1); 9407 assert(truncPow2(ulong.min) == 0); 9408 9409 assert(truncPow2(int.max) == (int.max / 2) + 1); 9410 assert(truncPow2(int.min) == int.min); 9411 assert(truncPow2(long.max) == (long.max / 2) + 1); 9412 assert(truncPow2(long.min) == long.min); 9413 } 9414 9415 /// 9416 @safe @nogc pure nothrow unittest 9417 { 9418 assert(truncPow2(2.1) == 2.0); 9419 assert(truncPow2(7.0) == 4.0); 9420 assert(truncPow2(-1.9) == -1.0); 9421 assert(truncPow2(0.24) == 0.125); 9422 assert(truncPow2(-7.0) == -4.0); 9423 9424 assert(truncPow2(double.infinity) == double.infinity); 9425 } 9426 9427 @safe @nogc pure nothrow unittest 9428 { 9429 assert(truncPow2(ubyte(3)) == 2); 9430 assert(truncPow2(ubyte(4)) == 4); 9431 assert(truncPow2(ubyte(10)) == 8); 9432 9433 assert(truncPow2(byte(3)) == 2); 9434 assert(truncPow2(byte(4)) == 4); 9435 assert(truncPow2(byte(10)) == 8); 9436 9437 assert(truncPow2(ushort(3)) == 2); 9438 assert(truncPow2(ushort(4)) == 4); 9439 assert(truncPow2(ushort(10)) == 8); 9440 assert(truncPow2(ushort(4000)) == 2048); 9441 9442 assert(truncPow2(short(3)) == 2); 9443 assert(truncPow2(short(4)) == 4); 9444 assert(truncPow2(short(10)) == 8); 9445 assert(truncPow2(short(4000)) == 2048); 9446 } 9447 9448 @safe @nogc pure nothrow unittest 9449 { 9450 foreach (ulong i; 1 .. 62) 9451 { 9452 assert(truncPow2(2UL << i) == 2UL << i); 9453 assert(truncPow2((2UL << i) + 1) == 2UL << i); 9454 assert(truncPow2((2UL << i) - 1) == 1UL << i); 9455 assert(truncPow2((2UL << i) - (2UL<<(i-1))) == 1UL << i); 9456 } 9457 } 9458 9459 @safe @nogc pure nothrow unittest 9460 { 9461 import std.meta : AliasSeq; 9462 9463 static foreach (T; AliasSeq!(float, double, real)) 9464 { 9465 assert(truncPow2(T(0.0)) == 0.0); 9466 9467 assert(truncPow2(T(4.0)) == 4.0); 9468 assert(truncPow2(T(2.1)) == 2.0); 9469 assert(truncPow2(T(3.5)) == 2.0); 9470 assert(truncPow2(T(7.0)) == 4.0); 9471 assert(truncPow2(T(0.24)) == 0.125); 9472 9473 assert(truncPow2(T(-2.0)) == -2.0); 9474 assert(truncPow2(T(-2.1)) == -2.0); 9475 assert(truncPow2(T(-3.1)) == -2.0); 9476 assert(truncPow2(T(-7.0)) == -4.0); 9477 assert(truncPow2(T(-0.24)) == -0.125); 9478 9479 assert(truncPow2(T.infinity) == T.infinity); 9480 assert(truncPow2(T.init).isNaN); 9481 } 9482 } 9483 9484 /** 9485 Check whether a number is an integer power of two. 9486 9487 Note that only positive numbers can be integer powers of two. This 9488 function always return `false` if `x` is negative or zero. 9489 9490 Params: 9491 x = the number to test 9492 9493 Returns: 9494 `true` if `x` is an integer power of two. 9495 */ 9496 bool isPowerOf2(X)(const X x) pure @safe nothrow @nogc 9497 if (isNumeric!X) 9498 { 9499 static if (isFloatingPoint!X) 9500 { 9501 int exp; 9502 const X sig = frexp(x, exp); 9503 9504 return (exp != int.min) && (sig is cast(X) 0.5L); 9505 } 9506 else 9507 { 9508 static if (isSigned!X) 9509 { 9510 auto y = cast(typeof(x + 0))x; 9511 return y > 0 && !(y & (y - 1)); 9512 } 9513 else 9514 { 9515 auto y = cast(typeof(x + 0u))x; 9516 return (y & -y) > (y - 1); 9517 } 9518 } 9519 } 9520 /// 9521 @safe unittest 9522 { 9523 assert( isPowerOf2(1.0L)); 9524 assert( isPowerOf2(2.0L)); 9525 assert( isPowerOf2(0.5L)); 9526 assert( isPowerOf2(pow(2.0L, 96))); 9527 assert( isPowerOf2(pow(2.0L, -77))); 9528 9529 assert(!isPowerOf2(-2.0L)); 9530 assert(!isPowerOf2(-0.5L)); 9531 assert(!isPowerOf2(0.0L)); 9532 assert(!isPowerOf2(4.315)); 9533 assert(!isPowerOf2(1.0L / 3.0L)); 9534 9535 assert(!isPowerOf2(real.nan)); 9536 assert(!isPowerOf2(real.infinity)); 9537 } 9538 /// 9539 @safe unittest 9540 { 9541 assert( isPowerOf2(1)); 9542 assert( isPowerOf2(2)); 9543 assert( isPowerOf2(1uL << 63)); 9544 9545 assert(!isPowerOf2(-4)); 9546 assert(!isPowerOf2(0)); 9547 assert(!isPowerOf2(1337u)); 9548 } 9549 9550 @safe unittest 9551 { 9552 import std.meta : AliasSeq; 9553 9554 enum smallP2 = pow(2.0L, -62); 9555 enum bigP2 = pow(2.0L, 50); 9556 enum smallP7 = pow(7.0L, -35); 9557 enum bigP7 = pow(7.0L, 30); 9558 9559 static foreach (X; AliasSeq!(float, double, real)) 9560 {{ 9561 immutable min_sub = X.min_normal * X.epsilon; 9562 9563 foreach (x; [smallP2, min_sub, X.min_normal, .25L, 0.5L, 1.0L, 9564 2.0L, 8.0L, pow(2.0L, X.max_exp - 1), bigP2]) 9565 { 9566 assert( isPowerOf2(cast(X) x)); 9567 assert(!isPowerOf2(cast(X)-x)); 9568 } 9569 9570 foreach (x; [0.0L, 3 * min_sub, smallP7, 0.1L, 1337.0L, bigP7, X.max, real.nan, real.infinity]) 9571 { 9572 assert(!isPowerOf2(cast(X) x)); 9573 assert(!isPowerOf2(cast(X)-x)); 9574 } 9575 }} 9576 9577 static foreach (X; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 9578 {{ 9579 foreach (x; [1, 2, 4, 8, (X.max >>> 1) + 1]) 9580 { 9581 assert( isPowerOf2(cast(X) x)); 9582 static if (isSigned!X) 9583 assert(!isPowerOf2(cast(X)-x)); 9584 } 9585 9586 foreach (x; [0, 3, 5, 13, 77, X.min, X.max]) 9587 assert(!isPowerOf2(cast(X) x)); 9588 }} 9589 9590 // CTFE 9591 static foreach (X; AliasSeq!(float, double, real)) 9592 {{ 9593 enum min_sub = X.min_normal * X.epsilon; 9594 9595 static foreach (x; [smallP2, min_sub, X.min_normal, .25L, 0.5L, 1.0L, 9596 2.0L, 8.0L, pow(2.0L, X.max_exp - 1), bigP2]) 9597 { 9598 static assert( isPowerOf2(cast(X) x)); 9599 static assert(!isPowerOf2(cast(X)-x)); 9600 } 9601 9602 static foreach (x; [0.0L, 3 * min_sub, smallP7, 0.1L, 1337.0L, bigP7, X.max, real.nan, real.infinity]) 9603 { 9604 static assert(!isPowerOf2(cast(X) x)); 9605 static assert(!isPowerOf2(cast(X)-x)); 9606 } 9607 }} 9608 9609 static foreach (X; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 9610 {{ 9611 static foreach (x; [1, 2, 4, 8, (X.max >>> 1) + 1]) 9612 { 9613 static assert( isPowerOf2(cast(X) x)); 9614 static if (isSigned!X) 9615 static assert(!isPowerOf2(cast(X)-x)); 9616 } 9617 9618 static foreach (x; [0, 3, 5, 13, 77, X.min, X.max]) 9619 static assert(!isPowerOf2(cast(X) x)); 9620 }} 9621 } 9622 9623 package: // Not public yet 9624 /* Return the value that lies halfway between x and y on the IEEE number line. 9625 * 9626 * Formally, the result is the arithmetic mean of the binary significands of x 9627 * and y, multiplied by the geometric mean of the binary exponents of x and y. 9628 * x and y must have the same sign, and must not be NaN. 9629 * Note: this function is useful for ensuring O(log n) behaviour in algorithms 9630 * involving a 'binary chop'. 9631 * 9632 * Special cases: 9633 * If x and y are within a factor of 2, (ie, feqrel(x, y) > 0), the return value 9634 * is the arithmetic mean (x + y) / 2. 9635 * If x and y are even powers of 2, the return value is the geometric mean, 9636 * ieeeMean(x, y) = sqrt(x * y). 9637 * 9638 */ 9639 T ieeeMean(T)(const T x, const T y) @trusted pure nothrow @nogc 9640 in 9641 { 9642 // both x and y must have the same sign, and must not be NaN. 9643 assert(signbit(x) == signbit(y)); 9644 assert(x == x && y == y); 9645 } 9646 do 9647 { 9648 // Runtime behaviour for contract violation: 9649 // If signs are opposite, or one is a NaN, return 0. 9650 if (!((x >= 0 && y >= 0) || (x <= 0 && y <= 0))) return 0.0; 9651 9652 // The implementation is simple: cast x and y to integers, 9653 // average them (avoiding overflow), and cast the result back to a floating-point number. 9654 9655 alias F = floatTraits!(T); 9656 T u; 9657 static if (F.realFormat == RealFormat.ieeeExtended) 9658 { 9659 // There's slight additional complexity because they are actually 9660 // 79-bit reals... 9661 ushort *ue = cast(ushort *)&u; 9662 ulong *ul = cast(ulong *)&u; 9663 ushort *xe = cast(ushort *)&x; 9664 ulong *xl = cast(ulong *)&x; 9665 ushort *ye = cast(ushort *)&y; 9666 ulong *yl = cast(ulong *)&y; 9667 9668 // Ignore the useless implicit bit. (Bonus: this prevents overflows) 9669 ulong m = ((*xl) & 0x7FFF_FFFF_FFFF_FFFFL) + ((*yl) & 0x7FFF_FFFF_FFFF_FFFFL); 9670 9671 // @@@ BUG? @@@ 9672 // Cast shouldn't be here 9673 ushort e = cast(ushort) ((xe[F.EXPPOS_SHORT] & F.EXPMASK) 9674 + (ye[F.EXPPOS_SHORT] & F.EXPMASK)); 9675 if (m & 0x8000_0000_0000_0000L) 9676 { 9677 ++e; 9678 m &= 0x7FFF_FFFF_FFFF_FFFFL; 9679 } 9680 // Now do a multi-byte right shift 9681 const uint c = e & 1; // carry 9682 e >>= 1; 9683 m >>>= 1; 9684 if (c) 9685 m |= 0x4000_0000_0000_0000L; // shift carry into significand 9686 if (e) 9687 *ul = m | 0x8000_0000_0000_0000L; // set implicit bit... 9688 else 9689 *ul = m; // ... unless exponent is 0 (subnormal or zero). 9690 9691 ue[4]= e | (xe[F.EXPPOS_SHORT]& 0x8000); // restore sign bit 9692 } 9693 else static if (F.realFormat == RealFormat.ieeeQuadruple) 9694 { 9695 // This would be trivial if 'ucent' were implemented... 9696 ulong *ul = cast(ulong *)&u; 9697 ulong *xl = cast(ulong *)&x; 9698 ulong *yl = cast(ulong *)&y; 9699 9700 // Multi-byte add, then multi-byte right shift. 9701 import core.checkedint : addu; 9702 bool carry; 9703 ulong ml = addu(xl[MANTISSA_LSB], yl[MANTISSA_LSB], carry); 9704 9705 ulong mh = carry + (xl[MANTISSA_MSB] & 0x7FFF_FFFF_FFFF_FFFFL) + 9706 (yl[MANTISSA_MSB] & 0x7FFF_FFFF_FFFF_FFFFL); 9707 9708 ul[MANTISSA_MSB] = (mh >>> 1) | (xl[MANTISSA_MSB] & 0x8000_0000_0000_0000); 9709 ul[MANTISSA_LSB] = (ml >>> 1) | (mh & 1) << 63; 9710 } 9711 else static if (F.realFormat == RealFormat.ieeeDouble) 9712 { 9713 ulong *ul = cast(ulong *)&u; 9714 ulong *xl = cast(ulong *)&x; 9715 ulong *yl = cast(ulong *)&y; 9716 ulong m = (((*xl) & 0x7FFF_FFFF_FFFF_FFFFL) 9717 + ((*yl) & 0x7FFF_FFFF_FFFF_FFFFL)) >>> 1; 9718 m |= ((*xl) & 0x8000_0000_0000_0000L); 9719 *ul = m; 9720 } 9721 else static if (F.realFormat == RealFormat.ieeeSingle) 9722 { 9723 uint *ul = cast(uint *)&u; 9724 uint *xl = cast(uint *)&x; 9725 uint *yl = cast(uint *)&y; 9726 uint m = (((*xl) & 0x7FFF_FFFF) + ((*yl) & 0x7FFF_FFFF)) >>> 1; 9727 m |= ((*xl) & 0x8000_0000); 9728 *ul = m; 9729 } 9730 else 9731 { 9732 assert(0, "Not implemented"); 9733 } 9734 return u; 9735 } 9736 9737 @safe pure nothrow @nogc unittest 9738 { 9739 assert(ieeeMean(-0.0,-1e-20)<0); 9740 assert(ieeeMean(0.0,1e-20)>0); 9741 9742 assert(ieeeMean(1.0L,4.0L)==2L); 9743 assert(ieeeMean(2.0*1.013,8.0*1.013)==4*1.013); 9744 assert(ieeeMean(-1.0L,-4.0L)==-2L); 9745 assert(ieeeMean(-1.0,-4.0)==-2); 9746 assert(ieeeMean(-1.0f,-4.0f)==-2f); 9747 assert(ieeeMean(-1.0,-2.0)==-1.5); 9748 assert(ieeeMean(-1*(1+8*real.epsilon),-2*(1+8*real.epsilon)) 9749 ==-1.5*(1+5*real.epsilon)); 9750 assert(ieeeMean(0x1p60,0x1p-10)==0x1p25); 9751 9752 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended) 9753 { 9754 assert(ieeeMean(1.0L,real.infinity)==0x1p8192L); 9755 assert(ieeeMean(0.0L,real.infinity)==1.5); 9756 } 9757 assert(ieeeMean(0.5*real.min_normal*(1-4*real.epsilon),0.5*real.min_normal) 9758 == 0.5*real.min_normal*(1-2*real.epsilon)); 9759 } 9760 9761 9762 // The following IEEE 'real' formats are currently supported. 9763 version (LittleEndian) 9764 { 9765 static assert(real.mant_dig == 53 || real.mant_dig == 64 9766 || real.mant_dig == 113, 9767 "Only 64-bit, 80-bit, and 128-bit reals"~ 9768 " are supported for LittleEndian CPUs"); 9769 } 9770 else 9771 { 9772 static assert(real.mant_dig == 53 || real.mant_dig == 113, 9773 "Only 64-bit and 128-bit reals are supported for BigEndian CPUs."); 9774 } 9775 9776 // Underlying format exposed through floatTraits 9777 enum RealFormat 9778 { 9779 ieeeHalf, 9780 ieeeSingle, 9781 ieeeDouble, 9782 ieeeExtended, // x87 80-bit real 9783 ieeeExtended53, // x87 real rounded to precision of double. 9784 ibmExtended, // IBM 128-bit extended 9785 ieeeQuadruple, 9786 } 9787 9788 // Constants used for extracting the components of the representation. 9789 // They supplement the built-in floating point properties. 9790 template floatTraits(T) 9791 { 9792 // EXPMASK is a ushort mask to select the exponent portion (without sign) 9793 // EXPSHIFT is the number of bits the exponent is left-shifted by in its ushort 9794 // EXPBIAS is the exponent bias - 1 (exp == EXPBIAS yields ×2^-1). 9795 // EXPPOS_SHORT is the index of the exponent when represented as a ushort array. 9796 // SIGNPOS_BYTE is the index of the sign when represented as a ubyte array. 9797 // RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal 9798 enum Unqual!T RECIP_EPSILON = (1/T.epsilon); 9799 static if (T.mant_dig == 24) 9800 { 9801 // Single precision float 9802 enum ushort EXPMASK = 0x7F80; 9803 enum ushort EXPSHIFT = 7; 9804 enum ushort EXPBIAS = 0x3F00; 9805 enum uint EXPMASK_INT = 0x7F80_0000; 9806 enum uint MANTISSAMASK_INT = 0x007F_FFFF; 9807 enum realFormat = RealFormat.ieeeSingle; 9808 version (LittleEndian) 9809 { 9810 enum EXPPOS_SHORT = 1; 9811 enum SIGNPOS_BYTE = 3; 9812 } 9813 else 9814 { 9815 enum EXPPOS_SHORT = 0; 9816 enum SIGNPOS_BYTE = 0; 9817 } 9818 } 9819 else static if (T.mant_dig == 53) 9820 { 9821 static if (T.sizeof == 8) 9822 { 9823 // Double precision float, or real == double 9824 enum ushort EXPMASK = 0x7FF0; 9825 enum ushort EXPSHIFT = 4; 9826 enum ushort EXPBIAS = 0x3FE0; 9827 enum uint EXPMASK_INT = 0x7FF0_0000; 9828 enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only 9829 enum realFormat = RealFormat.ieeeDouble; 9830 version (LittleEndian) 9831 { 9832 enum EXPPOS_SHORT = 3; 9833 enum SIGNPOS_BYTE = 7; 9834 } 9835 else 9836 { 9837 enum EXPPOS_SHORT = 0; 9838 enum SIGNPOS_BYTE = 0; 9839 } 9840 } 9841 else static if (T.sizeof == 12) 9842 { 9843 // Intel extended real80 rounded to double 9844 enum ushort EXPMASK = 0x7FFF; 9845 enum ushort EXPSHIFT = 0; 9846 enum ushort EXPBIAS = 0x3FFE; 9847 enum realFormat = RealFormat.ieeeExtended53; 9848 version (LittleEndian) 9849 { 9850 enum EXPPOS_SHORT = 4; 9851 enum SIGNPOS_BYTE = 9; 9852 } 9853 else 9854 { 9855 enum EXPPOS_SHORT = 0; 9856 enum SIGNPOS_BYTE = 0; 9857 } 9858 } 9859 else 9860 static assert(false, "No traits support for " ~ T.stringof); 9861 } 9862 else static if (T.mant_dig == 64) 9863 { 9864 // Intel extended real80 9865 enum ushort EXPMASK = 0x7FFF; 9866 enum ushort EXPSHIFT = 0; 9867 enum ushort EXPBIAS = 0x3FFE; 9868 enum realFormat = RealFormat.ieeeExtended; 9869 version (LittleEndian) 9870 { 9871 enum EXPPOS_SHORT = 4; 9872 enum SIGNPOS_BYTE = 9; 9873 } 9874 else 9875 { 9876 enum EXPPOS_SHORT = 0; 9877 enum SIGNPOS_BYTE = 0; 9878 } 9879 } 9880 else static if (T.mant_dig == 113) 9881 { 9882 // Quadruple precision float 9883 enum ushort EXPMASK = 0x7FFF; 9884 enum ushort EXPSHIFT = 0; 9885 enum ushort EXPBIAS = 0x3FFE; 9886 enum realFormat = RealFormat.ieeeQuadruple; 9887 version (LittleEndian) 9888 { 9889 enum EXPPOS_SHORT = 7; 9890 enum SIGNPOS_BYTE = 15; 9891 } 9892 else 9893 { 9894 enum EXPPOS_SHORT = 0; 9895 enum SIGNPOS_BYTE = 0; 9896 } 9897 } 9898 else static if (T.mant_dig == 106) 9899 { 9900 // IBM Extended doubledouble 9901 enum ushort EXPMASK = 0x7FF0; 9902 enum ushort EXPSHIFT = 4; 9903 enum realFormat = RealFormat.ibmExtended; 9904 9905 // For IBM doubledouble the larger magnitude double comes first. 9906 // It's really a double[2] and arrays don't index differently 9907 // between little and big-endian targets. 9908 enum DOUBLEPAIR_MSB = 0; 9909 enum DOUBLEPAIR_LSB = 1; 9910 9911 // The exponent/sign byte is for most significant part. 9912 version (LittleEndian) 9913 { 9914 enum EXPPOS_SHORT = 3; 9915 enum SIGNPOS_BYTE = 7; 9916 } 9917 else 9918 { 9919 enum EXPPOS_SHORT = 0; 9920 enum SIGNPOS_BYTE = 0; 9921 } 9922 } 9923 else 9924 static assert(false, "No traits support for " ~ T.stringof); 9925 } 9926 9927 // These apply to all floating-point types 9928 version (LittleEndian) 9929 { 9930 enum MANTISSA_LSB = 0; 9931 enum MANTISSA_MSB = 1; 9932 } 9933 else 9934 { 9935 enum MANTISSA_LSB = 1; 9936 enum MANTISSA_MSB = 0; 9937 } 9938 9939 // Common code for math implementations. 9940 9941 // Helper for floor/ceil 9942 T floorImpl(T)(const T x) @trusted pure nothrow @nogc 9943 { 9944 alias F = floatTraits!(T); 9945 // Take care not to trigger library calls from the compiler, 9946 // while ensuring that we don't get defeated by some optimizers. 9947 union floatBits 9948 { 9949 T rv; 9950 ushort[T.sizeof/2] vu; 9951 9952 // Other kinds of extractors for real formats. 9953 static if (F.realFormat == RealFormat.ieeeSingle) 9954 int vi; 9955 } 9956 floatBits y = void; 9957 y.rv = x; 9958 9959 // Find the exponent (power of 2) 9960 // Do this by shifting the raw value so that the exponent lies in the low bits, 9961 // then mask out the sign bit, and subtract the bias. 9962 static if (F.realFormat == RealFormat.ieeeSingle) 9963 { 9964 int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f; 9965 } 9966 else static if (F.realFormat == RealFormat.ieeeDouble) 9967 { 9968 int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff; 9969 9970 version (LittleEndian) 9971 int pos = 0; 9972 else 9973 int pos = 3; 9974 } 9975 else static if (F.realFormat == RealFormat.ieeeExtended) 9976 { 9977 int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff; 9978 9979 version (LittleEndian) 9980 int pos = 0; 9981 else 9982 int pos = 4; 9983 } 9984 else static if (F.realFormat == RealFormat.ieeeQuadruple) 9985 { 9986 int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff; 9987 9988 version (LittleEndian) 9989 int pos = 0; 9990 else 9991 int pos = 7; 9992 } 9993 else 9994 static assert(false, "Not implemented for this architecture"); 9995 9996 if (exp < 0) 9997 { 9998 if (x < 0.0) 9999 return -1.0; 10000 else 10001 return 0.0; 10002 } 10003 10004 static if (F.realFormat == RealFormat.ieeeSingle) 10005 { 10006 if (exp < (T.mant_dig - 1)) 10007 { 10008 // Clear all bits representing the fraction part. 10009 const uint fraction_mask = F.MANTISSAMASK_INT >> exp; 10010 10011 if ((y.vi & fraction_mask) != 0) 10012 { 10013 // If 'x' is negative, then first substract 1.0 from the value. 10014 if (y.vi < 0) 10015 y.vi += 0x00800000 >> exp; 10016 y.vi &= ~fraction_mask; 10017 } 10018 } 10019 } 10020 else 10021 { 10022 exp = (T.mant_dig - 1) - exp; 10023 10024 // Zero 16 bits at a time. 10025 while (exp >= 16) 10026 { 10027 version (LittleEndian) 10028 y.vu[pos++] = 0; 10029 else 10030 y.vu[pos--] = 0; 10031 exp -= 16; 10032 } 10033 10034 // Clear the remaining bits. 10035 if (exp > 0) 10036 y.vu[pos] &= 0xffff ^ ((1 << exp) - 1); 10037 10038 if ((x < 0.0) && (x != y.rv)) 10039 y.rv -= 1.0; 10040 } 10041 10042 return y.rv; 10043 }