1 // Written in the D programming language.
2
3 /**
4 * Contains the elementary mathematical functions (powers, roots,
5 * and trigonometric functions), and low-level floating-point operations.
6 * Mathematical special functions are available in $(D std.mathspecial).
7 *
8 $(SCRIPT inhibitQuickIndex = 1;)
9
10 $(DIVC quickindex,
11 $(BOOKTABLE ,
12 $(TR $(TH Category) $(TH Members) )
13 $(TR $(TDNW Constants) $(TD
14 $(MYREF E) $(MYREF PI) $(MYREF PI_2) $(MYREF PI_4) $(MYREF M_1_PI)
15 $(MYREF M_2_PI) $(MYREF M_2_SQRTPI) $(MYREF LN10) $(MYREF LN2)
16 $(MYREF LOG2) $(MYREF LOG2E) $(MYREF LOG2T) $(MYREF LOG10E)
17 $(MYREF SQRT2) $(MYREF SQRT1_2)
18 ))
19 $(TR $(TDNW Classics) $(TD
20 $(MYREF abs) $(MYREF fabs) $(MYREF sqrt) $(MYREF cbrt) $(MYREF hypot)
21 $(MYREF poly) $(MYREF nextPow2) $(MYREF truncPow2)
22 ))
23 $(TR $(TDNW Trigonometry) $(TD
24 $(MYREF sin) $(MYREF cos) $(MYREF tan) $(MYREF asin) $(MYREF acos)
25 $(MYREF atan) $(MYREF atan2) $(MYREF sinh) $(MYREF cosh) $(MYREF tanh)
26 $(MYREF asinh) $(MYREF acosh) $(MYREF atanh) $(MYREF expi)
27 ))
28 $(TR $(TDNW Rounding) $(TD
29 $(MYREF ceil) $(MYREF floor) $(MYREF round) $(MYREF lround)
30 $(MYREF trunc) $(MYREF rint) $(MYREF lrint) $(MYREF nearbyint)
31 $(MYREF rndtol) $(MYREF quantize)
32 ))
33 $(TR $(TDNW Exponentiation & Logarithms) $(TD
34 $(MYREF pow) $(MYREF exp) $(MYREF exp2) $(MYREF expm1) $(MYREF ldexp)
35 $(MYREF frexp) $(MYREF log) $(MYREF log2) $(MYREF log10) $(MYREF logb)
36 $(MYREF ilogb) $(MYREF log1p) $(MYREF scalbn)
37 ))
38 $(TR $(TDNW Modulus) $(TD
39 $(MYREF fmod) $(MYREF modf) $(MYREF remainder)
40 ))
41 $(TR $(TDNW Floating-point operations) $(TD
42 $(MYREF approxEqual) $(MYREF feqrel) $(MYREF fdim) $(MYREF fmax)
43 $(MYREF fmin) $(MYREF fma) $(MYREF nextDown) $(MYREF nextUp)
44 $(MYREF nextafter) $(MYREF NaN) $(MYREF getNaNPayload)
45 $(MYREF cmp)
46 ))
47 $(TR $(TDNW Introspection) $(TD
48 $(MYREF isFinite) $(MYREF isIdentical) $(MYREF isInfinity) $(MYREF isNaN)
49 $(MYREF isNormal) $(MYREF isSubnormal) $(MYREF signbit) $(MYREF sgn)
50 $(MYREF copysign) $(MYREF isPowerOf2)
51 ))
52 $(TR $(TDNW Complex Numbers) $(TD
53 $(MYREF abs) $(MYREF conj) $(MYREF sin) $(MYREF cos) $(MYREF expi)
54 ))
55 $(TR $(TDNW Hardware Control) $(TD
56 $(MYREF IeeeFlags) $(MYREF FloatingPointControl)
57 ))
58 )
59 )
60
61 * The functionality closely follows the IEEE754-2008 standard for
62 * floating-point arithmetic, including the use of camelCase names rather
63 * than C99-style lower case names. All of these functions behave correctly
64 * when presented with an infinity or NaN.
65 *
66 * The following IEEE 'real' formats are currently supported:
67 * $(UL
68 * $(LI 64 bit Big-endian 'double' (eg PowerPC))
69 * $(LI 128 bit Big-endian 'quadruple' (eg SPARC))
70 * $(LI 64 bit Little-endian 'double' (eg x86-SSE2))
71 * $(LI 80 bit Little-endian, with implied bit 'real80' (eg x87, Itanium))
72 * $(LI 128 bit Little-endian 'quadruple' (not implemented on any known processor!))
73 * $(LI Non-IEEE 128 bit Big-endian 'doubledouble' (eg PowerPC) has partial support)
74 * )
75 * Unlike C, there is no global 'errno' variable. Consequently, almost all of
76 * these functions are pure nothrow.
77 *
78 * Status:
79 * The semantics and names of feqrel and approxEqual will be revised.
80 *
81 * Macros:
82 * TABLE_SV = <table border="1" cellpadding="4" cellspacing="0">
83 * <caption>Special Values</caption>
84 * $0</table>
85 * SVH = $(TR $(TH $1) $(TH $2))
86 * SV = $(TR $(TD $1) $(TD $2))
87 * TH3 = $(TR $(TH $1) $(TH $2) $(TH $3))
88 * TD3 = $(TR $(TD $1) $(TD $2) $(TD $3))
89 * TABLE_DOMRG = <table border="1" cellpadding="4" cellspacing="0">
90 * $(SVH Domain X, Range Y)
91 $(SV $1, $2)
92 * </table>
93 * DOMAIN=$1
94 * RANGE=$1
95
96 * NAN = $(RED NAN)
97 * SUP = <span style="vertical-align:super;font-size:smaller">$0</span>
98 * GAMMA = Γ
99 * THETA = θ
100 * INTEGRAL = ∫
101 * INTEGRATE = $(BIG ∫<sub>$(SMALL $1)</sub><sup>$2</sup>)
102 * POWER = $1<sup>$2</sup>
103 * SUB = $1<sub>$2</sub>
104 * BIGSUM = $(BIG Σ <sup>$2</sup><sub>$(SMALL $1)</sub>)
105 * CHOOSE = $(BIG () <sup>$(SMALL $1)</sup><sub>$(SMALL $2)</sub> $(BIG ))
106 * PLUSMN = ±
107 * INFIN = ∞
108 * PLUSMNINF = ±∞
109 * PI = π
110 * LT = <
111 * GT = >
112 * SQRT = √
113 * HALF = ½
114 *
115 * Copyright: Copyright Digital Mars 2000 - 2011.
116 * D implementations of tan, atan, atan2, exp, expm1, exp2, log, log10, log1p,
117 * log2, floor, ceil and lrint functions are based on the CEPHES math library,
118 * which is Copyright (C) 2001 Stephen L. Moshier $(LT)steve@moshier.net$(GT)
119 * and are incorporated herein by permission of the author. The author
120 * reserves the right to distribute this material elsewhere under different
121 * copying permissions. These modifications are distributed here under
122 * the following terms:
123 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
124 * Authors: $(HTTP digitalmars.com, Walter Bright), Don Clugston,
125 * Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger
126 * Source: $(PHOBOSSRC std/_math.d)
127 */
128
129 /* NOTE: This file has been patched from the original DMD distribution to
130 * work with the GDC compiler.
131 */
132 module std.math;
133
version(Win64)134 version (Win64)
135 {
136 version (D_InlineAsm_X86_64)
137 version = Win64_DMD_InlineAsm;
138 }
139
140 static import core.math;
141 static import core.stdc.math;
142 static import core.stdc.fenv;
143 import std.traits; // CommonType, isFloatingPoint, isIntegral, isSigned, isUnsigned, Largest, Unqual
144
version(LDC)145 version (LDC)
146 {
147 import ldc.intrinsics;
148 }
149
version(DigitalMars)150 version (DigitalMars)
151 {
152 version = INLINE_YL2X; // x87 has opcodes for these
153 }
154
155 version (X86) version = X86_Any;
156 version (X86_64) version = X86_Any;
157 version (PPC) version = PPC_Any;
158 version (PPC64) version = PPC_Any;
159 version (MIPS32) version = MIPS_Any;
160 version (MIPS64) version = MIPS_Any;
161 version (AArch64) version = ARM_Any;
162 version (ARM) version = ARM_Any;
163 version (S390) version = IBMZ_Any;
164 version (SPARC) version = SPARC_Any;
165 version (SPARC64) version = SPARC_Any;
166 version (SystemZ) version = IBMZ_Any;
167 version (RISCV32) version = RISCV_Any;
168 version (RISCV64) version = RISCV_Any;
169
version(D_InlineAsm_X86)170 version (D_InlineAsm_X86)
171 {
172 version = InlineAsm_X86_Any;
173 }
version(D_InlineAsm_X86_64)174 else version (D_InlineAsm_X86_64)
175 {
176 version = InlineAsm_X86_Any;
177 }
178
version(CRuntime_Microsoft)179 version (CRuntime_Microsoft)
180 {
181 version (InlineAsm_X86_Any)
182 version = MSVC_InlineAsm;
183 }
184
185 version (X86_64) version = StaticallyHaveSSE;
186 version (X86) version (OSX) version = StaticallyHaveSSE;
187
version(StaticallyHaveSSE)188 version (StaticallyHaveSSE)
189 {
190 private enum bool haveSSE = true;
191 }
version(X86)192 else version (X86)
193 {
194 static import core.cpuid;
195 private alias haveSSE = core.cpuid.sse;
196 }
197
version(D_SoftFloat)198 version (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 }
204 else version (X86_Any) version = IeeeFlagsSupport;
205 else version (PPC_Any) version = IeeeFlagsSupport;
206 else version (RISCV_Any) version = IeeeFlagsSupport;
207 else version (MIPS_Any) version = IeeeFlagsSupport;
208 else version (ARM_Any) version = IeeeFlagsSupport;
209
210 // Struct FloatingPointControl is only available if hardware FP units are available.
version(D_HardFloat)211 version (D_HardFloat)
212 {
213 // FloatingPointControl.clearExceptions() depends on version IeeeFlagsSupport
214 version (IeeeFlagsSupport) version = FloatingPointControlSupport;
215 }
216
version(GNU)217 version (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 }
224 else
225 {
226 version = IeeeFlagsUnittest;
227 version = FloatingPointControlUnittest;
228 }
229
version(unittest)230 version (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
282 package:
283 // The following IEEE 'real' formats are currently supported.
version(LittleEndian)284 version (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 }
291 else
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
300 enum 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.
floatTraits(T)313 template 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
version(LittleEndian)451 version (LittleEndian)
452 {
453 enum MANTISSA_LSB = 0;
454 enum MANTISSA_MSB = 1;
455 }
456 else
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
floorImpl(T)465 T 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
568 public:
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).
572 enum real E = 0x1.5bf0a8b1457695355fb8ac404e7a8p+1L; /** e = 2.718281... */
573 enum real LOG2T = 0x1.a934f0979a3715fc9257edfe9b5fbp+1L; /** $(SUB log, 2)10 = 3.321928... */
574 enum real LOG2E = 0x1.71547652b82fe1777d0ffda0d23a8p+0L; /** $(SUB log, 2)e = 1.442695... */
575 enum real LOG2 = 0x1.34413509f79fef311f12b35816f92p-2L; /** $(SUB log, 10)2 = 0.301029... */
576 enum real LOG10E = 0x1.bcb7b1526e50e32a6ab7555f5a67cp-2L; /** $(SUB log, 10)e = 0.434294... */
577 enum real LN2 = 0x1.62e42fefa39ef35793c7673007e5fp-1L; /** ln 2 = 0.693147... */
578 enum real LN10 = 0x1.26bb1bbb5551582dd4adac5705a61p+1L; /** ln 10 = 2.302585... */
579 enum real PI = 0x1.921fb54442d18469898cc51701b84p+1L; /** $(_PI) = 3.141592... */
580 enum real PI_2 = PI/2; /** $(PI) / 2 = 1.570796... */
581 enum real PI_4 = PI/4; /** $(PI) / 4 = 0.785398... */
582 enum real M_1_PI = 0x1.45f306dc9c882a53f84eafa3ea69cp-2L; /** 1 / $(PI) = 0.318309... */
583 enum real M_2_PI = 2*M_1_PI; /** 2 / $(PI) = 0.636619... */
584 enum real M_2_SQRTPI = 0x1.20dd750429b6d11ae3a914fed7fd8p+0L; /** 2 / $(SQRT)$(PI) = 1.128379... */
585 enum real SQRT2 = 0x1.6a09e667f3bcc908b2fb1366ea958p+0L; /** $(SQRT)2 = 1.414213... */
586 enum 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 */
608 Num abs(Num)(Num x) @safe pure nothrow
609 if (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
620 auto abs(Num)(Num z) @safe pure nothrow @nogc
621 if (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
628 auto abs(Num)(Num y) @safe pure nothrow @nogc
629 if (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 */
673 auto conj(Num)(Num z) @safe pure nothrow @nogc
674 if (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 */
686 auto conj(Num)(Num y) @safe pure nothrow @nogc
687 if (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
cos(real x)730 real cos(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.cos(x); }
731 //FIXME
732 ///ditto
cos(double x)733 double cos(double x) @safe pure nothrow @nogc { return cos(cast(real) x); }
734 //FIXME
735 ///ditto
cos(float x)736 float 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
sin(real x)764 real sin(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.sin(x); }
765 //FIXME
766 ///ditto
sin(double x)767 double sin(double x) @safe pure nothrow @nogc { return sin(cast(real) x); }
768 //FIXME
769 ///ditto
sin(float x)770 float 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
someFunc()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 */
sin(creal z)800 creal 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 */
sin(ireal y)808 ireal 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 */
cos(creal z)825 creal 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 */
cos(ireal y)833 real 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
tan(real x)857 real 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
869 SC18: 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 ;
877 SC17: fprem1 ;
878 fstsw AX ;
879 sahf ;
880 jp SC17 ;
881 fstp ST(1) ; // remove pi from stack
882 jmp SC18 ;
883
884 trigerr:
885 jnp Lret ; // if theta is NAN, return theta
886 fstp ST(0) ; // dump theta
887 }
888 return real.nan;
889
890 Clear1: asm pure nothrow @nogc{
891 fstp ST(0) ; // dump X, which is always 1
892 }
893
894 Lret: {}
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
919 SC18: 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 ;
927 SC17: fprem1 ;
928 fstsw AX ;
929 test AH,4 ;
930 jnz SC17 ;
931 fstp ST(1) ; // remove pi from stack
932 jmp SC18 ;
933
934 trigerr:
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
941 Clear1: asm pure nothrow @nogc{
942 fstp ST(0) ; // dump X, which is always 1
943 }
944
945 Lret: {}
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 */
acos(real x)1113 real acos(real x) @safe pure nothrow @nogc
1114 {
1115 return atan2(sqrt(1-x*x), x);
1116 }
1117
1118 /// ditto
acos(double x)1119 double acos(double x) @safe pure nothrow @nogc { return acos(cast(real) x); }
1120
1121 /// ditto
acos(float x)1122 float 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 */
asin(real x)1140 real asin(real x) @safe pure nothrow @nogc
1141 {
1142 return atan2(x, sqrt(1-x*x));
1143 }
1144
1145 /// ditto
asin(double x)1146 double asin(double x) @safe pure nothrow @nogc { return asin(cast(real) x); }
1147
1148 /// ditto
asin(float x)1149 float 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 */
atan(real x)1166 real 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
atan(double x)1262 double atan(double x) @safe pure nothrow @nogc { return atan(cast(real) x); }
1263
1264 /// ditto
atan(float x)1265 float 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 */
atan2(real y,real x)1293 real 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
atan2(double y,double x)1369 double atan2(double y, double x) @safe pure nothrow @nogc
1370 {
1371 return atan2(cast(real) y, cast(real) x);
1372 }
1373
1374 /// ditto
atan2(float y,float x)1375 float 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 */
cosh(real x)1393 real 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
cosh(double x)1402 double cosh(double x) @safe pure nothrow @nogc { return cosh(cast(real) x); }
1403
1404 /// ditto
cosh(float x)1405 float 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 */
sinh(real x)1421 real 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
sinh(double x)1437 double sinh(double x) @safe pure nothrow @nogc { return sinh(cast(real) x); }
1438
1439 /// ditto
sinh(float x)1440 float 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 */
tanh(real x)1456 real 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
tanh(double x)1469 double tanh(double x) @safe pure nothrow @nogc { return tanh(cast(real) x); }
1470
1471 /// ditto
tanh(float x)1472 float 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
1479 package:
1480
1481 /* Returns cosh(x) + I * sinh(x)
1482 * Only one call to exp() is performed.
1483 */
coshisinh(real x)1484 creal 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
1506 public:
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 */
acosh(real x)1526 real 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
acosh(double x)1535 double acosh(double x) @safe pure nothrow @nogc { return acosh(cast(real) x); }
1536
1537 /// ditto
acosh(float x)1538 float 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 */
asinh(real x)1567 real 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
asinh(double x)1577 double asinh(double x) @safe pure nothrow @nogc { return asinh(cast(real) x); }
1578
1579 /// ditto
asinh(float x)1580 float 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 */
atanh(real x)1610 real 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
atanh(double x)1617 double atanh(double x) @safe pure nothrow @nogc { return atanh(cast(real) x); }
1618
1619 /// ditto
atanh(float x)1620 float 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 */
rndtol(real x)1639 long rndtol(real x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.rndtol(x); }
1640 //FIXME
1641 ///ditto
rndtol(double x)1642 long rndtol(double x) @safe pure nothrow @nogc { return rndtol(cast(real) x); }
1643 //FIXME
1644 ///ditto
rndtol(float x)1645 long 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 */
1659 extern (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 */
sqrt(float x)1671 float sqrt(float x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.sqrt(x); }
1672
1673 /// ditto
sqrt(double x)1674 double sqrt(double x) @nogc @safe pure nothrow { pragma(inline, true); return core.math.sqrt(x); }
1675
1676 /// ditto
sqrt(real x)1677 real 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
sqrt(creal z)1701 creal 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 */
exp(real x)1752 real 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
exp(double x)1878 double exp(double x) @safe pure nothrow @nogc { return exp(cast(real) x); }
1879
1880 /// ditto
exp(float x)1881 float 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 */
expm1(real x)1903 real 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
1951 L_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;
1959 L_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!
1966 L_was_nan:
1967 add ESP,12+8;
1968 ret PARAMSIZE;
1969 L_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
2039 L_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;
2047 L_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!
2054 L_was_nan:
2055 add RSP,24;
2056 ret;
2057
2058 L_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 */
pragma(inline,true)2166 pragma(inline, true)
2167 real 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
version(InlineAsm_X86_Any)2182 version (InlineAsm_X86_Any)
2183 private 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;
2227 L_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
2236 L_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
2247 L_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;
2258 L_overflow:
2259 // Set scratchreal = real.max.
2260 // squaring it will create infinity, and set overflow flag.
2261 mov word ptr [ESP+8+8], 0x7FFE;
2262 L_waslargenegative:
2263 fstp ST(0);
2264 fld real ptr [ESP+8]; // load scratchreal
2265 fmul ST(0), ST; // square it, to create havoc!
2266 L_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;
2328 L_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
2337 L_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
2348 L_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;
2359 L_overflow:
2360 // Set scratchreal = real.max.
2361 // squaring it will create infinity, and set overflow flag.
2362 mov word ptr [RSP+8+8], 0x7FFE;
2363 L_waslargenegative:
2364 fstp ST(0);
2365 fld real ptr [RSP+8]; // load scratchreal
2366 fmul ST(0), ST; // square it, to create havoc!
2367 L_was_nan:
2368 add RSP,24;
2369 ret;
2370 }
2371 }
2372 else
2373 static assert(0);
2374 }
2375
exp2Impl(real x)2376 private 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 {
version(CRuntime_Microsoft)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 {
version(FloatingPointControlSupport)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;
version(IeeeFlagsSupport)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.
version(IeeeFlagsSupport)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 */
expi(real y)2584 creal 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 */
2640 T frexp(T)(const T value, out int exp) @trusted pure nothrow @nogc
2641 if (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
foreach(elem;vals)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 ];
foreach(elem;extendedvals)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;
foo()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 */
2923 int ilogb(T)(const T x) @trusted pure nothrow @nogc
2924 if (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
3064 int ilogb(T)(const T x) @safe pure nothrow @nogc
3065 if (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
3077 int ilogb(T)(const T x) @safe pure nothrow @nogc
3078 if (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
3087 alias FP_ILOGB0 = core.stdc.math.FP_ILOGB0;
3088 alias 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
foreach(elem;vals)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
ldexp(real n,int exp)3155 real ldexp(real n, int exp) @nogc @safe pure nothrow { pragma(inline, true); return core.math.ldexp(n, exp); }
3156 //FIXME
3157 ///ditto
ldexp(double n,int exp)3158 double ldexp(double n, int exp) @safe pure nothrow @nogc { return ldexp(cast(real) n, exp); }
3159 //FIXME
3160 ///ditto
ldexp(float n,int exp)3161 float 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
3263 private
3264 {
version(INLINE_YL2X)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 */
log(real x)3371 real 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 */
log10(real x)3464 real 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 */
log1p(real x)3565 real 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 */
log2(real x)3600 real 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 */
logb(real x)3693 real 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 */
fmod(real x,real y)3733 real 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 */
modf(real x,ref real i)3754 real 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 */
scalbn(real x,int n)3777 real 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 */
cbrt(real x)3826 real 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 */
fabs(real x)3849 real fabs(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.fabs(x); }
3850 //FIXME
3851 ///ditto
fabs(double x)3852 double fabs(double x) @safe pure nothrow @nogc { return fabs(cast(real) x); }
3853 //FIXME
3854 ///ditto
fabs(float x)3855 float 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
hypot(real x,real y)3882 real 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 */
ceil(real x)3972 real 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
ceil(double x)4041 double 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
ceil(float x)4069 float 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 */
floor(real x)4100 real 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
floor(double x)4165 double 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
floor(float x)4189 float 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 */
4217 Unqual!F quantize(alias rfunc = rint, F)(const F val, const F unit)
4218 if (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 */
4256 Unqual!F quantize(real base, alias rfunc = rint, F, E)(const F val, const E exp)
4257 if (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
4264 Unqual!F quantize(real base, long exp = 1, alias rfunc = rint, F)(const F val)
4265 if (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 */
4310 real 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 */
4328 real rint(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.rint(x); }
4329 //FIXME
4330 ///ditto
4331 double rint(double x) @safe pure nothrow @nogc { return rint(cast(real) x); }
4332 //FIXME
4333 ///ditto
4334 float 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 */
4352 long 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
4537 static 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 */
4553 real 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 */
4577 long 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
4585 version (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 */
4600 real 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 */
4665 real 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
4676 real 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
4685 version (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 */
4696 struct IeeeFlags
4697 {
4698 private:
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
4736 private:
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 }
4908 public:
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 ///
4946 version (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
4975 version (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.
5023 void 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
5034 version (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
5053 Example:
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:
5080 assert(!FloatingPointControl.enabledExceptions);
5081 assert(FloatingPointControl.rounding == FloatingPointControl.roundToNearest);
5082 assert(rint(1.1) == 1);
5083 ----
5084
5085 */
5086 struct 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
5292 public:
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
5356 private:
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
5635 version (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 */
5701 bool isNaN(X)(X x) @nogc @trusted pure nothrow
5702 if (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 */
5789 bool 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 */
5836 bool 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 */
5882 bool 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 */
5944 bool isInfinity(X)(X x) @nogc @trusted pure nothrow
5945 if (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 */
6061 bool 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 */
6087 int 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 */
6128 R copysign(R, X)(R to, X from) @trusted pure nothrow @nogc
6129 if (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
6142 R copysign(R, X)(X to, R from) @trusted pure nothrow @nogc
6143 if (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 /*********************************
6185 Returns $(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 */
6188 F 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 */
6217 real 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 */
6305 ulong 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
6345 debug(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 */
6387 real 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 */
6483 double 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 */
6510 float 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 */
6554 real nextDown(real x) @safe pure nothrow @nogc
6555 {
6556 return -nextUp(-x);
6557 }
6558
6559 /** ditto */
6560 double nextDown(double x) @safe pure nothrow @nogc
6561 {
6562 return -nextUp(-x);
6563 }
6564
6565 /** ditto */
6566 float 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 */
6660 T 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 */
6693 real 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 */
6698 real 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 */
6703 real 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 */
6711 real 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 */
6716 Unqual!F pow(F, G)(F x, G n) @nogc @trusted pure nothrow
6717 if (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 */
6818 typeof(Unqual!(F).init * Unqual!(G).init) pow(F, G)(F x, G n) @nogc @trusted pure nothrow
6819 if (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.*/
6875 real pow(I, F)(I x, F y) @nogc @trusted pure nothrow
6876 if (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 */
6923 Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow
6924 if (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 */
7206 int feqrel(X)(const X x, const X y) @trusted pure nothrow @nogc
7207 if (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
7336 package: // 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 */
7352 T ieeeMean(T)(const T x, const T y) @trusted pure nothrow @nogc
7353 in
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 }
7359 body
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
7474 public:
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 */
7487 Unqual!(CommonType!(T1, T2)) poly(T1, T2)(T1 x, in T2[] A) @trusted pure nothrow @nogc
7488 if (isFloatingPoint!T1 && isFloatingPoint!T2)
7489 in
7490 {
7491 assert(A.length > 0);
7492 }
7493 body
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
7531 private Unqual!(CommonType!(T1, T2)) polyImplBase(T1, T2)(T1 x, in T2[] A) @trusted pure nothrow @nogc
7532 if (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
7544 private 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 */
7752 bool 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 */
7823 bool 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 */
7969 int cmp(T)(const(T) x, const(T) y) @nogc @trusted pure nothrow
7970 if (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
8174 private enum PowType
8175 {
8176 floor,
8177 ceil
8178 }
8179
8180 pragma(inline, true)
8181 private 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
8196 private 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 */
8233 T nextPow2(T)(const T val)
8234 if (isIntegral!T)
8235 {
8236 return powIntegralImpl!(PowType.ceil)(val);
8237 }
8238
8239 /// ditto
8240 T nextPow2(T)(const T val)
8241 if (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 */
8358 T truncPow2(T)(const T val)
8359 if (isIntegral!T)
8360 {
8361 return powIntegralImpl!(PowType.floor)(val);
8362 }
8363
8364 /// ditto
8365 T truncPow2(T)(const T val)
8366 if (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 /**
8463 Check whether a number is an integer power of two.
8464
8465 Note that only positive numbers can be integer powers of two. This
8466 function always return `false` if `x` is negative or zero.
8467
8468 Params:
8469 x = the number to test
8470
8471 Returns:
8472 `true` if `x` is an integer power of two.
8473 */
8474 bool isPowerOf2(X)(const X x) pure @safe nothrow @nogc
8475 if (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