1 module nxt.math_ex; 2 3 import std.traits : isIntegral, isUnsigned, isNumeric; 4 5 /** Check if `x` is an exact (binary) power of 2. 6 * 7 * See_Also: http://forum.dlang.org/thread/zumhmosfkvwjymjhmtlt@forum.dlang.org#post-fvnmurrctavpfkunssdf:40forum.dlang.org 8 * See_Also: http://forum.dlang.org/post/hloonbgclzloqemycnth@forum.dlang.org 9 */ 10 bool isPow2(T)(T x) 11 if (isNumeric!T) 12 { 13 import std.math : isPowerOf2; // https://github.com/dlang/phobos/pull/4327/files 14 return isPowerOf2(x); 15 } 16 alias isPowerOf2 = isPow2; 17 18 /// ditto 19 bool isPow2A(T)(T x) if (isIntegral!T) 20 { 21 return x && !(x & (x - 1)); 22 } 23 24 /// ditto 25 bool isPow2B(T)(T x) if (isIntegral!T) 26 { 27 return (x & -x) > (x - 1); 28 } 29 30 bool isPow2D(T)(T x) if (isIntegral!T) 31 { 32 return (x > 0) && !(x & (x - 1)); 33 } 34 35 /// ditto, avoids a jump instruction. 36 bool isPow2E(T)(T x) if (isIntegral!T) 37 { 38 return (x > 0) & !(x & (x - 1)); 39 } 40 41 /// ditto 42 bool isPow2F(T)(T x) if (isIntegral!T) 43 { 44 return (x & -x) > (x >>> 1); 45 } 46 47 /// 48 @safe pure nothrow @nogc unittest 49 { 50 import std.meta : AliasSeq; 51 foreach (fn; AliasSeq!(isPow2, isPow2A, isPow2D, isPow2E, isPow2F)) 52 { 53 // run-time 54 assert(!fn(7)); 55 assert(fn(8)); 56 assert(!fn(9)); 57 58 // compile-time 59 static assert(!fn(7)); 60 static assert(fn(8)); 61 static assert(!fn(9)); 62 63 assert(!fn(0)); 64 assert(fn(1)); 65 assert(fn(2)); 66 assert(!fn(3)); 67 assert(fn(4)); 68 assert(!fn(5)); 69 assert(!fn(6)); 70 assert(!fn(7)); 71 assert(fn(8)); 72 } 73 } 74 75 /** Check if `x` is an exact (binary) power of 2, except when `x` is zero then 76 * zero is returned. 77 * 78 * See_Also: http://forum.dlang.org/thread/zumhmosfkvwjymjhmtlt@forum.dlang.org#post-fvnmurrctavpfkunssdf:40forum.dlang.org 79 * See_Also: http://forum.dlang.org/post/hloonbgclzloqemycnth@forum.dlang.org 80 */ 81 bool isPow2fast(T)(T x) 82 if (isUnsigned!T) 83 { 84 return (x & (x - 1)) == 0; 85 } 86 87 @safe pure nothrow @nogc unittest 88 { 89 import std.meta : AliasSeq; 90 foreach (fn; AliasSeq!(isPow2fast)) 91 { 92 // run-time 93 assert(!fn(7U)); 94 assert(fn(8U)); 95 assert(!fn(9U)); 96 97 // compile-time 98 static assert(!fn(7U)); 99 static assert(fn(8U)); 100 static assert(!fn(9U)); 101 102 assert(fn(1U)); 103 assert(fn(2U)); 104 assert(!fn(3U)); 105 assert(fn(4U)); 106 assert(!fn(5U)); 107 assert(!fn(6U)); 108 assert(!fn(7U)); 109 assert(fn(8U)); 110 } 111 }