c++: Implement for namespace statics CWG 2867 - Order of initialization for structure...
[gcc.git] / libphobos / src / std / math / traits.d
blob8aba6a6b1c67deec6d241fa38815abfbc9d2cc5e
1 // Written in the D programming language.
3 /**
4 This is a submodule of $(MREF std, math).
6 It contains several functions for introspection on numerical values.
8 Copyright: Copyright The D Language Foundation 2000 - 2011.
9 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
10 Authors: $(HTTP digitalmars.com, Walter Bright), Don Clugston,
11 Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger
12 Source: $(PHOBOSSRC std/math/traits.d)
14 Macros:
15 NAN = $(RED NAN)
16 PLUSMN = ±
17 INFIN = ∞
20 module std.math.traits;
22 import std.traits : isFloatingPoint, isIntegral, isNumeric, isSigned;
25 /*********************************
26 * Determines if $(D_PARAM x) is NaN.
27 * Params:
28 * x = a floating point number.
29 * Returns:
30 * `true` if $(D_PARAM x) is Nan.
32 bool isNaN(X)(X x) @nogc @trusted pure nothrow
33 if (isFloatingPoint!(X))
35 version (all)
37 return x != x;
39 else
42 Code kept for historical context. At least on Intel, the simple test
43 x != x uses one dedicated instruction (ucomiss/ucomisd) that runs in one
44 cycle. Code for 80- and 128-bits is larger but still smaller than the
45 integrals-based solutions below. Future revisions may enable the code
46 below conditionally depending on hardware.
48 alias F = floatTraits!(X);
49 static if (F.realFormat == RealFormat.ieeeSingle)
51 const uint p = *cast(uint *)&x;
52 // Sign bit (MSB) is irrelevant so mask it out.
53 // Next 8 bits should be all set.
54 // At least one bit among the least significant 23 bits should be set.
55 return (p & 0x7FFF_FFFF) > 0x7F80_0000;
57 else static if (F.realFormat == RealFormat.ieeeDouble)
59 const ulong p = *cast(ulong *)&x;
60 // Sign bit (MSB) is irrelevant so mask it out.
61 // Next 11 bits should be all set.
62 // At least one bit among the least significant 52 bits should be set.
63 return (p & 0x7FFF_FFFF_FFFF_FFFF) > 0x7FF0_0000_0000_0000;
65 else static if (F.realFormat == RealFormat.ieeeExtended ||
66 F.realFormat == RealFormat.ieeeExtended53)
68 const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
69 const ulong ps = *cast(ulong *)&x;
70 return e == F.EXPMASK &&
71 ps & 0x7FFF_FFFF_FFFF_FFFF; // not infinity
73 else static if (F.realFormat == RealFormat.ieeeQuadruple)
75 const ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
76 const ulong psLsb = (cast(ulong *)&x)[MANTISSA_LSB];
77 const ulong psMsb = (cast(ulong *)&x)[MANTISSA_MSB];
78 return e == F.EXPMASK &&
79 (psLsb | (psMsb& 0x0000_FFFF_FFFF_FFFF)) != 0;
81 else
83 return x != x;
88 ///
89 @safe pure nothrow @nogc unittest
91 assert( isNaN(float.init));
92 assert( isNaN(-double.init));
93 assert( isNaN(real.nan));
94 assert( isNaN(-real.nan));
95 assert(!isNaN(cast(float) 53.6));
96 assert(!isNaN(cast(real)-53.6));
99 @safe pure nothrow @nogc unittest
101 import std.meta : AliasSeq;
103 static foreach (T; AliasSeq!(float, double, real))
105 // CTFE-able tests
106 assert(isNaN(T.init));
107 assert(isNaN(-T.init));
108 assert(isNaN(T.nan));
109 assert(isNaN(-T.nan));
110 assert(!isNaN(T.infinity));
111 assert(!isNaN(-T.infinity));
112 assert(!isNaN(cast(T) 53.6));
113 assert(!isNaN(cast(T)-53.6));
115 // Runtime tests
116 shared T f;
117 f = T.init;
118 assert(isNaN(f));
119 assert(isNaN(-f));
120 f = T.nan;
121 assert(isNaN(f));
122 assert(isNaN(-f));
123 f = T.infinity;
124 assert(!isNaN(f));
125 assert(!isNaN(-f));
126 f = cast(T) 53.6;
127 assert(!isNaN(f));
128 assert(!isNaN(-f));
132 /*********************************
133 * Determines if $(D_PARAM x) is finite.
134 * Params:
135 * x = a floating point number.
136 * Returns:
137 * `true` if $(D_PARAM x) is finite.
139 bool isFinite(X)(X x) @trusted pure nothrow @nogc
141 import std.math.traits : floatTraits, RealFormat;
143 static if (__traits(isFloating, X))
144 if (__ctfe)
145 return x == x && x != X.infinity && x != -X.infinity;
146 alias F = floatTraits!(X);
147 ushort* pe = cast(ushort *)&x;
148 return (pe[F.EXPPOS_SHORT] & F.EXPMASK) != F.EXPMASK;
152 @safe pure nothrow @nogc unittest
154 assert( isFinite(1.23f));
155 assert( isFinite(float.max));
156 assert( isFinite(float.min_normal));
157 assert(!isFinite(float.nan));
158 assert(!isFinite(float.infinity));
161 @safe pure nothrow @nogc unittest
163 assert(isFinite(1.23));
164 assert(isFinite(double.max));
165 assert(isFinite(double.min_normal));
166 assert(!isFinite(double.nan));
167 assert(!isFinite(double.infinity));
169 assert(isFinite(1.23L));
170 assert(isFinite(real.max));
171 assert(isFinite(real.min_normal));
172 assert(!isFinite(real.nan));
173 assert(!isFinite(real.infinity));
175 //CTFE
176 static assert(isFinite(1.23));
177 static assert(isFinite(double.max));
178 static assert(isFinite(double.min_normal));
179 static assert(!isFinite(double.nan));
180 static assert(!isFinite(double.infinity));
182 static assert(isFinite(1.23L));
183 static assert(isFinite(real.max));
184 static assert(isFinite(real.min_normal));
185 static assert(!isFinite(real.nan));
186 static assert(!isFinite(real.infinity));
190 /*********************************
191 * Determines if $(D_PARAM x) is normalized.
193 * A normalized number must not be zero, subnormal, infinite nor $(NAN).
195 * Params:
196 * x = a floating point number.
197 * Returns:
198 * `true` if $(D_PARAM x) is normalized.
201 /* Need one for each format because subnormal floats might
202 * be converted to normal reals.
204 bool isNormal(X)(X x) @trusted pure nothrow @nogc
206 import std.math.traits : floatTraits, RealFormat;
208 static if (__traits(isFloating, X))
209 if (__ctfe)
210 return (x <= -X.min_normal && x != -X.infinity) || (x >= X.min_normal && x != X.infinity);
211 alias F = floatTraits!(X);
212 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
213 return (e != F.EXPMASK && e != 0);
217 @safe pure nothrow @nogc unittest
219 float f = 3;
220 double d = 500;
221 real e = 10e+48;
223 assert(isNormal(f));
224 assert(isNormal(d));
225 assert(isNormal(e));
226 f = d = e = 0;
227 assert(!isNormal(f));
228 assert(!isNormal(d));
229 assert(!isNormal(e));
230 assert(!isNormal(real.infinity));
231 assert(isNormal(-real.max));
232 assert(!isNormal(real.min_normal/4));
236 @safe pure nothrow @nogc unittest
238 // CTFE
239 enum float f = 3;
240 enum double d = 500;
241 enum real e = 10e+48;
243 static assert(isNormal(f));
244 static assert(isNormal(d));
245 static assert(isNormal(e));
247 static assert(!isNormal(0.0f));
248 static assert(!isNormal(0.0));
249 static assert(!isNormal(0.0L));
250 static assert(!isNormal(real.infinity));
251 static assert(isNormal(-real.max));
252 static assert(!isNormal(real.min_normal/4));
255 /*********************************
256 * Determines if $(D_PARAM x) is subnormal.
258 * Subnormals (also known as "denormal number"), have a 0 exponent
259 * and a 0 most significant mantissa bit.
261 * Params:
262 * x = a floating point number.
263 * Returns:
264 * `true` if $(D_PARAM x) is a denormal number.
266 bool isSubnormal(X)(X x) @trusted pure nothrow @nogc
268 import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB;
270 static if (__traits(isFloating, X))
271 if (__ctfe)
272 return -X.min_normal < x && x < X.min_normal;
274 Need one for each format because subnormal floats might
275 be converted to normal reals.
277 alias F = floatTraits!(X);
278 static if (F.realFormat == RealFormat.ieeeSingle)
280 uint *p = cast(uint *)&x;
281 return (*p & F.EXPMASK_INT) == 0 && *p & F.MANTISSAMASK_INT;
283 else static if (F.realFormat == RealFormat.ieeeDouble)
285 uint *p = cast(uint *)&x;
286 return (p[MANTISSA_MSB] & F.EXPMASK_INT) == 0
287 && (p[MANTISSA_LSB] || p[MANTISSA_MSB] & F.MANTISSAMASK_INT);
289 else static if (F.realFormat == RealFormat.ieeeQuadruple)
291 ushort e = F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT];
292 long* ps = cast(long *)&x;
293 return (e == 0 &&
294 ((ps[MANTISSA_LSB]|(ps[MANTISSA_MSB]& 0x0000_FFFF_FFFF_FFFF)) != 0));
296 else static if (F.realFormat == RealFormat.ieeeExtended ||
297 F.realFormat == RealFormat.ieeeExtended53)
299 ushort* pe = cast(ushort *)&x;
300 long* ps = cast(long *)&x;
302 return (pe[F.EXPPOS_SHORT] & F.EXPMASK) == 0 && *ps > 0;
304 else
306 static assert(false, "Not implemented for this architecture");
311 @safe pure nothrow @nogc unittest
313 import std.meta : AliasSeq;
315 static foreach (T; AliasSeq!(float, double, real))
317 T f;
318 for (f = 1.0; !isSubnormal(f); f /= 2)
319 assert(f != 0);
323 @safe pure nothrow @nogc unittest
325 static bool subnormalTest(T)()
327 T f;
328 for (f = 1.0; !isSubnormal(f); f /= 2)
329 if (f == 0)
330 return false;
331 return true;
333 static assert(subnormalTest!float());
334 static assert(subnormalTest!double());
335 static assert(subnormalTest!real());
338 /*********************************
339 * Determines if $(D_PARAM x) is $(PLUSMN)$(INFIN).
340 * Params:
341 * x = a floating point number.
342 * Returns:
343 * `true` if $(D_PARAM x) is $(PLUSMN)$(INFIN).
345 bool isInfinity(X)(X x) @nogc @trusted pure nothrow
346 if (isFloatingPoint!(X))
348 import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB;
350 alias F = floatTraits!(X);
351 static if (F.realFormat == RealFormat.ieeeSingle)
353 return ((*cast(uint *)&x) & 0x7FFF_FFFF) == 0x7F80_0000;
355 else static if (F.realFormat == RealFormat.ieeeDouble)
357 return ((*cast(ulong *)&x) & 0x7FFF_FFFF_FFFF_FFFF)
358 == 0x7FF0_0000_0000_0000;
360 else static if (F.realFormat == RealFormat.ieeeExtended ||
361 F.realFormat == RealFormat.ieeeExtended53)
363 const ushort e = cast(ushort)(F.EXPMASK & (cast(ushort *)&x)[F.EXPPOS_SHORT]);
364 const ulong ps = *cast(ulong *)&x;
366 // On Motorola 68K, infinity can have hidden bit = 1 or 0. On x86, it is always 1.
367 return e == F.EXPMASK && (ps & 0x7FFF_FFFF_FFFF_FFFF) == 0;
369 else static if (F.realFormat == RealFormat.ieeeQuadruple)
371 const long psLsb = (cast(long *)&x)[MANTISSA_LSB];
372 const long psMsb = (cast(long *)&x)[MANTISSA_MSB];
373 return (psLsb == 0)
374 && (psMsb & 0x7FFF_FFFF_FFFF_FFFF) == 0x7FFF_0000_0000_0000;
376 else
378 return (x < -X.max) || (X.max < x);
383 @nogc @safe pure nothrow unittest
385 assert(!isInfinity(float.init));
386 assert(!isInfinity(-float.init));
387 assert(!isInfinity(float.nan));
388 assert(!isInfinity(-float.nan));
389 assert(isInfinity(float.infinity));
390 assert(isInfinity(-float.infinity));
391 assert(isInfinity(-1.0f / 0.0f));
394 @safe pure nothrow @nogc unittest
396 // CTFE-able tests
397 assert(!isInfinity(double.init));
398 assert(!isInfinity(-double.init));
399 assert(!isInfinity(double.nan));
400 assert(!isInfinity(-double.nan));
401 assert(isInfinity(double.infinity));
402 assert(isInfinity(-double.infinity));
403 assert(isInfinity(-1.0 / 0.0));
405 assert(!isInfinity(real.init));
406 assert(!isInfinity(-real.init));
407 assert(!isInfinity(real.nan));
408 assert(!isInfinity(-real.nan));
409 assert(isInfinity(real.infinity));
410 assert(isInfinity(-real.infinity));
411 assert(isInfinity(-1.0L / 0.0L));
413 // Runtime tests
414 shared float f;
415 f = float.init;
416 assert(!isInfinity(f));
417 assert(!isInfinity(-f));
418 f = float.nan;
419 assert(!isInfinity(f));
420 assert(!isInfinity(-f));
421 f = float.infinity;
422 assert(isInfinity(f));
423 assert(isInfinity(-f));
424 f = (-1.0f / 0.0f);
425 assert(isInfinity(f));
427 shared double d;
428 d = double.init;
429 assert(!isInfinity(d));
430 assert(!isInfinity(-d));
431 d = double.nan;
432 assert(!isInfinity(d));
433 assert(!isInfinity(-d));
434 d = double.infinity;
435 assert(isInfinity(d));
436 assert(isInfinity(-d));
437 d = (-1.0 / 0.0);
438 assert(isInfinity(d));
440 shared real e;
441 e = real.init;
442 assert(!isInfinity(e));
443 assert(!isInfinity(-e));
444 e = real.nan;
445 assert(!isInfinity(e));
446 assert(!isInfinity(-e));
447 e = real.infinity;
448 assert(isInfinity(e));
449 assert(isInfinity(-e));
450 e = (-1.0L / 0.0L);
451 assert(isInfinity(e));
454 @nogc @safe pure nothrow unittest
456 import std.meta : AliasSeq;
457 static bool foo(T)(inout T x) { return isInfinity(x); }
458 foreach (T; AliasSeq!(float, double, real))
460 assert(!foo(T(3.14f)));
461 assert(foo(T.infinity));
465 /*********************************
466 * Is the binary representation of x identical to y?
468 bool isIdentical(real x, real y) @trusted pure nothrow @nogc
470 if (__ctfe)
472 if (x !is y) return false;
473 if (x == x) return true; // If not NaN `is` implies identical representation.
474 static if (double.mant_dig != real.mant_dig)
476 // Works because we are in CTFE and there is no way in CTFE to set more
477 // bits of NaN payload than can fit in a double, and since 2.087
478 // changed real.init to be non-signaling I *think* there is no way in
479 // CTFE for a real to be a signaling NaN unless real and double have
480 // the same representation so real's bits can be manipulated directly.
481 double d1 = x, d2 = y;
483 else
485 // Alias to avoid converting signaling to quiet.
486 alias d1 = x;
487 alias d2 = y;
489 return *cast(long*) &d1 == *cast(long*) &d2;
491 // We're doing a bitwise comparison so the endianness is irrelevant.
492 long* pxs = cast(long *)&x;
493 long* pys = cast(long *)&y;
494 alias F = floatTraits!(real);
495 static if (F.realFormat == RealFormat.ieeeDouble)
497 return pxs[0] == pys[0];
499 else static if (F.realFormat == RealFormat.ieeeQuadruple)
501 return pxs[0] == pys[0] && pxs[1] == pys[1];
503 else static if (F.realFormat == RealFormat.ieeeExtended)
505 ushort* pxe = cast(ushort *)&x;
506 ushort* pye = cast(ushort *)&y;
507 return pxe[4] == pye[4] && pxs[0] == pys[0];
509 else
511 assert(0, "isIdentical not implemented");
515 @safe @nogc pure nothrow unittest
517 // We're forcing the CTFE to run by assigning the result of the function to an enum
518 enum test1 = isIdentical(1.0,1.0);
519 enum test2 = isIdentical(real.nan,real.nan);
520 enum test3 = isIdentical(real.infinity, real.infinity);
521 enum test4 = isIdentical(real.infinity, real.infinity);
522 enum test5 = isIdentical(0.0, 0.0);
524 assert(test1);
525 assert(test2);
526 assert(test3);
527 assert(test4);
528 assert(test5);
530 enum test6 = !isIdentical(0.0, -0.0);
531 enum test7 = !isIdentical(real.nan, -real.nan);
532 enum test8 = !isIdentical(real.infinity, -real.infinity);
534 assert(test6);
535 assert(test7);
536 assert(test8);
539 @safe @nogc pure nothrow unittest
541 assert( !isIdentical(1.2,1.3));
542 assert( isIdentical(0.0, 0.0));
543 assert( isIdentical(1.0, 1.0));
544 assert( isIdentical(real.infinity, real.infinity));
545 assert( isIdentical(-real.infinity, -real.infinity));
546 assert( isIdentical(real.nan, real.nan));
548 assert(!isIdentical(0.0, -0.0));
549 assert(!isIdentical(real.nan, -real.nan));
550 assert(!isIdentical(real.infinity, -real.infinity));
552 /*********************************
553 * Return 1 if sign bit of e is set, 0 if not.
555 int signbit(X)(X x) @nogc @trusted pure nothrow
557 import std.math.traits : floatTraits, RealFormat;
559 if (__ctfe)
561 double dval = cast(double) x; // Precision can increase or decrease but sign won't change (even NaN).
562 return 0 > *cast(long*) &dval;
565 alias F = floatTraits!(X);
566 return ((cast(ubyte *)&x)[F.SIGNPOS_BYTE] & 0x80) != 0;
570 @nogc @safe pure nothrow unittest
572 assert(!signbit(float.nan));
573 assert(signbit(-float.nan));
574 assert(!signbit(168.1234f));
575 assert(signbit(-168.1234f));
576 assert(!signbit(0.0f));
577 assert(signbit(-0.0f));
578 assert(signbit(-float.max));
579 assert(!signbit(float.max));
581 assert(!signbit(double.nan));
582 assert(signbit(-double.nan));
583 assert(!signbit(168.1234));
584 assert(signbit(-168.1234));
585 assert(!signbit(0.0));
586 assert(signbit(-0.0));
587 assert(signbit(-double.max));
588 assert(!signbit(double.max));
590 assert(!signbit(real.nan));
591 assert(signbit(-real.nan));
592 assert(!signbit(168.1234L));
593 assert(signbit(-168.1234L));
594 assert(!signbit(0.0L));
595 assert(signbit(-0.0L));
596 assert(signbit(-real.max));
597 assert(!signbit(real.max));
600 @nogc @safe pure nothrow unittest
602 // CTFE
603 static assert(!signbit(float.nan));
604 static assert(signbit(-float.nan));
605 static assert(!signbit(168.1234f));
606 static assert(signbit(-168.1234f));
607 static assert(!signbit(0.0f));
608 static assert(signbit(-0.0f));
609 static assert(signbit(-float.max));
610 static assert(!signbit(float.max));
612 static assert(!signbit(double.nan));
613 static assert(signbit(-double.nan));
614 static assert(!signbit(168.1234));
615 static assert(signbit(-168.1234));
616 static assert(!signbit(0.0));
617 static assert(signbit(-0.0));
618 static assert(signbit(-double.max));
619 static assert(!signbit(double.max));
621 static assert(!signbit(real.nan));
622 static assert(signbit(-real.nan));
623 static assert(!signbit(168.1234L));
624 static assert(signbit(-168.1234L));
625 static assert(!signbit(0.0L));
626 static assert(signbit(-0.0L));
627 static assert(signbit(-real.max));
628 static assert(!signbit(real.max));
632 Params:
633 to = the numeric value to use
634 from = the sign value to use
635 Returns:
636 a value composed of to with from's sign bit.
638 R copysign(R, X)(R to, X from) @trusted pure nothrow @nogc
639 if (isFloatingPoint!(R) && isFloatingPoint!(X))
641 import std.math.traits : floatTraits, RealFormat;
643 if (__ctfe)
645 return signbit(to) == signbit(from) ? to : -to;
647 ubyte* pto = cast(ubyte *)&to;
648 const ubyte* pfrom = cast(ubyte *)&from;
650 alias T = floatTraits!(R);
651 alias F = floatTraits!(X);
652 pto[T.SIGNPOS_BYTE] &= 0x7F;
653 pto[T.SIGNPOS_BYTE] |= pfrom[F.SIGNPOS_BYTE] & 0x80;
654 return to;
657 /// ditto
658 R copysign(R, X)(X to, R from) @trusted pure nothrow @nogc
659 if (isIntegral!(X) && isFloatingPoint!(R))
661 return copysign(cast(R) to, from);
665 @safe pure nothrow @nogc unittest
667 assert(copysign(1.0, 1.0) == 1.0);
668 assert(copysign(1.0, -0.0) == -1.0);
669 assert(copysign(1UL, -1.0) == -1.0);
670 assert(copysign(-1.0, -1.0) == -1.0);
672 assert(copysign(real.infinity, -1.0) == -real.infinity);
673 assert(copysign(real.nan, 1.0) is real.nan);
674 assert(copysign(-real.nan, 1.0) is real.nan);
675 assert(copysign(real.nan, -1.0) is -real.nan);
678 @safe pure nothrow @nogc unittest
680 import std.meta : AliasSeq;
682 static foreach (X; AliasSeq!(float, double, real, int, long))
684 static foreach (Y; AliasSeq!(float, double, real))
686 X x = 21;
687 Y y = 23.8;
688 Y e = void;
690 e = copysign(x, y);
691 assert(e == 21.0);
693 e = copysign(-x, y);
694 assert(e == 21.0);
696 e = copysign(x, -y);
697 assert(e == -21.0);
699 e = copysign(-x, -y);
700 assert(e == -21.0);
702 static if (isFloatingPoint!X)
704 e = copysign(X.nan, y);
705 assert(isNaN(e) && !signbit(e));
707 e = copysign(X.nan, -y);
708 assert(isNaN(e) && signbit(e));
712 // CTFE
713 static foreach (X; AliasSeq!(float, double, real, int, long))
715 static foreach (Y; AliasSeq!(float, double, real))
717 enum X x = 21;
718 enum Y y = 23.8;
720 assert(21.0 == copysign(x, y));
721 assert(21.0 == copysign(-x, y));
722 assert(-21.0 == copysign(x, -y));
723 assert(-21.0 == copysign(-x, -y));
725 static if (isFloatingPoint!X)
727 static assert(isNaN(copysign(X.nan, y)) && !signbit(copysign(X.nan, y)));
728 assert(isNaN(copysign(X.nan, -y)) && signbit(copysign(X.nan, -y)));
734 /*********************************
735 Returns `-1` if $(D x < 0), `x` if $(D x == 0), `1` if
736 $(D x > 0), and $(NAN) if x==$(NAN).
738 F sgn(F)(F x) @safe pure nothrow @nogc
739 if (isFloatingPoint!F || isIntegral!F)
741 // @@@TODO@@@: make this faster
742 return x > 0 ? 1 : x < 0 ? -1 : x;
746 @safe pure nothrow @nogc unittest
748 assert(sgn(168.1234) == 1);
749 assert(sgn(-168.1234) == -1);
750 assert(sgn(0.0) == 0);
751 assert(sgn(-0.0) == 0);
755 Check whether a number is an integer power of two.
757 Note that only positive numbers can be integer powers of two. This
758 function always return `false` if `x` is negative or zero.
760 Params:
761 x = the number to test
763 Returns:
764 `true` if `x` is an integer power of two.
766 bool isPowerOf2(X)(const X x) pure @safe nothrow @nogc
767 if (isNumeric!X)
769 import std.math.exponential : frexp;
771 static if (isFloatingPoint!X)
773 int exp;
774 const X sig = frexp(x, exp);
776 return (exp != int.min) && (sig is cast(X) 0.5L);
778 else
780 static if (isSigned!X)
782 auto y = cast(typeof(x + 0))x;
783 return y > 0 && !(y & (y - 1));
785 else
787 auto y = cast(typeof(x + 0u))x;
788 return (y & -y) > (y - 1);
793 @safe unittest
795 import std.math.exponential : pow;
797 assert( isPowerOf2(1.0L));
798 assert( isPowerOf2(2.0L));
799 assert( isPowerOf2(0.5L));
800 assert( isPowerOf2(pow(2.0L, 96)));
801 assert( isPowerOf2(pow(2.0L, -77)));
803 assert(!isPowerOf2(-2.0L));
804 assert(!isPowerOf2(-0.5L));
805 assert(!isPowerOf2(0.0L));
806 assert(!isPowerOf2(4.315));
807 assert(!isPowerOf2(1.0L / 3.0L));
809 assert(!isPowerOf2(real.nan));
810 assert(!isPowerOf2(real.infinity));
813 @safe unittest
815 assert( isPowerOf2(1));
816 assert( isPowerOf2(2));
817 assert( isPowerOf2(1uL << 63));
819 assert(!isPowerOf2(-4));
820 assert(!isPowerOf2(0));
821 assert(!isPowerOf2(1337u));
824 @safe unittest
826 import std.math.exponential : pow;
827 import std.meta : AliasSeq;
829 enum smallP2 = pow(2.0L, -62);
830 enum bigP2 = pow(2.0L, 50);
831 enum smallP7 = pow(7.0L, -35);
832 enum bigP7 = pow(7.0L, 30);
834 static foreach (X; AliasSeq!(float, double, real))
836 immutable min_sub = X.min_normal * X.epsilon;
838 foreach (x; [smallP2, min_sub, X.min_normal, .25L, 0.5L, 1.0L,
839 2.0L, 8.0L, pow(2.0L, X.max_exp - 1), bigP2])
841 assert( isPowerOf2(cast(X) x));
842 assert(!isPowerOf2(cast(X)-x));
845 foreach (x; [0.0L, 3 * min_sub, smallP7, 0.1L, 1337.0L, bigP7, X.max, real.nan, real.infinity])
847 assert(!isPowerOf2(cast(X) x));
848 assert(!isPowerOf2(cast(X)-x));
852 static foreach (X; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
854 foreach (x; [1, 2, 4, 8, (X.max >>> 1) + 1])
856 assert( isPowerOf2(cast(X) x));
857 static if (isSigned!X)
858 assert(!isPowerOf2(cast(X)-x));
861 foreach (x; [0, 3, 5, 13, 77, X.min, X.max])
862 assert(!isPowerOf2(cast(X) x));
865 // CTFE
866 static foreach (X; AliasSeq!(float, double, real))
868 enum min_sub = X.min_normal * X.epsilon;
870 static foreach (x; [smallP2, min_sub, X.min_normal, .25L, 0.5L, 1.0L,
871 2.0L, 8.0L, pow(2.0L, X.max_exp - 1), bigP2])
873 static assert( isPowerOf2(cast(X) x));
874 static assert(!isPowerOf2(cast(X)-x));
877 static foreach (x; [0.0L, 3 * min_sub, smallP7, 0.1L, 1337.0L, bigP7, X.max, real.nan, real.infinity])
879 static assert(!isPowerOf2(cast(X) x));
880 static assert(!isPowerOf2(cast(X)-x));
884 static foreach (X; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
886 static foreach (x; [1, 2, 4, 8, (X.max >>> 1) + 1])
888 static assert( isPowerOf2(cast(X) x));
889 static if (isSigned!X)
890 static assert(!isPowerOf2(cast(X)-x));
893 static foreach (x; [0, 3, 5, 13, 77, X.min, X.max])
894 static assert(!isPowerOf2(cast(X) x));
898 // Underlying format exposed through floatTraits
899 enum RealFormat
901 ieeeHalf,
902 ieeeSingle,
903 ieeeDouble,
904 ieeeExtended, // x87 80-bit real
905 ieeeExtended53, // x87 real rounded to precision of double.
906 ibmExtended, // IBM 128-bit extended
907 ieeeQuadruple,
910 // Constants used for extracting the components of the representation.
911 // They supplement the built-in floating point properties.
912 template floatTraits(T)
914 import std.traits : Unqual;
916 // EXPMASK is a ushort mask to select the exponent portion (without sign)
917 // EXPSHIFT is the number of bits the exponent is left-shifted by in its ushort
918 // EXPBIAS is the exponent bias - 1 (exp == EXPBIAS yields ×2^-1).
919 // EXPPOS_SHORT is the index of the exponent when represented as a ushort array.
920 // SIGNPOS_BYTE is the index of the sign when represented as a ubyte array.
921 // RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal
922 enum Unqual!T RECIP_EPSILON = (1/T.epsilon);
923 static if (T.mant_dig == 24)
925 // Single precision float
926 enum ushort EXPMASK = 0x7F80;
927 enum ushort EXPSHIFT = 7;
928 enum ushort EXPBIAS = 0x3F00;
929 enum uint EXPMASK_INT = 0x7F80_0000;
930 enum uint MANTISSAMASK_INT = 0x007F_FFFF;
931 enum realFormat = RealFormat.ieeeSingle;
932 version (LittleEndian)
934 enum EXPPOS_SHORT = 1;
935 enum SIGNPOS_BYTE = 3;
937 else
939 enum EXPPOS_SHORT = 0;
940 enum SIGNPOS_BYTE = 0;
943 else static if (T.mant_dig == 53)
945 static if (T.sizeof == 8)
947 // Double precision float, or real == double
948 enum ushort EXPMASK = 0x7FF0;
949 enum ushort EXPSHIFT = 4;
950 enum ushort EXPBIAS = 0x3FE0;
951 enum uint EXPMASK_INT = 0x7FF0_0000;
952 enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only
953 enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF;
954 enum realFormat = RealFormat.ieeeDouble;
955 version (LittleEndian)
957 enum EXPPOS_SHORT = 3;
958 enum SIGNPOS_BYTE = 7;
960 else
962 enum EXPPOS_SHORT = 0;
963 enum SIGNPOS_BYTE = 0;
966 else static if (T.sizeof == 12)
968 // Intel extended real80 rounded to double
969 enum ushort EXPMASK = 0x7FFF;
970 enum ushort EXPSHIFT = 0;
971 enum ushort EXPBIAS = 0x3FFE;
972 enum realFormat = RealFormat.ieeeExtended53;
973 version (LittleEndian)
975 enum EXPPOS_SHORT = 4;
976 enum SIGNPOS_BYTE = 9;
978 else
980 enum EXPPOS_SHORT = 0;
981 enum SIGNPOS_BYTE = 0;
984 else
985 static assert(false, "No traits support for " ~ T.stringof);
987 else static if (T.mant_dig == 64)
989 // Intel extended real80
990 enum ushort EXPMASK = 0x7FFF;
991 enum ushort EXPSHIFT = 0;
992 enum ushort EXPBIAS = 0x3FFE;
993 enum realFormat = RealFormat.ieeeExtended;
994 version (LittleEndian)
996 enum EXPPOS_SHORT = 4;
997 enum SIGNPOS_BYTE = 9;
999 else
1001 enum EXPPOS_SHORT = 0;
1002 enum SIGNPOS_BYTE = 0;
1005 else static if (T.mant_dig == 113)
1007 // Quadruple precision float
1008 enum ushort EXPMASK = 0x7FFF;
1009 enum ushort EXPSHIFT = 0;
1010 enum ushort EXPBIAS = 0x3FFE;
1011 enum realFormat = RealFormat.ieeeQuadruple;
1012 version (LittleEndian)
1014 enum EXPPOS_SHORT = 7;
1015 enum SIGNPOS_BYTE = 15;
1017 else
1019 enum EXPPOS_SHORT = 0;
1020 enum SIGNPOS_BYTE = 0;
1023 else static if (T.mant_dig == 106)
1025 // IBM Extended doubledouble
1026 enum ushort EXPMASK = 0x7FF0;
1027 enum ushort EXPSHIFT = 4;
1028 enum realFormat = RealFormat.ibmExtended;
1030 // For IBM doubledouble the larger magnitude double comes first.
1031 // It's really a double[2] and arrays don't index differently
1032 // between little and big-endian targets.
1033 enum DOUBLEPAIR_MSB = 0;
1034 enum DOUBLEPAIR_LSB = 1;
1036 // The exponent/sign byte is for most significant part.
1037 version (LittleEndian)
1039 enum EXPPOS_SHORT = 3;
1040 enum SIGNPOS_BYTE = 7;
1042 else
1044 enum EXPPOS_SHORT = 0;
1045 enum SIGNPOS_BYTE = 0;
1048 else
1049 static assert(false, "No traits support for " ~ T.stringof);
1052 // These apply to all floating-point types
1053 version (LittleEndian)
1055 enum MANTISSA_LSB = 0;
1056 enum MANTISSA_MSB = 1;
1058 else
1060 enum MANTISSA_LSB = 1;
1061 enum MANTISSA_MSB = 0;