| 1 | // Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | module math |
| 5 | |
| 6 | const uvnan = u64(0x7FF8000000000001) |
| 7 | const uvinf = u64(0x7FF0000000000000) |
| 8 | const uvneginf = u64(0xFFF0000000000000) |
| 9 | const uvone = u64(0x3FF0000000000000) |
| 10 | const mask = 0x7FF |
| 11 | const shift = 64 - 11 - 1 |
| 12 | const bias = 1023 |
| 13 | const normalize_smallest_mask = u64(u64(1) << 52) |
| 14 | const sign_mask = u64(0x8000000000000000) // (u64(1) << 63) |
| 15 | |
| 16 | const frac_mask = u64((u64(1) << u64(shift)) - u64(1)) |
| 17 | |
| 18 | // inf returns positive infinity if sign >= 0, negative infinity if sign < 0. |
| 19 | pub fn inf(sign int) f64 { |
| 20 | v := if sign >= 0 { uvinf } else { uvneginf } |
| 21 | return f64_from_bits(v) |
| 22 | } |
| 23 | |
| 24 | // nan returns an IEEE 754 ``not-a-number'' value. |
| 25 | pub fn nan() f64 { |
| 26 | return f64_from_bits(uvnan) |
| 27 | } |
| 28 | |
| 29 | // is_nan reports whether f is an IEEE 754 ``not-a-number'' value. |
| 30 | pub fn is_nan(f f64) bool { |
| 31 | $if fast_math { |
| 32 | if f64_bits(f) == uvnan { |
| 33 | return true |
| 34 | } |
| 35 | } |
| 36 | // IEEE 754 says that only NaNs satisfy f != f. |
| 37 | // To avoid the floating-point hardware, could use: |
| 38 | // x := f64_bits(f); |
| 39 | // return u32(x>>shift)&mask == mask && x != uvinf && x != uvneginf |
| 40 | return f != f |
| 41 | } |
| 42 | |
| 43 | // is_inf reports whether f is an infinity, according to sign. |
| 44 | // If sign > 0, is_inf reports whether f is positive infinity. |
| 45 | // If sign < 0, is_inf reports whether f is negative infinity. |
| 46 | // If sign == 0, is_inf reports whether f is either infinity. |
| 47 | pub fn is_inf(f f64, sign int) bool { |
| 48 | // Test for infinity by comparing against maximum float. |
| 49 | // To avoid the floating-point hardware, could use: |
| 50 | // x := f64_bits(f); |
| 51 | // return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf; |
| 52 | return (sign >= 0 && f > max_f64) || (sign <= 0 && f < -max_f64) |
| 53 | } |
| 54 | |
| 55 | // is_finite returns true if f is finite |
| 56 | pub fn is_finite(f f64) bool { |
| 57 | return !is_nan(f) && !is_inf(f, 0) |
| 58 | } |
| 59 | |
| 60 | // normalize returns a normal number y and exponent exp |
| 61 | // satisfying x == y × 2**exp. It assumes x is finite and non-zero. |
| 62 | pub fn normalize(x f64) (f64, int) { |
| 63 | smallest_normal := 2.2250738585072014e-308 // 2**-1022 |
| 64 | if abs(x) < smallest_normal { |
| 65 | return x * normalize_smallest_mask, -52 |
| 66 | } |
| 67 | return x, 0 |
| 68 | } |
| 69 | |