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