1use std::cmp::Ordering;
2use std::fmt::{self, Debug, Formatter};
3use std::hash::{Hash, Hasher};
4use std::iter::Sum;
5use std::ops::{
6 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
7};
8
9use crate::Numeric;
10
11#[derive(Default, Copy, Clone)]
15pub struct Scalar(f64);
16
17impl Scalar {
18 pub const ZERO: Self = Self(0.0);
20
21 pub const ONE: Self = Self(1.0);
23
24 pub const INFINITY: Self = Self(f64::INFINITY);
26
27 pub const fn new(x: f64) -> Self {
31 Self(if x.is_nan() { 0.0 } else { x })
32 }
33
34 pub const fn get(self) -> f64 {
36 self.0
37 }
38}
39
40impl Numeric for Scalar {
41 fn zero() -> Self {
42 Self(0.0)
43 }
44
45 fn is_finite(self) -> bool {
46 self.0.is_finite()
47 }
48}
49
50impl Debug for Scalar {
51 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
52 self.0.fmt(f)
53 }
54}
55
56impl Eq for Scalar {}
57
58impl PartialEq for Scalar {
59 fn eq(&self, other: &Self) -> bool {
60 assert!(!self.0.is_nan() && !other.0.is_nan(), "float is NaN");
61 self.0 == other.0
62 }
63}
64
65impl PartialEq<f64> for Scalar {
66 fn eq(&self, other: &f64) -> bool {
67 self == &Self(*other)
68 }
69}
70
71impl Ord for Scalar {
72 fn cmp(&self, other: &Self) -> Ordering {
73 self.0.partial_cmp(&other.0).expect("float is NaN")
74 }
75}
76
77impl PartialOrd for Scalar {
78 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
79 Some(self.cmp(other))
80 }
81}
82
83impl Hash for Scalar {
84 fn hash<H: Hasher>(&self, state: &mut H) {
85 debug_assert!(!self.0.is_nan(), "float is NaN");
86 self.0.to_bits().hash(state);
87 }
88}
89
90impl From<f64> for Scalar {
91 fn from(float: f64) -> Self {
92 Self::new(float)
93 }
94}
95
96impl From<Scalar> for f64 {
97 fn from(scalar: Scalar) -> Self {
98 scalar.0
99 }
100}
101
102impl Neg for Scalar {
103 type Output = Self;
104
105 fn neg(self) -> Self::Output {
106 Self::new(-self.0)
107 }
108}
109
110impl<T: Into<Self>> Add<T> for Scalar {
111 type Output = Self;
112
113 fn add(self, rhs: T) -> Self::Output {
114 Self::new(self.0 + rhs.into().0)
115 }
116}
117
118impl<T: Into<Self>> AddAssign<T> for Scalar {
119 fn add_assign(&mut self, rhs: T) {
120 *self = *self + rhs.into();
121 }
122}
123
124impl<T: Into<Self>> Sub<T> for Scalar {
125 type Output = Self;
126
127 fn sub(self, rhs: T) -> Self::Output {
128 Self::new(self.0 - rhs.into().0)
129 }
130}
131
132impl<T: Into<Self>> SubAssign<T> for Scalar {
133 fn sub_assign(&mut self, rhs: T) {
134 *self = *self - rhs.into();
135 }
136}
137
138impl<T: Into<Self>> Mul<T> for Scalar {
139 type Output = Self;
140
141 fn mul(self, rhs: T) -> Self::Output {
142 Self::new(self.0 * rhs.into().0)
143 }
144}
145
146impl<T: Into<Self>> MulAssign<T> for Scalar {
147 fn mul_assign(&mut self, rhs: T) {
148 *self = *self * rhs.into();
149 }
150}
151
152impl<T: Into<Self>> Div<T> for Scalar {
153 type Output = Self;
154
155 fn div(self, rhs: T) -> Self::Output {
156 Self::new(self.0 / rhs.into().0)
157 }
158}
159
160impl<T: Into<Self>> DivAssign<T> for Scalar {
161 fn div_assign(&mut self, rhs: T) {
162 *self = *self / rhs.into();
163 }
164}
165
166impl<T: Into<Self>> Rem<T> for Scalar {
167 type Output = Self;
168
169 fn rem(self, rhs: T) -> Self::Output {
170 Self::new(self.0 % rhs.into().0)
171 }
172}
173
174impl<T: Into<Self>> RemAssign<T> for Scalar {
175 fn rem_assign(&mut self, rhs: T) {
176 *self = *self % rhs.into();
177 }
178}
179
180impl Sum for Scalar {
181 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
182 Self::new(iter.map(|s| s.0).sum())
183 }
184}
185
186impl<'a> Sum<&'a Self> for Scalar {
187 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
188 Self::new(iter.map(|s| s.0).sum())
189 }
190}