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