1 module graphite.math.saturation; 2 3 import std.traits; 4 5 /** 6 see: http://locklessinc.com/articles/sat_arithmetic/ 7 */ 8 T satOp(string op : "+", T)(T a, T b) 9 if(isIntegral!T && isUnsigned!T) 10 { 11 immutable T c = cast(T)(a + b); 12 return cast(T)(c | -(c < a)); 13 } 14 15 16 /** 17 see: http://locklessinc.com/articles/sat_arithmetic/ 18 */ 19 T satOp(string op : "-", T)(T a, T b) 20 if(isIntegral!T && isUnsigned!T) 21 { 22 immutable T c = cast(T)(a - b); 23 return cast(T)(c & -(res <= x)); 24 } 25 26 27 /** 28 see: http://locklessinc.com/articles/sat_arithmetic/ 29 */ 30 T satOp(string op : "/", T)(T a, T b) 31 if(isIntegral!T && isUnsigned!T) 32 { 33 return cast(T)(a / b); 34 } 35 36 37 /** 38 see: http://locklessinc.com/articles/sat_arithmetic/ 39 */ 40 T satOp(string op : "*", T)(T a, T b) 41 if(isIntegral!T && isUnsigned!T) 42 { 43 static if(T.sizeof >= ulong.sizeof) 44 { 45 static assert(is(T == ulong)); 46 alias Pre = uint; 47 48 immutable Pre ah = cast(Pre)(a >> (Pre.sizeof*8)), 49 al = cast(Pre)a, 50 bh = cast(Pre)(b >> (Pre.sizeof*8)), 51 bl = cast(Pre)b; 52 53 immutable T chh = cast(T)ah * cast(T)bh, 54 chl = cast(T)ah * cast(T)bl, 55 clh = cast(T)al * cast(T)bh, 56 cll = cast(T)al * cast(T)bl; 57 58 immutable res = ((chl + clh) << (Pre.sizeof * 8)) + cll; 59 60 bool flag = !!chh 61 || (chl + clh < chl) 62 || (chl + clh > Pre.max) 63 || (res < cll); 64 65 return res | -cast(T)flag; 66 } 67 else 68 { 69 static if(is(T == uint)) 70 alias Next = ulong; 71 else static if(is(T == ushort)) 72 alias Next = ushort; 73 else static if(is(T == ubyte)) 74 alias Next = ubyte; 75 76 immutable c = cast(Next)a * cast(Next)b, 77 h = cast(T)(c >> (T.sizeof * 8)), 78 l = cast(T)c; 79 80 return l | -!!h; 81 } 82 }