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