1#[macro_export]
2macro_rules! impl_quantity {
3 ($type:ident, $unit:ty, $display_unit:expr) => {
4 use $crate::small_linalg::{Matrix3, Vector3};
5
6 #[derive(Copy, Clone)]
7 pub struct $type {
8 pub(crate) multiplyer: f64,
9 pub(crate) power: i32,
10 }
11
12 impl PhysicsQuantity for $type {
13 type Unit = $unit;
14
15 fn new(value: f64, unit: Self::Unit) -> Self {
16 if value.is_infinite() {
17 if value.is_sign_negative() {
18 return Self::NEG_INFINITY;
19 } else {
20 return Self::INFINITY;
21 }
22 }
23 let (unit_multiplyer, unit_power) = unit.base_per_x();
24 let (multiplyer, power) = Self::split_value(value);
25 Self {
26 multiplyer: multiplyer * unit_multiplyer,
27 power: power + unit_power,
28 }
29 }
30
31 fn split_value(v: f64) -> (f64, i32) {
32 if v.is_zero() {
33 (0.0, 0)
34 } else {
35 let power = v.abs().log10().floor() as i32;
36 let multiplier = v / 10f64.powi(power);
37 (multiplier, power)
38 }
39 }
40
41 fn zero() -> Self {
42 Self {
43 multiplyer: 0.,
44 power: 0,
45 }
46 }
47
48 fn get_value(&self) -> f64 {
49 self.multiplyer * 10_f64.powi(self.power)
50 }
51
52 fn get_power(&self) -> i32 {
53 self.power
54 }
55
56 fn get_multiplyer(&self) -> f64 {
57 self.multiplyer
58 }
59
60 fn get_tuple(&self) -> (f64, i32) {
61 (self.multiplyer, self.power)
62 }
63
64 fn to(&self, unit: Self::Unit) -> f64 {
65 let (unit_multiplyer, unit_power) = unit.base_per_x();
66 self.multiplyer / unit_multiplyer * 10_f64.powi(self.power - unit_power)
67 }
68
69 fn abs(self) -> Self {
70 Self {
71 multiplyer: self.multiplyer.abs(),
72 power: self.power,
73 }
74 }
75
76 fn to_raw(&self) -> f64 {
77 self.get_value()
78 }
79
80 fn from_raw(value: f64) -> Self {
81 if value.is_infinite() {
82 if value.is_sign_negative() {
83 return Self::NEG_INFINITY;
84 } else {
85 return Self::INFINITY;
86 }
87 }
88 let (multiplyer, power) = Self::split_value(value);
89 Self { multiplyer, power }
90 }
91
92 fn from_exponential(multiplyer: f64, power: i32) -> Self {
93 Self { multiplyer, power }
94 }
95
96 fn min(self, other: Self) -> Self {
97 if self.get_value() < other.get_value() {
98 self
99 } else {
100 other
101 }
102 }
103
104 fn max(self, other: Self) -> Self {
105 if self.get_value() > other.get_value() {
106 self
107 } else {
108 other
109 }
110 }
111
112 const INFINITY: Self = Self {
113 multiplyer: f64::INFINITY,
114 power: 0,
115 };
116 const NEG_INFINITY: Self = Self {
117 multiplyer: f64::NEG_INFINITY,
118 power: 0,
119 };
120 }
121
122 impl fmt::Display for $type {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 let base_unit = $display_unit;
125 let unit_name = if base_unit.name() == "°" {
126 "°".to_string()
127 } else {
128 format!(" {}", base_unit.name())
129 };
130 let value = self.to(base_unit);
131 let rounded = if value.is_zero() {
132 value
133 } else {
134 let didgits = value.log10().ceil() as i32;
135 let rounding_multiplyer = 10_f64.powi(3 - didgits);
136 (value * rounding_multiplyer).round() as f64 / rounding_multiplyer as f64
137 };
138
139 write!(f, "{}{}", rounded, unit_name)
140 }
141 }
142
143 impl Neg for $type {
144 type Output = Self;
145
146 fn neg(self) -> Self::Output {
147 Self {
148 multiplyer: -self.multiplyer,
149 power: self.power,
150 }
151 }
152 }
153
154 impl PartialEq<Self> for $type {
155 fn eq(&self, other: &Self) -> bool {
156 self.power == other.power && self.multiplyer == other.multiplyer
157 }
158 }
159
160 impl PartialOrd for $type {
161 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
162 self.get_value().partial_cmp(&other.get_value())
163 }
164 }
165
166 impl FromPrimitive for $type {
167 fn from_i64(n: i64) -> Option<Self> {
168 Some(Self::from_raw(n as f64))
169 }
170
171 fn from_u64(n: u64) -> Option<Self> {
172 Some(Self::from_raw(n as f64))
173 }
174
175 fn from_f64(n: f64) -> Option<Self> {
176 Some(Self::from_raw(n))
177 }
178 }
179
180 impl Add for $type {
181 type Output = Self;
182
183 fn add(self, other: Self) -> Self {
184 let common_power = (self.power + other.power) / 2;
185 let multiplyer = self.multiplyer * 10_f64.powi(self.power - common_power)
186 + other.multiplyer * 10_f64.powi(other.power - common_power);
187
188 Self {
189 multiplyer,
190 power: common_power,
191 }
192 }
193 }
194
195 impl Sub for $type {
196 type Output = Self;
197
198 fn sub(self, other: Self) -> Self {
199 let common_power = (self.power + other.power) / 2;
200 let multiplyer = self.multiplyer * 10_f64.powi(self.power - common_power)
201 - other.multiplyer * 10_f64.powi(other.power - common_power);
202
203 Self {
204 multiplyer,
205 power: common_power,
206 }
207 }
208 }
209
210 impl Div<f64> for $type {
211 type Output = Self;
212
213 fn div(self, rhs: f64) -> Self::Output {
214 let (rhs_multiplyer, rhs_power) = Self::split_value(rhs);
215 Self {
216 multiplyer: self.multiplyer / rhs_multiplyer,
217 power: self.power - rhs_power,
218 }
219 }
220 }
221
222 impl Mul<f64> for $type {
223 type Output = Self;
224
225 fn mul(self, rhs: f64) -> Self::Output {
226 let (rhs_multiplyer, rhs_power) = Self::split_value(rhs);
227 Self {
228 multiplyer: self.multiplyer * rhs_multiplyer,
229 power: self.power + rhs_power,
230 }
231 }
232 }
233
234 impl Mul<$type> for f64 {
235 type Output = $type;
236
237 fn mul(self, rhs: $type) -> Self::Output {
238 rhs * self
239 }
240 }
241
242 impl AddAssign for $type {
243 fn add_assign(&mut self, other: Self) {
244 let common_power = (self.power + other.power) / 2;
245 self.multiplyer = self.multiplyer * 10_f64.powi(self.power - common_power)
246 + other.multiplyer * 10_f64.powi(other.power - common_power);
247 self.power = common_power;
248 }
249 }
250
251 impl SubAssign for $type {
252 fn sub_assign(&mut self, other: Self) {
253 let common_power = (self.power + other.power) / 2;
254 self.multiplyer = self.multiplyer * 10_f64.powi(self.power - common_power)
255 - other.multiplyer * 10_f64.powi(other.power - common_power);
256 self.power = common_power;
257 }
258 }
259
260 impl MulAssign<f64> for $type {
261 fn mul_assign(&mut self, rhs: f64) {
262 let (rhs_multiplyer, rhs_power) = Self::split_value(rhs);
263 self.multiplyer *= rhs_multiplyer;
264 self.power += rhs_power;
265 }
266 }
267
268 impl DivAssign<f64> for $type {
269 fn div_assign(&mut self, rhs: f64) {
270 let (rhs_multiplyer, rhs_power) = Self::split_value(rhs);
271 self.multiplyer /= rhs_multiplyer;
272 self.power -= rhs_power;
273 }
274 }
275
276 impl Mul<Vector3<f64>> for $type {
277 type Output = Vector3<$type>;
278
279 fn mul(self, rhs: Vector3<f64>) -> Self::Output {
280 Vector3::new([self * rhs[0], self * rhs[1], self * rhs[2]])
281 }
282 }
283
284 impl Mul<Matrix3<f64>> for $type {
285 type Output = Matrix3<$type>;
286
287 fn mul(self, rhs: Matrix3<f64>) -> Self::Output {
288 Matrix3::new([
289 [self * rhs[(0, 0)], self * rhs[(0, 1)], self * rhs[(0, 2)]],
290 [self * rhs[(1, 0)], self * rhs[(1, 1)], self * rhs[(1, 2)]],
291 [self * rhs[(2, 0)], self * rhs[(2, 1)], self * rhs[(2, 2)]],
292 ])
293 }
294 }
295
296 impl Zero for $type {
297 fn zero() -> Self {
298 Self {
299 multiplyer: 0.0,
300 power: 0,
301 }
302 }
303
304 fn is_zero(&self) -> bool {
305 self.multiplyer == 0.0
306 }
307 }
308
309 impl fmt::Debug for $type {
310 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311 fmt::Display::fmt(self, f)
312 }
313 }
314
315 impl QuantityArray2<$unit> for Array2<$type> {
316 fn from_raw(raw: ArrayView2<f64>, unit: $unit) -> Self {
317 let mut res = Array2::zeros(raw.dim());
318 for i in 0..raw.dim().0 {
319 for j in 0..raw.dim().1 {
320 res[[i, j]] = <$type>::new(raw[[i, j]], unit);
321 }
322 }
323 res
324 }
325
326 fn to_raw(&self) -> Array2<f64> {
327 let mut res = Array2::zeros(self.dim());
328 for i in 0..self.dim().0 {
329 for j in 0..self.dim().1 {
330 res[[i, j]] = self[[i, j]].to_raw();
331 }
332 }
333 res
334 }
335
336 fn to(&self, unit: $unit) -> Array2<f64> {
337 let mut res = Array2::zeros(self.dim());
338 for i in 0..self.dim().0 {
339 for j in 0..self.dim().1 {
340 res[[i, j]] = self[[i, j]].to(unit);
341 }
342 }
343 res
344 }
345 }
346
347 impl QuantityArray1<$unit> for Array1<$type> {
348 fn from_raw(raw: ArrayView1<f64>, unit: $unit) -> Self {
349 let mut res = Array1::zeros(raw.dim());
350 for i in 0..raw.dim() {
351 res[i] = <$type>::new(raw[i], unit);
352 }
353 res
354 }
355
356 fn to_raw(&self) -> Array1<f64> {
357 let mut res = Array1::zeros(self.dim());
358 for i in 0..self.dim() {
359 res[i] = self[i].to_raw();
360 }
361 res
362 }
363
364 fn to(&self, unit: $unit) -> Array1<f64> {
365 let mut res = Array1::zeros(self.dim());
366 for i in 0..self.dim() {
367 res[i] = self[i].to(unit);
368 }
369 res
370 }
371 }
372 };
373}
374
375#[macro_export]
376macro_rules! impl_const {
377 ($type:ident, $name:ident, $multiplier:expr, $power:expr) => {
378 impl $type {
379 pub fn $name() -> Self {
380 Self {
381 multiplyer: $multiplier,
382 power: $power,
383 }
384 }
385 }
386 };
387}
388
389#[macro_export]
390macro_rules! impl_sqrt {
391 ($lhs:ty, $res:ty) => {
392 impl Sqrt<$res> for $lhs {
393 fn sqrt(self) -> $res {
394 if self.power % 2 == 0 {
395 <$res>::from_exponential(self.multiplyer.sqrt(), self.power / 2)
396 } else {
397 <$res>::from_exponential(
398 self.multiplyer.sqrt() * 10_f64.sqrt(),
399 (self.power - 1) / 2,
400 )
401 }
402 }
403 }
404 };
405}
406
407#[macro_export]
408macro_rules! impl_div_with_self_to_f64 {
409 ($lhs:ty) => {
410 impl Div<$lhs> for $lhs {
411 type Output = f64;
412
413 fn div(self, rhs: Self) -> Self::Output {
414 (self.multiplyer / rhs.multiplyer) * 10_f64.powi(self.power - rhs.power)
415 }
416 }
417 };
418}
419
420#[macro_export]
421macro_rules! impl_div_with_self {
422 ($lhs:ty, $res:ty, $res_type:ident) => {
423 impl Div<$lhs> for $lhs {
424 type Output = $res;
425
426 fn div(self, rhs: Self) -> Self::Output {
427 $res_type {
428 multiplyer: self.multiplyer / rhs.multiplyer,
429 power: self.power - rhs.power,
430 }
431 }
432 }
433 };
434}
435
436#[macro_export]
437macro_rules! impl_mul {
438 ($lhs:ty, $rhs:ty, $result:ty) => {
439 impl std::ops::Mul<$rhs> for $lhs {
440 type Output = $result;
441
442 fn mul(self, rhs: $rhs) -> Self::Output {
443 <$result>::from_exponential(
444 self.multiplyer * rhs.multiplyer,
445 self.power + rhs.power,
446 )
447 }
448 }
449
450 impl std::ops::Mul<$lhs> for $rhs {
451 type Output = $result;
452
453 fn mul(self, rhs: $lhs) -> Self::Output {
454 <$result>::from_exponential(
455 self.multiplyer * rhs.multiplyer,
456 self.power + rhs.power,
457 )
458 }
459 }
460
461 impl MulArray1<$rhs> for Array1<$lhs> {
462 type Output = Array1<$result>;
463
464 fn mul_array1(self, rhs: Array1<$rhs>) -> Array1<$result> {
465 self.into_iter()
466 .zip(rhs.into_iter())
467 .map(|(force, distance)| force * distance)
468 .collect()
469 }
470 }
471
472 impl MulArray2<$rhs> for Array2<$lhs> {
473 type Output = Array2<$result>;
474
475 fn mul_array2(self, rhs: Array2<$rhs>) -> Result<Array2<$result>, String> {
476 let mut results = Vec::new();
477
478 for (lhs_row, rhs_row) in self.outer_iter().zip(rhs.outer_iter()) {
479 let result_row: Array1<$result> = lhs_row
480 .iter()
481 .zip(rhs_row.iter())
482 .map(|(&lhs, &rhs)| lhs * rhs)
483 .collect();
484 results.push(result_row);
485 }
486
487 let nrows = results.len();
488 let ncols = if nrows > 0 { results[0].len() } else { 0 };
489 let data: Vec<$result> = results
490 .into_iter()
491 .flat_map(|r| {
492 let (raw_vec, _) = r.into_raw_vec_and_offset();
493 raw_vec
494 })
495 .collect();
496
497 Array2::from_shape_vec((nrows, ncols), data)
498 .map_err(|_| "Shape mismatch".to_string())
499 }
500 }
501
502 impl MulArray1<$lhs> for Array1<$rhs> {
503 type Output = Array1<$result>;
504
505 fn mul_array1(self, rhs: Array1<$lhs>) -> Array1<$result> {
506 self.into_iter()
507 .zip(rhs.into_iter())
508 .map(|(force, distance)| force * distance)
509 .collect()
510 }
511 }
512
513 impl MulArray2<$lhs> for Array2<$rhs> {
514 type Output = Array2<$result>;
515
516 fn mul_array2(self, rhs: Array2<$lhs>) -> Result<Array2<$result>, String> {
517 let mut results = Vec::new();
518
519 for (force_row, distance_row) in self.outer_iter().zip(rhs.outer_iter()) {
520 let result_row: Array1<$result> = force_row
521 .iter()
522 .zip(distance_row.iter())
523 .map(|(&force, &distance)| force * distance)
524 .collect();
525 results.push(result_row);
526 }
527
528 let nrows = results.len();
529 let ncols = if nrows > 0 { results[0].len() } else { 0 };
530 let data: Vec<$result> = results
531 .into_iter()
532 .flat_map(|r| {
533 let (raw_vec, _) = r.into_raw_vec_and_offset();
534 raw_vec
535 })
536 .collect();
537
538 Array2::from_shape_vec((nrows, ncols), data)
539 .map_err(|_| "Shape mismatch".to_string())
540 }
541 }
542 };
543}
544
545#[macro_export]
546macro_rules! impl_mul_with_self {
547 ($lhs:ty,$result:ty) => {
548 impl std::ops::Mul<$lhs> for $lhs {
549 type Output = $result;
550
551 fn mul(self, rhs: $lhs) -> Self::Output {
552 <$result>::from_exponential(
553 self.multiplyer * rhs.multiplyer,
554 self.power + rhs.power,
555 )
556 }
557 }
558
559 impl MulArray1<$lhs> for Array1<$lhs> {
560 type Output = Array1<$result>;
561
562 fn mul_array1(self, rhs: Array1<$lhs>) -> Array1<$result> {
563 self.into_iter()
564 .zip(rhs.into_iter())
565 .map(|(force, distance)| force * distance)
566 .collect()
567 }
568 }
569
570 impl MulArray2<$lhs> for Array2<$lhs> {
571 type Output = Array2<$result>;
572
573 fn mul_array2(self, rhs: Array2<$lhs>) -> Result<Array2<$result>, String> {
574 let mut results = Vec::new();
575
576 for (force_row, distance_row) in self.outer_iter().zip(rhs.outer_iter()) {
577 let result_row: Array1<$result> = force_row
578 .iter()
579 .zip(distance_row.iter())
580 .map(|(&force, &distance)| force * distance)
581 .collect();
582 results.push(result_row);
583 }
584
585 let nrows = results.len();
586 let ncols = if nrows > 0 { results[0].len() } else { 0 };
587 let data: Vec<$result> = results
588 .into_iter()
589 .flat_map(|r| {
590 let (raw_vec, _) = r.into_raw_vec_and_offset();
591 raw_vec
592 })
593 .collect();
594
595 Array2::from_shape_vec((nrows, ncols), data)
596 .map_err(|_| "Shape mismatch".to_string())
597 }
598 }
599 };
600}
601
602#[macro_export]
603macro_rules! impl_div {
604 ($lhs:ty, $rhs:ty, $result:ty) => {
605 impl std::ops::Div<$rhs> for $lhs {
606 type Output = $result;
607
608 fn div(self, rhs: $rhs) -> Self::Output {
609 <$result>::from_exponential(
610 self.multiplyer / rhs.multiplyer,
611 self.power - rhs.power,
612 )
613 }
614 }
615
616 impl DivArray1<$rhs> for Array1<$lhs> {
617 type Output = Array1<$result>;
618
619 fn div_array1(self, rhs: Array1<$rhs>) -> Array1<$result> {
620 self.into_iter()
621 .zip(rhs.into_iter())
622 .map(|(force, distance)| force / distance)
623 .collect()
624 }
625 }
626
627 impl DivArray2<$rhs> for Array2<$lhs> {
628 type Output = Array2<$result>;
629
630 fn div_array2(self, rhs: Array2<$rhs>) -> Result<Array2<$result>, String> {
631 let mut results = Vec::new();
632
633 for (force_row, distance_row) in self.outer_iter().zip(rhs.outer_iter()) {
634 let result_row: Array1<$result> = force_row
635 .iter()
636 .zip(distance_row.iter())
637 .map(|(&force, &distance)| force / distance)
638 .collect();
639 results.push(result_row);
640 }
641
642 let nrows = results.len();
643 let ncols = if nrows > 0 { results[0].len() } else { 0 };
644 let data: Vec<$result> = results
645 .into_iter()
646 .flat_map(|r| {
647 let (raw_vec, _) = r.into_raw_vec_and_offset();
648 raw_vec
649 })
650 .collect();
651
652 Array2::from_shape_vec((nrows, ncols), data)
653 .map_err(|_| "Shape mismatch".to_string())
654 }
655 }
656 };
657}
658
659pub mod macros {
660 pub use crate::impl_const;
661 pub use crate::impl_div;
662 pub use crate::impl_div_with_self;
663 pub use crate::impl_div_with_self_to_f64;
664 pub use crate::impl_mul;
665 pub use crate::impl_mul_with_self;
666 pub use crate::impl_quantity;
667 pub use crate::impl_sqrt;
668}