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}