master
1const std = @import("std");
2const Self = @This();
3
4// Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
5min_exponent_fast_path: comptime_int,
6
7// Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
8max_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)⌋`
12max_exponent_fast_path_disguised: comptime_int,
13
14// Maximum mantissa for the fast-path (`1 << 53` for f64).
15max_mantissa_fast_path: comptime_int,
16
17// Smallest decimal exponent for a non-zero value. Including subnormals.
18smallest_power_of_ten: comptime_int,
19
20// Largest decimal exponent for a non-infinite value.
21largest_power_of_ten: comptime_int,
22
23// The number of bits in the significand, *excluding* the hidden bit.
24mantissa_explicit_bits: comptime_int,
25
26// Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`.
27minimum_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.
47min_exponent_round_to_even: comptime_int,
48max_exponent_round_to_even: comptime_int,
49
50// Largest exponent value `(1 << EXP_BITS) - 1`.
51infinite_power: comptime_int,
52
53// Following should compute based on derived calculations where possible.
54pub 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}