Skip to main content

thermite_special/tables/
bernoulli.rs

1// @generated by gen_consts.py at the workspace root. DO NOT EDIT BY HAND.
2//! Bernoulli numbers `$B_{2n}$`, as one static table per float format.
3//!
4//! **The tables start at `$B_2$`**, so entry `i` is `$B_{2i+2}$`. They are even-index
5//! only: every odd-index Bernoulli number past `$B_1$` is zero, so storing them would
6//! double the table for nothing.
7//!
8//! ```
9//! use thermite_special::tables::bernoulli::BernoulliNumbers;
10//!
11//! assert_eq!(f64::B2N[0], 1.0 / 6.0);           // B_2
12//! assert_eq!(f64::B2N[2], 1.0 / 42.0);          // B_6
13//! ```
14//!
15//! # `$B_0$` and `$B_1$` are deliberately absent
16//!
17//! `$B_1$` is the single value the two competing conventions disagree on: `$-1/2$` if
18//! you take the generating function to be `$x/(e^x - 1)$`, `$+1/2$` if you take it to be
19//! `$x/(1 - e^{-x})$` (Knuth has argued in print for the latter). Every _other_ Bernoulli
20//! number is identical under both, so omitting `$B_1$` makes this table convention-free
21//! rather than convention-bearing.
22//!
23//! `$B_0 = 1$` is not contested, but it goes with it, because the two co-occur. A formula
24//! that indexes the sequence from zero (Faulhaber's sum of powers, the binomial
25//! recurrence, the Bernoulli polynomials) reaches `$B_1$` at `$k = 1$` and therefore
26//! already special-cases the head of the sequence. A formula that skips `$B_1$`
27//! (Euler-Maclaurin, the `$\ln\Gamma$` / `$\psi$` asymptotic series, the `$\zeta(2n)$`
28//! identity) starts at `$B_2$` and never wanted `$B_0$` either. Nothing sits in the gap,
29//! so the table holds exactly the values that need a table.
30//!
31//! Callers who want the head should let their heart guide them on `$B_1 = \pm\tfrac{1}{2}$`
32//! and write `$B_0 = 1$` beside it.
33//!
34//! # The table ends where the format does
35//!
36//! `$|B_{2n}|$` grows factorially,
37//!
38//! ```math
39//! |B_{2n}| = \frac{2\,(2n)!}{(2\pi)^{2n}}\,\zeta(2n)
40//!     \sim 4\sqrt{\pi n}\left(\frac{n}{\pi e}\right)^{2n}
41//! ```
42//!
43//! with consecutive terms growing by roughly `$n^2/\pi^2$`, so each format has a _last_
44//! representable Bernoulli number and nothing beyond it to return.
45//!
46//! The tables stop exactly there, which means **`B2N.len()` is the overflow boundary**:
47//! `B2N.get(i)` is `None` precisely where the value would be infinite. There is no
48//! overflow policy, no error type and no limit constant, because the slice length
49//! already carries that information.
50//!
51//! There is no underflow at the other end. `$|B_{2n}|$` bottoms out at
52//! `$B_6 = 1/42$` and grows monotonically after it, so no entry is denormal.
53//!
54//! | format | entries | first | last finite | first to overflow |
55//! |---|---|---|---|---|
56//! | `f32` | 32 | `$B_2$` | `$B_{64}$` | `$B_{66}$` |
57//! | `f64` | 129 | `$B_2$` | `$B_{258}$` | `$B_{260}$` |
58//!
59//! `thermite-compensated` implements the same trait for `Compensated<f32>` and
60//! `Compensated<f64>` under its `special` feature. Those tables are the SAME lengths: a
61//! double-double carries twice the mantissa but the same exponent range, so widening the
62//! type buys precision, not reach.
63
64use thermite::element::FloatElement;
65
66/// Static Bernoulli number tables for a float format.
67///
68/// Implemented for `f32` and `f64` here, and for `Compensated<f32>` /
69/// `Compensated<f64>` by `thermite-compensated` under its `special` feature.
70pub trait BernoulliNumbers: FloatElement {
71    /// `$B_2, B_4, B_6, \ldots$`, every even-index Bernoulli number finite in `Self`,
72    /// starting at `$B_2$`, so that entry `i` is `$B_{2i+2}$`.
73    ///
74    /// See the [module docs](self) for why the table ends where it does, and why
75    /// `$B_0$` and `$B_1$` are not in it.
76    const B2N: &'static [Self];
77}
78
79/// `$B_{2n}$`, or `None` when it is not tabulated: either `$n = 0$`, or `$B_{2n}$`
80/// overflows `E`.
81///
82/// The argument is `n` as in `$B_{2n}$`, following the mathematics rather than the
83/// slice index, so `bernoulli_b2n::<f64>(1)` is `$B_2$`, the first entry. Reach for
84/// [`BernoulliNumbers::B2N`] directly when iterating, where entry `i` is `$B_{2i+2}$`.
85#[inline]
86#[must_use]
87pub fn bernoulli_b2n<E: BernoulliNumbers>(n: usize) -> Option<E> {
88    E::B2N.get(n.checked_sub(1)?).copied()
89}
90
91impl BernoulliNumbers for f32 {
92    #[rustfmt::skip]
93    const B2N: &'static [f32] = &[
94        0.16666667,  // B_2
95        -0.033333335,  // B_4
96        0.023809524,  // B_6
97        -0.033333335,  // B_8
98        0.07575758,  // B_10
99        -0.25311357,  // B_12
100        1.1666666,  // B_14
101        -7.092157,  // B_16
102        54.971176,  // B_18
103        -529.12427,  // B_20
104        6192.123,  // B_22
105        -86580.25,  // B_24
106        1425517.1,  // B_26
107        -27298232.0,  // B_28
108        6.0158086e+08,  // B_30
109        -1.5116316e+10,  // B_32
110        4.2961463e+11,  // B_34
111        -1.3711655e+13,  // B_36
112        4.883323e+14,  // B_38
113        -1.929658e+16,  // B_40
114        8.4169306e+17,  // B_42
115        -4.0338073e+19,  // B_44
116        2.1150749e+21,  // B_46
117        -1.20866265e+23,  // B_48
118        7.500867e+24,  // B_50
119        -5.038778e+26,  // B_52
120        3.6528777e+28,  // B_54
121        -2.849877e+30,  // B_56
122        2.3865428e+32,  // B_58
123        -2.139995e+34,  // B_60
124        2.0500976e+36,  // B_62
125        -2.0938006e+38,  // B_64
126    ];
127}
128
129impl BernoulliNumbers for f64 {
130    #[rustfmt::skip]
131    const B2N: &'static [f64] = &[
132        0.16666666666666666,  // B_2
133        -0.03333333333333333,  // B_4
134        0.023809523809523808,  // B_6
135        -0.03333333333333333,  // B_8
136        0.07575757575757576,  // B_10
137        -0.2531135531135531,  // B_12
138        1.1666666666666667,  // B_14
139        -7.092156862745098,  // B_16
140        54.971177944862156,  // B_18
141        -529.1242424242424,  // B_20
142        6192.123188405797,  // B_22
143        -86580.25311355312,  // B_24
144        1425517.1666666667,  // B_26
145        -27298231.067816094,  // B_28
146        601580873.9006424,  // B_30
147        -15116315767.092157,  // B_32
148        429614643061.1667,  // B_34
149        -13711655205088.332,  // B_36
150        488332318973593.2,  // B_38
151        -1.9296579341940068e+16,  // B_40
152        8.416930475736826e+17,  // B_42
153        -4.0338071854059454e+19,  // B_44
154        2.1150748638081993e+21,  // B_46
155        -1.2086626522296526e+23,  // B_48
156        7.500866746076964e+24,  // B_50
157        -5.038778101481069e+26,  // B_52
158        3.6528776484818122e+28,  // B_54
159        -2.849876930245088e+30,  // B_56
160        2.3865427499683627e+32,  // B_58
161        -2.1399949257225335e+34,  // B_60
162        2.0500975723478097e+36,  // B_62
163        -2.093800591134638e+38,  // B_64
164        2.2752696488463515e+40,  // B_66
165        -2.6257710286239577e+42,  // B_68
166        3.212508210271803e+44,  // B_70
167        -4.159827816679471e+46,  // B_72
168        5.692069548203528e+48,  // B_74
169        -8.218362941978458e+50,  // B_76
170        1.2502904327166994e+53,  // B_78
171        -2.001558323324837e+55,  // B_80
172        3.3674982915364376e+57,  // B_82
173        -5.947097050313545e+59,  // B_84
174        1.1011910323627977e+62,  // B_86
175        -2.1355259545253502e+64,  // B_88
176        4.3328896986641194e+66,  // B_90
177        -9.188552824166933e+68,  // B_92
178        2.0346896776329074e+71,  // B_94
179        -4.700383395803573e+73,  // B_96
180        1.131804344548425e+76,  // B_98
181        -2.8382249570693707e+78,  // B_100
182        7.406424897967885e+80,  // B_102
183        -2.0096454802756605e+83,  // B_104
184        5.665717005080594e+85,  // B_106
185        -1.6584511154136216e+88,  // B_108
186        5.036885995049238e+90,  // B_110
187        -1.5861468237658186e+93,  // B_112
188        5.1756743617545625e+95,  // B_114
189        -1.7488921840217116e+98,  // B_116
190        6.116051999495218e+100,  // B_118
191        -2.2122776912707833e+103,  // B_120
192        8.272277679877097e+105,  // B_122
193        -3.195892511141571e+108,  // B_124
194        1.2750082223387793e+111,  // B_126
195        -5.250092308677413e+113,  // B_128
196        2.2301817894241627e+116,  // B_130
197        -9.76845219309552e+118,  // B_132
198        4.409836197845295e+121,  // B_134
199        -2.050857088646409e+124,  // B_136
200        9.821443327979128e+126,  // B_138
201        -4.841260079820888e+129,  // B_140
202        2.4553088801480982e+132,  // B_142
203        -1.2806926804084748e+135,  // B_144
204        6.867616710466858e+137,  // B_146
205        -3.7846468581969106e+140,  // B_148
206        2.142610125066529e+143,  // B_150
207        -1.2456727137183695e+146,  // B_152
208        7.434578755100016e+148,  // B_154
209        -4.5535795304641704e+151,  // B_156
210        2.861211281685887e+154,  // B_158
211        -1.843772355203387e+157,  // B_160
212        1.2181154536221047e+160,  // B_162
213        -8.248218718531412e+162,  // B_164
214        5.722587793783294e+165,  // B_166
215        -4.0668530525059105e+168,  // B_168
216        2.9596092064642052e+171,  // B_170
217        -2.2049522565189457e+174,  // B_172
218        1.68125970728896e+177,  // B_174
219        -1.3116736213556958e+180,  // B_176
220        1.0467894009478039e+183,  // B_178
221        -8.543289357883371e+185,  // B_180
222        7.128782132248655e+188,  // B_182
223        -6.08029314555359e+191,  // B_184
224        5.299677642484992e+194,  // B_186
225        -4.719425916874586e+197,  // B_188
226        4.292841379140298e+200,  // B_190
227        -3.9876744968232205e+203,  // B_192
228        3.781978041935888e+206,  // B_194
229        -3.661423368368119e+209,  // B_196
230        3.617609027237286e+212,  // B_198
231        -3.647077264519136e+215,  // B_200
232        3.750875543645441e+218,  // B_202
233        -3.934586729643903e+221,  // B_204
234        4.208821114819008e+224,  // B_206
235        -4.590229622061792e+227,  // B_208
236        5.103172577262957e+230,  // B_210
237        -5.782276230365695e+233,  // B_212
238        6.676248216783588e+236,  // B_214
239        -7.853530764445042e+239,  // B_216
240        9.410689406705872e+242,  // B_218
241        -1.1484933873465185e+246,  // B_220
242        1.4272958742848785e+249,  // B_222
243        -1.805955958690931e+252,  // B_224
244        2.3261535307660807e+255,  // B_226
245        -3.0495751715499594e+258,  // B_228
246        4.068580607643398e+261,  // B_230
247        -5.523103132197436e+264,  // B_232
248        7.6277279396434395e+267,  // B_234
249        -1.0715571119697886e+271,  // B_236
250        1.5310200895969188e+274,  // B_238
251        -2.2244891682179836e+277,  // B_240
252        3.286267919069014e+280,  // B_242
253        -4.935592895596035e+283,  // B_244
254        7.534957120083251e+286,  // B_246
255        -1.1691485154584178e+290,  // B_248
256        1.843526146783894e+293,  // B_250
257        -2.953682617296808e+296,  // B_252
258        4.807932127750157e+299,  // B_254
259        -7.950212504588525e+302,  // B_256
260        1.3352784187354634e+306,  // B_258
261    ];
262}
Last built: 2026-09-08 21:35:55 UTC