1 /** Count leading zeros. 2 */ 3 module nxt.clz; 4 5 import std.traits : Unqual; 6 7 /******************************************************************************* 8 * 9 * Count leading zeroes. 10 * 11 * Params: 12 * u = the unsigned value to scan 13 * 14 * Returns: 15 * The number of leading zero bits before the first one bit. If `u` is `0`, 16 * the result is undefined. 17 * 18 **************************************/ 19 version (DigitalMars) { 20 pragma(inline, true) 21 U clz(U)(U u) @safe @nogc pure nothrow 22 if (is(Unqual!U == uint) || 23 is(Unqual!U == size_t)) 24 => (cast(U)(8 * U.sizeof - 1)) - bsr(u); 25 26 static if (isX86) { 27 pragma(inline, true) 28 uint clz(U)(U u) @safe @nogc pure nothrow 29 if (is(Unqual!U == ulong)) { 30 uint hi = u >> 32; 31 return hi ? 31 - bsr(hi) : 63 - bsr(cast(uint)u); 32 } 33 } 34 } 35 else version (GNU) { 36 import gcc.builtins; 37 alias clz = __builtin_clz; 38 static if (isX86) { 39 @safe @nogc pure nothrow uint 40 clz(ulong u) { 41 uint hi = u >> 32; 42 return hi ? __builtin_clz(hi) : 32 + __builtin_clz(cast(uint)u); 43 } 44 } 45 else alias clz = __builtin_clzl; 46 } 47 else version (LDC) { 48 import ldc.intrinsics; 49 pragma(inline, true) 50 U clz(U)(U u) @safe @nogc pure nothrow 51 if (is(Unqual!U == uint) || is(Unqual!U == size_t)) 52 => llvm_ctlz(u, false); 53 54 static if (isX86) { 55 pragma(inline, true) 56 uint clz(U)(U u) @safe @nogc pure nothrow 57 if (is(Unqual!U == ulong)) 58 => cast(uint)llvm_ctlz(u, false); 59 } 60 } 61 62 version (X86_64) { 63 private enum isAMD64 = true; 64 private enum isX86 = false; 65 } 66 else version (X86) { 67 private enum isAMD64 = false; 68 private enum isX86 = true; 69 } 70 71 version (X86_64) 72 private enum hasSSE2 = true; 73 else 74 private enum hasSSE2 = false; 75 76 static import core.bitop; 77 78 alias bsr = core.bitop.bsr; 79 alias bsf = core.bitop.bsf; 80 81 pure nothrow @safe @nogc unittest { 82 assert(clz(uint(0x01234567)) == 7); 83 assert(clz(ulong(0x0123456701234567)) == 7); 84 assert(clz(ulong(0x0000000001234567)) == 7+32); 85 assert(bsr(uint(0x01234567)) == 24); 86 assert(bsr(ulong(0x0123456701234567)) == 24+32); 87 assert(bsr(ulong(0x0000000001234567)) == 24); 88 assert(bsf(uint(0x76543210)) == 4); 89 assert(bsf(ulong(0x7654321076543210)) == 4); 90 assert(bsf(ulong(0x7654321000000000)) == 4+32); 91 }