num_t/
lib.rs

1#![warn(
2    clippy::unwrap_used,
3    clippy::cast_lossless,
4    clippy::unimplemented,
5    clippy::indexing_slicing,
6    clippy::expect_used
7)]
8
9use std::iter::Sum;
10use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
11use std::str::FromStr;
12
13#[derive(Debug)]
14#[repr(transparent)]
15pub struct TypedNum<Number, Type>(pub Number, std::marker::PhantomData<Type>);
16
17impl<Scalar: Clone, Type> Clone for TypedNum<Scalar, Type> {
18    fn clone(&self) -> Self {
19        TypedNum(self.0.clone(), self.1)
20    }
21}
22
23impl<Scalar: Copy, Type> Copy for TypedNum<Scalar, Type> {}
24
25impl<Scalar: Default, Type> Default for TypedNum<Scalar, Type> {
26    fn default() -> Self {
27        TypedNum(Scalar::default(), std::marker::PhantomData::<Type>)
28    }
29}
30
31impl<Scalar, Type> From<Scalar> for TypedNum<Scalar, Type> {
32    fn from(number: Scalar) -> Self {
33        TypedNum(number, std::marker::PhantomData::<Type>)
34    }
35}
36
37impl<Scalar, Type> TypedNum<Scalar, Type> {
38    #[inline]
39    pub fn new(number: Scalar) -> TypedNum<Scalar, Type> {
40        TypedNum(number, std::marker::PhantomData::<Type>)
41    }
42}
43
44impl<Scalar: PartialOrd, Type> PartialOrd for TypedNum<Scalar, Type> {
45    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
46        self.0.partial_cmp(&other.0)
47    }
48}
49
50impl<Scalar: PartialEq, Type> PartialEq for TypedNum<Scalar, Type> {
51    fn eq(&self, other: &Self) -> bool {
52        self.0 == other.0
53    }
54}
55
56impl<Scalar: std::cmp::Eq, Type> std::cmp::Eq for TypedNum<Scalar, Type> {}
57
58impl<Scalar: Add<Output = Scalar>, Type> Add for TypedNum<Scalar, Type> {
59    type Output = Self;
60
61    fn add(self, other: Self) -> Self::Output {
62        TypedNum::new(self.0 + other.0)
63    }
64}
65
66impl<Scalar: Sub<Output = Scalar>, Type> Sub for TypedNum<Scalar, Type> {
67    type Output = Self;
68
69    fn sub(self, other: Self) -> Self::Output {
70        TypedNum::new(self.0 - other.0)
71    }
72}
73
74impl<Scalar: Mul<Output = Scalar>, Type> Mul for TypedNum<Scalar, Type> {
75    type Output = Self;
76
77    fn mul(self, other: Self) -> Self::Output {
78        TypedNum::new(self.0 * other.0)
79    }
80}
81
82impl<Scalar: Div<Output = Scalar>, Type> Div for TypedNum<Scalar, Type> {
83    type Output = Self;
84
85    fn div(self, other: Self) -> Self::Output {
86        TypedNum::new(self.0 / other.0)
87    }
88}
89
90impl<Scalar: Rem<Output = Scalar>, Type> Rem for TypedNum<Scalar, Type> {
91    type Output = Self;
92
93    fn rem(self, other: Self) -> Self::Output {
94        TypedNum::new(self.0 % other.0)
95    }
96}
97
98impl<Scalar: AddAssign, Type> AddAssign for TypedNum<Scalar, Type> {
99    fn add_assign(&mut self, other: Self) {
100        self.0 += other.0;
101    }
102}
103
104impl<Scalar: SubAssign, Type> SubAssign for TypedNum<Scalar, Type> {
105    fn sub_assign(&mut self, other: Self) {
106        self.0 -= other.0;
107    }
108}
109
110impl<Scalar: MulAssign, Type> MulAssign for TypedNum<Scalar, Type> {
111    fn mul_assign(&mut self, other: Self) {
112        self.0 *= other.0;
113    }
114}
115
116impl<Scalar: DivAssign, Type> DivAssign for TypedNum<Scalar, Type> {
117    fn div_assign(&mut self, other: Self) {
118        self.0 /= other.0;
119    }
120}
121
122impl<Scalar: RemAssign, Type> RemAssign for TypedNum<Scalar, Type> {
123    fn rem_assign(&mut self, other: Self) {
124        self.0 %= other.0;
125    }
126}
127
128impl<Scalar: num_traits::ToPrimitive, Type> num_traits::ToPrimitive for TypedNum<Scalar, Type> {
129    fn to_i64(&self) -> Option<i64> {
130        self.0.to_i64()
131    }
132
133    fn to_u64(&self) -> Option<u64> {
134        self.0.to_u64()
135    }
136
137    fn to_f32(&self) -> Option<f32> {
138        self.0.to_f32()
139    }
140
141    fn to_f64(&self) -> Option<f64> {
142        self.0.to_f64()
143    }
144
145    fn to_i128(&self) -> Option<i128> {
146        self.0.to_i128()
147    }
148
149    fn to_u128(&self) -> Option<u128> {
150        self.0.to_u128()
151    }
152
153    fn to_i16(&self) -> Option<i16> {
154        self.0.to_i16()
155    }
156
157    fn to_u16(&self) -> Option<u16> {
158        self.0.to_u16()
159    }
160
161    fn to_i32(&self) -> Option<i32> {
162        self.0.to_i32()
163    }
164
165    fn to_u32(&self) -> Option<u32> {
166        self.0.to_u32()
167    }
168
169    fn to_i8(&self) -> Option<i8> {
170        self.0.to_i8()
171    }
172
173    fn to_isize(&self) -> Option<isize> {
174        self.0.to_isize()
175    }
176
177    fn to_u8(&self) -> Option<u8> {
178        self.0.to_u8()
179    }
180
181    fn to_usize(&self) -> Option<usize> {
182        self.0.to_usize()
183    }
184}
185
186impl<Scalar: num_traits::NumCast, Type> num_traits::NumCast for TypedNum<Scalar, Type> {
187    fn from<T: num_traits::ToPrimitive>(n: T) -> Option<Self> {
188        Scalar::from(n).map(TypedNum::new)
189    }
190}
191
192impl<Scalar: num_traits::Num, Type> num_traits::Num for TypedNum<Scalar, Type> {
193    type FromStrRadixErr = Scalar::FromStrRadixErr;
194
195    fn from_str_radix(
196        str: &str,
197        radix: u32,
198    ) -> Result<Self, <Self as num_traits::Num>::FromStrRadixErr> {
199        Ok(TypedNum::new(Scalar::from_str_radix(str, radix)?))
200    }
201}
202
203impl<Scalar: num_traits::One, Type> num_traits::One for TypedNum<Scalar, Type> {
204    fn one() -> Self {
205        TypedNum::new(Scalar::one())
206    }
207}
208
209impl<Scalar: num_traits::Zero, Type> num_traits::Zero for TypedNum<Scalar, Type> {
210    fn zero() -> Self {
211        TypedNum::new(Scalar::zero())
212    }
213
214    fn is_zero(&self) -> bool {
215        self.0.is_zero()
216    }
217}
218
219impl<Scalar: num_traits::Float, Type> num_traits::Float for TypedNum<Scalar, Type>
220where
221    Self: std::ops::Neg<Output = Self> + std::fmt::Debug,
222{
223    fn nan() -> Self {
224        TypedNum::new(Scalar::nan())
225    }
226
227    fn infinity() -> Self {
228        TypedNum::new(Scalar::infinity())
229    }
230
231    fn neg_infinity() -> Self {
232        TypedNum::new(Scalar::neg_infinity())
233    }
234
235    fn neg_zero() -> Self {
236        TypedNum::new(Scalar::neg_zero())
237    }
238
239    fn min_value() -> Self {
240        TypedNum::new(Scalar::min_value())
241    }
242
243    fn min_positive_value() -> Self {
244        TypedNum::new(Scalar::min_positive_value())
245    }
246
247    fn max_value() -> Self {
248        TypedNum::new(Scalar::max_value())
249    }
250
251    fn is_nan(self) -> bool {
252        self.0.is_nan()
253    }
254
255    fn is_infinite(self) -> bool {
256        self.0.is_infinite()
257    }
258
259    fn is_finite(self) -> bool {
260        self.0.is_finite()
261    }
262
263    fn is_normal(self) -> bool {
264        self.0.is_normal()
265    }
266
267    fn classify(self) -> std::num::FpCategory {
268        self.0.classify()
269    }
270
271    fn floor(self) -> Self {
272        TypedNum::new(self.0.floor())
273    }
274
275    fn ceil(self) -> Self {
276        TypedNum::new(self.0.ceil())
277    }
278
279    fn round(self) -> Self {
280        TypedNum::new(self.0.round())
281    }
282
283    fn trunc(self) -> Self {
284        TypedNum::new(self.0.trunc())
285    }
286
287    fn fract(self) -> Self {
288        TypedNum::new(self.0.fract())
289    }
290
291    fn abs(self) -> Self {
292        TypedNum::new(self.0.abs())
293    }
294
295    fn signum(self) -> Self {
296        TypedNum::new(self.0.signum())
297    }
298
299    fn is_sign_positive(self) -> bool {
300        self.0.is_sign_positive()
301    }
302
303    fn is_sign_negative(self) -> bool {
304        self.0.is_sign_negative()
305    }
306
307    fn mul_add(self, a: Self, b: Self) -> Self {
308        TypedNum::new(self.0.mul_add(a.0, b.0))
309    }
310
311    fn recip(self) -> Self {
312        TypedNum::new(self.0.recip())
313    }
314
315    fn powi(self, n: i32) -> Self {
316        TypedNum::new(self.0.powi(n))
317    }
318
319    fn powf(self, n: Self) -> Self {
320        TypedNum::new(self.0.powf(n.0))
321    }
322
323    fn sqrt(self) -> Self {
324        TypedNum::new(self.0.sqrt())
325    }
326
327    fn exp(self) -> Self {
328        TypedNum::new(self.0.exp())
329    }
330
331    fn exp2(self) -> Self {
332        TypedNum::new(self.0.exp2())
333    }
334
335    fn ln(self) -> Self {
336        TypedNum::new(self.0.ln())
337    }
338
339    fn log(self, base: Self) -> Self {
340        TypedNum::new(self.0.log(base.0))
341    }
342
343    fn log2(self) -> Self {
344        TypedNum::new(self.0.log2())
345    }
346
347    fn log10(self) -> Self {
348        TypedNum::new(self.0.log10())
349    }
350
351    fn max(self, other: Self) -> Self {
352        TypedNum::new(self.0.max(other.0))
353    }
354
355    fn min(self, other: Self) -> Self {
356        TypedNum::new(self.0.min(other.0))
357    }
358
359    fn abs_sub(self, other: Self) -> Self {
360        TypedNum::new(self.0.abs_sub(other.0))
361    }
362
363    fn cbrt(self) -> Self {
364        TypedNum::new(self.0.cbrt())
365    }
366
367    fn hypot(self, other: Self) -> Self {
368        TypedNum::new(self.0.hypot(other.0))
369    }
370
371    fn sin(self) -> Self {
372        TypedNum::new(self.0.sin())
373    }
374
375    fn cos(self) -> Self {
376        TypedNum::new(self.0.cos())
377    }
378
379    fn tan(self) -> Self {
380        TypedNum::new(self.0.tan())
381    }
382
383    fn asin(self) -> Self {
384        TypedNum::new(self.0.asin())
385    }
386
387    fn acos(self) -> Self {
388        TypedNum::new(self.0.acos())
389    }
390
391    fn atan(self) -> Self {
392        TypedNum::new(self.0.atan())
393    }
394
395    fn atan2(self, other: Self) -> Self {
396        TypedNum::new(self.0.atan2(other.0))
397    }
398
399    fn sin_cos(self) -> (Self, Self) {
400        let (sin, cos) = self.0.sin_cos();
401        (TypedNum::new(sin), TypedNum::new(cos))
402    }
403
404    fn exp_m1(self) -> Self {
405        TypedNum::new(self.0.exp_m1())
406    }
407
408    fn ln_1p(self) -> Self {
409        TypedNum::new(self.0.ln_1p())
410    }
411
412    fn sinh(self) -> Self {
413        TypedNum::new(self.0.sinh())
414    }
415
416    fn cosh(self) -> Self {
417        TypedNum::new(self.0.cosh())
418    }
419
420    fn tanh(self) -> Self {
421        TypedNum::new(self.0.tanh())
422    }
423
424    fn asinh(self) -> Self {
425        TypedNum::new(self.0.asinh())
426    }
427
428    fn acosh(self) -> Self {
429        TypedNum::new(self.0.acosh())
430    }
431
432    fn atanh(self) -> Self {
433        TypedNum::new(self.0.atanh())
434    }
435
436    fn integer_decode(self) -> (u64, i16, i8) {
437        self.0.integer_decode()
438    }
439}
440
441#[cfg(feature = "float_next_after")]
442impl<Scalar: float_next_after::NextAfter, Type> float_next_after::NextAfter
443    for TypedNum<Scalar, Type>
444{
445    fn next_after(self, other: Self) -> Self {
446        TypedNum::new(self.0.next_after(other.0))
447    }
448}
449
450impl<Scalar: num_traits::Bounded, Type> num_traits::Bounded for TypedNum<Scalar, Type> {
451    fn min_value() -> Self {
452        TypedNum::new(Scalar::min_value())
453    }
454
455    fn max_value() -> Self {
456        TypedNum::new(Scalar::max_value())
457    }
458}
459
460impl<Scalar: std::ops::Neg<Output = Scalar>, Type> std::ops::Neg for TypedNum<Scalar, Type> {
461    type Output = Self;
462
463    fn neg(self) -> Self::Output {
464        TypedNum::new(-self.0)
465    }
466}
467
468impl<Scalar: num_traits::Signed + std::ops::Neg<Output = Scalar> + num_traits::Num, Type>
469    num_traits::Signed for TypedNum<Scalar, Type>
470where
471    Self: std::ops::Neg<Output = Self>,
472{
473    fn abs(&self) -> Self {
474        TypedNum::new(self.0.abs())
475    }
476
477    fn abs_sub(&self, other: &Self) -> Self {
478        TypedNum::new(self.0.abs_sub(&other.0))
479    }
480
481    fn signum(&self) -> Self {
482        TypedNum::new(self.0.signum())
483    }
484
485    fn is_positive(&self) -> bool {
486        self.0.is_positive()
487    }
488
489    fn is_negative(&self) -> bool {
490        self.0.is_negative()
491    }
492}
493
494#[cfg(feature = "geo")]
495impl<Scalar: geo::GeoNum, Type: std::fmt::Debug> geo::GeoNum for TypedNum<Scalar, Type>
496where
497    Self: std::ops::Neg<Output = Self>,
498    <Scalar as geo::GeoNum>::Ker: geo::Kernel<TypedNum<Scalar, Type>>,
499{
500    type Ker = <Scalar as geo::GeoNum>::Ker;
501
502    fn total_cmp(&self, other: &Self) -> std::cmp::Ordering {
503        self.0.total_cmp(&other.0)
504    }
505}
506
507impl<Scalar: FromStr, Type> FromStr for TypedNum<Scalar, Type> {
508    type Err = Scalar::Err;
509
510    fn from_str(s: &str) -> Result<Self, Self::Err> {
511        Ok(TypedNum::new(Scalar::from_str(s)?))
512    }
513}
514
515impl<Scalar: num_traits::FromPrimitive, Type> num_traits::FromPrimitive for TypedNum<Scalar, Type> {
516    fn from_i64(n: i64) -> Option<Self> {
517        Scalar::from_i64(n).map(TypedNum::new)
518    }
519
520    fn from_u64(n: u64) -> Option<Self> {
521        Scalar::from_u64(n).map(TypedNum::new)
522    }
523}
524
525impl<Scalar: std::cmp::Ord, Type> std::cmp::Ord for TypedNum<Scalar, Type> {
526    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
527        self.0.cmp(&other.0)
528    }
529}
530
531impl<Scalar: std::fmt::Display, Type> std::fmt::Display for TypedNum<Scalar, Type> {
532    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
533        self.0.fmt(f)
534    }
535}
536
537impl<Scalar: Sum, Type> Sum for TypedNum<Scalar, Type> {
538    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
539        TypedNum::new(iter.map(|n| n.0).sum())
540    }
541}