| 241 | using numeric_integer = long long int; |
| 242 | |
| 243 | class numeric final { |
| 244 | union { |
| 245 | numeric_float _num; |
| 246 | numeric_integer _int; |
| 247 | } data; |
| 248 | bool type = 1; |
| 249 | |
| 250 | static COVSCRIPT_ALWAYS_INLINE std::uint8_t get_composite_type(bool lhs, bool rhs) noexcept |
| 251 | { |
| 252 | return lhs << 1 | rhs; |
| 253 | } |
| 254 | |
| 255 | static inline numeric int_pow(numeric_integer base, numeric_integer exp) |
| 256 | { |
| 257 | if (exp == 0) // base^0 |
| 258 | return 1; |
| 259 | if (base == 0 && exp < 0) { |
| 260 | // 0^negative |
| 261 | errno = EDOM; |
| 262 | feraiseexcept(FE_DIVBYZERO); |
| 263 | return std::numeric_limits<numeric_float>::infinity(); |
| 264 | } |
| 265 | bool neg = false; |
| 266 | if (exp < 0) { |
| 267 | // negative exponent |
| 268 | neg = true; |
| 269 | if (exp == (std::numeric_limits<numeric_integer>::min)()) |
| 270 | return numeric_float(1.0) / (int_pow(base, exp + 1).as_float() * base); |
| 271 | exp = -exp; |
| 272 | } |
| 273 | numeric_integer result = 1; |
| 274 | while (exp > 0) { |
| 275 | if (exp & 1) result *= base; |
| 276 | base *= base; |
| 277 | exp >>= 1; |
| 278 | } |
| 279 | if (neg) // return float if negative exponent |
| 280 | return numeric_float(1.0) / result; |
| 281 | else |
| 282 | return result; |
| 283 | } |
| 284 | |
| 285 | public: |
| 286 | numeric() |