1 /** 2 Copyright: Copyright Thomas Stuart Bockman 2015 3 License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 4 Authors: Thomas Stuart Bockman 5 */ 6 7 module checkedint.tests.contract.smartop; 8 import checkedint.tests.contract.internal; 9 10 import checkedint.flags; 11 12 void all() { 13 writeln(); 14 write("Testing smartOp... "); 15 stdout.flush(); 16 17 cmp(); 18 abs(); 19 unary(); 20 binary(); 21 byPow2(); 22 pow(); 23 24 writeln("DONE"); 25 } 26 27 /+@safe:+/ 28 29 void cmp(string op = null, N = void, M = void)() { 30 static if(op == null) { 31 foreach(op1; AliasSeq!("==", "!=", "<", "<=", ">", ">=")) 32 cmp!(op1, N, M)(); 33 } else 34 static if(is(N == void)) { 35 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 36 cmp!(op, N1, M)(); 37 } else 38 static if(is(M == void)) { 39 foreach(M1; AliasSeq!(IntegralTypes, CharTypes)) 40 cmp!(op, N, M1)(); 41 } else { 42 static assert(isScalarType!N && isScalarType!M); 43 44 static void cover(bool direct)() { 45 static if(direct) 46 enum sc = "smartOp.cmp!\"" ~ op ~ "\"(n, m)"; 47 else 48 enum sc = "smartOp.cmp(n, m) " ~ op ~ " 0"; 49 50 static assert(real.mant_dig >= max(precision!N, precision!M)); 51 auto control(const real n, const real m) { 52 auto wret = stdm.cmp(n, m); 53 return mixin("wret " ~ op ~ " 0"); 54 } 55 56 fuzz!(sc, Unqual, OutIs!bool, control, N, M)(); 57 } 58 cover!true(); 59 cover!false(); 60 } 61 } 62 alias cmp(N, M = void) = cmp!(null, N, M); 63 64 void abs(N = void)() { 65 static if(is(N == void)) { 66 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 67 abs!N1(); 68 } else { 69 static assert(isFixedPoint!N); 70 71 enum sc = "smartOp.abs(n)"; 72 73 static assert(real.mant_dig >= precision!N); 74 auto control(const real n, Unused m = null) { 75 return stdm.abs(n); } 76 alias R = Unsigned!(IntFromChar!N); 77 78 fuzz!(sc, Unqual, OutIs!R, control, N)(); 79 } 80 } 81 82 void unary(string op = null, N = void)() { 83 static if(op == null) { 84 foreach(op1; AliasSeq!("~", "+", "-", "++", "--")) 85 unary!(op1, N)(); 86 } else 87 static if(is(N == void)) { 88 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 89 unary!(op, N1)(); 90 } else { 91 static assert(isFixedPoint!N); 92 93 enum sc = "smartOp.unary!\"" ~ op ~ "\"(n)"; 94 95 static assert(real.mant_dig >= precision!N); 96 auto control(Select!(op == "~", N, real) n, Unused m = null) { 97 return mixin(op ~ "n"); } 98 enum isVO(N, M, PR) = (PR.sizeof >= N.sizeof) && (isSigned!PR || !op.among!("-", "+")); 99 100 static if(isIntegral!N || !op.among!("++", "--")) 101 fuzz!(sc, Unqual, isVO, control, N)(); 102 else 103 forbid!(sc, N)(); 104 } 105 } 106 alias unary(N) = unary!(null, N); 107 108 void binary(string op = null, N = void, M = void)() { 109 static if(op == null) { 110 foreach(op1; AliasSeq!("+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", "|", "^")) 111 binary!(op1, N, M)(); 112 } else 113 static if(is(N == void)) { 114 foreach(N1; AliasSeq!(IntegralTypes/+TODO:, CharTypes+/)) 115 binary!(op, N1, M)(); 116 } else 117 static if(is(M == void)) { 118 foreach(M1; AliasSeq!(IntegralTypes/+TODO:, CharTypes+/)) 119 binary!(op, N, M1)(); 120 } else { 121 static assert(isFixedPoint!N && isFixedPoint!M); 122 123 enum sc = "smartOp.binary!\"" ~ op ~ "\"(n, m)"; 124 125 static assert(real.mant_dig >= max(precision!N, precision!M)); 126 static if(op.among!("<<", ">>", ">>>")) { 127 static N control(const N n, const M m) { 128 const shL = (op == "<<") ^ (m < 0); 129 enum int maxSh = (8 * N.sizeof) - 1; 130 const um = cast(Unsigned!M)std.math.abs(m); 131 132 static if(op == ">>>") 133 auto wret = cast(Unsigned!N)n; 134 else 135 N wret = n; 136 bool again = um > maxSh; 137 const im = again? maxSh : cast(int)um; 138 Lagain: 139 wret = cast(typeof(wret))(shL? 140 wret << im : 141 wret >> im); 142 if(again) { 143 again = false; 144 goto Lagain; 145 } 146 147 return cast(N)wret; 148 } 149 enum isVO(N, M, PR) = is(PR == N); 150 } else 151 static if(op.among!("&", "|", "^")) { 152 static auto control(const N n, const M m) { 153 alias P = Select!(N.sizeof >= M.sizeof, N, M); 154 alias R = Select!(isSigned!N && isSigned!M, P, Unsigned!P); 155 156 return cast(R)mixin("n " ~ op ~ " m"); 157 } 158 template isVO(N, M, PR) { 159 private alias UR = Unsigned!PR; 160 enum isVO = (isSigned!PR == (isSigned!N && isSigned!M)) && 161 (is(UR == Unsigned!N) || is(UR == Unsigned!M)); 162 } 163 } else { 164 static auto control(const real n, const real m) { 165 static if(op == "/") 166 return stdm.trunc(n / m); 167 else 168 return mixin("n " ~ op ~ " m"); 169 } 170 enum isVO(N, M, PR) = isIntegral!PR && 171 ((isSigned!PR == (isSigned!N || (isSigned!M && op != "%"))) || op == "-"); 172 } 173 174 fuzz!(sc, Unqual, isVO, control, N, M)(); 175 } 176 } 177 alias binary(N, M = void) = binary!(null, N, M); 178 179 void byPow2(N = void, M = void)() { 180 static if(is(N == void)) { 181 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 182 byPow2!(N1, M)(); 183 } else 184 static if(is(M == void)) { 185 foreach(M1; AliasSeq!(IntegralTypes, CharTypes)) 186 byPow2!(N, M1)(); 187 } else { 188 static assert(isScalarType!N && isScalarType!M); 189 190 static void cover(bool mul)() { 191 enum sc = "smartOp." ~ (mul? "mul" : "div") ~ "Pow2(n, m)"; 192 193 static assert(real.mant_dig >= max(precision!N, precision!M)); 194 real control(const real n, const real m) { 195 if(n == 0 && stdm.isFinite(m)) 196 return 0; 197 else { 198 const p2 = stdm.exp2(m); 199 const wret = mul? (n * p2) : (n / p2); 200 static if(isFloatingPoint!N || isFloatingPoint!M) 201 return wret; 202 else 203 return stdm.trunc(wret); 204 } 205 } 206 enum isVO(N, M, PR) = (PR.sizeof >= N.sizeof) && 207 ((isFloatingPoint!N || isFloatingPoint!M)? 208 isFloatingPoint!PR : 209 isIntegral!PR && (isSigned!PR || !isSigned!N)); 210 211 fuzz!(sc, Unqual, isVO, control, N, M)(); 212 } 213 cover!true(); 214 cover!false(); 215 } 216 } 217 218 void pow(N = void, M = void)() { 219 static if(is(N == void)) { 220 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 221 pow!(N1, M)(); 222 } else 223 static if(is(M == void)) { 224 foreach(M1; AliasSeq!(IntegralTypes, CharTypes)) 225 pow!(N, M1)(); 226 } else { 227 static assert(isFixedPoint!N && isFixedPoint!M); 228 forbid!("smartOp.binary!\"^^\"(n, m)", N, M)(); 229 forbid!("smartOp.binary!\"^^=\"(n, m)", N, M)(); 230 231 enum sc = "smartOp.pow(n, m)"; 232 233 static assert(real.mant_dig >= max(precision!N, precision!M)); 234 real control(const real n, const real m) { 235 static if(__VERSION__ >= 2070) { 236 version(GNU) { static assert(false); } 237 return stdm.trunc(stdm.pow(n, m)); 238 } else { 239 // DMD issue #14786 240 if(n == -1 && stdm.fabs(m) <= ulong.max) 241 return (cast(ulong)m & 0x1)? -1 : 1; 242 else 243 return stdm.trunc(stdm.pow(n, m)); 244 } 245 } 246 enum isVO(N, M, PR) = isIntegral!PR && (PR.sizeof >= N.sizeof) && (isSigned!PR == isSigned!N); 247 248 fuzz!(sc, Unqual, isVO, control, N, M)(); 249 } 250 }