github.com/tawesoft/golib/v2@v2.10.0/legacy/operator/template_numbers_test.go (about) 1 package operator 2 3 import "math" // CLASS floats 4 // IGNORE 5 // This file is templated by template-numbers.py // IGNORE 6 // The token _t is replaced by a snakeCase type // IGNORE 7 // The token _T is replaced by a CamelCase type // IGNORE 8 // And lines are conditionally filtered by a command or command; options comment // IGNORE 9 type _t int // IGNORE 10 const max_T = 1000 // IGNORE 11 const min_T = -1000 // IGNORE 12 13 // Some overflow checks with reference to stackoverflow.com/a/1514309/5654201 14 15 type _tUnary struct { 16 Identity func(_t) _t 17 Abs func(_t) _t // CLASS integers, floats; signed 18 Negation func(_t) _t // CLASS integers, floats; signed 19 Not func(_t) _t // CLASS integers; unsigned 20 Zero func(_t) bool 21 NonZero func(_t) bool 22 Positive func(_t) bool 23 Negative func(_t) bool 24 } 25 26 type _tUnaryChecked struct { 27 Abs func(_t) (_t, error) // CLASS integers, floats; signed 28 Negation func(_t) (_t, error) // CLASS integers, floats; signed 29 } 30 31 type _tBinary struct { 32 Add func(_t, _t) _t // CLASS integers, floats, complex 33 Sub func(_t, _t) _t // CLASS integers, floats, complex 34 Mul func(_t, _t) _t // CLASS integers, floats, complex 35 Div func(_t, _t) _t // CLASS integers, floats, complex 36 Mod func(_t, _t) _t // CLASS integers, floats, complex 37 38 Eq func(_t, _t) bool // CLASS integers, floats, complex 39 Neq func(_t, _t) bool // CLASS integers, floats, complex 40 Lt func(_t, _t) bool // CLASS integers, floats, complex 41 Lte func(_t, _t) bool // CLASS integers, floats, complex 42 Gt func(_t, _t) bool // CLASS integers, floats, complex 43 Gte func(_t, _t) bool // CLASS integers, floats, complex 44 45 And func(_t, _t) _t // CLASS integers 46 Or func(_t, _t) _t // CLASS integers 47 Xor func(_t, _t) _t // CLASS integers 48 AndNot func(_t, _t) _t // CLASS integers 49 50 Shl func(_t, uint) _t // CLASS integers 51 Shr func(_t, uint) _t // CLASS integers 52 } 53 54 type _tBinaryChecked struct { 55 Add func(_t, _t) (_t, error) // CLASS integers, floats, complex 56 Sub func(_t, _t) (_t, error) // CLASS integers, floats, complex 57 Mul func(_t, _t) (_t, error) // CLASS integers, floats, complex 58 Div func(_t, _t) (_t, error) // CLASS integers, floats, complex 59 60 Shl func(_t, uint) (_t, error) // CLASS integers 61 Shr func(_t, uint) (_t, error) // CLASS integers 62 } 63 64 type _tNary struct { 65 Add func(... _t) _t // CLASS integers, floats, complex 66 Sub func(... _t) _t // CLASS integers, floats, complex 67 Mul func(... _t) _t // CLASS integers, floats, complex 68 } 69 70 type _tNaryChecked struct { 71 Add func(... _t) (_t, error) // CLASS integers, floats, complex 72 Sub func(... _t) (_t, error) // CLASS integers, floats, complex 73 Mul func(... _t) (_t, error) // CLASS integers, floats, complex 74 } 75 76 // _T implements operations on one (unary), two (binary), or many (nary) arguments of type _t. 77 var _T = struct { 78 Unary _tUnary 79 Binary _tBinary 80 Nary _tNary 81 Reduce func(operatorIdentity _t, operator func(_t, _t) _t, elements ... _t) _t 82 }{ 83 Unary: _tUnary{ 84 Identity: func(a _t) _t { return a }, 85 Abs: _tUnaryAbs, // CLASS integers, floats; signed 86 Negation: func(a _t) _t { return -a }, // CLASS integers, floats; signed 87 Not: func(a _t) _t { return ^a }, // CLASS integers; unsigned 88 Zero: func(a _t) bool { return a == 0 }, 89 NonZero: func(a _t) bool { return a != 0 }, 90 Positive: _tUnaryPositive, 91 Negative: _tUnaryNegative, 92 }, 93 94 Binary: _tBinary{ 95 Add: func(a _t, b _t) _t { return a + b }, // CLASS integers, floats, complex 96 Sub: func(a _t, b _t) _t { return a - b }, // CLASS integers, floats, complex 97 Mul: func(a _t, b _t) _t { return a * b }, // CLASS integers, floats, complex 98 Div: func(a _t, b _t) _t { return a / b }, // CLASS integers, floats, complex 99 100 Eq: func(a _t, b _t) bool { return a == b }, // CLASS integers, floats, complex 101 Neq: func(a _t, b _t) bool { return a != b }, // CLASS integers, floats, complex 102 Lt: func(a _t, b _t) bool { return a < b }, // CLASS integers, floats, complex 103 Lte: func(a _t, b _t) bool { return a <= b }, // CLASS integers, floats, complex 104 Gt: func(a _t, b _t) bool { return a > b }, // CLASS integers, floats, complex 105 Gte: func(a _t, b _t) bool { return a >= b }, // CLASS integers, floats, complex 106 107 And: func(a _t, b _t) _t { return a & b }, // CLASS integers 108 Or: func(a _t, b _t) _t { return a | b }, // CLASS integers 109 Xor: func(a _t, b _t) _t { return a ^ b }, // CLASS integers 110 AndNot: func(a _t, b _t) _t { return a &^ b }, // CLASS integers 111 Mod: func(a _t, b _t) _t { return a % b }, // CLASS integers 112 113 Shl: func(a _t, b uint) _t { return a << b }, // CLASS integers 114 Shr: func(a _t, b uint) _t { return a >> b }, // CLASS integers 115 }, 116 117 Nary: _tNary{ 118 Add: _tNaryAdd, // CLASS integers, floats, complex 119 Mul: _tNaryMul, // CLASS integers, floats, complex 120 }, 121 122 Reduce: _tReduce, 123 } 124 125 // _TChecked implements operations on one (unary), two (binary), or many (nary) arguments of type _t, returning an 126 // error in cases such as overflow or an undefined operation. 127 var _TChecked = struct { 128 Unary _tUnaryChecked 129 Binary _tBinaryChecked 130 Nary _tNaryChecked 131 Reduce func(operatorIdentity _t, operator func(_t, _t) (_t, error), elements ... _t) (_t, error) 132 }{ 133 Unary: _tUnaryChecked{ 134 Abs: _tUnaryCheckedAbs, // CLASS integers, floats; signed 135 Negation: _tUnaryCheckedNegation, // CLASS integers, floats; signed 136 }, 137 138 Binary: _tBinaryChecked{ 139 Add: _tBinaryCheckedAdd, // CLASS integers, floats, complex 140 Sub: _tBinaryCheckedSub, // CLASS integers, floats, complex 141 Mul: _tBinaryCheckedMul, // CLASS integers, floats, complex 142 Div: _tBinaryCheckedDiv, // CLASS integers, floats, complex 143 Shl: _tBinaryCheckedShl, // CLASS integers 144 }, 145 146 Nary: _tNaryChecked{ 147 Add: _tNaryCheckedAdd, // CLASS integers, floats, complex 148 Mul: _tNaryCheckedMul, // CLASS integers, floats, complex 149 }, 150 151 Reduce: _tCheckedReduce, 152 } 153 154 func _tUnaryPositive(a _t) bool { 155 return math.Signbit(float64(a)) == false // CLASS floats 156 return a > 0 // CLASS integers 157 } 158 159 func _tUnaryNegative(a _t) bool { 160 return math.Signbit(float64(a)) == true // CLASS floats 161 return a < 0 // CLASS integers 162 } 163 164 func _tUnaryAbs(a _t) _t { // CLASS integers, floats; signed 165 return _t(math.Abs(float64(a))) // CLASS floats 166 if a < 0 { return -a } // CLASS integers; signed 167 return a // CLASS integers; signed 168 } // CLASS integers, floats; signed 169 170 // note abs(+/- Inf) = +Inf // CLASS floats 171 func _tUnaryCheckedAbs(a _t) (v _t, err error) { // CLASS integers, floats; signed 172 if a == min_T { return v, ErrorOverflow } // CLASS integers; signed 173 if math.IsNaN(float64(a)) { return v, ErrorNaN } // CLASS floats 174 return _t(math.Abs(float64(a))), nil // CLASS floats 175 if a < 0 { return -a, nil } // CLASS integers; signed 176 return a, nil // CLASS integers; signed 177 } // CLASS integers, floats; signed 178 179 func _tUnaryCheckedNegation(a _t) (v _t, err error) { // CLASS integers, floats; signed 180 if (a == min_T) { return v, ErrorOverflow } // CLASS integers; signed 181 if math.IsNaN(float64(a)) { return v, ErrorNaN } // CLASS floats 182 return -a, nil // CLASS integers, floats; signed 183 } // CLASS integers, floats; signed 184 185 func _tBinaryCheckedAdd(a _t, b _t) (v _t, err error) { 186 if (b > 0) && (a > (max_T - b)) { return v, ErrorOverflow } 187 if (b < 0) && (a < (min_T - b)) { return v, ErrorOverflow } 188 return a + b, nil 189 } 190 191 func _tBinaryCheckedSub(a _t, b _t) (v _t, err error) { 192 if (b < 0) && (a > (max_T + b)) { return v, ErrorOverflow } 193 if (b > 0) && (a < (min_T + b)) { return v, ErrorOverflow } 194 return a - b, nil 195 } 196 197 func _tBinaryCheckedMul(a _t, b _t) (v _t, err error) { 198 if (a == -1) && (b == min_T) { return v, ErrorOverflow } // CLASS integers; signed 199 if (b == -1) && (a == min_T) { return v, ErrorOverflow } // CLASS integers; signed 200 if (a > (max_T / b)) { return v, ErrorOverflow } 201 if (a < (min_T / b)) { return v, ErrorOverflow } 202 203 return a * b, nil 204 } 205 206 func _tBinaryCheckedDiv(a _t, b _t) (v _t, err error) { 207 if math.IsNaN(float64(a)) { return v, ErrorNaN } // CLASS floats 208 if (b == -1) && (a == min_T) { return v, ErrorOverflow } // CLASS integers; signed 209 if (b == 0) { return v, ErrorUndefined } 210 211 return a / b, nil 212 } 213 214 func _tBinaryCheckedShl(a _t, b uint) (v _t, err error) { // CLASS integers 215 if a < 0 { return v, ErrorUndefined } // CLASS integers; signed 216 if b > uint(_tMostSignificantBit(max_T)) { return v, ErrorOverflow } // CLASS integers 217 return v, err // CLASS integers 218 } // CLASS integers 219 220 func _tMostSignificantBit(a _t) (result int) { // CLASS integers 221 for a > 0 { // CLASS integers 222 a >>= 1 // CLASS integers 223 result++ // CLASS integers 224 } // CLASS integers 225 return result; // CLASS integers 226 } // CLASS integers 227 228 func _tNaryAdd(xs ... _t) (result _t) { 229 for i := 0; i < len(xs); i++ { 230 result += xs[i] 231 } 232 return result 233 } 234 235 func _tNaryCheckedAdd(xs ... _t) (result _t, err error) { 236 for i := 0; i < len(xs); i++ { 237 result, err = _tBinaryCheckedAdd(result, xs[i]) 238 if err != nil { return result, err } 239 } 240 return result, nil 241 } 242 243 func _tNaryMul(xs ... _t) (result _t) { 244 result = 1 245 for i := 0; i < len(xs); i++ { 246 result *= xs[i] 247 } 248 return result 249 } 250 251 func _tNaryCheckedMul(xs ... _t) (result _t, err error) { 252 result = 1 253 for i := 0; i < len(xs); i++ { 254 result, err = _tBinaryCheckedMul(result, xs[i]) 255 if err != nil { return result, err } 256 } 257 return result, nil 258 } 259 260 func _tReduce(operatorIdentity _t, operator func(_t, _t) _t, elements ... _t) (result _t) { 261 result = operatorIdentity 262 for i := 0; i < len(elements); i++ { 263 result = operator(result, elements[i]) 264 } 265 return result 266 } 267 268 func _tCheckedReduce(operatorIdentity _t, operator func(_t, _t) (_t, error), elements ... _t) (result _t, err error) { 269 result = operatorIdentity 270 for i := 0; i < len(elements); i++ { 271 result, err = operator(result, elements[i]) 272 if err != nil { return result, err } 273 } 274 return result, err 275 } 276