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