| 1 | const std = @import("std"); |
| 2 | const Self = @This(); |
| 3 | |
| 4 | // Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` |
| 5 | min_exponent_fast_path: comptime_int, |
| 6 | |
| 7 | // Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` |
| 8 | max_exponent_fast_path: comptime_int, |
| 9 | |
| 10 | // Maximum exponent that can be represented for a disguised-fast path case. |
| 11 | // This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋` |
| 12 | max_exponent_fast_path_disguised: comptime_int, |
| 13 | |
| 14 | // Maximum mantissa for the fast-path (`1 << 53` for f64). |
| 15 | max_mantissa_fast_path: comptime_int, |
| 16 | |
| 17 | // Smallest decimal exponent for a non-zero value. Including subnormals. |
| 18 | smallest_power_of_ten: comptime_int, |
| 19 | |
| 20 | // Largest decimal exponent for a non-infinite value. |
| 21 | largest_power_of_ten: comptime_int, |
| 22 | |
| 23 | // The number of bits in the significand, *excluding* the hidden bit. |
| 24 | mantissa_explicit_bits: comptime_int, |
| 25 | |
| 26 | // Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`. |
| 27 | minimum_exponent: comptime_int, |
| 28 | |
| 29 | // Round-to-even only happens for negative values of q |
| 30 | // when q ≥ −4 in the 64-bit case and when q ≥ −17 in |
| 31 | // the 32-bitcase. |
| 32 | // |
| 33 | // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we |
| 34 | // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have |
| 35 | // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10. |
| 36 | // |
| 37 | // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64 |
| 38 | // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case) |
| 39 | // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64 |
| 40 | // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11 |
| 41 | // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase). |
| 42 | // |
| 43 | // Thus we have that we only need to round ties to even when |
| 44 | // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10] |
| 45 | // (in the 32-bit case). In both cases,the power of five(5^|q|) |
| 46 | // fits in a 64-bit word. |
| 47 | min_exponent_round_to_even: comptime_int, |
| 48 | max_exponent_round_to_even: comptime_int, |
| 49 | |
| 50 | // Largest exponent value `(1 << EXP_BITS) - 1`. |
| 51 | infinite_power: comptime_int, |
| 52 | |
| 53 | // Following should compute based on derived calculations where possible. |
| 54 | pub fn from(comptime T: type) Self { |
| 55 | return switch (T) { |
| 56 | f16 => .{ |
| 57 | // Fast-Path |
| 58 | .min_exponent_fast_path = -4, |
| 59 | .max_exponent_fast_path = 4, |
| 60 | .max_exponent_fast_path_disguised = 7, |
| 61 | .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T), |
| 62 | // Slow + Eisel-Lemire |
| 63 | .mantissa_explicit_bits = std.math.floatFractionalBits(T), |
| 64 | .infinite_power = 0x1f, |
| 65 | // Eisel-Lemire |
| 66 | .smallest_power_of_ten = -26, // TODO: refine, fails one test |
| 67 | .largest_power_of_ten = 4, |
| 68 | .minimum_exponent = -15, |
| 69 | // w >= (2m+1) * 5^-q and w < 2^64 |
| 70 | // => 2m+1 > 2^11 |
| 71 | // => 2^11*5^-q < 2^64 |
| 72 | // => 5^-q < 2^53 |
| 73 | // => q >= -23 |
| 74 | .min_exponent_round_to_even = -22, |
| 75 | .max_exponent_round_to_even = 5, |
| 76 | }, |
| 77 | f32 => .{ |
| 78 | // Fast-Path |
| 79 | .min_exponent_fast_path = -10, |
| 80 | .max_exponent_fast_path = 10, |
| 81 | .max_exponent_fast_path_disguised = 17, |
| 82 | .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T), |
| 83 | // Slow + Eisel-Lemire |
| 84 | .mantissa_explicit_bits = std.math.floatFractionalBits(T), |
| 85 | .infinite_power = 0xff, |
| 86 | // Eisel-Lemire |
| 87 | .smallest_power_of_ten = -65, |
| 88 | .largest_power_of_ten = 38, |
| 89 | .minimum_exponent = -127, |
| 90 | .min_exponent_round_to_even = -17, |
| 91 | .max_exponent_round_to_even = 10, |
| 92 | }, |
| 93 | f64 => .{ |
| 94 | // Fast-Path |
| 95 | .min_exponent_fast_path = -22, |
| 96 | .max_exponent_fast_path = 22, |
| 97 | .max_exponent_fast_path_disguised = 37, |
| 98 | .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T), |
| 99 | // Slow + Eisel-Lemire |
| 100 | .mantissa_explicit_bits = std.math.floatMantissaBits(T), |
| 101 | .infinite_power = 0x7ff, |
| 102 | // Eisel-Lemire |
| 103 | .smallest_power_of_ten = -342, |
| 104 | .largest_power_of_ten = 308, |
| 105 | .minimum_exponent = -1023, |
| 106 | .min_exponent_round_to_even = -4, |
| 107 | .max_exponent_round_to_even = 23, |
| 108 | }, |
| 109 | f80 => .{ |
| 110 | // Fast-Path |
| 111 | .min_exponent_fast_path = -27, |
| 112 | .max_exponent_fast_path = 27, |
| 113 | .max_exponent_fast_path_disguised = 46, |
| 114 | .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T), |
| 115 | // Slow + Eisel-Lemire |
| 116 | .mantissa_explicit_bits = std.math.floatFractionalBits(T), |
| 117 | .infinite_power = 0x7fff, |
| 118 | // Eisel-Lemire. |
| 119 | // NOTE: Not yet tested (no f80 eisel-lemire implementation) |
| 120 | .smallest_power_of_ten = -4966, |
| 121 | .largest_power_of_ten = 4932, |
| 122 | .minimum_exponent = -16382, |
| 123 | // 2^65 * 5^-q < 2^80 |
| 124 | // 5^-q < 2^15 |
| 125 | // => q >= -6 |
| 126 | .min_exponent_round_to_even = -6, |
| 127 | .max_exponent_round_to_even = 28, |
| 128 | }, |
| 129 | f128 => .{ |
| 130 | // Fast-Path |
| 131 | .min_exponent_fast_path = -48, |
| 132 | .max_exponent_fast_path = 48, |
| 133 | .max_exponent_fast_path_disguised = 82, |
| 134 | .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T), |
| 135 | // Slow + Eisel-Lemire |
| 136 | .mantissa_explicit_bits = std.math.floatFractionalBits(T), |
| 137 | .infinite_power = 0x7fff, |
| 138 | // Eisel-Lemire. |
| 139 | // NOTE: Not yet tested (no f128 eisel-lemire implementation) |
| 140 | .smallest_power_of_ten = -4966, |
| 141 | .largest_power_of_ten = 4932, |
| 142 | .minimum_exponent = -16382, |
| 143 | // 2^113 * 5^-q < 2^128 |
| 144 | // 5^-q < 2^15 |
| 145 | // => q >= -6 |
| 146 | .min_exponent_round_to_even = -6, |
| 147 | .max_exponent_round_to_even = 49, |
| 148 | }, |
| 149 | else => unreachable, |
| 150 | }; |
| 151 | } |