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