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}