retrofire_core/math/
space.rs1use core::marker::PhantomData;
6
7use crate::math::vary::{Iter, Vary};
8
9pub trait Affine: Sized {
14 type Space;
16 type Diff: Linear;
19
20 const DIM: usize;
22
23 fn add(&self, diff: &Self::Diff) -> Self;
27
28 fn sub(&self, other: &Self) -> Self::Diff;
32}
33
34pub trait Linear: Affine<Diff = Self> {
46 type Scalar: Sized;
48
49 fn zero() -> Self;
51
52 fn neg(&self) -> Self;
54
55 fn mul(&self, scalar: Self::Scalar) -> Self;
68}
69
70#[derive(Copy, Clone, Default, Eq, PartialEq)]
73pub struct Real<const DIM: usize, Basis = ()>(PhantomData<Basis>);
74
75#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
79pub struct Proj4;
80
81impl Affine for f32 {
82 type Space = ();
83 type Diff = Self;
84 const DIM: usize = 1;
85
86 fn add(&self, other: &f32) -> f32 {
87 self + other
88 }
89 fn sub(&self, other: &f32) -> f32 {
90 self - other
91 }
92}
93
94impl Linear for f32 {
95 type Scalar = f32;
96
97 fn zero() -> f32 {
98 0.0
99 }
100 fn neg(&self) -> f32 {
101 -*self
102 }
103 fn mul(&self, rhs: f32) -> f32 {
104 self * rhs
105 }
106}
107
108impl Affine for i32 {
109 type Space = ();
110 type Diff = Self;
111 const DIM: usize = 1;
112
113 fn add(&self, rhs: &i32) -> i32 {
114 self + rhs
115 }
116 fn sub(&self, rhs: &i32) -> i32 {
117 self - rhs
118 }
119}
120
121impl Linear for i32 {
122 type Scalar = Self;
123
124 fn zero() -> i32 {
125 0
126 }
127 fn neg(&self) -> i32 {
128 -self
129 }
130 fn mul(&self, rhs: i32) -> i32 {
131 self * rhs
132 }
133}
134
135impl Affine for u32 {
136 type Space = ();
137 type Diff = i32;
138 const DIM: usize = 1;
139
140 fn add(&self, rhs: &i32) -> u32 {
141 let (res, o) = self.overflowing_add_signed(*rhs);
142 debug_assert!(!o, "overflow adding {rhs}_i32 to {self}_u32");
143 res
144 }
145
146 fn sub(&self, rhs: &u32) -> i32 {
147 let diff = *self as i64 - *rhs as i64;
148 debug_assert!(
149 i32::try_from(diff).is_ok(),
150 "overflow subtracting {rhs}_u32 from {self}_u32"
151 );
152 diff as i32
153 }
154}
155
156impl<V: Clone> Vary for V
157where
158 Self: Linear<Scalar = f32>,
159{
160 type Iter = Iter<Self>;
161 type Diff = <Self as Affine>::Diff;
162
163 #[inline]
164 fn vary(self, step: Self::Diff, n: Option<u32>) -> Self::Iter {
165 Iter { val: self, step, n }
166 }
167
168 fn dv_dt(&self, other: &Self, recip_dt: f32) -> Self::Diff {
169 other.sub(self).mul(recip_dt)
170 }
171
172 #[inline]
174 fn step(&self, delta: &Self::Diff) -> Self {
175 self.add(delta)
176 }
177
178 fn z_div(&self, z: f32) -> Self {
179 self.mul(z.recip())
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 mod f32 {
188 use super::*;
189
190 #[test]
191 fn affine_ops() {
192 assert_eq!(f32::DIM, 1);
193
194 assert_eq!(1_f32.add(&2_f32), 3_f32);
195 assert_eq!(3_f32.add(&-2_f32), 1_f32);
196
197 assert_eq!(3_f32.sub(&2_f32), 1_f32);
198 assert_eq!(1_f32.sub(&4_f32), -3_f32);
199 }
200
201 #[test]
202 fn linear_ops() {
203 assert_eq!(f32::zero(), 0.0);
204
205 assert_eq!(2_f32.neg(), -2_f32);
206 assert_eq!(-3_f32.neg(), 3_f32);
207
208 assert_eq!(3_f32.mul(2_f32), 6_f32);
209 assert_eq!(3_f32.mul(0.5_f32), 1.5_f32);
210 assert_eq!(3_f32.mul(-2_f32), -6_f32);
211 }
212 }
213
214 mod i32 {
215 use super::*;
216
217 #[test]
218 fn affine_ops() {
219 assert_eq!(i32::DIM, 1);
220
221 assert_eq!(1_i32.add(&2_i32), 3_i32);
222 assert_eq!(2_i32.add(&-3_i32), -1_i32);
223
224 assert_eq!(3_i32.sub(&2_i32), 1_i32);
225 assert_eq!(3_i32.sub(&4_i32), -1_i32);
226 }
227
228 #[test]
229 fn linear_ops() {
230 assert_eq!(i32::zero(), 0);
231
232 assert_eq!(2_i32.neg(), -2_i32);
233 assert_eq!(-3_i32.neg(), 3_i32);
234
235 assert_eq!(3_i32.mul(2_i32), 6_i32);
236 assert_eq!(2_i32.mul(-3_i32), -6_i32);
237 }
238 }
239
240 mod u32 {
241 use super::*;
242
243 #[test]
244 fn affine_ops() {
245 assert_eq!(u32::DIM, 1);
246
247 assert_eq!(1_u32.add(&2_i32), 3_u32);
248 assert_eq!(3_u32.add(&-2_i32), 1_u32);
249
250 assert_eq!(3_u32.sub(&2_u32), 1_i32);
251 assert_eq!(3_u32.sub(&4_u32), -1_i32);
252 }
253
254 #[test]
255 #[should_panic]
256 fn affine_add_underflow_should_panic() {
257 _ = 3_u32.add(&-4_i32);
258 }
259
260 #[test]
261 #[should_panic]
262 fn affine_add_overflow_should_panic() {
263 _ = (u32::MAX / 2 + 2).add(&i32::MAX);
264 }
265
266 #[test]
267 #[should_panic]
268 fn affine_sub_underflow_should_panic() {
269 _ = 3_u32.sub(&u32::MAX);
270 }
271
272 #[test]
273 #[should_panic]
274 fn affine_sub_overflow_should_panic() {
275 _ = u32::MAX.sub(&1_u32);
276 }
277 }
278}