Skip to main content

decimal_scaled/
consts_wide.rs

1//! Per-width raw constants for the wide-tier decimal types.
2//!
3//! The raw constants are computed at build time by `build.rs` using a
4//! hand-rolled multi-precision arithmetic core (no external deps).
5//! Each width gets its own `SCALE_REF` matched to its storage's max
6//! precision: D76 at 75 frac digits, D153 at 153, D307 at 307. The
7//! corresponding raw values land in `OUT_DIR/wide_consts.rs` as
8//! decimal-digit strings, parsed at compile time by
9//! `Int*::from_str_radix` (a `const fn`).
10//!
11//! This closes the SCALE > 37 panic in `D76<76>::pi()` etc. and
12//! tightens the 0.5 ULP contract on `DecimalConsts` for every
13//! wide-tier scale.
14
15// These imports are only reachable when at least one wide-tier
16// feature is enabled — every item in this module is per-tier
17// `#[cfg]`-gated below. Narrow-only builds compile the module
18// empty.
19#[cfg(any(feature = "d76", feature = "d153", feature = "d307", feature = "wide", feature = "x-wide"))]
20use crate::wide_int::{Int256, Int512, Int1024};
21#[cfg(any(feature = "d76", feature = "d153", feature = "d307", feature = "wide", feature = "x-wide"))]
22use crate::consts::DecimalConsts;
23
24include!(concat!(env!("OUT_DIR"), "/wide_consts.rs"));
25
26// ─── D76 ─────────────────────────────────────────────────────────────
27
28#[cfg(any(feature = "d76", feature = "wide"))]
29const D76_SCALE_REF: u32 = 75;
30
31#[cfg(any(feature = "d76", feature = "wide"))]
32const PI_RAW_D256: Int256 = match Int256::from_str_radix(PI_D76_S75, 10) {
33    Ok(v) => v,
34    Err(()) => panic!("consts_wide: PI_D76_S75 not parseable"),
35};
36#[cfg(any(feature = "d76", feature = "wide"))]
37const TAU_RAW_D256: Int256 = match Int256::from_str_radix(TAU_D76_S75, 10) {
38    Ok(v) => v,
39    Err(()) => panic!("consts_wide: TAU_D76_S75 not parseable"),
40};
41#[cfg(any(feature = "d76", feature = "wide"))]
42const HALF_PI_RAW_D256: Int256 = match Int256::from_str_radix(HALF_PI_D76_S75, 10) {
43    Ok(v) => v,
44    Err(()) => panic!("consts_wide: HALF_PI_D76_S75 not parseable"),
45};
46#[cfg(any(feature = "d76", feature = "wide"))]
47const QUARTER_PI_RAW_D256: Int256 = match Int256::from_str_radix(QUARTER_PI_D76_S75, 10) {
48    Ok(v) => v,
49    Err(()) => panic!("consts_wide: QUARTER_PI_D76_S75 not parseable"),
50};
51#[cfg(any(feature = "d76", feature = "wide"))]
52const E_RAW_D256: Int256 = match Int256::from_str_radix(E_D76_S75, 10) {
53    Ok(v) => v,
54    Err(()) => panic!("consts_wide: E_D76_S75 not parseable"),
55};
56#[cfg(any(feature = "d76", feature = "wide"))]
57const GOLDEN_RAW_D256: Int256 = match Int256::from_str_radix(GOLDEN_D76_S75, 10) {
58    Ok(v) => v,
59    Err(()) => panic!("consts_wide: GOLDEN_D76_S75 not parseable"),
60};
61
62#[cfg(any(feature = "d76", feature = "wide"))]
63pub(crate) fn pi_at_target_d76<const TARGET: u32>() -> Int256 {
64    use crate::core_type::D76;
65    D76::<D76_SCALE_REF>::from_bits(PI_RAW_D256)
66        .rescale::<TARGET>()
67        .to_bits()
68}
69#[cfg(any(feature = "d76", feature = "wide"))]
70pub(crate) fn tau_at_target_d76<const TARGET: u32>() -> Int256 {
71    use crate::core_type::D76;
72    D76::<D76_SCALE_REF>::from_bits(TAU_RAW_D256)
73        .rescale::<TARGET>()
74        .to_bits()
75}
76#[cfg(any(feature = "d76", feature = "wide"))]
77pub(crate) fn half_pi_at_target_d76<const TARGET: u32>() -> Int256 {
78    use crate::core_type::D76;
79    D76::<D76_SCALE_REF>::from_bits(HALF_PI_RAW_D256)
80        .rescale::<TARGET>()
81        .to_bits()
82}
83#[cfg(any(feature = "d76", feature = "wide"))]
84pub(crate) fn quarter_pi_at_target_d76<const TARGET: u32>() -> Int256 {
85    use crate::core_type::D76;
86    D76::<D76_SCALE_REF>::from_bits(QUARTER_PI_RAW_D256)
87        .rescale::<TARGET>()
88        .to_bits()
89}
90#[cfg(any(feature = "d76", feature = "wide"))]
91pub(crate) fn e_at_target_d76<const TARGET: u32>() -> Int256 {
92    use crate::core_type::D76;
93    D76::<D76_SCALE_REF>::from_bits(E_RAW_D256)
94        .rescale::<TARGET>()
95        .to_bits()
96}
97#[cfg(any(feature = "d76", feature = "wide"))]
98pub(crate) fn golden_at_target_d76<const TARGET: u32>() -> Int256 {
99    use crate::core_type::D76;
100    D76::<D76_SCALE_REF>::from_bits(GOLDEN_RAW_D256)
101        .rescale::<TARGET>()
102        .to_bits()
103}
104
105// ─── D153 ─────────────────────────────────────────────────────────────
106
107#[cfg(any(feature = "d153", feature = "wide"))]
108const D153_SCALE_REF: u32 = 153;
109
110#[cfg(any(feature = "d153", feature = "wide"))]
111const PI_RAW_D512: Int512 = match Int512::from_str_radix(PI_D153_S153, 10) {
112    Ok(v) => v,
113    Err(()) => panic!("consts_wide: PI_D153_S153 not parseable"),
114};
115#[cfg(any(feature = "d153", feature = "wide"))]
116const TAU_RAW_D512: Int512 = match Int512::from_str_radix(TAU_D153_S153, 10) {
117    Ok(v) => v,
118    Err(()) => panic!("consts_wide: TAU_D153_S153 not parseable"),
119};
120#[cfg(any(feature = "d153", feature = "wide"))]
121const HALF_PI_RAW_D512: Int512 = match Int512::from_str_radix(HALF_PI_D153_S153, 10) {
122    Ok(v) => v,
123    Err(()) => panic!("consts_wide: HALF_PI_D153_S153 not parseable"),
124};
125#[cfg(any(feature = "d153", feature = "wide"))]
126const QUARTER_PI_RAW_D512: Int512 = match Int512::from_str_radix(QUARTER_PI_D153_S153, 10) {
127    Ok(v) => v,
128    Err(()) => panic!("consts_wide: QUARTER_PI_D153_S153 not parseable"),
129};
130#[cfg(any(feature = "d153", feature = "wide"))]
131const E_RAW_D512: Int512 = match Int512::from_str_radix(E_D153_S153, 10) {
132    Ok(v) => v,
133    Err(()) => panic!("consts_wide: E_D153_S153 not parseable"),
134};
135#[cfg(any(feature = "d153", feature = "wide"))]
136const GOLDEN_RAW_D512: Int512 = match Int512::from_str_radix(GOLDEN_D153_S153, 10) {
137    Ok(v) => v,
138    Err(()) => panic!("consts_wide: GOLDEN_D153_S153 not parseable"),
139};
140
141#[cfg(any(feature = "d153", feature = "wide"))]
142pub(crate) fn pi_at_target_d153<const TARGET: u32>() -> Int512 {
143    use crate::core_type::D153;
144    D153::<D153_SCALE_REF>::from_bits(PI_RAW_D512)
145        .rescale::<TARGET>()
146        .to_bits()
147}
148#[cfg(any(feature = "d153", feature = "wide"))]
149pub(crate) fn tau_at_target_d153<const TARGET: u32>() -> Int512 {
150    use crate::core_type::D153;
151    D153::<D153_SCALE_REF>::from_bits(TAU_RAW_D512)
152        .rescale::<TARGET>()
153        .to_bits()
154}
155#[cfg(any(feature = "d153", feature = "wide"))]
156pub(crate) fn half_pi_at_target_d153<const TARGET: u32>() -> Int512 {
157    use crate::core_type::D153;
158    D153::<D153_SCALE_REF>::from_bits(HALF_PI_RAW_D512)
159        .rescale::<TARGET>()
160        .to_bits()
161}
162#[cfg(any(feature = "d153", feature = "wide"))]
163pub(crate) fn quarter_pi_at_target_d153<const TARGET: u32>() -> Int512 {
164    use crate::core_type::D153;
165    D153::<D153_SCALE_REF>::from_bits(QUARTER_PI_RAW_D512)
166        .rescale::<TARGET>()
167        .to_bits()
168}
169#[cfg(any(feature = "d153", feature = "wide"))]
170pub(crate) fn e_at_target_d153<const TARGET: u32>() -> Int512 {
171    use crate::core_type::D153;
172    D153::<D153_SCALE_REF>::from_bits(E_RAW_D512)
173        .rescale::<TARGET>()
174        .to_bits()
175}
176#[cfg(any(feature = "d153", feature = "wide"))]
177pub(crate) fn golden_at_target_d153<const TARGET: u32>() -> Int512 {
178    use crate::core_type::D153;
179    D153::<D153_SCALE_REF>::from_bits(GOLDEN_RAW_D512)
180        .rescale::<TARGET>()
181        .to_bits()
182}
183
184// ─── D307 ────────────────────────────────────────────────────────────
185
186#[cfg(any(feature = "d307", feature = "wide"))]
187const D307_SCALE_REF: u32 = 307;
188
189#[cfg(any(feature = "d307", feature = "wide"))]
190const PI_RAW_D1024: Int1024 = match Int1024::from_str_radix(PI_D307_S307, 10) {
191    Ok(v) => v,
192    Err(()) => panic!("consts_wide: PI_D307_S307 not parseable"),
193};
194#[cfg(any(feature = "d307", feature = "wide"))]
195const TAU_RAW_D1024: Int1024 = match Int1024::from_str_radix(TAU_D307_S307, 10) {
196    Ok(v) => v,
197    Err(()) => panic!("consts_wide: TAU_D307_S307 not parseable"),
198};
199#[cfg(any(feature = "d307", feature = "wide"))]
200const HALF_PI_RAW_D1024: Int1024 = match Int1024::from_str_radix(HALF_PI_D307_S307, 10) {
201    Ok(v) => v,
202    Err(()) => panic!("consts_wide: HALF_PI_D307_S307 not parseable"),
203};
204#[cfg(any(feature = "d307", feature = "wide"))]
205const QUARTER_PI_RAW_D1024: Int1024 = match Int1024::from_str_radix(QUARTER_PI_D307_S307, 10) {
206    Ok(v) => v,
207    Err(()) => panic!("consts_wide: QUARTER_PI_D307_S307 not parseable"),
208};
209#[cfg(any(feature = "d307", feature = "wide"))]
210const E_RAW_D1024: Int1024 = match Int1024::from_str_radix(E_D307_S307, 10) {
211    Ok(v) => v,
212    Err(()) => panic!("consts_wide: E_D307_S307 not parseable"),
213};
214#[cfg(any(feature = "d307", feature = "wide"))]
215const GOLDEN_RAW_D1024: Int1024 = match Int1024::from_str_radix(GOLDEN_D307_S307, 10) {
216    Ok(v) => v,
217    Err(()) => panic!("consts_wide: GOLDEN_D307_S307 not parseable"),
218};
219
220#[cfg(any(feature = "d307", feature = "wide"))]
221pub(crate) fn pi_at_target_d307<const TARGET: u32>() -> Int1024 {
222    use crate::core_type::D307;
223    D307::<D307_SCALE_REF>::from_bits(PI_RAW_D1024)
224        .rescale::<TARGET>()
225        .to_bits()
226}
227#[cfg(any(feature = "d307", feature = "wide"))]
228pub(crate) fn tau_at_target_d307<const TARGET: u32>() -> Int1024 {
229    use crate::core_type::D307;
230    D307::<D307_SCALE_REF>::from_bits(TAU_RAW_D1024)
231        .rescale::<TARGET>()
232        .to_bits()
233}
234#[cfg(any(feature = "d307", feature = "wide"))]
235pub(crate) fn half_pi_at_target_d307<const TARGET: u32>() -> Int1024 {
236    use crate::core_type::D307;
237    D307::<D307_SCALE_REF>::from_bits(HALF_PI_RAW_D1024)
238        .rescale::<TARGET>()
239        .to_bits()
240}
241#[cfg(any(feature = "d307", feature = "wide"))]
242pub(crate) fn quarter_pi_at_target_d307<const TARGET: u32>() -> Int1024 {
243    use crate::core_type::D307;
244    D307::<D307_SCALE_REF>::from_bits(QUARTER_PI_RAW_D1024)
245        .rescale::<TARGET>()
246        .to_bits()
247}
248#[cfg(any(feature = "d307", feature = "wide"))]
249pub(crate) fn e_at_target_d307<const TARGET: u32>() -> Int1024 {
250    use crate::core_type::D307;
251    D307::<D307_SCALE_REF>::from_bits(E_RAW_D1024)
252        .rescale::<TARGET>()
253        .to_bits()
254}
255#[cfg(any(feature = "d307", feature = "wide"))]
256pub(crate) fn golden_at_target_d307<const TARGET: u32>() -> Int1024 {
257    use crate::core_type::D307;
258    D307::<D307_SCALE_REF>::from_bits(GOLDEN_RAW_D1024)
259        .rescale::<TARGET>()
260        .to_bits()
261}
262
263// ─── DecimalConsts impls ──────────────────────────────────────────────
264//
265// These shadow the impls that `decl_decimal_consts!(wide …)` would
266// emit. To avoid duplicate trait impls, the wide-arm macro invocations
267// in `core_type.rs` were removed (search for `decl_decimal_consts!(wide`).
268
269#[cfg(any(feature = "d76", feature = "wide"))]
270impl<const SCALE: u32> DecimalConsts for crate::core_type::D76<SCALE> {
271    #[inline] fn pi() -> Self { Self(pi_at_target_d76::<SCALE>()) }
272    #[inline] fn tau() -> Self { Self(tau_at_target_d76::<SCALE>()) }
273    #[inline] fn half_pi() -> Self { Self(half_pi_at_target_d76::<SCALE>()) }
274    #[inline] fn quarter_pi() -> Self { Self(quarter_pi_at_target_d76::<SCALE>()) }
275    #[inline] fn golden() -> Self { Self(golden_at_target_d76::<SCALE>()) }
276    #[inline] fn e() -> Self { Self(e_at_target_d76::<SCALE>()) }
277    #[inline] fn pi_with(mode: crate::rounding::RoundingMode) -> Self {
278        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(PI_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
279    }
280    #[inline] fn tau_with(mode: crate::rounding::RoundingMode) -> Self {
281        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(TAU_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
282    }
283    #[inline] fn half_pi_with(mode: crate::rounding::RoundingMode) -> Self {
284        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(HALF_PI_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
285    }
286    #[inline] fn quarter_pi_with(mode: crate::rounding::RoundingMode) -> Self {
287        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(QUARTER_PI_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
288    }
289    #[inline] fn golden_with(mode: crate::rounding::RoundingMode) -> Self {
290        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(GOLDEN_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
291    }
292    #[inline] fn e_with(mode: crate::rounding::RoundingMode) -> Self {
293        Self(crate::core_type::D76::<D76_SCALE_REF>::from_bits(E_RAW_D256).rescale_with::<SCALE>(mode).to_bits())
294    }
295}
296
297#[cfg(any(feature = "d153", feature = "wide"))]
298impl<const SCALE: u32> DecimalConsts for crate::core_type::D153<SCALE> {
299    #[inline] fn pi() -> Self { Self(pi_at_target_d153::<SCALE>()) }
300    #[inline] fn tau() -> Self { Self(tau_at_target_d153::<SCALE>()) }
301    #[inline] fn half_pi() -> Self { Self(half_pi_at_target_d153::<SCALE>()) }
302    #[inline] fn quarter_pi() -> Self { Self(quarter_pi_at_target_d153::<SCALE>()) }
303    #[inline] fn golden() -> Self { Self(golden_at_target_d153::<SCALE>()) }
304    #[inline] fn e() -> Self { Self(e_at_target_d153::<SCALE>()) }
305    #[inline] fn pi_with(mode: crate::rounding::RoundingMode) -> Self {
306        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(PI_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
307    }
308    #[inline] fn tau_with(mode: crate::rounding::RoundingMode) -> Self {
309        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(TAU_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
310    }
311    #[inline] fn half_pi_with(mode: crate::rounding::RoundingMode) -> Self {
312        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(HALF_PI_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
313    }
314    #[inline] fn quarter_pi_with(mode: crate::rounding::RoundingMode) -> Self {
315        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(QUARTER_PI_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
316    }
317    #[inline] fn golden_with(mode: crate::rounding::RoundingMode) -> Self {
318        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(GOLDEN_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
319    }
320    #[inline] fn e_with(mode: crate::rounding::RoundingMode) -> Self {
321        Self(crate::core_type::D153::<D153_SCALE_REF>::from_bits(E_RAW_D512).rescale_with::<SCALE>(mode).to_bits())
322    }
323}
324
325#[cfg(any(feature = "d307", feature = "wide", feature = "x-wide"))]
326impl<const SCALE: u32> DecimalConsts for crate::core_type::D307<SCALE> {
327    #[inline] fn pi() -> Self { Self(pi_at_target_d307::<SCALE>()) }
328    #[inline] fn tau() -> Self { Self(tau_at_target_d307::<SCALE>()) }
329    #[inline] fn half_pi() -> Self { Self(half_pi_at_target_d307::<SCALE>()) }
330    #[inline] fn quarter_pi() -> Self { Self(quarter_pi_at_target_d307::<SCALE>()) }
331    #[inline] fn golden() -> Self { Self(golden_at_target_d307::<SCALE>()) }
332    #[inline] fn e() -> Self { Self(e_at_target_d307::<SCALE>()) }
333    #[inline] fn pi_with(mode: crate::rounding::RoundingMode) -> Self {
334        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(PI_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
335    }
336    #[inline] fn tau_with(mode: crate::rounding::RoundingMode) -> Self {
337        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(TAU_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
338    }
339    #[inline] fn half_pi_with(mode: crate::rounding::RoundingMode) -> Self {
340        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(HALF_PI_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
341    }
342    #[inline] fn quarter_pi_with(mode: crate::rounding::RoundingMode) -> Self {
343        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(QUARTER_PI_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
344    }
345    #[inline] fn golden_with(mode: crate::rounding::RoundingMode) -> Self {
346        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(GOLDEN_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
347    }
348    #[inline] fn e_with(mode: crate::rounding::RoundingMode) -> Self {
349        Self(crate::core_type::D307::<D307_SCALE_REF>::from_bits(E_RAW_D1024).rescale_with::<SCALE>(mode).to_bits())
350    }
351}
352
353// ─── New half-width and wider tiers ──────────────────────────────────
354//
355// Generated per the build.rs `for &scale in &[57, 115, 230, 462, 616,
356// 924, 1232]` loop. Each tier mirrors the D76 / D153 / D307 pattern:
357// (1) a raw `Int*` const parsed from the build-time decimal string,
358// (2) a `<const_name>_at_target_d<scale>::<TARGET>()` accessor that
359// rescales down to the caller's SCALE, and (3) a `DecimalConsts` impl
360// on the decimal type.
361//
362// Macro to compress the repetition: each invocation produces one
363// tier's full set of consts + accessor + impl.
364macro_rules! decl_wide_consts_tier {
365    (
366        $D:ident, $Storage:ty, $scale:literal, $scale_ref:ident,
367        $PI:ident, $TAU:ident, $HALF_PI:ident, $QUARTER_PI:ident,
368        $E:ident, $GOLDEN:ident,
369        $PI_RAW:ident, $TAU_RAW:ident, $HALF_PI_RAW:ident,
370        $QUARTER_PI_RAW:ident, $E_RAW:ident, $GOLDEN_RAW:ident,
371        $pi_fn:ident, $tau_fn:ident, $half_pi_fn:ident,
372        $quarter_pi_fn:ident, $e_fn:ident, $golden_fn:ident,
373        $feature:literal, $umbrella:literal $(,)?
374    ) => {
375        #[cfg(any(feature = $feature, feature = $umbrella))]
376        const $scale_ref: u32 = $scale;
377
378        #[cfg(any(feature = $feature, feature = $umbrella))]
379        const $PI_RAW: $Storage = match <$Storage>::from_str_radix($PI, 10) {
380            Ok(v) => v,
381            Err(()) => panic!(concat!("consts_wide: ", stringify!($PI), " not parseable")),
382        };
383        #[cfg(any(feature = $feature, feature = $umbrella))]
384        const $TAU_RAW: $Storage = match <$Storage>::from_str_radix($TAU, 10) {
385            Ok(v) => v,
386            Err(()) => panic!(concat!("consts_wide: ", stringify!($TAU), " not parseable")),
387        };
388        #[cfg(any(feature = $feature, feature = $umbrella))]
389        const $HALF_PI_RAW: $Storage = match <$Storage>::from_str_radix($HALF_PI, 10) {
390            Ok(v) => v,
391            Err(()) => panic!(concat!("consts_wide: ", stringify!($HALF_PI), " not parseable")),
392        };
393        #[cfg(any(feature = $feature, feature = $umbrella))]
394        const $QUARTER_PI_RAW: $Storage = match <$Storage>::from_str_radix($QUARTER_PI, 10) {
395            Ok(v) => v,
396            Err(()) => panic!(concat!("consts_wide: ", stringify!($QUARTER_PI), " not parseable")),
397        };
398        #[cfg(any(feature = $feature, feature = $umbrella))]
399        const $E_RAW: $Storage = match <$Storage>::from_str_radix($E, 10) {
400            Ok(v) => v,
401            Err(()) => panic!(concat!("consts_wide: ", stringify!($E), " not parseable")),
402        };
403        #[cfg(any(feature = $feature, feature = $umbrella))]
404        const $GOLDEN_RAW: $Storage = match <$Storage>::from_str_radix($GOLDEN, 10) {
405            Ok(v) => v,
406            Err(()) => panic!(concat!("consts_wide: ", stringify!($GOLDEN), " not parseable")),
407        };
408
409        #[cfg(any(feature = $feature, feature = $umbrella))]
410        pub(crate) fn $pi_fn<const TARGET: u32>() -> $Storage {
411            use crate::core_type::$D;
412            $D::<{ $scale }>::from_bits($PI_RAW).rescale::<TARGET>().to_bits()
413        }
414        #[cfg(any(feature = $feature, feature = $umbrella))]
415        pub(crate) fn $tau_fn<const TARGET: u32>() -> $Storage {
416            use crate::core_type::$D;
417            $D::<{ $scale }>::from_bits($TAU_RAW).rescale::<TARGET>().to_bits()
418        }
419        #[cfg(any(feature = $feature, feature = $umbrella))]
420        pub(crate) fn $half_pi_fn<const TARGET: u32>() -> $Storage {
421            use crate::core_type::$D;
422            $D::<{ $scale }>::from_bits($HALF_PI_RAW).rescale::<TARGET>().to_bits()
423        }
424        #[cfg(any(feature = $feature, feature = $umbrella))]
425        pub(crate) fn $quarter_pi_fn<const TARGET: u32>() -> $Storage {
426            use crate::core_type::$D;
427            $D::<{ $scale }>::from_bits($QUARTER_PI_RAW).rescale::<TARGET>().to_bits()
428        }
429        #[cfg(any(feature = $feature, feature = $umbrella))]
430        pub(crate) fn $e_fn<const TARGET: u32>() -> $Storage {
431            use crate::core_type::$D;
432            $D::<{ $scale }>::from_bits($E_RAW).rescale::<TARGET>().to_bits()
433        }
434        #[cfg(any(feature = $feature, feature = $umbrella))]
435        pub(crate) fn $golden_fn<const TARGET: u32>() -> $Storage {
436            use crate::core_type::$D;
437            $D::<{ $scale }>::from_bits($GOLDEN_RAW).rescale::<TARGET>().to_bits()
438        }
439
440        #[cfg(any(feature = $feature, feature = $umbrella))]
441        impl<const SCALE: u32> DecimalConsts for crate::core_type::$D<SCALE> {
442            #[inline] fn pi() -> Self { Self($pi_fn::<SCALE>()) }
443            #[inline] fn tau() -> Self { Self($tau_fn::<SCALE>()) }
444            #[inline] fn half_pi() -> Self { Self($half_pi_fn::<SCALE>()) }
445            #[inline] fn quarter_pi() -> Self { Self($quarter_pi_fn::<SCALE>()) }
446            #[inline] fn golden() -> Self { Self($golden_fn::<SCALE>()) }
447            #[inline] fn e() -> Self { Self($e_fn::<SCALE>()) }
448            #[inline] fn pi_with(mode: crate::rounding::RoundingMode) -> Self {
449                Self(crate::core_type::$D::<{ $scale }>::from_bits($PI_RAW).rescale_with::<SCALE>(mode).to_bits())
450            }
451            #[inline] fn tau_with(mode: crate::rounding::RoundingMode) -> Self {
452                Self(crate::core_type::$D::<{ $scale }>::from_bits($TAU_RAW).rescale_with::<SCALE>(mode).to_bits())
453            }
454            #[inline] fn half_pi_with(mode: crate::rounding::RoundingMode) -> Self {
455                Self(crate::core_type::$D::<{ $scale }>::from_bits($HALF_PI_RAW).rescale_with::<SCALE>(mode).to_bits())
456            }
457            #[inline] fn quarter_pi_with(mode: crate::rounding::RoundingMode) -> Self {
458                Self(crate::core_type::$D::<{ $scale }>::from_bits($QUARTER_PI_RAW).rescale_with::<SCALE>(mode).to_bits())
459            }
460            #[inline] fn golden_with(mode: crate::rounding::RoundingMode) -> Self {
461                Self(crate::core_type::$D::<{ $scale }>::from_bits($GOLDEN_RAW).rescale_with::<SCALE>(mode).to_bits())
462            }
463            #[inline] fn e_with(mode: crate::rounding::RoundingMode) -> Self {
464                Self(crate::core_type::$D::<{ $scale }>::from_bits($E_RAW).rescale_with::<SCALE>(mode).to_bits())
465            }
466        }
467    };
468}
469
470#[cfg(any(feature = "d56", feature = "wide"))]
471use crate::wide_int::Int192;
472#[cfg(any(feature = "d114", feature = "wide"))]
473use crate::wide_int::Int384;
474#[cfg(any(feature = "d230", feature = "wide"))]
475use crate::wide_int::Int768;
476#[cfg(any(feature = "d461", feature = "x-wide"))]
477use crate::wide_int::Int1536;
478#[cfg(any(feature = "d615", feature = "x-wide"))]
479use crate::wide_int::Int2048;
480#[cfg(any(feature = "d923", feature = "xx-wide"))]
481use crate::wide_int::Int3072;
482#[cfg(any(feature = "d1231", feature = "xx-wide"))]
483use crate::wide_int::Int4096;
484
485// SCALE_REF per tier = highest k where τ × 10^k still fits the
486// storage's signed range. Computed in build.rs and matched here.
487// D56/D114/D461/D615/D923/D1231 cannot use their nominal tier max
488// because τ ≈ 6.28 pushes just past the i_max boundary; D230 and
489// D1231 borderline cases work at 230 / 1231 respectively.
490decl_wide_consts_tier!(
491    D56, Int192, 56, D56_SCALE_REF,
492    PI_D56_S56, TAU_D56_S56, HALF_PI_D56_S56, QUARTER_PI_D56_S56, E_D56_S56, GOLDEN_D56_S56,
493    PI_RAW_D192, TAU_RAW_D192, HALF_PI_RAW_D192, QUARTER_PI_RAW_D192, E_RAW_D192, GOLDEN_RAW_D192,
494    pi_at_target_d56, tau_at_target_d56, half_pi_at_target_d56,
495    quarter_pi_at_target_d56, e_at_target_d56, golden_at_target_d56,
496    "d56", "wide",
497);
498
499decl_wide_consts_tier!(
500    D114, Int384, 114, D114_SCALE_REF,
501    PI_D114_S114, TAU_D114_S114, HALF_PI_D114_S114, QUARTER_PI_D114_S114, E_D114_S114, GOLDEN_D114_S114,
502    PI_RAW_D384, TAU_RAW_D384, HALF_PI_RAW_D384, QUARTER_PI_RAW_D384, E_RAW_D384, GOLDEN_RAW_D384,
503    pi_at_target_d114, tau_at_target_d114, half_pi_at_target_d114,
504    quarter_pi_at_target_d114, e_at_target_d114, golden_at_target_d114,
505    "d114", "wide",
506);
507
508decl_wide_consts_tier!(
509    D230, Int768, 230, D230_SCALE_REF,
510    PI_D230_S230, TAU_D230_S230, HALF_PI_D230_S230, QUARTER_PI_D230_S230, E_D230_S230, GOLDEN_D230_S230,
511    PI_RAW_D768, TAU_RAW_D768, HALF_PI_RAW_D768, QUARTER_PI_RAW_D768, E_RAW_D768, GOLDEN_RAW_D768,
512    pi_at_target_d230, tau_at_target_d230, half_pi_at_target_d230,
513    quarter_pi_at_target_d230, e_at_target_d230, golden_at_target_d230,
514    "d230", "wide",
515);
516
517decl_wide_consts_tier!(
518    D461, Int1536, 461, D461_SCALE_REF,
519    PI_D461_S461, TAU_D461_S461, HALF_PI_D461_S461, QUARTER_PI_D461_S461, E_D461_S461, GOLDEN_D461_S461,
520    PI_RAW_D1536, TAU_RAW_D1536, HALF_PI_RAW_D1536, QUARTER_PI_RAW_D1536, E_RAW_D1536, GOLDEN_RAW_D1536,
521    pi_at_target_d461, tau_at_target_d461, half_pi_at_target_d461,
522    quarter_pi_at_target_d461, e_at_target_d461, golden_at_target_d461,
523    "d461", "x-wide",
524);
525
526decl_wide_consts_tier!(
527    D615, Int2048, 615, D615_SCALE_REF,
528    PI_D615_S615, TAU_D615_S615, HALF_PI_D615_S615, QUARTER_PI_D615_S615, E_D615_S615, GOLDEN_D615_S615,
529    PI_RAW_D2048, TAU_RAW_D2048, HALF_PI_RAW_D2048, QUARTER_PI_RAW_D2048, E_RAW_D2048, GOLDEN_RAW_D2048,
530    pi_at_target_d615, tau_at_target_d615, half_pi_at_target_d615,
531    quarter_pi_at_target_d615, e_at_target_d615, golden_at_target_d615,
532    "d615", "x-wide",
533);
534
535decl_wide_consts_tier!(
536    D923, Int3072, 923, D923_SCALE_REF,
537    PI_D923_S923, TAU_D923_S923, HALF_PI_D923_S923, QUARTER_PI_D923_S923, E_D923_S923, GOLDEN_D923_S923,
538    PI_RAW_D3072, TAU_RAW_D3072, HALF_PI_RAW_D3072, QUARTER_PI_RAW_D3072, E_RAW_D3072, GOLDEN_RAW_D3072,
539    pi_at_target_d923, tau_at_target_d923, half_pi_at_target_d923,
540    quarter_pi_at_target_d923, e_at_target_d923, golden_at_target_d923,
541    "d923", "xx-wide",
542);
543
544decl_wide_consts_tier!(
545    D1231, Int4096, 1231, D1231_SCALE_REF,
546    PI_D1231_S1231, TAU_D1231_S1231, HALF_PI_D1231_S1231, QUARTER_PI_D1231_S1231, E_D1231_S1231, GOLDEN_D1231_S1231,
547    PI_RAW_D4096, TAU_RAW_D4096, HALF_PI_RAW_D4096, QUARTER_PI_RAW_D4096, E_RAW_D4096, GOLDEN_RAW_D4096,
548    pi_at_target_d1231, tau_at_target_d1231, half_pi_at_target_d1231,
549    quarter_pi_at_target_d1231, e_at_target_d1231, golden_at_target_d1231,
550    "d1231", "xx-wide",
551);