1 /** 2 * Number stuff 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.utils.math; 15 16 public import std.algorithm : min, max, swap; 17 public import std.math; 18 import std.traits : Signed, Unsigned; 19 import core.bitop : bswap; 20 21 typeof(Ta+Tb+Tc) bound(Ta, Tb, Tc)(Ta a, Tb b, Tc c) { return a<b?b:a>c?c:a; } 22 bool between(T)(T point, T a, T b) { return a <= point && point <= b; } /// Assumes points are sorted (was there a faster way?) 23 auto sqr(T)(T x) { return x*x; } 24 25 void sort2(T)(ref T x, ref T y) { if (x > y) { T z=x; x=y; y=z; } } 26 27 T itpl(T, U)(T low, T high, U r, U rLow, U rHigh) 28 { 29 return cast(T)(low + (cast(Signed!T)high-cast(Signed!T)low) * (cast(Signed!U)r - cast(Signed!U)rLow) / (cast(Signed!U)rHigh - cast(Signed!U)rLow)); 30 } 31 32 byte sign(T)(T x) { return x<0 ? -1 : x>0 ? 1 : 0; } 33 34 int compare(T)(T a, T b) 35 { 36 return a<b ? -1 : a>b ? 1 : 0; 37 } 38 39 auto op(string OP, T...)(T args) 40 { 41 auto result = args[0]; 42 foreach (arg; args[1..$]) 43 mixin("result" ~ OP ~ "=arg;"); 44 return result; 45 } 46 47 auto sum(T...)(T args) { return op!"+"(args); } 48 auto average(T...)(T args) { return sum(args) / args.length; } 49 50 T swapBytes(T)(T b) 51 { 52 static if (b.sizeof == 1) 53 return b; 54 else 55 static if (b.sizeof == 2) 56 return cast(T)((b >> 8) | (b << 8)); 57 else 58 static if (b.sizeof == 4) 59 return bswap(b); 60 else 61 static assert(false, "Don't know how to bswap " ~ T.stringof); 62 } 63 64 bool isPowerOfTwo(T)(T x) { return (x & (x-1)) == 0; } 65 T roundUpToPowerOfTwo(T)(T x) { return nextPowerOfTwo(x-1); } 66 T nextPowerOfTwo(T)(T x) 67 { 68 x |= x >> 1; 69 x |= x >> 2; 70 x |= x >> 4; 71 static if (T.sizeof > 1) 72 x |= x >> 8; 73 static if (T.sizeof > 2) 74 x |= x >> 16; 75 static if (T.sizeof > 4) 76 x |= x >> 32; 77 return x + 1; 78 } 79 80 /// Integer log2. 81 ubyte ilog2(T)(T n) 82 { 83 ubyte result = 0; 84 while (n >>= 1) 85 result++; 86 return result; 87 } 88 89 unittest 90 { 91 assert(ilog2(0) == 0); 92 assert(ilog2(1) == 0); 93 assert(ilog2(2) == 1); 94 assert(ilog2(3) == 1); 95 assert(ilog2(4) == 2); 96 } 97 98 /// Returns the number of bits needed to 99 /// store a number up to n (inclusive). 100 ubyte bitsFor(T)(T n) 101 { 102 return cast(ubyte)(ilog2(n)+1); 103 } 104 105 unittest 106 { 107 assert(bitsFor( int.max) == 31); 108 assert(bitsFor(uint.max) == 32); 109 } 110 111 /// Get the smallest built-in unsigned integer type 112 /// that can store this many bits of data. 113 template TypeForBits(uint bits) 114 { 115 static if (bits <= 8) 116 alias TypeForBits = ubyte; 117 else 118 static if (bits <= 16) 119 alias TypeForBits = ushort; 120 else 121 static if (bits <= 32) 122 alias TypeForBits = uint; 123 else 124 static if (bits <= 64) 125 alias TypeForBits = ulong; 126 else 127 static assert(false, "No integer type big enough for " ~ bits.stringof ~ " bits"); 128 } 129 130 static assert(is(TypeForBits!7 == ubyte)); 131 static assert(is(TypeForBits!8 == ubyte)); 132 static assert(is(TypeForBits!9 == ushort)); 133 static assert(is(TypeForBits!64 == ulong)); 134 static assert(!is(TypeForBits!65));