nexus_decimal/constants.rs
1//! Named constants for common decimal values.
2//!
3//! Core constants (`ZERO`, `ONE`, `MAX`, `MIN`) are generated for each
4//! backing type. Financial constants (CENT, BASIS_POINT, etc.) are
5//! in `financial.rs`.
6
7use crate::Decimal;
8
9macro_rules! impl_decimal_constants {
10 ($backing:ty) => {
11 impl<const D: u8> Decimal<$backing, D> {
12 /// Zero (`0`).
13 pub const ZERO: Self = Self { value: 0 };
14
15 /// One (`1.0`).
16 pub const ONE: Self = Self { value: Self::SCALE };
17
18 /// Negative one (`-1.0`).
19 pub const NEG_ONE: Self = Self {
20 value: -Self::SCALE,
21 };
22
23 /// Maximum representable value.
24 pub const MAX: Self = Self {
25 value: <$backing>::MAX,
26 };
27
28 /// Minimum representable value.
29 pub const MIN: Self = Self {
30 value: <$backing>::MIN,
31 };
32
33 /// Smallest positive representable value (`from_raw(1)`).
34 ///
35 /// Represents `1 / 10^D` — the resolution of this decimal type.
36 pub const EPSILON: Self = Self { value: 1 };
37
38 /// One half (`0.5`).
39 ///
40 /// # Compile-time constraint
41 ///
42 /// Requires `D >= 1`. Referencing `HALF` on a `Decimal` with
43 /// `D = 0` is a compile error — the value 0.5 is not
44 /// representable with zero fractional digits.
45 pub const HALF: Self = {
46 assert!(
47 D >= 1,
48 "HALF requires D >= 1: 0.5 is not representable with zero fractional digits"
49 );
50 Self {
51 value: Self::SCALE / 2,
52 }
53 };
54
55 /// One basis point (`0.0001`).
56 ///
57 /// # Compile-time constraint
58 ///
59 /// Requires `D >= 4`. Referencing `BASIS_POINT` on a `Decimal`
60 /// with fewer than 4 fractional digits is a compile error.
61 pub const BASIS_POINT: Self = {
62 assert!(
63 D >= 4,
64 "BASIS_POINT requires D >= 4: 0.0001 is not representable with fewer than 4 fractional digits"
65 );
66 Self {
67 value: Self::SCALE / 10000,
68 }
69 };
70
71 /// Two (`2.0`).
72 ///
73 /// # Compile-time constraint
74 ///
75 /// Requires the backing type to be wide enough that `2 * SCALE`
76 /// does not overflow. This holds for all valid `D` on `i32` and
77 /// `i64`; on `i128` it fails at `D = 38`.
78 pub const TWO: Self = {
79 assert!(
80 Self::SCALE <= <$backing>::MAX / 2,
81 "TWO requires 2*SCALE to fit in the backing type"
82 );
83 Self {
84 value: Self::SCALE * 2,
85 }
86 };
87 }
88 };
89}
90
91impl_decimal_constants!(i32);
92impl_decimal_constants!(i64);
93impl_decimal_constants!(i128);