num_lazy/
lib.rs

1/*
2 * num-lazy is licensed under The 3-Clause BSD, see LICENSE.
3 * Copyright 2025 Sira Pornsiriprasert <code@psira.me>
4 */
5
6/*! **num-lazy** helps you write numbers for generic-typed functions.
7```
8use num_lazy::declare_nums;
9use num_traits::Float;
10// Assign to generic type T.
11// Important. Use the braces!
12declare_nums!{T}
13
14fn circumference<T: Float>(radius: T) -> T {
15    two!() * pi!() * radius
16}
17#
18# fn main() {
19#     assert!(circumference(1.0_f64) == 6.283185307179586);
20# }
21```
22
23See what numbers are declared in [declare_nums].
24
25If you `declare_nums!()` in the root of your crate, you don't even need
26to import the macros to submodules. This will not re-export the macros
27to the public crate.
28
29lib.rs or main.rs
30```ignore
31use num_lazy::declare_nums;
32declare_nums!{T}
33
34// My submodules
35pub mod generic_math;
36```
37
38generic_math.rs
39```ignore
40pub fn circle_area<T: Float>(radius: T) -> T {
41    pi!() * radius * radius
42}
43```
44
45If you want to declare the numbers in the root of your crate but keep
46the macro contained in a module, you can simply:
47
48lib.rs or main.rs
49```ignore
50mod generics {
51    use num_lazy::declare_nums;
52    declare_nums!{T}
53}
54```
55
56generic_math.rs
57```ignore
58use crate::generics::*;
59
60pub fn circle_area<T: Float>(radius: T) -> T {
61    pi!() * radius * radius
62}
63```
64*/
65
66/// Declare commonly used num generics in the module or crate root.
67///
68/// ```
69/// use num_lazy::declare_nums;
70/// use num_traits::Float;
71/// // Assign to generic type T.
72/// // Important. Use the braces!
73/// declare_nums!{T}
74///
75/// fn add_tiny<T: Float>(a: T) -> T {
76///     let tiny = five!() * epsilon!();
77///     a + tiny
78/// }
79///
80/// fn main() {
81///     assert!(add_tiny(1.0_f64) == 1.000000000000001);
82///     assert!(add_tiny(1.0_f32) == 1.0000006);
83/// }
84/// ```
85///
86/// This macro will populate the module with:
87/// - `num!($n)`: equivalent to `$t::from($n).unwrap()`, where `$t` is the generic type identifier you
88///    declared, and `$n` is any expression evaluated to a number.
89/// - **Literals**
90///     - `zero!()` to `ten!()`
91///     - `hundred!()`, `thousand!()`, and `million!()`
92///     - `half!()`, `third!()`, and `quarter!()`
93///     - `tenth!()`, `hundredth!()`, `thousandth!()`, and `millionth!()`
94/// - **Constants**
95///     - `pi!()`, `pi_2!()`, `pi_3!()`, `frac_1_pi!()`, `frac_2_pi!()`, and `frac_2_sqrt_pi!()`
96///     - `tau!()`
97///     - `e!()`
98///     - `ln_2!()`, `ln_10!()`, `log2_10!()`, `log2_e!()`, `log10_2!()`, and `log10_e!()`
99///     - `sqrt_2!()` and `frac_1_sqrt_2!()`
100///     - The golden ratio: `phi!()`
101/// - **Special Constants**
102///     - Infinity: `inf!()` and `neg_inf!()`
103///     - `nan!()`
104///     - Min/max type representation value: `min_val!()`, `max_val!()`, and `min_positive!()`
105///     - Machine epsilon: `epsilon!()`
106///     - Negative zero: `neg_zero!()`
107/// - **Others**
108///     - `_declare`: An internal function for declaring new numbers.
109///         - `_declare!{@literal fourty_two, 42.0, "The universe constant `42`"}`
110///         - `_declare!{@constant pi, PI, "π = `3.141592653589793`"}`
111///         - `_declare!{@special inf, infinity, "Infinity (`∞`)"}`
112#[macro_export]
113macro_rules! declare_nums {
114    ($t: ident) => {
115        /// Unwrap the expression into the specified generic type.
116        ///
117        /// Equivalent to `$t::from($n).unwrap()`, where `$t` is the generic type identifier you
118        /// declared, and `$n` is any expression evaluated to a number.
119        macro_rules! num {
120            ($n: expr) => {
121                $t::from($n).unwrap()
122            };
123        }
124
125        /// Declare new macro for a number. Meant to be used internally in num-lazy.
126        ///
127        /// `_declare!{@literal fourty_two, 42.0, "The universe constant `42`"}`
128        ///
129        /// `_declare!{@constant pi, PI, "π = `3.141592653589793`"}`
130        ///
131        /// `_declare!{@special inf, infinity, "Infinity (`∞`)"}`
132        ///
133        // It is documented this way to prevent doctest from compiling in the users' test.
134        // Using `ignore` will still show that the test is ignored, which can be annoying.
135        macro_rules! _declare {
136            ($name:ident, $value: expr, $doc: expr) => {
137                #[allow(unused_macros)]
138                #[doc=$doc]
139                macro_rules! $name {
140                    () => {
141                        $value
142                    };
143                }
144            };
145            (@literal $name:ident, $value: expr, $doc: expr) => {
146                _declare! {$name, num!($value), $doc}
147            };
148            (@special $name:ident, $const_fn: ident, $doc: expr) => {
149                _declare! {$name, $t::$const_fn(), $doc}
150            };
151            (@constant $name:ident, $constant: ident, $doc: expr) => {
152                _declare! {$name, $t::from(std::f64::consts::$constant).unwrap(), $doc}
153            };
154        }
155
156        _declare! {@literal zero, 0.0, "`0`"}
157        _declare! {@literal one, 1.0, "`1`"}
158        _declare! {@literal two, 2.0, "`2`"}
159        _declare! {@literal three, 3.0, "`3`"}
160        _declare! {@literal four, 4.0, "`4`"}
161        _declare! {@literal five, 5.0, "`5`"}
162        _declare! {@literal six, 6.0, "`6`"}
163        _declare! {@literal seven, 7.0, "`7`"}
164        _declare! {@literal eight, 8.0, "`8`"}
165        _declare! {@literal nine, 9.0, "`9`"}
166        _declare! {@literal ten, 10.0, "`10`"}
167        _declare! {@literal hundred, 100.0, "`100`"}
168        _declare! {@literal thousand, 1e3, "`1e3`"}
169        _declare! {@literal million, 1e6, "`1e6`"}
170        _declare! {@literal half, 0.5, "`0.5`"}
171        _declare! {@literal third, 1.0/3.0, "`1/3`"}
172        _declare! {@literal quarter, 0.25, "`0.25`"}
173        _declare! {@literal tenth, 0.1, "`0.1`"}
174        _declare! {@literal hundredth, 0.01, "`0.01`"}
175        _declare! {@literal thousandth, 1e-3, "`1e-3`"}
176        _declare! {@literal millionth, 1e-6, "`1e-6`"}
177
178        _declare! {@constant pi, PI, "π = `3.141592653589793`"}
179        _declare! {@constant pi_2, FRAC_PI_2, "π/2 = `1.5707963267948966`"}
180        _declare! {@constant pi_3, FRAC_PI_3, "π/3 = `1.0471975511965979`"}
181        _declare! {@constant frac_1_pi, FRAC_1_PI, "1/π = `0.3183098861837907`"}
182        _declare! {@constant frac_2_pi, FRAC_2_PI, "2/π = `0.6366197723675814`"}
183        _declare! {@constant frac_2_sqrt_pi, FRAC_2_SQRT_PI, "2/sqrt(π) = `1.1283791670955126`"}
184        _declare! {@constant tau, TAU, "τ = 2π = `6.283185307179586`"}
185        _declare! {@constant e, E, "Euler's number (e) = `2.718281828459045`"}
186        _declare! {@constant ln_2, LN_2, "ln(2) = `0.6931471805599453`"}
187        _declare! {@constant ln_10, LN_10, "ln(10) = `2.302585092994046`"}
188        _declare! {@constant log2_10, LOG2_10, "log₂(10) = `3.321928094887362`"}
189        _declare! {@constant log2_e, LOG2_E, "log₂(e) = `1.4426950408889634`"}
190        _declare! {@constant log10_2, LOG10_2, "log₁₀(2) = `0.3010299956639812`"}
191        _declare! {@constant log10_e, LOG10_E, "log₁₀(e) = `0.4342944819032518`"}
192        _declare! {@constant sqrt_2, SQRT_2, "sqrt(2) = `1.4142135623730951`"}
193        _declare! {@constant frac_1_sqrt_2, FRAC_1_SQRT_2, "1/sqrt(2) = `0.7071067811865476`"}
194        _declare! {@constant phi, PHI, "The golden ratio (φ) = `1.618033988749895`"}
195
196        _declare! {@special inf, infinity, "Infinity (`∞`)"}
197        _declare! {@special neg_inf, neg_infinity, "Negative infinity (`-∞`)"}
198        _declare! {@special nan, nan, "`NaN`"}
199        _declare! {@special min_val, min_value, "The smallest finite value that this type can represent.\n- f32: `-3.4028235e38`\n- f64: `-1.7976931348623157e308`"}
200        _declare! {@special max_val, max_value, "The largest finite value that this type can represent.\n- f32: `3.4028235e38`\n- f64: `1.7976931348623157e308`"}
201        _declare! {@special min_positive, min_positive_value, "The smallest positive value that this type can represent.\n- f32: `1.1754944e-38`\n- f64: `2.2250738585072014e-308`"}
202        _declare! {@special epsilon, epsilon, "`Machine epsilon` value for this type. This is the difference between `1.0` and the next larger representable number.\n- f32: `1.1920929e-7`\n- f64: `2.220446049250313e-16`"}
203        _declare! {@special neg_zero, neg_zero, "`-0.0`"}
204    };
205}