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.safeop; 8 import checkedint.tests.contract.internal; 9 10 import checkedint.flags, checkedint.noex.safeop; 11 12 void all() { 13 writeln(); 14 write("Testing safeOp... "); 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 = "safeOp.cmp!\"" ~ op ~ "\"(n, m)"; 47 else 48 enum sc = "safeOp.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 static if(mostNegative!N <= cast(M)0 && mostNegative!M <= cast(N)0) 57 fuzz!(sc, Unqual, OutIs!bool, control, N, M)(); 58 else 59 forbid!(sc, N, M)(); 60 } 61 cover!true(); 62 cover!false(); 63 } 64 } 65 alias cmp(N, M = void) = cmp!(null, N, M); 66 67 void abs(N = void)() { 68 static if(is(N == void)) { 69 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 70 abs!N1(); 71 } else { 72 static assert(isFixedPoint!N); 73 74 enum sc = "safeOp.abs(n)"; 75 76 static assert(real.mant_dig >= (8 * N.sizeof)); 77 auto control(const real n, Unused m = null) { 78 return stdm.abs(n); } 79 alias R = CallType!(stdm.abs, N); 80 81 static if(isIntegral!R) 82 fuzz!(sc, Unqual, OutIs!R, control, N)(); 83 else 84 forbid!(sc, N)(); 85 } 86 } 87 88 void unary(string op = null, N = void)() { 89 static if(op == null) { 90 foreach(op1; AliasSeq!("+", "-", "~", "++", "--")) 91 unary!(op1, N)(); 92 } else 93 static if(is(N == void)) { 94 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 95 unary!(op, N1)(); 96 } else { 97 static assert(isFixedPoint!N); 98 99 enum sc = "safeOp.unary!\"" ~ op ~ "\"(n)"; 100 101 static assert(real.mant_dig >= precision!N); 102 auto control(Select!(op == "~", N, real) n, Unused m = null) { 103 return mixin(op ~ "n"); } 104 alias R = OpType!(op, N); 105 106 static if((op != "-" || isSigned!N) && isIntegral!R) 107 fuzz!(sc, Unqual, OutIs!R, control, N)(); 108 else 109 forbid!(sc, N)(); 110 } 111 } 112 alias unary(N) = unary!(null, N); 113 114 void binary(string op = null, N = void, M = void)() { 115 static if(op == null) { 116 foreach(op1; AliasSeq!("+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", "|", "^")) 117 binary!(op1, N, M)(); 118 } else 119 static if(is(N == void)) { 120 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 121 binary!(op, N1, M)(); 122 } else 123 static if(is(M == void)) { 124 foreach(M1; AliasSeq!(IntegralTypes, CharTypes)) 125 binary!(op, N, M1)(); 126 } else { 127 static assert(isFixedPoint!N && isFixedPoint!M); 128 129 static void cover(bool assign)() { 130 enum sc = "safeOp.binary!\"" ~ op ~ (assign? "=" : "") ~ "\"(n, m)"; 131 132 alias P = OpType!(N, op, M); 133 alias R = Select!(assign, N, P); 134 135 static assert(real.mant_dig >= max(precision!N, precision!M)); 136 enum bc = "n " ~ op ~ " m"; 137 static if(op.among!("<<", ">>", ">>>")) { 138 real control(const N n, const M m) { 139 if(m < 0 || m >= (8 * Promoted!(N).sizeof)) 140 return real.nan; 141 142 const wret = mixin(bc); 143 return assign? cast(N)wret : wret; 144 } 145 } else 146 static if(op.among!("&", "|", "^")) { 147 auto control(const N n, const M m) { 148 const wret = mixin(bc); 149 static if(assign) 150 return cast(N)wret; 151 else 152 return wret; 153 } 154 } else { 155 real control(const real n , const real m) { 156 const wret = mixin(bc); 157 static if(op == "/") 158 return stdm.trunc(wret); 159 else 160 static if(op == "%") 161 return ((R.min < 0) && (n == R.min) && (m == -1))? real.nan : wret; 162 else 163 return wret; 164 } 165 } 166 167 enum matchedSigns = (!isSigned!N && !isSigned!M) || 168 (isSigned!P && (isSigned!R || (op == "%" && !isSigned!N))); 169 static if((matchedSigns || op.among!("<<", ">>", ">>>", "&", "|", "^")) && isIntegral!R) 170 fuzz!(sc, Unqual, OutIs!R, control, N, M)(); 171 else 172 forbid!(sc, N, M)(); 173 } 174 cover!false(); 175 cover!true(); 176 } 177 } 178 alias binary(N, M = void) = binary!(null, N, M); 179 180 void byPow2(N = void, M = void)() { 181 static if(is(N == void)) { 182 foreach(N1; AliasSeq!(IntegralTypes, CharTypes)) 183 byPow2!(N1, M)(); 184 } else 185 static if(is(M == void)) { 186 foreach(M1; AliasSeq!(IntegralTypes, CharTypes)) 187 byPow2!(N, M1)(); 188 } else { 189 static assert(isScalarType!N && isScalarType!M); 190 191 static void cover(bool mul)() { 192 enum sc = "safeOp." ~ (mul? "mul" : "div") ~ "Pow2(n, m)"; 193 194 static assert(real.mant_dig >= max(precision!N, precision!M)); 195 real control(const real n, const real m) { 196 if(n == 0 && stdm.isFinite(m)) 197 return 0; 198 else { 199 const p2 = stdm.exp2(m); 200 const wret = mul? (n * p2) : (n / p2); 201 static if(isFloatingPoint!N || isFloatingPoint!M) 202 return wret; 203 else 204 return stdm.trunc(wret); 205 } 206 } 207 enum isVO(N, M, PR) = (PR.sizeof >= N.sizeof) && 208 ((isFloatingPoint!N || isFloatingPoint!M)? 209 isFloatingPoint!PR : 210 isIntegral!PR && (isSigned!PR || !isSigned!N)); 211 212 fuzz!(sc, Unqual, isVO, control, N, M)(); 213 } 214 cover!true(); 215 cover!false(); 216 } 217 } 218 219 void pow(N = void, M = void)() { 220 static if(is(N == void)) { 221 foreach(N1; IntegralTypes) 222 pow!(N1, M)(); 223 } else 224 static if(is(M == void)) { 225 foreach(M1; IntegralTypes) 226 pow!(N, M1)(); 227 } else { 228 static assert(isFixedPoint!N && isFixedPoint!M); 229 forbid!("safeOp.binary!\"^^\"(n, m)", N, M)(); 230 forbid!("safeOp.binary!\"^^=\"(n, m)", N, M)(); 231 232 enum sc = "safeOp.pow(n, m)"; 233 234 static assert(real.mant_dig >= max(precision!N, precision!M)); 235 real control(const real n, const real m) { 236 return (m < 0)? 237 real.nan : 238 stdm.pow(n, m); 239 } 240 alias R = CallType!(stdm.pow, N, M); 241 242 static if((!isSigned!N || isSigned!R) && isIntegral!R) 243 fuzz!(sc, Unqual, OutIs!R, control, N, M)(); 244 else 245 forbid!(sc, N, M)(); 246 } 247 }