1 module libd.util.maths; 2 3 import libd.meta.traits; 4 5 T alignTo(alias Boundary, T)(T value) pure 6 { 7 static if(isPowerOfTwo(Boundary)) 8 return (value + (Boundary * (value % Boundary > 0))) & ~(Boundary-1); 9 else static assert(false, "TODO"); 10 } 11 /// 12 @("alignTo") 13 unittest 14 { 15 assert(alignTo!16(0) == 0); 16 assert(alignTo!16(16) == 16); 17 assert(alignTo!16(8) == 16); 18 assert(alignTo!16(31) == 32); 19 } 20 21 bool isPowerOfTwo(T)(T value) 22 { 23 return (value != 0) && (value & (value - 1)) == 0; 24 } 25 /// 26 @("isPowerOfTwo") 27 unittest 28 { 29 assert(2.isPowerOfTwo); 30 assert(4.isPowerOfTwo); 31 assert(128.isPowerOfTwo); 32 assert(!3.isPowerOfTwo); 33 } 34 35 UnsignedOf!NumT abs(NumT)(NumT value) 36 { 37 static if(__traits(isIntegral, NumT)) 38 return cast(typeof(return))(value * ((value > 0) - (value < 0))); 39 else static assert(false, "Don't know how to abs type '"~NumT.stringof~"'"); 40 } 41 /// 42 @("abs") 43 unittest 44 { 45 assert(0.abs == 0); 46 assert(1.abs == 1); 47 assert((-1).abs == 1); 48 assert((-128).abs!byte == 128); 49 } 50 51 // https://stackoverflow.com/a/11398748 52 private const uint[32] tab32 = [ 53 0, 9, 1, 10, 13, 21, 2, 29, 54 11, 14, 16, 18, 22, 25, 3, 30, 55 8, 12, 20, 28, 15, 17, 24, 7, 56 19, 27, 23, 6, 26, 5, 4, 31]; 57 private uint log2_32 (uint value) @safe @nogc nothrow pure 58 { 59 value |= value >> 1; 60 value |= value >> 2; 61 value |= value >> 4; 62 value |= value >> 8; 63 value |= value >> 16; 64 return tab32[cast(uint)(value*0x07C4ACDD) >> 27]; 65 } 66 private const uint[64] tab64 = [ 67 63, 0, 58, 1, 59, 47, 53, 2, 68 60, 39, 48, 27, 54, 33, 42, 3, 69 61, 51, 37, 40, 49, 18, 28, 20, 70 55, 30, 34, 11, 43, 14, 22, 4, 71 62, 57, 46, 52, 38, 26, 32, 41, 72 50, 36, 17, 19, 29, 10, 13, 21, 73 56, 45, 25, 31, 35, 16, 9, 12, 74 44, 24, 15, 8, 23, 7, 6, 5]; 75 private uint log2_64 (ulong value) @safe @nogc nothrow pure 76 { 77 value |= value >> 1; 78 value |= value >> 2; 79 value |= value >> 4; 80 value |= value >> 8; 81 value |= value >> 16; 82 value |= value >> 32; 83 return tab64[(cast(ulong)((value - (value >> 1))*0x07EDD5E59A4E28C2)) >> 58]; 84 } 85 86 uint log2(T)(const T value) 87 { 88 alias VT = typeof(value); 89 static if(is(VT == const int) || is(VT == const uint)) 90 return log2_32(value); 91 else static if(is(VT == const long) || is(VT == const ulong)) 92 return log2_64(value); 93 else 94 static assert(false, "Don't know how to log2 type: "~T.stringof); 95 } 96 97 IntT ceilToInt(IntT)(double value) 98 { 99 const isNegative = value < 0; 100 const isWhole = value % 1 == 0; 101 return cast(IntT)value + ( 102 (1 * (-1 * isNegative)) * !isWhole 103 ); 104 }