1 // Written in the D programming language. 2 3 /** 4 This is a submodule of $(MREF std, math). 5 6 It contains several functions for work with floating point numbers. 7 8 Copyright: Copyright The D Language Foundation 2000 - 2011. 9 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 10 Authors: $(HTTP digitalmars.com, Walter Bright), Don Clugston, 11 Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger 12 Source: $(PHOBOSSRC std/math/operations.d) 13 14 Macros: 15 TABLE_SV = <table border="1" cellpadding="4" cellspacing="0"> 16 <caption>Special Values</caption> 17 $0</table> 18 SVH = $(TR $(TH $1) $(TH $2)) 19 SV = $(TR $(TD $1) $(TD $2)) 20 NAN = $(RED NAN) 21 PLUSMN = ± 22 INFIN = ∞ 23 LT = < 24 GT = > 25 */ 26 27 module std.math.operations; 28 29 import std.traits : CommonType, isFloatingPoint, isIntegral, Unqual; 30 31 version (LDC) import ldc.intrinsics; 32 33 // Functions for NaN payloads 34 /* 35 * A 'payload' can be stored in the significand of a $(NAN). One bit is required 36 * to distinguish between a quiet and a signalling $(NAN). This leaves 22 bits 37 * of payload for a float; 51 bits for a double; 62 bits for an 80-bit real; 38 * and 111 bits for a 128-bit quad. 39 */ 40 /** 41 * Create a quiet $(NAN), storing an integer inside the payload. 42 * 43 * For floats, the largest possible payload is 0x3F_FFFF. 44 * For doubles, it is 0x3_FFFF_FFFF_FFFF. 45 * For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF. 46 */ 47 real NaN(ulong payload) @trusted pure nothrow @nogc 48 { 49 import std.math : floatTraits, RealFormat; 50 51 alias F = floatTraits!(real); 52 static if (F.realFormat == RealFormat.ieeeExtended || 53 F.realFormat == RealFormat.ieeeExtended53) 54 { 55 // real80 (in x86 real format, the implied bit is actually 56 // not implied but a real bit which is stored in the real) 57 ulong v = 3; // implied bit = 1, quiet bit = 1 58 } 59 else 60 { 61 ulong v = 1; // no implied bit. quiet bit = 1 62 } 63 if (__ctfe) 64 { 65 v = 1; // We use a double in CTFE. 66 assert(payload >>> 51 == 0, 67 "Cannot set more than 51 bits of NaN payload in CTFE."); 68 } 69 70 71 ulong a = payload; 72 73 // 22 Float bits 74 ulong w = a & 0x3F_FFFF; 75 a -= w; 76 77 v <<=22; 78 v |= w; 79 a >>=22; 80 81 // 29 Double bits 82 v <<=29; 83 w = a & 0xFFF_FFFF; 84 v |= w; 85 a -= w; 86 a >>=29; 87 88 if (__ctfe) 89 { 90 v |= 0x7FF0_0000_0000_0000; 91 return *cast(double*) &v; 92 } 93 else static if (F.realFormat == RealFormat.ieeeDouble) 94 { 95 v |= 0x7FF0_0000_0000_0000; 96 real x; 97 * cast(ulong *)(&x) = v; 98 return x; 99 } 100 else 101 { 102 v <<=11; 103 a &= 0x7FF; 104 v |= a; 105 real x = real.nan; 106 107 // Extended real bits 108 static if (F.realFormat == RealFormat.ieeeQuadruple) 109 { 110 v <<= 1; // there's no implicit bit 111 112 version (LittleEndian) 113 { 114 *cast(ulong*)(6+cast(ubyte*)(&x)) = v; 115 } 116 else 117 { 118 *cast(ulong*)(2+cast(ubyte*)(&x)) = v; 119 } 120 } 121 else 122 { 123 *cast(ulong *)(&x) = v; 124 } 125 return x; 126 } 127 } 128 129 /// 130 @safe @nogc pure nothrow unittest 131 { 132 import std.math.traits : isNaN; 133 134 real a = NaN(1_000_000); 135 assert(isNaN(a)); 136 assert(getNaNPayload(a) == 1_000_000); 137 } 138 139 @system pure nothrow @nogc unittest // not @safe because taking address of local. 140 { 141 import std.math : floatTraits, RealFormat; 142 143 static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) 144 { 145 auto x = NaN(1); 146 auto xl = *cast(ulong*)&x; 147 assert(xl & 0x8_0000_0000_0000UL); //non-signaling bit, bit 52 148 assert((xl & 0x7FF0_0000_0000_0000UL) == 0x7FF0_0000_0000_0000UL); //all exp bits set 149 } 150 } 151 152 /** 153 * Extract an integral payload from a $(NAN). 154 * 155 * Returns: 156 * the integer payload as a ulong. 157 * 158 * For floats, the largest possible payload is 0x3F_FFFF. 159 * For doubles, it is 0x3_FFFF_FFFF_FFFF. 160 * For 80-bit or 128-bit reals, it is 0x3FFF_FFFF_FFFF_FFFF. 161 */ 162 ulong getNaNPayload(real x) @trusted pure nothrow @nogc 163 { 164 import std.math : floatTraits, RealFormat; 165 166 // assert(isNaN(x)); 167 alias F = floatTraits!(real); 168 ulong m = void; 169 if (__ctfe) 170 { 171 double y = x; 172 m = *cast(ulong*) &y; 173 // Make it look like an 80-bit significand. 174 // Skip exponent, and quiet bit 175 m &= 0x0007_FFFF_FFFF_FFFF; 176 m <<= 11; 177 } 178 else static if (F.realFormat == RealFormat.ieeeDouble) 179 { 180 m = *cast(ulong*)(&x); 181 // Make it look like an 80-bit significand. 182 // Skip exponent, and quiet bit 183 m &= 0x0007_FFFF_FFFF_FFFF; 184 m <<= 11; 185 } 186 else static if (F.realFormat == RealFormat.ieeeQuadruple) 187 { 188 version (LittleEndian) 189 { 190 m = *cast(ulong*)(6+cast(ubyte*)(&x)); 191 } 192 else 193 { 194 m = *cast(ulong*)(2+cast(ubyte*)(&x)); 195 } 196 197 m >>= 1; // there's no implicit bit 198 } 199 else 200 { 201 m = *cast(ulong*)(&x); 202 } 203 204 // ignore implicit bit and quiet bit 205 206 const ulong f = m & 0x3FFF_FF00_0000_0000L; 207 208 ulong w = f >>> 40; 209 w |= (m & 0x00FF_FFFF_F800L) << (22 - 11); 210 w |= (m & 0x7FF) << 51; 211 return w; 212 } 213 214 /// 215 @safe @nogc pure nothrow unittest 216 { 217 import std.math.traits : isNaN; 218 219 real a = NaN(1_000_000); 220 assert(isNaN(a)); 221 assert(getNaNPayload(a) == 1_000_000); 222 } 223 224 @safe @nogc pure nothrow unittest 225 { 226 import std.math.traits : isIdentical, isNaN; 227 228 enum real a = NaN(1_000_000); 229 static assert(isNaN(a)); 230 static assert(getNaNPayload(a) == 1_000_000); 231 real b = NaN(1_000_000); 232 assert(isIdentical(b, a)); 233 // The CTFE version of getNaNPayload relies on it being impossible 234 // for a CTFE-constructed NaN to have more than 51 bits of payload. 235 enum nanNaN = NaN(getNaNPayload(real.nan)); 236 assert(isIdentical(real.nan, nanNaN)); 237 static if (real.init != real.init) 238 { 239 enum initNaN = NaN(getNaNPayload(real.init)); 240 assert(isIdentical(real.init, initNaN)); 241 } 242 } 243 244 debug(UnitTest) 245 { 246 @safe pure nothrow @nogc unittest 247 { 248 real nan4 = NaN(0x789_ABCD_EF12_3456); 249 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended 250 || floatTraits!(real).realFormat == RealFormat.ieeeQuadruple) 251 { 252 assert(getNaNPayload(nan4) == 0x789_ABCD_EF12_3456); 253 } 254 else 255 { 256 assert(getNaNPayload(nan4) == 0x1_ABCD_EF12_3456); 257 } 258 double nan5 = nan4; 259 assert(getNaNPayload(nan5) == 0x1_ABCD_EF12_3456); 260 float nan6 = nan4; 261 assert(getNaNPayload(nan6) == 0x12_3456); 262 nan4 = NaN(0xFABCD); 263 assert(getNaNPayload(nan4) == 0xFABCD); 264 nan6 = nan4; 265 assert(getNaNPayload(nan6) == 0xFABCD); 266 nan5 = NaN(0x100_0000_0000_3456); 267 assert(getNaNPayload(nan5) == 0x0000_0000_3456); 268 } 269 } 270 271 /** 272 * Calculate the next largest floating point value after x. 273 * 274 * Return the least number greater than x that is representable as a real; 275 * thus, it gives the next point on the IEEE number line. 276 * 277 * $(TABLE_SV 278 * $(SVH x, nextUp(x) ) 279 * $(SV -$(INFIN), -real.max ) 280 * $(SV $(PLUSMN)0.0, real.min_normal*real.epsilon ) 281 * $(SV real.max, $(INFIN) ) 282 * $(SV $(INFIN), $(INFIN) ) 283 * $(SV $(NAN), $(NAN) ) 284 * ) 285 */ 286 real nextUp(real x) @trusted pure nothrow @nogc 287 { 288 import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; 289 290 alias F = floatTraits!(real); 291 static if (F.realFormat != RealFormat.ieeeDouble) 292 { 293 if (__ctfe) 294 { 295 if (x == -real.infinity) 296 return -real.max; 297 if (!(x < real.infinity)) // Infinity or NaN. 298 return x; 299 real delta; 300 // Start with a decent estimate of delta. 301 if (x <= 0x1.ffffffffffffep+1023 && x >= -double.max) 302 { 303 const double d = cast(double) x; 304 delta = (cast(real) nextUp(d) - cast(real) d) * 0x1p-11L; 305 while (x + (delta * 0x1p-100L) > x) 306 delta *= 0x1p-100L; 307 } 308 else 309 { 310 delta = 0x1p960L; 311 while (!(x + delta > x) && delta < real.max * 0x1p-100L) 312 delta *= 0x1p100L; 313 } 314 if (x + delta > x) 315 { 316 while (x + (delta / 2) > x) 317 delta /= 2; 318 } 319 else 320 { 321 do { delta += delta; } while (!(x + delta > x)); 322 } 323 if (x < 0 && x + delta == 0) 324 return -0.0L; 325 return x + delta; 326 } 327 } 328 static if (F.realFormat == RealFormat.ieeeDouble) 329 { 330 return nextUp(cast(double) x); 331 } 332 else static if (F.realFormat == RealFormat.ieeeQuadruple) 333 { 334 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]; 335 if (e == F.EXPMASK) 336 { 337 // NaN or Infinity 338 if (x == -real.infinity) return -real.max; 339 return x; // +Inf and NaN are unchanged. 340 } 341 342 auto ps = cast(ulong *)&x; 343 if (ps[MANTISSA_MSB] & 0x8000_0000_0000_0000) 344 { 345 // Negative number 346 if (ps[MANTISSA_LSB] == 0 && ps[MANTISSA_MSB] == 0x8000_0000_0000_0000) 347 { 348 // it was negative zero, change to smallest subnormal 349 ps[MANTISSA_LSB] = 1; 350 ps[MANTISSA_MSB] = 0; 351 return x; 352 } 353 if (ps[MANTISSA_LSB] == 0) --ps[MANTISSA_MSB]; 354 --ps[MANTISSA_LSB]; 355 } 356 else 357 { 358 // Positive number 359 ++ps[MANTISSA_LSB]; 360 if (ps[MANTISSA_LSB] == 0) ++ps[MANTISSA_MSB]; 361 } 362 return x; 363 } 364 else static if (F.realFormat == RealFormat.ieeeExtended || 365 F.realFormat == RealFormat.ieeeExtended53) 366 { 367 // For 80-bit reals, the "implied bit" is a nuisance... 368 ushort *pe = cast(ushort *)&x; 369 ulong *ps = cast(ulong *)&x; 370 // EPSILON is 1 for 64-bit, and 2048 for 53-bit precision reals. 371 enum ulong EPSILON = 2UL ^^ (64 - real.mant_dig); 372 373 if ((pe[F.EXPPOS_SHORT] & F.EXPMASK) == F.EXPMASK) 374 { 375 // First, deal with NANs and infinity 376 if (x == -real.infinity) return -real.max; 377 return x; // +Inf and NaN are unchanged. 378 } 379 if (pe[F.EXPPOS_SHORT] & 0x8000) 380 { 381 // Negative number -- need to decrease the significand 382 *ps -= EPSILON; 383 // Need to mask with 0x7FFF... so subnormals are treated correctly. 384 if ((*ps & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FFF_FFFF_FFFF_FFFF) 385 { 386 if (pe[F.EXPPOS_SHORT] == 0x8000) // it was negative zero 387 { 388 *ps = 1; 389 pe[F.EXPPOS_SHORT] = 0; // smallest subnormal. 390 return x; 391 } 392 393 --pe[F.EXPPOS_SHORT]; 394 395 if (pe[F.EXPPOS_SHORT] == 0x8000) 396 return x; // it's become a subnormal, implied bit stays low. 397 398 *ps = 0xFFFF_FFFF_FFFF_FFFF; // set the implied bit 399 return x; 400 } 401 return x; 402 } 403 else 404 { 405 // Positive number -- need to increase the significand. 406 // Works automatically for positive zero. 407 *ps += EPSILON; 408 if ((*ps & 0x7FFF_FFFF_FFFF_FFFF) == 0) 409 { 410 // change in exponent 411 ++pe[F.EXPPOS_SHORT]; 412 *ps = 0x8000_0000_0000_0000; // set the high bit 413 } 414 } 415 return x; 416 } 417 else // static if (F.realFormat == RealFormat.ibmExtended) 418 { 419 assert(0, "nextUp not implemented"); 420 } 421 } 422 423 /** ditto */ 424 double nextUp(double x) @trusted pure nothrow @nogc 425 { 426 ulong s = *cast(ulong *)&x; 427 428 if ((s & 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) 429 { 430 // First, deal with NANs and infinity 431 if (x == -x.infinity) return -x.max; 432 return x; // +INF and NAN are unchanged. 433 } 434 if (s & 0x8000_0000_0000_0000) // Negative number 435 { 436 if (s == 0x8000_0000_0000_0000) // it was negative zero 437 { 438 s = 0x0000_0000_0000_0001; // change to smallest subnormal 439 return *cast(double*) &s; 440 } 441 --s; 442 } 443 else 444 { // Positive number 445 ++s; 446 } 447 return *cast(double*) &s; 448 } 449 450 /** ditto */ 451 float nextUp(float x) @trusted pure nothrow @nogc 452 { 453 uint s = *cast(uint *)&x; 454 455 if ((s & 0x7F80_0000) == 0x7F80_0000) 456 { 457 // First, deal with NANs and infinity 458 if (x == -x.infinity) return -x.max; 459 460 return x; // +INF and NAN are unchanged. 461 } 462 if (s & 0x8000_0000) // Negative number 463 { 464 if (s == 0x8000_0000) // it was negative zero 465 { 466 s = 0x0000_0001; // change to smallest subnormal 467 return *cast(float*) &s; 468 } 469 470 --s; 471 } 472 else 473 { 474 // Positive number 475 ++s; 476 } 477 return *cast(float*) &s; 478 } 479 480 /// 481 @safe @nogc pure nothrow unittest 482 { 483 assert(nextUp(1.0 - 1.0e-6).feqrel(0.999999) > 16); 484 assert(nextUp(1.0 - real.epsilon).feqrel(1.0) > 16); 485 } 486 487 /** 488 * Calculate the next smallest floating point value before x. 489 * 490 * Return the greatest number less than x that is representable as a real; 491 * thus, it gives the previous point on the IEEE number line. 492 * 493 * $(TABLE_SV 494 * $(SVH x, nextDown(x) ) 495 * $(SV $(INFIN), real.max ) 496 * $(SV $(PLUSMN)0.0, -real.min_normal*real.epsilon ) 497 * $(SV -real.max, -$(INFIN) ) 498 * $(SV -$(INFIN), -$(INFIN) ) 499 * $(SV $(NAN), $(NAN) ) 500 * ) 501 */ 502 real nextDown(real x) @safe pure nothrow @nogc 503 { 504 return -nextUp(-x); 505 } 506 507 /** ditto */ 508 double nextDown(double x) @safe pure nothrow @nogc 509 { 510 return -nextUp(-x); 511 } 512 513 /** ditto */ 514 float nextDown(float x) @safe pure nothrow @nogc 515 { 516 return -nextUp(-x); 517 } 518 519 /// 520 @safe pure nothrow @nogc unittest 521 { 522 assert( nextDown(1.0 + real.epsilon) == 1.0); 523 } 524 525 @safe pure nothrow @nogc unittest 526 { 527 import std.math : floatTraits, RealFormat; 528 import std.math.traits : isIdentical; 529 530 static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended || 531 floatTraits!(real).realFormat == RealFormat.ieeeDouble || 532 floatTraits!(real).realFormat == RealFormat.ieeeExtended53 || 533 floatTraits!(real).realFormat == RealFormat.ieeeQuadruple) 534 { 535 // Tests for reals 536 assert(isIdentical(nextUp(NaN(0xABC)), NaN(0xABC))); 537 //static assert(isIdentical(nextUp(NaN(0xABC)), NaN(0xABC))); 538 // negative numbers 539 assert( nextUp(-real.infinity) == -real.max ); 540 assert( nextUp(-1.0L-real.epsilon) == -1.0 ); 541 assert( nextUp(-2.0L) == -2.0 + real.epsilon); 542 static assert( nextUp(-real.infinity) == -real.max ); 543 static assert( nextUp(-1.0L-real.epsilon) == -1.0 ); 544 static assert( nextUp(-2.0L) == -2.0 + real.epsilon); 545 // subnormals and zero 546 assert( nextUp(-real.min_normal) == -real.min_normal*(1-real.epsilon) ); 547 assert( nextUp(-real.min_normal*(1-real.epsilon)) == -real.min_normal*(1-2*real.epsilon) ); 548 assert( isIdentical(-0.0L, nextUp(-real.min_normal*real.epsilon)) ); 549 assert( nextUp(-0.0L) == real.min_normal*real.epsilon ); 550 assert( nextUp(0.0L) == real.min_normal*real.epsilon ); 551 assert( nextUp(real.min_normal*(1-real.epsilon)) == real.min_normal ); 552 assert( nextUp(real.min_normal) == real.min_normal*(1+real.epsilon) ); 553 static assert( nextUp(-real.min_normal) == -real.min_normal*(1-real.epsilon) ); 554 static assert( nextUp(-real.min_normal*(1-real.epsilon)) == -real.min_normal*(1-2*real.epsilon) ); 555 static assert( -0.0L is nextUp(-real.min_normal*real.epsilon) ); 556 static assert( nextUp(-0.0L) == real.min_normal*real.epsilon ); 557 static assert( nextUp(0.0L) == real.min_normal*real.epsilon ); 558 static assert( nextUp(real.min_normal*(1-real.epsilon)) == real.min_normal ); 559 static assert( nextUp(real.min_normal) == real.min_normal*(1+real.epsilon) ); 560 // positive numbers 561 assert( nextUp(1.0L) == 1.0 + real.epsilon ); 562 assert( nextUp(2.0L-real.epsilon) == 2.0 ); 563 assert( nextUp(real.max) == real.infinity ); 564 assert( nextUp(real.infinity)==real.infinity ); 565 static assert( nextUp(1.0L) == 1.0 + real.epsilon ); 566 static assert( nextUp(2.0L-real.epsilon) == 2.0 ); 567 static assert( nextUp(real.max) == real.infinity ); 568 static assert( nextUp(real.infinity)==real.infinity ); 569 // ctfe near double.max boundary 570 static assert(nextUp(nextDown(cast(real) double.max)) == cast(real) double.max); 571 } 572 573 double n = NaN(0xABC); 574 assert(isIdentical(nextUp(n), n)); 575 // negative numbers 576 assert( nextUp(-double.infinity) == -double.max ); 577 assert( nextUp(-1-double.epsilon) == -1.0 ); 578 assert( nextUp(-2.0) == -2.0 + double.epsilon); 579 // subnormals and zero 580 581 assert( nextUp(-double.min_normal) == -double.min_normal*(1-double.epsilon) ); 582 assert( nextUp(-double.min_normal*(1-double.epsilon)) == -double.min_normal*(1-2*double.epsilon) ); 583 assert( isIdentical(-0.0, nextUp(-double.min_normal*double.epsilon)) ); 584 assert( nextUp(0.0) == double.min_normal*double.epsilon ); 585 assert( nextUp(-0.0) == double.min_normal*double.epsilon ); 586 assert( nextUp(double.min_normal*(1-double.epsilon)) == double.min_normal ); 587 assert( nextUp(double.min_normal) == double.min_normal*(1+double.epsilon) ); 588 // positive numbers 589 assert( nextUp(1.0) == 1.0 + double.epsilon ); 590 assert( nextUp(2.0-double.epsilon) == 2.0 ); 591 assert( nextUp(double.max) == double.infinity ); 592 593 float fn = NaN(0xABC); 594 assert(isIdentical(nextUp(fn), fn)); 595 float f = -float.min_normal*(1-float.epsilon); 596 float f1 = -float.min_normal; 597 assert( nextUp(f1) == f); 598 f = 1.0f+float.epsilon; 599 f1 = 1.0f; 600 assert( nextUp(f1) == f ); 601 f1 = -0.0f; 602 assert( nextUp(f1) == float.min_normal*float.epsilon); 603 assert( nextUp(float.infinity)==float.infinity ); 604 605 assert(nextDown(1.0L+real.epsilon)==1.0); 606 assert(nextDown(1.0+double.epsilon)==1.0); 607 f = 1.0f+float.epsilon; 608 assert(nextDown(f)==1.0); 609 assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0); 610 611 // CTFE 612 613 enum double ctfe_n = NaN(0xABC); 614 //static assert(isIdentical(nextUp(ctfe_n), ctfe_n)); // FIXME: https://issues.dlang.org/show_bug.cgi?id=20197 615 static assert(nextUp(double.nan) is double.nan); 616 // negative numbers 617 static assert( nextUp(-double.infinity) == -double.max ); 618 static assert( nextUp(-1-double.epsilon) == -1.0 ); 619 static assert( nextUp(-2.0) == -2.0 + double.epsilon); 620 // subnormals and zero 621 622 static assert( nextUp(-double.min_normal) == -double.min_normal*(1-double.epsilon) ); 623 static assert( nextUp(-double.min_normal*(1-double.epsilon)) == -double.min_normal*(1-2*double.epsilon) ); 624 static assert( -0.0 is nextUp(-double.min_normal*double.epsilon) ); 625 static assert( nextUp(0.0) == double.min_normal*double.epsilon ); 626 static assert( nextUp(-0.0) == double.min_normal*double.epsilon ); 627 static assert( nextUp(double.min_normal*(1-double.epsilon)) == double.min_normal ); 628 static assert( nextUp(double.min_normal) == double.min_normal*(1+double.epsilon) ); 629 // positive numbers 630 static assert( nextUp(1.0) == 1.0 + double.epsilon ); 631 static assert( nextUp(2.0-double.epsilon) == 2.0 ); 632 static assert( nextUp(double.max) == double.infinity ); 633 634 enum float ctfe_fn = NaN(0xABC); 635 //static assert(isIdentical(nextUp(ctfe_fn), ctfe_fn)); // FIXME: https://issues.dlang.org/show_bug.cgi?id=20197 636 static assert(nextUp(float.nan) is float.nan); 637 static assert(nextUp(-float.min_normal) == -float.min_normal*(1-float.epsilon)); 638 static assert(nextUp(1.0f) == 1.0f+float.epsilon); 639 static assert(nextUp(-0.0f) == float.min_normal*float.epsilon); 640 static assert(nextUp(float.infinity)==float.infinity); 641 static assert(nextDown(1.0L+real.epsilon)==1.0); 642 static assert(nextDown(1.0+double.epsilon)==1.0); 643 static assert(nextDown(1.0f+float.epsilon)==1.0); 644 static assert(nextafter(1.0+real.epsilon, -real.infinity)==1.0); 645 } 646 647 648 649 /****************************************** 650 * Calculates the next representable value after x in the direction of y. 651 * 652 * If y > x, the result will be the next largest floating-point value; 653 * if y < x, the result will be the next smallest value. 654 * If x == y, the result is y. 655 * If x or y is a NaN, the result is a NaN. 656 * 657 * Remarks: 658 * This function is not generally very useful; it's almost always better to use 659 * the faster functions nextUp() or nextDown() instead. 660 * 661 * The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and 662 * the function result is infinite. The FE_INEXACT and FE_UNDERFLOW 663 * exceptions will be raised if the function value is subnormal, and x is 664 * not equal to y. 665 */ 666 T nextafter(T)(const T x, const T y) @safe pure nothrow @nogc 667 { 668 import std.math.traits : isNaN; 669 670 if (x == y || isNaN(y)) 671 { 672 return y; 673 } 674 675 if (isNaN(x)) 676 { 677 return x; 678 } 679 680 return ((y>x) ? nextUp(x) : nextDown(x)); 681 } 682 683 /// 684 @safe pure nothrow @nogc unittest 685 { 686 import std.math.traits : isNaN; 687 688 float a = 1; 689 assert(is(typeof(nextafter(a, a)) == float)); 690 assert(nextafter(a, a.infinity) > a); 691 assert(isNaN(nextafter(a, a.nan))); 692 assert(isNaN(nextafter(a.nan, a))); 693 694 double b = 2; 695 assert(is(typeof(nextafter(b, b)) == double)); 696 assert(nextafter(b, b.infinity) > b); 697 assert(isNaN(nextafter(b, b.nan))); 698 assert(isNaN(nextafter(b.nan, b))); 699 700 real c = 3; 701 assert(is(typeof(nextafter(c, c)) == real)); 702 assert(nextafter(c, c.infinity) > c); 703 assert(isNaN(nextafter(c, c.nan))); 704 assert(isNaN(nextafter(c.nan, c))); 705 } 706 707 @safe pure nothrow @nogc unittest 708 { 709 import std.math.traits : isNaN, signbit; 710 711 // CTFE 712 enum float a = 1; 713 static assert(is(typeof(nextafter(a, a)) == float)); 714 static assert(nextafter(a, a.infinity) > a); 715 static assert(isNaN(nextafter(a, a.nan))); 716 static assert(isNaN(nextafter(a.nan, a))); 717 718 enum double b = 2; 719 static assert(is(typeof(nextafter(b, b)) == double)); 720 static assert(nextafter(b, b.infinity) > b); 721 static assert(isNaN(nextafter(b, b.nan))); 722 static assert(isNaN(nextafter(b.nan, b))); 723 724 enum real c = 3; 725 static assert(is(typeof(nextafter(c, c)) == real)); 726 static assert(nextafter(c, c.infinity) > c); 727 static assert(isNaN(nextafter(c, c.nan))); 728 static assert(isNaN(nextafter(c.nan, c))); 729 730 enum real negZero = nextafter(+0.0L, -0.0L); 731 static assert(negZero == -0.0L); 732 static assert(signbit(negZero)); 733 734 static assert(nextafter(c, c) == c); 735 } 736 737 //real nexttoward(real x, real y) { return core.stdc.math.nexttowardl(x, y); } 738 739 /** 740 * Returns the positive difference between x and y. 741 * 742 * Equivalent to `fmax(x-y, 0)`. 743 * 744 * Returns: 745 * $(TABLE_SV 746 * $(TR $(TH x, y) $(TH fdim(x, y))) 747 * $(TR $(TD x $(GT) y) $(TD x - y)) 748 * $(TR $(TD x $(LT)= y) $(TD +0.0)) 749 * ) 750 */ 751 real fdim(real x, real y) @safe pure nothrow @nogc 752 { 753 return (x < y) ? +0.0 : x - y; 754 } 755 756 /// 757 @safe pure nothrow @nogc unittest 758 { 759 import std.math.traits : isNaN; 760 761 assert(fdim(2.0, 0.0) == 2.0); 762 assert(fdim(-2.0, 0.0) == 0.0); 763 assert(fdim(real.infinity, 2.0) == real.infinity); 764 assert(isNaN(fdim(real.nan, 2.0))); 765 assert(isNaN(fdim(2.0, real.nan))); 766 assert(isNaN(fdim(real.nan, real.nan))); 767 } 768 769 /** 770 * Returns the larger of `x` and `y`. 771 * 772 * If one of the arguments is a `NaN`, the other is returned. 773 * 774 * See_Also: $(REF max, std,algorithm,comparison) is faster because it does not perform the `isNaN` test. 775 */ 776 pragma(inline, true) // LDC 777 F fmax(F)(const F x, const F y) @safe pure nothrow @nogc 778 if (__traits(isFloating, F)) 779 { 780 version (LDC) 781 { 782 return llvm_maxnum!F(x, y); 783 } 784 else 785 { 786 import std.math.traits : isNaN; 787 788 // Do the more predictable test first. Generates 0 branches with ldc and 1 branch with gdc. 789 // See https://godbolt.org/z/erxrW9 790 if (isNaN(x)) return y; 791 return y > x ? y : x; 792 } 793 } 794 795 /// 796 @safe pure nothrow @nogc unittest 797 { 798 import std.meta : AliasSeq; 799 static foreach (F; AliasSeq!(float, double, real)) 800 { 801 assert(fmax(F(0.0), F(2.0)) == 2.0); 802 assert(fmax(F(-2.0), 0.0) == F(0.0)); 803 assert(fmax(F.infinity, F(2.0)) == F.infinity); 804 assert(fmax(F.nan, F(2.0)) == F(2.0)); 805 assert(fmax(F(2.0), F.nan) == F(2.0)); 806 } 807 } 808 809 /** 810 * Returns the smaller of `x` and `y`. 811 * 812 * If one of the arguments is a `NaN`, the other is returned. 813 * 814 * See_Also: $(REF min, std,algorithm,comparison) is faster because it does not perform the `isNaN` test. 815 */ 816 pragma(inline, true) // LDC 817 F fmin(F)(const F x, const F y) @safe pure nothrow @nogc 818 if (__traits(isFloating, F)) 819 { 820 version (LDC) 821 { 822 return llvm_minnum!F(x, y); 823 } 824 else 825 { 826 import std.math.traits : isNaN; 827 828 // Do the more predictable test first. Generates 0 branches with ldc and 1 branch with gdc. 829 // See https://godbolt.org/z/erxrW9 830 if (isNaN(x)) return y; 831 return y < x ? y : x; 832 } 833 } 834 835 /// 836 @safe pure nothrow @nogc unittest 837 { 838 import std.meta : AliasSeq; 839 static foreach (F; AliasSeq!(float, double, real)) 840 { 841 assert(fmin(F(0.0), F(2.0)) == 0.0); 842 assert(fmin(F(-2.0), F(0.0)) == -2.0); 843 assert(fmin(F.infinity, F(2.0)) == 2.0); 844 assert(fmin(F.nan, F(2.0)) == 2.0); 845 assert(fmin(F(2.0), F.nan) == 2.0); 846 } 847 } 848 849 /************************************** 850 * Returns (x * y) + z, rounding only once according to the 851 * current rounding mode. 852 * 853 * BUGS: Not currently implemented - rounds twice. 854 */ 855 version (LDC) 856 { 857 pragma(inline, true): 858 real fma(real x, real y, real z) @safe pure nothrow @nogc { return llvm_fma(x, y, z); } 859 //double fma(double x, double y, double z) @safe pure nothrow @nogc { return llvm_fma(x, y, z); } 860 //float fma(float x, float y, float z) @safe pure nothrow @nogc { return llvm_fma(x, y, z); } 861 } 862 else 863 pragma(inline, true) 864 real fma(real x, real y, real z) @safe pure nothrow @nogc { return (x * y) + z; } 865 866 /// 867 @safe pure nothrow @nogc unittest 868 { 869 assert(fma(0.0, 2.0, 2.0) == 2.0); 870 assert(fma(2.0, 2.0, 2.0) == 6.0); 871 assert(fma(real.infinity, 2.0, 2.0) == real.infinity); 872 assert(fma(real.nan, 2.0, 2.0) is real.nan); 873 assert(fma(2.0, 2.0, real.nan) is real.nan); 874 } 875 876 /************************************** 877 * To what precision is x equal to y? 878 * 879 * Returns: the number of mantissa bits which are equal in x and y. 880 * eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision. 881 * 882 * $(TABLE_SV 883 * $(TR $(TH x) $(TH y) $(TH feqrel(x, y))) 884 * $(TR $(TD x) $(TD x) $(TD real.mant_dig)) 885 * $(TR $(TD x) $(TD $(GT)= 2*x) $(TD 0)) 886 * $(TR $(TD x) $(TD $(LT)= x/2) $(TD 0)) 887 * $(TR $(TD $(NAN)) $(TD any) $(TD 0)) 888 * $(TR $(TD any) $(TD $(NAN)) $(TD 0)) 889 * ) 890 */ 891 int feqrel(X)(const X x, const X y) @trusted pure nothrow @nogc 892 if (isFloatingPoint!(X)) 893 { 894 import std.math : floatTraits, RealFormat; 895 import core.math : fabs; 896 897 /* Public Domain. Author: Don Clugston, 18 Aug 2005. 898 */ 899 alias F = floatTraits!(X); 900 static if (F.realFormat == RealFormat.ieeeSingle 901 || F.realFormat == RealFormat.ieeeDouble 902 || F.realFormat == RealFormat.ieeeExtended 903 || F.realFormat == RealFormat.ieeeExtended53 904 || F.realFormat == RealFormat.ieeeQuadruple) 905 { 906 if (x == y) 907 return X.mant_dig; // ensure diff != 0, cope with INF. 908 909 Unqual!X diff = fabs(x - y); 910 911 ushort *pa = cast(ushort *)(&x); 912 ushort *pb = cast(ushort *)(&y); 913 ushort *pd = cast(ushort *)(&diff); 914 915 916 // The difference in abs(exponent) between x or y and abs(x-y) 917 // is equal to the number of significand bits of x which are 918 // equal to y. If negative, x and y have different exponents. 919 // If positive, x and y are equal to 'bitsdiff' bits. 920 // AND with 0x7FFF to form the absolute value. 921 // To avoid out-by-1 errors, we subtract 1 so it rounds down 922 // if the exponents were different. This means 'bitsdiff' is 923 // always 1 lower than we want, except that if bitsdiff == 0, 924 // they could have 0 or 1 bits in common. 925 926 int bitsdiff = ((( (pa[F.EXPPOS_SHORT] & F.EXPMASK) 927 + (pb[F.EXPPOS_SHORT] & F.EXPMASK) 928 - (1 << F.EXPSHIFT)) >> 1) 929 - (pd[F.EXPPOS_SHORT] & F.EXPMASK)) >> F.EXPSHIFT; 930 if ( (pd[F.EXPPOS_SHORT] & F.EXPMASK) == 0) 931 { // Difference is subnormal 932 // For subnormals, we need to add the number of zeros that 933 // lie at the start of diff's significand. 934 // We do this by multiplying by 2^^real.mant_dig 935 diff *= F.RECIP_EPSILON; 936 return bitsdiff + X.mant_dig - ((pd[F.EXPPOS_SHORT] & F.EXPMASK) >> F.EXPSHIFT); 937 } 938 939 if (bitsdiff > 0) 940 return bitsdiff + 1; // add the 1 we subtracted before 941 942 // Avoid out-by-1 errors when factor is almost 2. 943 if (bitsdiff == 0 944 && ((pa[F.EXPPOS_SHORT] ^ pb[F.EXPPOS_SHORT]) & F.EXPMASK) == 0) 945 { 946 return 1; 947 } else return 0; 948 } 949 else 950 { 951 static assert(false, "Not implemented for this architecture"); 952 } 953 } 954 955 /// 956 @safe pure unittest 957 { 958 assert(feqrel(2.0, 2.0) == 53); 959 assert(feqrel(2.0f, 2.0f) == 24); 960 assert(feqrel(2.0, double.nan) == 0); 961 962 // Test that numbers are within n digits of each 963 // other by testing if feqrel > n * log2(10) 964 965 // five digits 966 assert(feqrel(2.0, 2.00001) > 16); 967 // ten digits 968 assert(feqrel(2.0, 2.00000000001) > 33); 969 } 970 971 @safe pure nothrow @nogc unittest 972 { 973 void testFeqrel(F)() 974 { 975 // Exact equality 976 assert(feqrel(F.max, F.max) == F.mant_dig); 977 assert(feqrel!(F)(0.0, 0.0) == F.mant_dig); 978 assert(feqrel(F.infinity, F.infinity) == F.mant_dig); 979 980 // a few bits away from exact equality 981 F w=1; 982 for (int i = 1; i < F.mant_dig - 1; ++i) 983 { 984 assert(feqrel!(F)(1.0 + w * F.epsilon, 1.0) == F.mant_dig-i); 985 assert(feqrel!(F)(1.0 - w * F.epsilon, 1.0) == F.mant_dig-i); 986 assert(feqrel!(F)(1.0, 1 + (w-1) * F.epsilon) == F.mant_dig - i + 1); 987 w*=2; 988 } 989 990 assert(feqrel!(F)(1.5+F.epsilon, 1.5) == F.mant_dig-1); 991 assert(feqrel!(F)(1.5-F.epsilon, 1.5) == F.mant_dig-1); 992 assert(feqrel!(F)(1.5-F.epsilon, 1.5+F.epsilon) == F.mant_dig-2); 993 994 995 // Numbers that are close 996 assert(feqrel!(F)(0x1.Bp+84, 0x1.B8p+84) == 5); 997 assert(feqrel!(F)(0x1.8p+10, 0x1.Cp+10) == 2); 998 assert(feqrel!(F)(1.5 * (1 - F.epsilon), 1.0L) == 2); 999 assert(feqrel!(F)(1.5, 1.0) == 1); 1000 assert(feqrel!(F)(2 * (1 - F.epsilon), 1.0L) == 1); 1001 1002 // Factors of 2 1003 assert(feqrel(F.max, F.infinity) == 0); 1004 assert(feqrel!(F)(2 * (1 - F.epsilon), 1.0L) == 1); 1005 assert(feqrel!(F)(1.0, 2.0) == 0); 1006 assert(feqrel!(F)(4.0, 1.0) == 0); 1007 1008 // Extreme inequality 1009 assert(feqrel(F.nan, F.nan) == 0); 1010 assert(feqrel!(F)(0.0L, -F.nan) == 0); 1011 assert(feqrel(F.nan, F.infinity) == 0); 1012 assert(feqrel(F.infinity, -F.infinity) == 0); 1013 assert(feqrel(F.max, -F.max) == 0); 1014 1015 assert(feqrel(F.min_normal / 8, F.min_normal / 17) == 3); 1016 1017 const F Const = 2; 1018 immutable F Immutable = 2; 1019 auto Compiles = feqrel(Const, Immutable); 1020 } 1021 1022 assert(feqrel(7.1824L, 7.1824L) == real.mant_dig); 1023 1024 testFeqrel!(real)(); 1025 testFeqrel!(double)(); 1026 testFeqrel!(float)(); 1027 } 1028 1029 /** 1030 Computes whether a values is approximately equal to a reference value, 1031 admitting a maximum relative difference, and a maximum absolute difference. 1032 1033 Warning: 1034 This template is considered out-dated. It will be removed from 1035 Phobos in 2.106.0. Please use $(LREF isClose) instead. To achieve 1036 a similar behaviour to `approxEqual(a, b)` use 1037 `isClose(a, b, 1e-2, 1e-5)`. In case of comparing to 0.0, 1038 `isClose(a, b, 0.0, eps)` should be used, where `eps` 1039 represents the accepted deviation from 0.0." 1040 1041 Params: 1042 value = Value to compare. 1043 reference = Reference value. 1044 maxRelDiff = Maximum allowable difference relative to `reference`. 1045 Setting to 0.0 disables this check. Defaults to `1e-2`. 1046 maxAbsDiff = Maximum absolute difference. This is mainly usefull 1047 for comparing values to zero. Setting to 0.0 disables this check. 1048 Defaults to `1e-5`. 1049 1050 Returns: 1051 `true` if `value` is approximately equal to `reference` under 1052 either criterium. It is sufficient, when `value ` satisfies 1053 one of the two criteria. 1054 1055 If one item is a range, and the other is a single value, then 1056 the result is the logical and-ing of calling `approxEqual` on 1057 each element of the ranged item against the single item. If 1058 both items are ranges, then `approxEqual` returns `true` if 1059 and only if the ranges have the same number of elements and if 1060 `approxEqual` evaluates to `true` for each pair of elements. 1061 1062 See_Also: 1063 Use $(LREF feqrel) to get the number of equal bits in the mantissa. 1064 */ 1065 deprecated("approxEqual will be removed in 2.106.0. Please use isClose instead.") 1066 bool approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 1e-2, V maxAbsDiff = 1e-5) 1067 { 1068 import core.math : fabs; 1069 import std.range.primitives : empty, front, isInputRange, popFront; 1070 static if (isInputRange!T) 1071 { 1072 static if (isInputRange!U) 1073 { 1074 // Two ranges 1075 for (;; value.popFront(), reference.popFront()) 1076 { 1077 if (value.empty) return reference.empty; 1078 if (reference.empty) return value.empty; 1079 if (!approxEqual(value.front, reference.front, maxRelDiff, maxAbsDiff)) 1080 return false; 1081 } 1082 } 1083 else static if (isIntegral!U) 1084 { 1085 // convert reference to real 1086 return approxEqual(value, real(reference), maxRelDiff, maxAbsDiff); 1087 } 1088 else 1089 { 1090 // value is range, reference is number 1091 for (; !value.empty; value.popFront()) 1092 { 1093 if (!approxEqual(value.front, reference, maxRelDiff, maxAbsDiff)) 1094 return false; 1095 } 1096 return true; 1097 } 1098 } 1099 else 1100 { 1101 static if (isInputRange!U) 1102 { 1103 // value is number, reference is range 1104 for (; !reference.empty; reference.popFront()) 1105 { 1106 if (!approxEqual(value, reference.front, maxRelDiff, maxAbsDiff)) 1107 return false; 1108 } 1109 return true; 1110 } 1111 else static if (isIntegral!T || isIntegral!U) 1112 { 1113 // convert both value and reference to real 1114 return approxEqual(real(value), real(reference), maxRelDiff, maxAbsDiff); 1115 } 1116 else 1117 { 1118 // two numbers 1119 //static assert(is(T : real) && is(U : real)); 1120 if (reference == 0) 1121 { 1122 return fabs(value) <= maxAbsDiff; 1123 } 1124 static if (is(typeof(value.infinity)) && is(typeof(reference.infinity))) 1125 { 1126 if (value == value.infinity && reference == reference.infinity || 1127 value == -value.infinity && reference == -reference.infinity) return true; 1128 } 1129 return fabs((value - reference) / reference) <= maxRelDiff 1130 || maxAbsDiff != 0 && fabs(value - reference) <= maxAbsDiff; 1131 } 1132 } 1133 } 1134 1135 deprecated @safe pure nothrow unittest 1136 { 1137 assert(approxEqual(1.0, 1.0099)); 1138 assert(!approxEqual(1.0, 1.011)); 1139 assert(approxEqual(0.00001, 0.0)); 1140 assert(!approxEqual(0.00002, 0.0)); 1141 1142 assert(approxEqual(3.0, [3, 3.01, 2.99])); // several reference values is strange 1143 assert(approxEqual([3, 3.01, 2.99], 3.0)); // better 1144 1145 float[] arr1 = [ 1.0, 2.0, 3.0 ]; 1146 double[] arr2 = [ 1.001, 1.999, 3 ]; 1147 assert(approxEqual(arr1, arr2)); 1148 } 1149 1150 deprecated @safe pure nothrow unittest 1151 { 1152 // relative comparison depends on reference, make sure proper 1153 // side is used when comparing range to single value. Based on 1154 // https://issues.dlang.org/show_bug.cgi?id=15763 1155 auto a = [2e-3 - 1e-5]; 1156 auto b = 2e-3 + 1e-5; 1157 assert(a[0].approxEqual(b)); 1158 assert(!b.approxEqual(a[0])); 1159 assert(a.approxEqual(b)); 1160 assert(!b.approxEqual(a)); 1161 } 1162 1163 deprecated @safe pure nothrow @nogc unittest 1164 { 1165 assert(!approxEqual(0.0,1e-15,1e-9,0.0)); 1166 assert(approxEqual(0.0,1e-15,1e-9,1e-9)); 1167 assert(!approxEqual(1.0,3.0,0.0,1.0)); 1168 1169 assert(approxEqual(1.00000000099,1.0,1e-9,0.0)); 1170 assert(!approxEqual(1.0000000011,1.0,1e-9,0.0)); 1171 } 1172 1173 deprecated @safe pure nothrow @nogc unittest 1174 { 1175 // maybe unintuitive behavior 1176 assert(approxEqual(1000.0,1010.0)); 1177 assert(approxEqual(9_090_000_000.0,9_000_000_000.0)); 1178 assert(approxEqual(0.0,1e30,1.0)); 1179 assert(approxEqual(0.00001,1e-30)); 1180 assert(!approxEqual(-1e-30,1e-30,1e-2,0.0)); 1181 } 1182 1183 deprecated @safe pure nothrow @nogc unittest 1184 { 1185 int a = 10; 1186 assert(approxEqual(10, a)); 1187 1188 assert(!approxEqual(3, 0)); 1189 assert(approxEqual(3, 3)); 1190 assert(approxEqual(3.0, 3)); 1191 assert(approxEqual(3, 3.0)); 1192 1193 assert(approxEqual(0.0,0.0)); 1194 assert(approxEqual(-0.0,0.0)); 1195 assert(approxEqual(0.0f,0.0)); 1196 } 1197 1198 deprecated @safe pure nothrow @nogc unittest 1199 { 1200 real num = real.infinity; 1201 assert(num == real.infinity); 1202 assert(approxEqual(num, real.infinity)); 1203 num = -real.infinity; 1204 assert(num == -real.infinity); 1205 assert(approxEqual(num, -real.infinity)); 1206 1207 assert(!approxEqual(1,real.nan)); 1208 assert(!approxEqual(real.nan,real.max)); 1209 assert(!approxEqual(real.nan,real.nan)); 1210 } 1211 1212 deprecated @safe pure nothrow unittest 1213 { 1214 assert(!approxEqual([1.0,2.0,3.0],[1.0,2.0])); 1215 assert(!approxEqual([1.0,2.0],[1.0,2.0,3.0])); 1216 1217 assert(approxEqual!(real[],real[])([],[])); 1218 assert(approxEqual(cast(real[])[],cast(real[])[])); 1219 } 1220 1221 1222 /** 1223 Computes whether two values are approximately equal, admitting a maximum 1224 relative difference, and a maximum absolute difference. 1225 1226 Params: 1227 lhs = First item to compare. 1228 rhs = Second item to compare. 1229 maxRelDiff = Maximum allowable relative difference. 1230 Setting to 0.0 disables this check. Default depends on the type of 1231 `lhs` and `rhs`: It is approximately half the number of decimal digits of 1232 precision of the smaller type. 1233 maxAbsDiff = Maximum absolute difference. This is mainly usefull 1234 for comparing values to zero. Setting to 0.0 disables this check. 1235 Defaults to `0.0`. 1236 1237 Returns: 1238 `true` if the two items are approximately equal under either criterium. 1239 It is sufficient, when `value ` satisfies one of the two criteria. 1240 1241 If one item is a range, and the other is a single value, then 1242 the result is the logical and-ing of calling `isClose` on 1243 each element of the ranged item against the single item. If 1244 both items are ranges, then `isClose` returns `true` if 1245 and only if the ranges have the same number of elements and if 1246 `isClose` evaluates to `true` for each pair of elements. 1247 1248 See_Also: 1249 Use $(LREF feqrel) to get the number of equal bits in the mantissa. 1250 */ 1251 bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType!U)) 1252 (T lhs, U rhs, V maxRelDiff = CommonDefaultFor!(T,U), V maxAbsDiff = 0.0) 1253 { 1254 import std.range.primitives : empty, front, isInputRange, popFront; 1255 import std.complex : Complex; 1256 static if (isInputRange!T) 1257 { 1258 static if (isInputRange!U) 1259 { 1260 // Two ranges 1261 for (;; lhs.popFront(), rhs.popFront()) 1262 { 1263 if (lhs.empty) return rhs.empty; 1264 if (rhs.empty) return lhs.empty; 1265 if (!isClose(lhs.front, rhs.front, maxRelDiff, maxAbsDiff)) 1266 return false; 1267 } 1268 } 1269 else 1270 { 1271 // lhs is range, rhs is number 1272 for (; !lhs.empty; lhs.popFront()) 1273 { 1274 if (!isClose(lhs.front, rhs, maxRelDiff, maxAbsDiff)) 1275 return false; 1276 } 1277 return true; 1278 } 1279 } 1280 else static if (isInputRange!U) 1281 { 1282 // lhs is number, rhs is range 1283 for (; !rhs.empty; rhs.popFront()) 1284 { 1285 if (!isClose(lhs, rhs.front, maxRelDiff, maxAbsDiff)) 1286 return false; 1287 } 1288 return true; 1289 } 1290 else static if (is(T TE == Complex!TE)) 1291 { 1292 static if (is(U UE == Complex!UE)) 1293 { 1294 // Two complex numbers 1295 return isClose(lhs.re, rhs.re, maxRelDiff, maxAbsDiff) 1296 && isClose(lhs.im, rhs.im, maxRelDiff, maxAbsDiff); 1297 } 1298 else 1299 { 1300 // lhs is complex, rhs is number 1301 return isClose(lhs.re, rhs, maxRelDiff, maxAbsDiff) 1302 && isClose(lhs.im, 0.0, maxRelDiff, maxAbsDiff); 1303 } 1304 } 1305 else static if (is(U UE == Complex!UE)) 1306 { 1307 // lhs is number, rhs is complex 1308 return isClose(lhs, rhs.re, maxRelDiff, maxAbsDiff) 1309 && isClose(0.0, rhs.im, maxRelDiff, maxAbsDiff); 1310 } 1311 else 1312 { 1313 // two numbers 1314 if (lhs == rhs) return true; 1315 1316 static if (is(typeof(lhs.infinity))) 1317 if (lhs == lhs.infinity || lhs == -lhs.infinity) 1318 return false; 1319 static if (is(typeof(rhs.infinity))) 1320 if (rhs == rhs.infinity || rhs == -rhs.infinity) 1321 return false; 1322 1323 import std.math.algebraic : abs; 1324 1325 auto diff = abs(lhs - rhs); 1326 1327 return diff <= maxRelDiff*abs(lhs) 1328 || diff <= maxRelDiff*abs(rhs) 1329 || diff <= maxAbsDiff; 1330 } 1331 } 1332 1333 /// 1334 @safe pure nothrow @nogc unittest 1335 { 1336 assert(isClose(1.0,0.999_999_999)); 1337 assert(isClose(0.001, 0.000_999_999_999)); 1338 assert(isClose(1_000_000_000.0,999_999_999.0)); 1339 1340 assert(isClose(17.123_456_789, 17.123_456_78)); 1341 assert(!isClose(17.123_456_789, 17.123_45)); 1342 1343 // use explicit 3rd parameter for less (or more) accuracy 1344 assert(isClose(17.123_456_789, 17.123_45, 1e-6)); 1345 assert(!isClose(17.123_456_789, 17.123_45, 1e-7)); 1346 1347 // use 4th parameter when comparing close to zero 1348 assert(!isClose(1e-100, 0.0)); 1349 assert(isClose(1e-100, 0.0, 0.0, 1e-90)); 1350 assert(!isClose(1e-10, -1e-10)); 1351 assert(isClose(1e-10, -1e-10, 0.0, 1e-9)); 1352 assert(!isClose(1e-300, 1e-298)); 1353 assert(isClose(1e-300, 1e-298, 0.0, 1e-200)); 1354 1355 // different default limits for different floating point types 1356 assert(isClose(1.0f, 0.999_99f)); 1357 assert(!isClose(1.0, 0.999_99)); 1358 static if (real.sizeof > double.sizeof) 1359 assert(!isClose(1.0L, 0.999_999_999L)); 1360 } 1361 1362 /// 1363 @safe pure nothrow unittest 1364 { 1365 assert(isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001, 3.0])); 1366 assert(!isClose([1.0, 2.0], [0.999_999_999, 2.000_000_001, 3.0])); 1367 assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001])); 1368 1369 assert(isClose([2.0, 1.999_999_999, 2.000_000_001], 2.0)); 1370 assert(isClose(2.0, [2.0, 1.999_999_999, 2.000_000_001])); 1371 } 1372 1373 @safe pure nothrow unittest 1374 { 1375 assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 3.0, 3.0])); 1376 assert(!isClose([2.0, 1.999_999, 2.000_000_001], 2.0)); 1377 assert(!isClose(2.0, [2.0, 1.999_999_999, 2.000_000_999])); 1378 } 1379 1380 @safe pure nothrow @nogc unittest 1381 { 1382 immutable a = 1.00001f; 1383 const b = 1.000019; 1384 assert(isClose(a,b)); 1385 1386 assert(isClose(1.00001f,1.000019f)); 1387 assert(isClose(1.00001f,1.000019)); 1388 assert(isClose(1.00001,1.000019f)); 1389 assert(!isClose(1.00001,1.000019)); 1390 1391 real a1 = 1e-300L; 1392 real a2 = a1.nextUp; 1393 assert(isClose(a1,a2)); 1394 } 1395 1396 @safe pure nothrow unittest 1397 { 1398 float[] arr1 = [ 1.0, 2.0, 3.0 ]; 1399 double[] arr2 = [ 1.00001, 1.99999, 3 ]; 1400 assert(isClose(arr1, arr2)); 1401 } 1402 1403 @safe pure nothrow @nogc unittest 1404 { 1405 assert(!isClose(1000.0,1010.0)); 1406 assert(!isClose(9_090_000_000.0,9_000_000_000.0)); 1407 assert(isClose(0.0,1e30,1.0)); 1408 assert(!isClose(0.00001,1e-30)); 1409 assert(!isClose(-1e-30,1e-30,1e-2,0.0)); 1410 } 1411 1412 @safe pure nothrow @nogc unittest 1413 { 1414 assert(!isClose(3, 0)); 1415 assert(isClose(3, 3)); 1416 assert(isClose(3.0, 3)); 1417 assert(isClose(3, 3.0)); 1418 1419 assert(isClose(0.0,0.0)); 1420 assert(isClose(-0.0,0.0)); 1421 assert(isClose(0.0f,0.0)); 1422 } 1423 1424 @safe pure nothrow @nogc unittest 1425 { 1426 real num = real.infinity; 1427 assert(num == real.infinity); 1428 assert(isClose(num, real.infinity)); 1429 num = -real.infinity; 1430 assert(num == -real.infinity); 1431 assert(isClose(num, -real.infinity)); 1432 1433 assert(!isClose(1,real.nan)); 1434 assert(!isClose(real.nan,real.max)); 1435 assert(!isClose(real.nan,real.nan)); 1436 1437 assert(!isClose(-double.infinity, 1)); 1438 } 1439 1440 @safe pure nothrow @nogc unittest 1441 { 1442 assert(isClose!(real[],real[],real)([],[])); 1443 assert(isClose(cast(real[])[],cast(real[])[])); 1444 } 1445 1446 @safe pure nothrow @nogc unittest 1447 { 1448 import std.conv : to; 1449 1450 float f = 31.79f; 1451 double d = 31.79; 1452 double f2d = f.to!double; 1453 1454 assert(isClose(f,f2d)); 1455 assert(!isClose(d,f2d)); 1456 } 1457 1458 @safe pure nothrow @nogc unittest 1459 { 1460 import std.conv : to; 1461 1462 double d = 31.79; 1463 float f = d.to!float; 1464 double f2d = f.to!double; 1465 1466 assert(isClose(f,f2d)); 1467 assert(!isClose(d,f2d)); 1468 assert(isClose(d,f2d,1e-4)); 1469 } 1470 1471 package(std.math) template CommonDefaultFor(T,U) 1472 { 1473 import std.algorithm.comparison : min; 1474 1475 alias baseT = FloatingPointBaseType!T; 1476 alias baseU = FloatingPointBaseType!U; 1477 1478 enum CommonType!(baseT, baseU) CommonDefaultFor = 10.0L ^^ -((min(baseT.dig, baseU.dig) + 1) / 2 + 1); 1479 } 1480 1481 private template FloatingPointBaseType(T) 1482 { 1483 import std.range.primitives : ElementType; 1484 static if (isFloatingPoint!T) 1485 { 1486 alias FloatingPointBaseType = Unqual!T; 1487 } 1488 else static if (isFloatingPoint!(ElementType!(Unqual!T))) 1489 { 1490 alias FloatingPointBaseType = Unqual!(ElementType!(Unqual!T)); 1491 } 1492 else 1493 { 1494 alias FloatingPointBaseType = real; 1495 } 1496 } 1497 1498 /*********************************** 1499 * Defines a total order on all floating-point numbers. 1500 * 1501 * The order is defined as follows: 1502 * $(UL 1503 * $(LI All numbers in [-$(INFIN), +$(INFIN)] are ordered 1504 * the same way as by built-in comparison, with the exception of 1505 * -0.0, which is less than +0.0;) 1506 * $(LI If the sign bit is set (that is, it's 'negative'), $(NAN) is less 1507 * than any number; if the sign bit is not set (it is 'positive'), 1508 * $(NAN) is greater than any number;) 1509 * $(LI $(NAN)s of the same sign are ordered by the payload ('negative' 1510 * ones - in reverse order).) 1511 * ) 1512 * 1513 * Returns: 1514 * negative value if `x` precedes `y` in the order specified above; 1515 * 0 if `x` and `y` are identical, and positive value otherwise. 1516 * 1517 * See_Also: 1518 * $(MYREF isIdentical) 1519 * Standards: Conforms to IEEE 754-2008 1520 */ 1521 int cmp(T)(const(T) x, const(T) y) @nogc @trusted pure nothrow 1522 if (isFloatingPoint!T) 1523 { 1524 import std.math : floatTraits, RealFormat; 1525 1526 alias F = floatTraits!T; 1527 1528 static if (F.realFormat == RealFormat.ieeeSingle 1529 || F.realFormat == RealFormat.ieeeDouble) 1530 { 1531 static if (T.sizeof == 4) 1532 alias UInt = uint; 1533 else 1534 alias UInt = ulong; 1535 1536 union Repainter 1537 { 1538 T number; 1539 UInt bits; 1540 } 1541 1542 enum msb = ~(UInt.max >>> 1); 1543 1544 import std.typecons : Tuple; 1545 Tuple!(Repainter, Repainter) vars = void; 1546 vars[0].number = x; 1547 vars[1].number = y; 1548 1549 foreach (ref var; vars) 1550 if (var.bits & msb) 1551 var.bits = ~var.bits; 1552 else 1553 var.bits |= msb; 1554 1555 if (vars[0].bits < vars[1].bits) 1556 return -1; 1557 else if (vars[0].bits > vars[1].bits) 1558 return 1; 1559 else 1560 return 0; 1561 } 1562 else static if (F.realFormat == RealFormat.ieeeExtended53 1563 || F.realFormat == RealFormat.ieeeExtended 1564 || F.realFormat == RealFormat.ieeeQuadruple) 1565 { 1566 static if (F.realFormat == RealFormat.ieeeQuadruple) 1567 alias RemT = ulong; 1568 else 1569 alias RemT = ushort; 1570 1571 struct Bits 1572 { 1573 ulong bulk; 1574 RemT rem; 1575 } 1576 1577 union Repainter 1578 { 1579 T number; 1580 Bits bits; 1581 ubyte[T.sizeof] bytes; 1582 } 1583 1584 import std.typecons : Tuple; 1585 Tuple!(Repainter, Repainter) vars = void; 1586 vars[0].number = x; 1587 vars[1].number = y; 1588 1589 foreach (ref var; vars) 1590 if (var.bytes[F.SIGNPOS_BYTE] & 0x80) 1591 { 1592 var.bits.bulk = ~var.bits.bulk; 1593 var.bits.rem = cast(typeof(var.bits.rem))(-1 - var.bits.rem); // ~var.bits.rem 1594 } 1595 else 1596 { 1597 var.bytes[F.SIGNPOS_BYTE] |= 0x80; 1598 } 1599 1600 version (LittleEndian) 1601 { 1602 if (vars[0].bits.rem < vars[1].bits.rem) 1603 return -1; 1604 else if (vars[0].bits.rem > vars[1].bits.rem) 1605 return 1; 1606 else if (vars[0].bits.bulk < vars[1].bits.bulk) 1607 return -1; 1608 else if (vars[0].bits.bulk > vars[1].bits.bulk) 1609 return 1; 1610 else 1611 return 0; 1612 } 1613 else 1614 { 1615 if (vars[0].bits.bulk < vars[1].bits.bulk) 1616 return -1; 1617 else if (vars[0].bits.bulk > vars[1].bits.bulk) 1618 return 1; 1619 else if (vars[0].bits.rem < vars[1].bits.rem) 1620 return -1; 1621 else if (vars[0].bits.rem > vars[1].bits.rem) 1622 return 1; 1623 else 1624 return 0; 1625 } 1626 } 1627 else 1628 { 1629 // IBM Extended doubledouble does not follow the general 1630 // sign-exponent-significand layout, so has to be handled generically 1631 1632 import std.math.traits : signbit, isNaN; 1633 1634 const int xSign = signbit(x), 1635 ySign = signbit(y); 1636 1637 if (xSign == 1 && ySign == 1) 1638 return cmp(-y, -x); 1639 else if (xSign == 1) 1640 return -1; 1641 else if (ySign == 1) 1642 return 1; 1643 else if (x < y) 1644 return -1; 1645 else if (x == y) 1646 return 0; 1647 else if (x > y) 1648 return 1; 1649 else if (isNaN(x) && !isNaN(y)) 1650 return 1; 1651 else if (isNaN(y) && !isNaN(x)) 1652 return -1; 1653 else if (getNaNPayload(x) < getNaNPayload(y)) 1654 return -1; 1655 else if (getNaNPayload(x) > getNaNPayload(y)) 1656 return 1; 1657 else 1658 return 0; 1659 } 1660 } 1661 1662 /// Most numbers are ordered naturally. 1663 @safe unittest 1664 { 1665 assert(cmp(-double.infinity, -double.max) < 0); 1666 assert(cmp(-double.max, -100.0) < 0); 1667 assert(cmp(-100.0, -0.5) < 0); 1668 assert(cmp(-0.5, 0.0) < 0); 1669 assert(cmp(0.0, 0.5) < 0); 1670 assert(cmp(0.5, 100.0) < 0); 1671 assert(cmp(100.0, double.max) < 0); 1672 assert(cmp(double.max, double.infinity) < 0); 1673 1674 assert(cmp(1.0, 1.0) == 0); 1675 } 1676 1677 /// Positive and negative zeroes are distinct. 1678 @safe unittest 1679 { 1680 assert(cmp(-0.0, +0.0) < 0); 1681 assert(cmp(+0.0, -0.0) > 0); 1682 } 1683 1684 /// Depending on the sign, $(NAN)s go to either end of the spectrum. 1685 @safe unittest 1686 { 1687 assert(cmp(-double.nan, -double.infinity) < 0); 1688 assert(cmp(double.infinity, double.nan) < 0); 1689 assert(cmp(-double.nan, double.nan) < 0); 1690 } 1691 1692 version (LDC) version (Win32) version = LDC_Win32; 1693 1694 /// $(NAN)s of the same sign are ordered by the payload. 1695 @safe unittest 1696 { 1697 assert(cmp(NaN(10), NaN(20)) < 0); 1698 version (LDC_Win32) 1699 { 1700 // somehow fails with LLVM 8.0 + disabled optimizations 1701 } 1702 else 1703 { 1704 assert(cmp(-NaN(20), -NaN(10)) < 0); 1705 } 1706 } 1707 1708 @safe unittest 1709 { 1710 import std.meta : AliasSeq; 1711 static foreach (T; AliasSeq!(float, double, real)) 1712 {{ 1713 T[] values = [-cast(T) NaN(20), -cast(T) NaN(10), -T.nan, -T.infinity, 1714 -T.max, -T.max / 2, T(-16.0), T(-1.0).nextDown, 1715 T(-1.0), T(-1.0).nextUp, 1716 T(-0.5), -T.min_normal, (-T.min_normal).nextUp, 1717 -2 * T.min_normal * T.epsilon, 1718 -T.min_normal * T.epsilon, 1719 T(-0.0), T(0.0), 1720 T.min_normal * T.epsilon, 1721 2 * T.min_normal * T.epsilon, 1722 T.min_normal.nextDown, T.min_normal, T(0.5), 1723 T(1.0).nextDown, T(1.0), 1724 T(1.0).nextUp, T(16.0), T.max / 2, T.max, 1725 T.infinity, T.nan, cast(T) NaN(10), cast(T) NaN(20)]; 1726 1727 foreach (i, x; values) 1728 { 1729 foreach (y; values[i + 1 .. $]) 1730 { 1731 version (LDC_Win32) 1732 { 1733 // LLVM 8.0 + disabled optimizations: 1734 // failures for 64-bit negated NaNs with custom payload 1735 static if (T.sizeof == 8) 1736 if (i < 2) 1737 continue; 1738 } 1739 assert(cmp(x, y) < 0); 1740 assert(cmp(y, x) > 0); 1741 } 1742 assert(cmp(x, x) == 0); 1743 } 1744 }} 1745 } 1746 1747 package(std): // not yet public 1748 1749 struct FloatingPointBitpattern(T) 1750 if (isFloatingPoint!T) 1751 { 1752 static if (T.mant_dig <= 64) 1753 { 1754 ulong mantissa; 1755 } 1756 else 1757 { 1758 ulong mantissa_lsb; 1759 ulong mantissa_msb; 1760 } 1761 1762 int exponent; 1763 bool negative; 1764 } 1765 1766 FloatingPointBitpattern!T extractBitpattern(T)(const(T) value) @trusted 1767 if (isFloatingPoint!T) 1768 { 1769 import std.math : floatTraits, RealFormat; 1770 1771 T val = value; 1772 FloatingPointBitpattern!T ret; 1773 1774 alias F = floatTraits!T; 1775 static if (F.realFormat == RealFormat.ieeeExtended) 1776 { 1777 if (__ctfe) 1778 { 1779 import core.math : fabs, ldexp; 1780 import std.math.rounding : floor; 1781 import std.math.traits : isInfinity, isNaN, signbit; 1782 import std.math.exponential : log2; 1783 1784 if (isNaN(val) || isInfinity(val)) 1785 ret.exponent = 32767; 1786 else if (fabs(val) < real.min_normal) 1787 ret.exponent = 0; 1788 else if (fabs(val) >= nextUp(real.max / 2)) 1789 ret.exponent = 32766; 1790 else 1791 ret.exponent = cast(int) (val.fabs.log2.floor() + 16383); 1792 1793 if (ret.exponent == 32767) 1794 { 1795 // NaN or infinity 1796 ret.mantissa = isNaN(val) ? ((1L << 63) - 1) : 0; 1797 } 1798 else 1799 { 1800 auto delta = 16382 + 64 // bias + bits of ulong 1801 - (ret.exponent == 0 ? 1 : ret.exponent); // -1 in case of subnormals 1802 val = ldexp(val, delta); // val *= 2^^delta 1803 1804 ulong tmp = cast(ulong) fabs(val); 1805 if (ret.exponent != 32767 && ret.exponent > 0 && tmp <= ulong.max / 2) 1806 { 1807 // correction, due to log2(val) being rounded up: 1808 ret.exponent--; 1809 val *= 2; 1810 tmp = cast(ulong) fabs(val); 1811 } 1812 1813 ret.mantissa = tmp & long.max; 1814 } 1815 1816 ret.negative = (signbit(val) == 1); 1817 } 1818 else 1819 { 1820 ushort* vs = cast(ushort*) &val; 1821 ret.mantissa = (cast(ulong*) vs)[0] & long.max; 1822 ret.exponent = vs[4] & short.max; 1823 ret.negative = (vs[4] >> 15) & 1; 1824 } 1825 } 1826 else 1827 { 1828 static if (F.realFormat == RealFormat.ieeeSingle) 1829 { 1830 ulong ival = *cast(uint*) &val; 1831 } 1832 else static if (F.realFormat == RealFormat.ieeeDouble) 1833 { 1834 ulong ival = *cast(ulong*) &val; 1835 } 1836 else 1837 { 1838 static assert(false, "Floating point type `" ~ F.realFormat ~ "` not supported."); 1839 } 1840 1841 import std.math.exponential : log2; 1842 enum log2_max_exp = cast(int) log2(T(T.max_exp)); 1843 1844 ret.mantissa = ival & ((1L << (T.mant_dig - 1)) - 1); 1845 ret.exponent = (ival >> (T.mant_dig - 1)) & ((1L << (log2_max_exp + 1)) - 1); 1846 ret.negative = (ival >> (T.mant_dig + log2_max_exp)) & 1; 1847 } 1848 1849 // add leading 1 for normalized values and correct exponent for denormalied values 1850 if (ret.exponent != 0 && ret.exponent != 2 * T.max_exp - 1) 1851 ret.mantissa |= 1L << (T.mant_dig - 1); 1852 else if (ret.exponent == 0) 1853 ret.exponent = 1; 1854 1855 ret.exponent -= T.max_exp - 1; 1856 1857 return ret; 1858 } 1859 1860 @safe pure unittest 1861 { 1862 float f = 1.0f; 1863 auto bp = extractBitpattern(f); 1864 assert(bp.mantissa == 0x80_0000); 1865 assert(bp.exponent == 0); 1866 assert(bp.negative == false); 1867 1868 f = float.max; 1869 bp = extractBitpattern(f); 1870 assert(bp.mantissa == 0xff_ffff); 1871 assert(bp.exponent == 127); 1872 assert(bp.negative == false); 1873 1874 f = -1.5432e-17f; 1875 bp = extractBitpattern(f); 1876 assert(bp.mantissa == 0x8e_55c8); 1877 assert(bp.exponent == -56); 1878 assert(bp.negative == true); 1879 1880 // using double literal due to https://issues.dlang.org/show_bug.cgi?id=20361 1881 f = 2.3822073893521890206e-44; 1882 bp = extractBitpattern(f); 1883 assert(bp.mantissa == 0x00_0011); 1884 assert(bp.exponent == -126); 1885 assert(bp.negative == false); 1886 1887 f = -float.infinity; 1888 bp = extractBitpattern(f); 1889 assert(bp.mantissa == 0); 1890 assert(bp.exponent == 128); 1891 assert(bp.negative == true); 1892 1893 f = float.nan; 1894 bp = extractBitpattern(f); 1895 assert(bp.mantissa != 0); // we don't guarantee payloads 1896 assert(bp.exponent == 128); 1897 assert(bp.negative == false); 1898 } 1899 1900 @safe pure unittest 1901 { 1902 double d = 1.0; 1903 auto bp = extractBitpattern(d); 1904 assert(bp.mantissa == 0x10_0000_0000_0000L); 1905 assert(bp.exponent == 0); 1906 assert(bp.negative == false); 1907 1908 d = double.max; 1909 bp = extractBitpattern(d); 1910 assert(bp.mantissa == 0x1f_ffff_ffff_ffffL); 1911 assert(bp.exponent == 1023); 1912 assert(bp.negative == false); 1913 1914 d = -1.5432e-222; 1915 bp = extractBitpattern(d); 1916 assert(bp.mantissa == 0x11_d9b6_a401_3b04L); 1917 assert(bp.exponent == -737); 1918 assert(bp.negative == true); 1919 1920 d = 0.0.nextUp; 1921 bp = extractBitpattern(d); 1922 assert(bp.mantissa == 0x00_0000_0000_0001L); 1923 assert(bp.exponent == -1022); 1924 assert(bp.negative == false); 1925 1926 d = -double.infinity; 1927 bp = extractBitpattern(d); 1928 assert(bp.mantissa == 0); 1929 assert(bp.exponent == 1024); 1930 assert(bp.negative == true); 1931 1932 d = double.nan; 1933 bp = extractBitpattern(d); 1934 assert(bp.mantissa != 0); // we don't guarantee payloads 1935 assert(bp.exponent == 1024); 1936 assert(bp.negative == false); 1937 } 1938 1939 @safe pure unittest 1940 { 1941 import std.math : floatTraits, RealFormat; 1942 1943 alias F = floatTraits!real; 1944 static if (F.realFormat == RealFormat.ieeeExtended) 1945 { 1946 real r = 1.0L; 1947 auto bp = extractBitpattern(r); 1948 assert(bp.mantissa == 0x8000_0000_0000_0000L); 1949 assert(bp.exponent == 0); 1950 assert(bp.negative == false); 1951 1952 r = real.max; 1953 bp = extractBitpattern(r); 1954 assert(bp.mantissa == 0xffff_ffff_ffff_ffffL); 1955 assert(bp.exponent == 16383); 1956 assert(bp.negative == false); 1957 1958 r = -1.5432e-3333L; 1959 bp = extractBitpattern(r); 1960 assert(bp.mantissa == 0xc768_a2c7_a616_cc22L); 1961 assert(bp.exponent == -11072); 1962 assert(bp.negative == true); 1963 1964 r = 0.0L.nextUp; 1965 bp = extractBitpattern(r); 1966 assert(bp.mantissa == 0x0000_0000_0000_0001L); 1967 assert(bp.exponent == -16382); 1968 assert(bp.negative == false); 1969 1970 r = -float.infinity; 1971 bp = extractBitpattern(r); 1972 assert(bp.mantissa == 0); 1973 assert(bp.exponent == 16384); 1974 assert(bp.negative == true); 1975 1976 r = float.nan; 1977 bp = extractBitpattern(r); 1978 assert(bp.mantissa != 0); // we don't guarantee payloads 1979 assert(bp.exponent == 16384); 1980 assert(bp.negative == false); 1981 1982 r = nextDown(0x1p+16383L); 1983 bp = extractBitpattern(r); 1984 assert(bp.mantissa == 0xffff_ffff_ffff_ffffL); 1985 assert(bp.exponent == 16382); 1986 assert(bp.negative == false); 1987 } 1988 } 1989 1990 @safe pure unittest 1991 { 1992 import std.math : floatTraits, RealFormat; 1993 import std.math.exponential : log2; 1994 1995 alias F = floatTraits!real; 1996 1997 // log2 is broken for x87-reals on some computers in CTFE 1998 // the following test excludes these computers from the test 1999 // (https://issues.dlang.org/show_bug.cgi?id=21757) 2000 enum test = cast(int) log2(3.05e2312L); 2001 static if (F.realFormat == RealFormat.ieeeExtended && test == 7681) 2002 { 2003 enum r1 = 1.0L; 2004 enum bp1 = extractBitpattern(r1); 2005 static assert(bp1.mantissa == 0x8000_0000_0000_0000L); 2006 static assert(bp1.exponent == 0); 2007 static assert(bp1.negative == false); 2008 2009 enum r2 = real.max; 2010 enum bp2 = extractBitpattern(r2); 2011 static assert(bp2.mantissa == 0xffff_ffff_ffff_ffffL); 2012 static assert(bp2.exponent == 16383); 2013 static assert(bp2.negative == false); 2014 2015 enum r3 = -1.5432e-3333L; 2016 enum bp3 = extractBitpattern(r3); 2017 static assert(bp3.mantissa == 0xc768_a2c7_a616_cc22L); 2018 static assert(bp3.exponent == -11072); 2019 static assert(bp3.negative == true); 2020 2021 enum r4 = 0.0L.nextUp; 2022 enum bp4 = extractBitpattern(r4); 2023 static assert(bp4.mantissa == 0x0000_0000_0000_0001L); 2024 static assert(bp4.exponent == -16382); 2025 static assert(bp4.negative == false); 2026 2027 enum r5 = -real.infinity; 2028 enum bp5 = extractBitpattern(r5); 2029 static assert(bp5.mantissa == 0); 2030 static assert(bp5.exponent == 16384); 2031 static assert(bp5.negative == true); 2032 2033 enum r6 = real.nan; 2034 enum bp6 = extractBitpattern(r6); 2035 static assert(bp6.mantissa != 0); // we don't guarantee payloads 2036 static assert(bp6.exponent == 16384); 2037 static assert(bp6.negative == false); 2038 2039 enum r7 = nextDown(0x1p+16383L); 2040 enum bp7 = extractBitpattern(r7); 2041 static assert(bp7.mantissa == 0xffff_ffff_ffff_ffffL); 2042 static assert(bp7.exponent == 16382); 2043 static assert(bp7.negative == false); 2044 } 2045 }