fixed/
consts.rs

1// Copyright © 2018–2025 Trevor Spiteri
2
3// This library is free software: you can redistribute it and/or
4// modify it under the terms of either
5//
6//   * the Apache License, Version 2.0 or
7//   * the MIT License
8//
9// at your option.
10//
11// You should have recieved copies of the Apache License and the MIT
12// License along with the library. If not, see
13// <https://www.apache.org/licenses/LICENSE-2.0> and
14// <https://opensource.org/licenses/MIT>.
15
16/*!
17Mathematical constants.
18
19The constants have the maximum precision possible for a fixed-point
20number, and are rounded down at that precision.
21
22# Examples
23
24```rust
25use fixed::consts;
26use fixed::types::I4F28;
27let tau = I4F28::from_num(consts::TAU);
28println!("τ = 2π with eight binary places is {tau:.8b}");
29assert_eq!(format!("{tau:.8b}"), "110.01001000");
30println!("τ = 2π with eight decimal places is {tau:.8}");
31assert_eq!(format!("{tau:.8}"), "6.28318531");
32```
33*/
34
35use crate::types::{U0F128, U1F127, U2F126, U3F125};
36
37/*
38```rust
39use core::cmp::Ord;
40use rug::float::{Constant, Round};
41use rug::{Assign, Float};
42
43fn decimal_string(val: &Float, num_digits: usize) -> String {
44    let (sign, mut digits, exp) = val.to_sign_string_exp_round(10, Some(num_digits), Round::Down);
45    if let Some(exp) = exp {
46        if exp <= 0 {
47            let one_minus_exp = usize::try_from(1 - exp).unwrap();
48            digits.insert_str(0, &"0".repeat(one_minus_exp));
49            digits.insert(1, '.');
50        } else {
51            let exp = usize::try_from(exp).unwrap();
52            if exp >= num_digits {
53                digits.push_str(&"0".repeat(exp - num_digits));
54            } else {
55                digits.insert(exp, '.');
56            }
57        }
58    }
59    if sign {
60        digits.insert(0, '-');
61    }
62    digits
63}
64
65fn hex_bits(val: &Float, frac_bits: i32) -> String {
66    let val = val.clone() << frac_bits;
67    let int = val.to_integer_round(Round::Down).unwrap().0;
68    let mut s = format!("0x{int:016X}");
69    for i in 0..7 {
70        s.insert(6 + 5 * i, '_');
71    }
72    s
73}
74
75fn print(doc: &str, name: &str, val: Float) {
76    println!("/// {} = {}…", doc, decimal_string(&val, 6));
77    println!("// {} = {}...", name, decimal_string(&val, 40));
78    let int_bits = val.get_exp().unwrap().max(0);
79    let frac_bits = 128 - int_bits;
80    print!("pub const {}: U{}F{} = U{1}F{2}", name, int_bits, frac_bits,);
81    println!("::from_bits({});", hex_bits(&val, frac_bits));
82    println!();
83}
84
85fn float<T>(t: T) -> Float
86where
87    Float: Assign<T>,
88{
89    Float::with_val(1000, t)
90}
91
92fn main() {
93    print("A turn, τ", "TAU", float(Constant::Pi) * 2);
94    print("τ/2", "FRAC_TAU_2", float(Constant::Pi));
95    print("τ/3", "FRAC_TAU_3", float(Constant::Pi) * 2 / 3);
96    print("τ/4", "FRAC_TAU_4", float(Constant::Pi) / 2);
97    print("τ/6", "FRAC_TAU_6", float(Constant::Pi) / 3);
98    print("τ/8", "FRAC_TAU_8", float(Constant::Pi) / 4);
99    print("τ/12", "FRAC_TAU_12", float(Constant::Pi) / 6);
100    print("1/τ", "FRAC_1_TAU", 0.5 / float(Constant::Pi));
101    print("2/τ", "FRAC_2_TAU", 1 / float(Constant::Pi));
102    print("4/τ", "FRAC_4_TAU", 2 / float(Constant::Pi));
103    print("Archimedes’ constant, π", "PI", float(Constant::Pi));
104    print("π/2", "FRAC_PI_2", float(Constant::Pi) / 2);
105    print("π/3", "FRAC_PI_3", float(Constant::Pi) / 3);
106    print("π/4", "FRAC_PI_4", float(Constant::Pi) / 4);
107    print("π/6", "FRAC_PI_6", float(Constant::Pi) / 6);
108    print("π/8", "FRAC_PI_8", float(Constant::Pi) / 8);
109    print("1/π", "FRAC_1_PI", 1 / float(Constant::Pi));
110    print("2/π", "FRAC_2_PI", 2 / float(Constant::Pi));
111    print("√π", "SQRT_PI", float(Constant::Pi).sqrt());
112    print("√2π", "SQRT_2PI", (float(Constant::Pi) * 2u32).sqrt());
113    print("1/√π", "FRAC_1_SQRT_PI", 1 / float(Constant::Pi).sqrt());
114    print("1/√2π", "FRAC_1_SQRT_2PI", 1 / (float(Constant::Pi) * 2u32).sqrt());
115    print("2/√π", "FRAC_2_SQRT_PI", 2 / float(Constant::Pi).sqrt());
116    print("√2", "SQRT_2", float(2).sqrt());
117    print("1/√2", "FRAC_1_SQRT_2", float(0.5).sqrt());
118    print("√3", "SQRT_3", float(3).sqrt());
119    print("1/√3", "FRAC_1_SQRT_3", float(3).recip().sqrt());
120    print("Euler’s number, e", "E", float(1).exp());
121    print("√e", "SQRT_E", float(0.5).exp());
122    print("log<sub>2</sub> 10", "LOG2_10", float(10).log2());
123    print("log<sub>2</sub> e", "LOG2_E", float(1).exp().log2());
124    print("log<sub>10</sub> 2", "LOG10_2", float(2).log10());
125    print("log<sub>10</sub> e", "LOG10_E", float(1).exp().log10());
126    print("ln 2", "LN_2", float(2).ln());
127    print("ln 10", "LN_10", float(10).ln());
128    print("The golden ratio, φ", "PHI", float(1.25).sqrt() + 0.5);
129    print("The golden ratio conjugate, Φ = 1/φ", "FRAC_1_PHI", float(1.25).sqrt() - 0.5);
130    print("√φ", "SQRT_PHI", (float(1.25).sqrt() + 0.5f32).sqrt());
131    print("The Euler-Mascheroni constant, γ", "GAMMA", float(Constant::Euler));
132    print("Catalan’s constant", "CATALAN", float(Constant::Catalan));
133}
134```
135*/
136
137/// A turn, τ = 6.28318…
138// TAU = 6.283185307179586476925286766559005768394...
139pub const TAU: U3F125 = U3F125::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
140
141/// τ/2 = 3.14159…
142// FRAC_TAU_2 = 3.141592653589793238462643383279502884197...
143pub const FRAC_TAU_2: U2F126 = U2F126::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
144
145/// τ/3 = 2.09439…
146// FRAC_TAU_3 = 2.094395102393195492308428922186335256131...
147pub const FRAC_TAU_3: U2F126 = U2F126::from_bits(0x860A_91C1_6B9B_2C23_2DD9_9707_AB3D_688B);
148
149/// τ/4 = 1.57079…
150// FRAC_TAU_4 = 1.570796326794896619231321691639751442098...
151pub const FRAC_TAU_4: U1F127 = U1F127::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
152
153/// τ/6 = 1.04719…
154// FRAC_TAU_6 = 1.047197551196597746154214461093167628065...
155pub const FRAC_TAU_6: U1F127 = U1F127::from_bits(0x860A_91C1_6B9B_2C23_2DD9_9707_AB3D_688B);
156
157/// τ/8 = 0.785398…
158// FRAC_TAU_8 = 0.7853981633974483096156608458198757210492...
159pub const FRAC_TAU_8: U0F128 = U0F128::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
160
161/// τ/12 = 0.523598…
162// FRAC_TAU_12 = 0.5235987755982988730771072305465838140328...
163pub const FRAC_TAU_12: U0F128 = U0F128::from_bits(0x860A_91C1_6B9B_2C23_2DD9_9707_AB3D_688B);
164
165/// 1/τ = 0.159154…
166// FRAC_1_TAU = 0.1591549430918953357688837633725143620344...
167pub const FRAC_1_TAU: U0F128 = U0F128::from_bits(0x28BE_60DB_9391_054A_7F09_D5F4_7D4D_3770);
168
169/// 2/τ = 0.318309…
170// FRAC_2_TAU = 0.3183098861837906715377675267450287240689...
171pub const FRAC_2_TAU: U0F128 = U0F128::from_bits(0x517C_C1B7_2722_0A94_FE13_ABE8_FA9A_6EE0);
172
173/// 4/τ = 0.636619…
174// FRAC_4_TAU = 0.6366197723675813430755350534900574481378...
175pub const FRAC_4_TAU: U0F128 = U0F128::from_bits(0xA2F9_836E_4E44_1529_FC27_57D1_F534_DDC0);
176
177/// Archimedes’ constant, π = 3.14159…
178// PI = 3.141592653589793238462643383279502884197...
179pub const PI: U2F126 = U2F126::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
180
181/// π/2 = 1.57079…
182// FRAC_PI_2 = 1.570796326794896619231321691639751442098...
183pub const FRAC_PI_2: U1F127 = U1F127::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
184
185/// π/3 = 1.04719…
186// FRAC_PI_3 = 1.047197551196597746154214461093167628065...
187pub const FRAC_PI_3: U1F127 = U1F127::from_bits(0x860A_91C1_6B9B_2C23_2DD9_9707_AB3D_688B);
188
189/// π/4 = 0.785398…
190// FRAC_PI_4 = 0.7853981633974483096156608458198757210492...
191pub const FRAC_PI_4: U0F128 = U0F128::from_bits(0xC90F_DAA2_2168_C234_C4C6_628B_80DC_1CD1);
192
193/// π/6 = 0.523598…
194// FRAC_PI_6 = 0.5235987755982988730771072305465838140328...
195pub const FRAC_PI_6: U0F128 = U0F128::from_bits(0x860A_91C1_6B9B_2C23_2DD9_9707_AB3D_688B);
196
197/// π/8 = 0.392699…
198// FRAC_PI_8 = 0.3926990816987241548078304229099378605246...
199pub const FRAC_PI_8: U0F128 = U0F128::from_bits(0x6487_ED51_10B4_611A_6263_3145_C06E_0E68);
200
201/// 1/π = 0.318309…
202// FRAC_1_PI = 0.3183098861837906715377675267450287240689...
203pub const FRAC_1_PI: U0F128 = U0F128::from_bits(0x517C_C1B7_2722_0A94_FE13_ABE8_FA9A_6EE0);
204
205/// 2/π = 0.636619…
206// FRAC_2_PI = 0.6366197723675813430755350534900574481378...
207pub const FRAC_2_PI: U0F128 = U0F128::from_bits(0xA2F9_836E_4E44_1529_FC27_57D1_F534_DDC0);
208
209/// √π = 1.77245…
210// SQRT_PI = 1.772453850905516027298167483341145182797...
211pub const SQRT_PI: U1F127 = U1F127::from_bits(0xE2DF_C48D_A77B_553C_E1D8_2906_AEDC_9C1F);
212
213/// √2π = 2.50662…
214// SQRT_2PI = 2.506628274631000502415765284811045253006...
215pub const SQRT_2PI: U2F126 = U2F126::from_bits(0xA06C_98FF_B138_2CB2_BE52_0FD7_3916_7717);
216
217/// 1/√π = 0.564189…
218// FRAC_1_SQRT_PI = 0.5641895835477562869480794515607725858440...
219pub const FRAC_1_SQRT_PI: U0F128 = U0F128::from_bits(0x906E_BA82_14DB_688D_71D4_8A7F_6BFE_C344);
220
221/// 1/√2π = 0.398942…
222// FRAC_1_SQRT_2PI = 0.3989422804014326779399460599343818684758...
223pub const FRAC_1_SQRT_2PI: U0F128 = U0F128::from_bits(0x6621_14CF_50D9_4234_3F2C_F140_2EAE_38BF);
224
225/// 2/√π = 1.12837…
226// FRAC_2_SQRT_PI = 1.128379167095512573896158903121545171688...
227pub const FRAC_2_SQRT_PI: U1F127 = U1F127::from_bits(0x906E_BA82_14DB_688D_71D4_8A7F_6BFE_C344);
228
229/// √2 = 1.41421…
230// SQRT_2 = 1.414213562373095048801688724209698078569...
231pub const SQRT_2: U1F127 = U1F127::from_bits(0xB504_F333_F9DE_6484_597D_89B3_754A_BE9F);
232
233/// 1/√2 = 0.707106…
234// FRAC_1_SQRT_2 = 0.7071067811865475244008443621048490392848...
235pub const FRAC_1_SQRT_2: U0F128 = U0F128::from_bits(0xB504_F333_F9DE_6484_597D_89B3_754A_BE9F);
236
237/// √3 = 1.73205…
238// SQRT_3 = 1.732050807568877293527446341505872366942...
239pub const SQRT_3: U1F127 = U1F127::from_bits(0xDDB3_D742_C265_539D_92BA_16B8_3C5C_1DC4);
240
241/// 1/√3 = 0.577350…
242// FRAC_1_SQRT_3 = 0.5773502691896257645091487805019574556476...
243pub const FRAC_1_SQRT_3: U0F128 = U0F128::from_bits(0x93CD_3A2C_8198_E269_0C7C_0F25_7D92_BE83);
244
245/// Euler’s number, e = 2.71828…
246// E = 2.718281828459045235360287471352662497757...
247pub const E: U2F126 = U2F126::from_bits(0xADF8_5458_A2BB_4A9A_AFDC_5620_273D_3CF1);
248
249/// √e = 1.64872…
250// SQRT_E = 1.648721270700128146848650787814163571653...
251pub const SQRT_E: U1F127 = U1F127::from_bits(0xD309_4C70_F034_DE4B_96FF_7D5B_6F99_FCD8);
252
253/// log<sub>2</sub> 10 = 3.32192…
254// LOG2_10 = 3.321928094887362347870319429489390175864...
255pub const LOG2_10: U2F126 = U2F126::from_bits(0xD49A_784B_CD1B_8AFE_492B_F6FF_4DAF_DB4C);
256
257/// log<sub>2</sub> e = 1.44269…
258// LOG2_E = 1.442695040888963407359924681001892137426...
259pub const LOG2_E: U1F127 = U1F127::from_bits(0xB8AA_3B29_5C17_F0BB_BE87_FED0_691D_3E88);
260
261/// log<sub>10</sub> 2 = 0.301029…
262// LOG10_2 = 0.3010299956639811952137388947244930267681...
263pub const LOG10_2: U0F128 = U0F128::from_bits(0x4D10_4D42_7DE7_FBCC_47C4_ACD6_05BE_48BC);
264
265/// log<sub>10</sub> e = 0.434294…
266// LOG10_E = 0.4342944819032518276511289189166050822943...
267pub const LOG10_E: U0F128 = U0F128::from_bits(0x6F2D_EC54_9B94_38CA_9AAD_D557_D699_EE19);
268
269/// ln 2 = 0.693147…
270// LN_2 = 0.6931471805599453094172321214581765680755...
271pub const LN_2: U0F128 = U0F128::from_bits(0xB172_17F7_D1CF_79AB_C9E3_B398_03F2_F6AF);
272
273/// ln 10 = 2.30258…
274// LN_10 = 2.302585092994045684017991454684364207601...
275pub const LN_10: U2F126 = U2F126::from_bits(0x935D_8DDD_AAA8_AC16_EA56_D62B_82D3_0A28);
276
277/// The golden ratio, φ = 1.61803…
278// PHI = 1.618033988749894848204586834365638117720...
279pub const PHI: U1F127 = U1F127::from_bits(0xCF1B_BCDC_BFA5_3E0A_F9CE_6030_2E76_E41A);
280
281/// The golden ratio conjugate, Φ = 1/φ = 0.618033…
282// FRAC_1_PHI = 0.6180339887498948482045868343656381177203...
283pub const FRAC_1_PHI: U0F128 = U0F128::from_bits(0x9E37_79B9_7F4A_7C15_F39C_C060_5CED_C834);
284
285/// √φ = 1.27201…
286// SQRT_PHI = 1.272019649514068964252422461737491491715...
287pub const SQRT_PHI: U1F127 = U1F127::from_bits(0xA2D1_8A35_4422_AF49_2AA2_8089_0F62_6C86);
288
289/// The Euler-Mascheroni constant, γ = 0.577215…
290// GAMMA = 0.5772156649015328606065120900824024310421...
291pub const GAMMA: U0F128 = U0F128::from_bits(0x93C4_67E3_7DB0_C7A4_D1BE_3F81_0152_CB56);
292
293/// Catalan’s constant = 0.915965…
294// CATALAN = 0.9159655941772190150546035149323841107741...
295pub const CATALAN: U0F128 = U0F128::from_bits(0xEA7C_B89F_409A_E845_2158_22E3_7D32_D0C6);
296
297#[cfg(test)]
298mod tests {
299    use crate::consts::*;
300    use crate::traits::{Fixed, FromFixed};
301    use core::{f32, f64};
302
303    #[test]
304    fn cmp_f16() {
305        use half;
306        use half::f16 as half_f16;
307        assert_eq!(
308            half_f16::from_fixed(TAU),
309            half_f16::from_f32(f32::consts::PI * 2.0)
310        );
311        assert_eq!(half_f16::from_fixed(FRAC_TAU_2), half_f16::PI);
312        assert_eq!(
313            half_f16::from_fixed(FRAC_TAU_3),
314            half_f16::from_f32(f32::consts::FRAC_PI_3 * 2.0)
315        );
316        assert_eq!(half_f16::from_fixed(FRAC_TAU_4), half_f16::FRAC_PI_2);
317        assert_eq!(half_f16::from_fixed(FRAC_TAU_6), half_f16::FRAC_PI_3);
318        assert_eq!(half_f16::from_fixed(FRAC_TAU_8), half_f16::FRAC_PI_4);
319        assert_eq!(half_f16::from_fixed(FRAC_TAU_12), half_f16::FRAC_PI_6);
320        assert_eq!(
321            half_f16::from_fixed(FRAC_1_TAU),
322            half_f16::from_f32(f32::consts::FRAC_1_PI * 0.5)
323        );
324        assert_eq!(half_f16::from_fixed(FRAC_2_TAU), half_f16::FRAC_1_PI);
325        assert_eq!(half_f16::from_fixed(FRAC_4_TAU), half_f16::FRAC_2_PI);
326        assert_eq!(half_f16::from_fixed(PI), half_f16::PI);
327        assert_eq!(half_f16::from_fixed(FRAC_PI_2), half_f16::FRAC_PI_2);
328        assert_eq!(half_f16::from_fixed(FRAC_PI_3), half_f16::FRAC_PI_3);
329        assert_eq!(half_f16::from_fixed(FRAC_PI_4), half_f16::FRAC_PI_4);
330        assert_eq!(half_f16::from_fixed(FRAC_PI_6), half_f16::FRAC_PI_6);
331        assert_eq!(half_f16::from_fixed(FRAC_PI_8), half_f16::FRAC_PI_8);
332        assert_eq!(half_f16::from_fixed(FRAC_1_PI), half_f16::FRAC_1_PI);
333        assert_eq!(half_f16::from_fixed(FRAC_2_PI), half_f16::FRAC_2_PI);
334        assert_eq!(
335            half_f16::from_fixed(SQRT_PI),
336            half_f16::from_f32(f32::consts::PI.sqrt())
337        );
338        assert_eq!(
339            half_f16::from_fixed(FRAC_1_SQRT_PI),
340            half_f16::from_f32(f32::consts::FRAC_2_SQRT_PI / 2.0)
341        );
342        assert_eq!(
343            half_f16::from_fixed(FRAC_2_SQRT_PI),
344            half_f16::FRAC_2_SQRT_PI
345        );
346        assert_eq!(half_f16::from_fixed(SQRT_2), half_f16::SQRT_2);
347        assert_eq!(half_f16::from_fixed(FRAC_1_SQRT_2), half_f16::FRAC_1_SQRT_2);
348        assert_eq!(
349            half_f16::from_fixed(SQRT_3),
350            half_f16::from_f32(3f32.sqrt())
351        );
352        assert_eq!(
353            half_f16::from_fixed(FRAC_1_SQRT_3),
354            half_f16::from_f32(3f32.powf(-0.5))
355        );
356        assert_eq!(half_f16::from_fixed(E), half_f16::E);
357        assert_eq!(
358            half_f16::from_fixed(SQRT_E),
359            half_f16::from_f32(0.5f32.exp())
360        );
361        assert_eq!(half_f16::from_fixed(LOG2_10), half_f16::LOG2_10);
362        assert_eq!(half_f16::from_fixed(LOG2_E), half_f16::LOG2_E);
363        assert_eq!(half_f16::from_fixed(LOG10_2), half_f16::LOG10_2);
364        assert_eq!(half_f16::from_fixed(LOG10_E), half_f16::LOG10_E);
365        assert_eq!(half_f16::from_fixed(LN_2), half_f16::LN_2);
366        assert_eq!(half_f16::from_fixed(LN_10), half_f16::LN_10);
367        assert_eq!(
368            half_f16::from_fixed(PHI),
369            half_f16::from_f32(1.25f32.sqrt() + 0.5)
370        );
371        assert_eq!(
372            half_f16::from_fixed(FRAC_1_PHI),
373            half_f16::from_f32(1.25f32.sqrt() - 0.5)
374        );
375        assert_eq!(
376            half_f16::from_fixed(SQRT_PHI),
377            half_f16::from_f32((1.25f32.sqrt() + 0.5f32).sqrt())
378        );
379    }
380
381    #[test]
382    fn cmp_bf16() {
383        use half;
384        use half::bf16 as half_bf16;
385        assert_eq!(
386            half_bf16::from_fixed(TAU),
387            half_bf16::from_f32(f32::consts::PI * 2.0)
388        );
389        assert_eq!(half_bf16::from_fixed(FRAC_TAU_2), half_bf16::PI);
390        assert_eq!(
391            half_bf16::from_fixed(FRAC_TAU_3),
392            half_bf16::from_f32(f32::consts::FRAC_PI_3 * 2.0)
393        );
394        assert_eq!(half_bf16::from_fixed(FRAC_TAU_4), half_bf16::FRAC_PI_2);
395        assert_eq!(half_bf16::from_fixed(FRAC_TAU_6), half_bf16::FRAC_PI_3);
396        assert_eq!(half_bf16::from_fixed(FRAC_TAU_8), half_bf16::FRAC_PI_4);
397        assert_eq!(half_bf16::from_fixed(FRAC_TAU_12), half_bf16::FRAC_PI_6);
398        assert_eq!(
399            half_bf16::from_fixed(FRAC_1_TAU),
400            half_bf16::from_f32(f32::consts::FRAC_1_PI * 0.5)
401        );
402        assert_eq!(half_bf16::from_fixed(FRAC_2_TAU), half_bf16::FRAC_1_PI);
403        assert_eq!(half_bf16::from_fixed(FRAC_4_TAU), half_bf16::FRAC_2_PI);
404        assert_eq!(half_bf16::from_fixed(PI), half_bf16::PI);
405        assert_eq!(half_bf16::from_fixed(FRAC_PI_2), half_bf16::FRAC_PI_2);
406        assert_eq!(half_bf16::from_fixed(FRAC_PI_3), half_bf16::FRAC_PI_3);
407        assert_eq!(half_bf16::from_fixed(FRAC_PI_4), half_bf16::FRAC_PI_4);
408        assert_eq!(half_bf16::from_fixed(FRAC_PI_6), half_bf16::FRAC_PI_6);
409        assert_eq!(half_bf16::from_fixed(FRAC_PI_8), half_bf16::FRAC_PI_8);
410        assert_eq!(half_bf16::from_fixed(FRAC_1_PI), half_bf16::FRAC_1_PI);
411        assert_eq!(half_bf16::from_fixed(FRAC_2_PI), half_bf16::FRAC_2_PI);
412        assert_eq!(
413            half_bf16::from_fixed(SQRT_PI),
414            half_bf16::from_f32(f32::consts::PI.sqrt())
415        );
416        assert_eq!(
417            half_bf16::from_fixed(FRAC_1_SQRT_PI),
418            half_bf16::from_f32(f32::consts::FRAC_2_SQRT_PI / 2.0)
419        );
420        assert_eq!(
421            half_bf16::from_fixed(FRAC_2_SQRT_PI),
422            half_bf16::FRAC_2_SQRT_PI
423        );
424        assert_eq!(half_bf16::from_fixed(SQRT_2), half_bf16::SQRT_2);
425        assert_eq!(
426            half_bf16::from_fixed(FRAC_1_SQRT_2),
427            half_bf16::FRAC_1_SQRT_2
428        );
429        assert_eq!(
430            half_bf16::from_fixed(SQRT_3),
431            half_bf16::from_f32(3f32.sqrt())
432        );
433        assert_eq!(
434            half_bf16::from_fixed(FRAC_1_SQRT_3),
435            half_bf16::from_f32(3f32.powf(-0.5))
436        );
437        assert_eq!(half_bf16::from_fixed(E), half_bf16::E);
438        assert_eq!(
439            half_bf16::from_fixed(SQRT_E),
440            half_bf16::from_f32(0.5f32.exp())
441        );
442        assert_eq!(half_bf16::from_fixed(LOG2_10), half_bf16::LOG2_10);
443        assert_eq!(half_bf16::from_fixed(LOG2_E), half_bf16::LOG2_E);
444        assert_eq!(half_bf16::from_fixed(LOG10_2), half_bf16::LOG10_2);
445        assert_eq!(half_bf16::from_fixed(LOG10_E), half_bf16::LOG10_E);
446        assert_eq!(half_bf16::from_fixed(LN_2), half_bf16::LN_2);
447        assert_eq!(half_bf16::from_fixed(LN_10), half_bf16::LN_10);
448        assert_eq!(
449            half_bf16::from_fixed(PHI),
450            half_bf16::from_f32(1.25f32.sqrt() + 0.5)
451        );
452        assert_eq!(
453            half_bf16::from_fixed(FRAC_1_PHI),
454            half_bf16::from_f32(1.25f32.sqrt() - 0.5)
455        );
456        assert_eq!(
457            half_bf16::from_fixed(SQRT_PHI),
458            half_bf16::from_f32((1.25f32.sqrt() + 0.5f32).sqrt())
459        );
460    }
461
462    #[test]
463    fn cmp_f32() {
464        assert_eq!(f32::from_fixed(TAU), f32::consts::PI * 2.0);
465        assert_eq!(f32::from_fixed(FRAC_TAU_2), f32::consts::PI);
466        assert_eq!(f32::from_fixed(FRAC_TAU_3), f32::consts::FRAC_PI_3 * 2.0);
467        assert_eq!(f32::from_fixed(FRAC_TAU_4), f32::consts::FRAC_PI_2);
468        assert_eq!(f32::from_fixed(FRAC_TAU_6), f32::consts::FRAC_PI_3);
469        assert_eq!(f32::from_fixed(FRAC_TAU_8), f32::consts::FRAC_PI_4);
470        assert_eq!(f32::from_fixed(FRAC_TAU_12), f32::consts::FRAC_PI_6);
471        assert_eq!(f32::from_fixed(FRAC_1_TAU), f32::consts::FRAC_1_PI * 0.5);
472        assert_eq!(f32::from_fixed(FRAC_2_TAU), f32::consts::FRAC_1_PI);
473        assert_eq!(f32::from_fixed(FRAC_4_TAU), f32::consts::FRAC_2_PI);
474        assert_eq!(f32::from_fixed(PI), f32::consts::PI);
475        assert_eq!(f32::from_fixed(FRAC_PI_2), f32::consts::FRAC_PI_2);
476        assert_eq!(f32::from_fixed(FRAC_PI_3), f32::consts::FRAC_PI_3);
477        assert_eq!(f32::from_fixed(FRAC_PI_4), f32::consts::FRAC_PI_4);
478        assert_eq!(f32::from_fixed(FRAC_PI_6), f32::consts::FRAC_PI_6);
479        assert_eq!(f32::from_fixed(FRAC_PI_8), f32::consts::FRAC_PI_8);
480        assert_eq!(f32::from_fixed(FRAC_1_PI), f32::consts::FRAC_1_PI);
481        assert_eq!(f32::from_fixed(FRAC_2_PI), f32::consts::FRAC_2_PI);
482        assert_eq!(f32::from_fixed(SQRT_PI), f64::consts::PI.sqrt() as f32);
483        assert_eq!(
484            f32::from_fixed(FRAC_1_SQRT_PI),
485            f32::consts::FRAC_2_SQRT_PI / 2.0
486        );
487        assert_eq!(f32::from_fixed(FRAC_2_SQRT_PI), f32::consts::FRAC_2_SQRT_PI);
488        assert_eq!(f32::from_fixed(SQRT_2), f32::consts::SQRT_2);
489        assert_eq!(f32::from_fixed(FRAC_1_SQRT_2), f32::consts::FRAC_1_SQRT_2);
490        assert_eq!(f32::from_fixed(SQRT_3), 3f32.sqrt());
491        assert_eq!(f32::from_fixed(FRAC_1_SQRT_3), 3f32.powf(-0.5));
492        assert_eq!(f32::from_fixed(E), f32::consts::E);
493        assert_eq!(f32::from_fixed(SQRT_E), 0.5f32.exp());
494        assert_eq!(f32::from_fixed(LOG2_10), f32::consts::LOG2_10);
495        assert_eq!(f32::from_fixed(LOG2_E), f32::consts::LOG2_E);
496        assert_eq!(f32::from_fixed(LOG10_2), f32::consts::LOG10_2);
497        assert_eq!(f32::from_fixed(LOG10_E), f32::consts::LOG10_E);
498        assert_eq!(f32::from_fixed(LN_2), f32::consts::LN_2);
499        assert_eq!(f32::from_fixed(LN_10), f32::consts::LN_10);
500        assert_eq!(f32::from_fixed(PHI), 1.25f32.sqrt() + 0.5);
501        assert_eq!(f32::from_fixed(FRAC_1_PHI), (1.25f64.sqrt() - 0.5) as f32);
502        assert_eq!(
503            f32::from_fixed(SQRT_PHI),
504            (1.25f64.sqrt() + 0.5f64).sqrt() as f32
505        );
506    }
507
508    #[test]
509    fn cmp_f64() {
510        assert_eq!(f64::from_fixed(TAU), f64::consts::PI * 2.0);
511        assert_eq!(f64::from_fixed(FRAC_TAU_2), f64::consts::PI);
512        assert_eq!(f64::from_fixed(FRAC_TAU_3), f64::consts::FRAC_PI_3 * 2.0);
513        assert_eq!(f64::from_fixed(FRAC_TAU_4), f64::consts::FRAC_PI_2);
514        assert_eq!(f64::from_fixed(FRAC_TAU_6), f64::consts::FRAC_PI_3);
515        assert_eq!(f64::from_fixed(FRAC_TAU_8), f64::consts::FRAC_PI_4);
516        assert_eq!(f64::from_fixed(FRAC_TAU_12), f64::consts::FRAC_PI_6);
517        assert_eq!(f64::from_fixed(FRAC_1_TAU), f64::consts::FRAC_1_PI * 0.5);
518        assert_eq!(f64::from_fixed(FRAC_2_TAU), f64::consts::FRAC_1_PI);
519        assert_eq!(f64::from_fixed(FRAC_4_TAU), f64::consts::FRAC_2_PI);
520        assert_eq!(f64::from_fixed(PI), f64::consts::PI);
521        assert_eq!(f64::from_fixed(FRAC_PI_2), f64::consts::FRAC_PI_2);
522        assert_eq!(f64::from_fixed(FRAC_PI_3), f64::consts::FRAC_PI_3);
523        assert_eq!(f64::from_fixed(FRAC_PI_4), f64::consts::FRAC_PI_4);
524        assert_eq!(f64::from_fixed(FRAC_PI_6), f64::consts::FRAC_PI_6);
525        assert_eq!(f64::from_fixed(FRAC_PI_8), f64::consts::FRAC_PI_8);
526        assert_eq!(f64::from_fixed(FRAC_1_PI), f64::consts::FRAC_1_PI);
527        assert_eq!(f64::from_fixed(FRAC_2_PI), f64::consts::FRAC_2_PI);
528        // Since 1 < SQRT_PI < 2, we use EPSILON.
529        assert!((f64::from_fixed(SQRT_PI) - f64::consts::PI.sqrt()).abs() <= f64::EPSILON);
530        assert_eq!(
531            f64::from_fixed(FRAC_1_SQRT_PI),
532            f64::consts::FRAC_2_SQRT_PI / 2.0
533        );
534        assert_eq!(f64::from_fixed(FRAC_2_SQRT_PI), f64::consts::FRAC_2_SQRT_PI);
535        assert_eq!(f64::from_fixed(SQRT_2), f64::consts::SQRT_2);
536        assert_eq!(f64::from_fixed(FRAC_1_SQRT_2), f64::consts::FRAC_1_SQRT_2);
537        assert_eq!(f64::from_fixed(SQRT_3), 3f64.sqrt());
538        assert_eq!(f64::from_fixed(FRAC_1_SQRT_3), 3f64.powf(-0.5));
539        assert_eq!(f64::from_fixed(E), f64::consts::E);
540        assert_eq!(f64::from_fixed(SQRT_E), 0.5f64.exp());
541        assert_eq!(f64::from_fixed(LOG2_10), f64::consts::LOG2_10);
542        assert_eq!(f64::from_fixed(LOG2_E), f64::consts::LOG2_E);
543        assert_eq!(f64::from_fixed(LOG10_2), f64::consts::LOG10_2);
544        assert_eq!(f64::from_fixed(LOG10_E), f64::consts::LOG10_E);
545        assert_eq!(f64::from_fixed(LN_2), f64::consts::LN_2);
546        assert_eq!(f64::from_fixed(LN_10), f64::consts::LN_10);
547        assert_eq!(f64::from_fixed(PHI), 1.25f64.sqrt() + 0.5);
548        // Since 0.5 < FRAC_1_PHI < 1, we use EPSILON / 2.
549        assert!((f64::from_fixed(FRAC_1_PHI) - (1.25f64.sqrt() - 0.5)).abs() <= f64::EPSILON / 2.0);
550        // Since 1 < SQRT_PHI < 2, we use EPSILON.
551        assert!(
552            (f64::from_fixed(SQRT_PHI) - (1.25f64.sqrt() + 0.5f64).sqrt()).abs() <= f64::EPSILON
553        );
554    }
555
556    fn compare_parse<F: Fixed>(f: F, s: &str)
557    where
558        F::Bits: TryFrom<u8>,
559    {
560        let sf = F::from_str(s).unwrap();
561        let f_plus = f + F::from_bits(F::Bits::try_from(1).ok().unwrap());
562        assert!(f <= sf && sf <= f_plus);
563    }
564
565    #[test]
566    fn cmp_parse() {
567        compare_parse(TAU, "6.283185307179586476925286766559005768394");
568        compare_parse(FRAC_TAU_2, "3.141592653589793238462643383279502884197");
569        compare_parse(FRAC_TAU_3, "2.094395102393195492308428922186335256131");
570        compare_parse(FRAC_TAU_4, "1.570796326794896619231321691639751442098");
571        compare_parse(FRAC_TAU_6, "1.047197551196597746154214461093167628065");
572        compare_parse(FRAC_TAU_8, "0.7853981633974483096156608458198757210492");
573        compare_parse(FRAC_TAU_12, "0.5235987755982988730771072305465838140328");
574        compare_parse(FRAC_1_TAU, "0.1591549430918953357688837633725143620344");
575        compare_parse(FRAC_2_TAU, "0.3183098861837906715377675267450287240689");
576        compare_parse(FRAC_4_TAU, "0.6366197723675813430755350534900574481378");
577        compare_parse(PI, "3.141592653589793238462643383279502884197");
578        compare_parse(FRAC_PI_2, "1.570796326794896619231321691639751442098");
579        compare_parse(FRAC_PI_3, "1.047197551196597746154214461093167628065");
580        compare_parse(FRAC_PI_4, "0.7853981633974483096156608458198757210492");
581        compare_parse(FRAC_PI_6, "0.5235987755982988730771072305465838140328");
582        compare_parse(FRAC_PI_8, "0.3926990816987241548078304229099378605246");
583        compare_parse(FRAC_1_PI, "0.3183098861837906715377675267450287240689");
584        compare_parse(FRAC_2_PI, "0.6366197723675813430755350534900574481378");
585        compare_parse(SQRT_PI, "1.772453850905516027298167483341145182797");
586        compare_parse(FRAC_1_SQRT_PI, "0.5641895835477562869480794515607725858440");
587        compare_parse(FRAC_2_SQRT_PI, "1.128379167095512573896158903121545171688");
588        compare_parse(SQRT_2, "1.414213562373095048801688724209698078569");
589        compare_parse(FRAC_1_SQRT_2, "0.7071067811865475244008443621048490392848");
590        compare_parse(SQRT_3, "1.732050807568877293527446341505872366942");
591        compare_parse(FRAC_1_SQRT_3, "0.5773502691896257645091487805019574556476");
592        compare_parse(E, "2.718281828459045235360287471352662497757");
593        compare_parse(SQRT_E, "1.648721270700128146848650787814163571653");
594        compare_parse(LOG2_10, "3.321928094887362347870319429489390175864");
595        compare_parse(LOG2_E, "1.442695040888963407359924681001892137426");
596        compare_parse(LOG10_2, "0.3010299956639811952137388947244930267681");
597        compare_parse(LOG10_E, "0.4342944819032518276511289189166050822943");
598        compare_parse(LN_2, "0.6931471805599453094172321214581765680755");
599        compare_parse(LN_10, "2.302585092994045684017991454684364207601");
600        compare_parse(PHI, "1.618033988749894848204586834365638117720");
601        compare_parse(FRAC_1_PHI, "0.6180339887498948482045868343656381177203");
602        compare_parse(SQRT_PHI, "1.272019649514068964252422461737491491715");
603        compare_parse(GAMMA, "0.5772156649015328606065120900824024310421");
604        compare_parse(CATALAN, "0.9159655941772190150546035149323841107741");
605    }
606}