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