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 /// ditto 18 bool isPow2A(T)(T x) if (isIntegral!T) => x && !(x & (x - 1)); 19 /// ditto 20 bool isPow2B(T)(T x) if (isIntegral!T) => (x & -x) > (x - 1); 21 /// ditto 22 bool isPow2D(T)(T x) if (isIntegral!T) => (x > 0) && !(x & (x - 1)); 23 /// ditto, avoids a jump instruction. 24 bool isPow2E(T)(T x) if (isIntegral!T) => (x > 0) & !(x & (x - 1)); 25 /// ditto 26 bool isPow2F(T)(T x) if (isIntegral!T) => (x & -x) > (x >>> 1); 27 28 /// 29 pure nothrow @safe @nogc unittest { 30 import std.meta : AliasSeq; 31 foreach (fn; AliasSeq!(isPow2, isPow2A, isPow2D, isPow2E, isPow2F)) 32 { 33 // run-time 34 assert(!fn(7)); 35 assert(fn(8)); 36 assert(!fn(9)); 37 38 // compile-time 39 static assert(!fn(7)); 40 static assert(fn(8)); 41 static assert(!fn(9)); 42 43 assert(!fn(0)); 44 assert(fn(1)); 45 assert(fn(2)); 46 assert(!fn(3)); 47 assert(fn(4)); 48 assert(!fn(5)); 49 assert(!fn(6)); 50 assert(!fn(7)); 51 assert(fn(8)); 52 } 53 } 54 55 /** Check if `x` is an exact (binary) power of 2, except when `x` is zero then 56 * zero is returned. 57 * 58 * See_Also: http://forum.dlang.org/thread/zumhmosfkvwjymjhmtlt@forum.dlang.org#post-fvnmurrctavpfkunssdf:40forum.dlang.org 59 * See_Also: http://forum.dlang.org/post/hloonbgclzloqemycnth@forum.dlang.org 60 */ 61 bool isPow2fast(T)(T x) if (isUnsigned!T) => (x & (x - 1)) == 0; 62 63 pure nothrow @safe @nogc unittest { 64 import std.meta : AliasSeq; 65 foreach (fn; AliasSeq!(isPow2fast)) 66 { 67 // run-time 68 assert(!fn(7U)); 69 assert(fn(8U)); 70 assert(!fn(9U)); 71 72 // compile-time 73 static assert(!fn(7U)); 74 static assert(fn(8U)); 75 static assert(!fn(9U)); 76 77 assert(fn(1U)); 78 assert(fn(2U)); 79 assert(!fn(3U)); 80 assert(fn(4U)); 81 assert(!fn(5U)); 82 assert(!fn(6U)); 83 assert(!fn(7U)); 84 assert(fn(8U)); 85 } 86 }