unitforge/
prelude.rs

1use ndarray::{Array1, Array2, ArrayView1, ArrayView2};
2use num_traits::{FromPrimitive, Zero};
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5#[macro_export]
6macro_rules! power {
7    ($x:expr, 1) => {
8        $x
9    };
10    ($x:expr, 2) => {
11        $x * $x
12    };
13    ($x:expr, 3) => {
14        $x * $x * $x
15    };
16    ($x:expr, 4) => {
17        $x * $x * $x * $x
18    };
19    ($x:expr, 5) => {
20        $x * $x * $x * $x * $x
21    };
22    ($x:expr, 6) => {
23        $x * $x * $x * $x * $x * $x
24    };
25}
26
27pub trait MulArray1<RHS> {
28    type Output;
29
30    fn mul_array1(self, rhs: Array1<RHS>) -> Self::Output;
31}
32
33pub trait MulArray2<RHS> {
34    type Output;
35
36    fn mul_array2(self, rhs: Array2<RHS>) -> Result<Self::Output, String>;
37}
38
39pub trait DivArray1<RHS> {
40    type Output;
41
42    fn div_array1(self, rhs: Array1<RHS>) -> Self::Output;
43}
44
45pub trait DivArray2<RHS> {
46    type Output;
47
48    fn div_array2(self, rhs: Array2<RHS>) -> Result<Self::Output, String>;
49}
50
51pub trait QuantityArray2<T> {
52    fn from_raw(raw: ArrayView2<f64>, unit: T) -> Self;
53    fn to_raw(&self) -> Array2<f64>;
54    fn to(&self, unit: T) -> Array2<f64>;
55}
56
57pub trait QuantityArray1<T> {
58    fn from_raw(raw: ArrayView1<f64>, unit: T) -> Self;
59    fn to_raw(&self) -> Array1<f64>;
60    fn to(&self, unit: T) -> Array1<f64>;
61}
62
63pub trait PhysicsQuantity:
64    Copy
65    + FromPrimitive
66    + Zero
67    + Add<Output = Self>
68    + AddAssign
69    + Div<f64, Output = Self>
70    + DivAssign<f64>
71    + Mul<f64, Output = Self>
72    + MulAssign<f64>
73    + Sub<Output = Self>
74    + SubAssign
75    + PartialOrd
76    + Neg<Output = Self>
77    + From<f64>
78{
79    fn as_f64(&self) -> f64;
80    type Unit: PhysicsUnit;
81    fn new(value: f64, unit: Self::Unit) -> Self;
82    fn to(&self, unit: Self::Unit) -> f64;
83    fn zero() -> Self;
84    fn get_tuple(&self) -> (f64, i32);
85    fn abs(self) -> Self;
86    fn from_raw(value: f64) -> Self;
87    fn from_exponential(multiplier: f64, power: i32) -> Self;
88    fn min(self, other: Self) -> Self;
89    fn max(self, other: Self) -> Self;
90    #[deprecated(since = "0.2.9", note = "please use `as_f64()` instead")]
91    fn to_raw(&self) -> f64 {
92        self.as_f64()
93    }
94    #[deprecated(since = "0.2.9", note = "please use `as_f64()` instead")]
95    fn get_value(&self) -> f64 {
96        self.as_f64()
97    }
98    fn get_power(&self) -> i32;
99    fn get_multiplier(&self) -> f64;
100    fn split_value(v: f64) -> (f64, i32);
101    fn is_close(&self, other: &Self, tolerance: &Self) -> bool;
102    fn optimize(&mut self);
103    const INFINITY: Self;
104    const NEG_INFINITY: Self;
105}
106
107pub trait Sqrt<T> {
108    fn sqrt(self) -> T;
109}
110
111impl PhysicsQuantity for f64 {
112    fn as_f64(&self) -> f64 {
113        *self
114    }
115
116    type Unit = NoUnit;
117
118    fn new(value: f64, _unit: Self::Unit) -> Self {
119        value
120    }
121
122    fn to(&self, _unit: Self::Unit) -> f64 {
123        self.as_f64()
124    }
125
126    fn zero() -> Self {
127        0.
128    }
129
130    fn get_tuple(&self) -> (f64, i32) {
131        (self.get_multiplier(), self.get_power())
132    }
133
134    fn abs(self) -> Self {
135        self.abs()
136    }
137
138    fn from_raw(value: f64) -> Self {
139        value
140    }
141
142    fn from_exponential(multiplier: f64, power: i32) -> Self {
143        multiplier * 10_f64.powi(power)
144    }
145
146    fn min(self, other: Self) -> Self {
147        if self < other {
148            self
149        } else {
150            other
151        }
152    }
153
154    fn max(self, other: Self) -> Self {
155        if self > other {
156            self
157        } else {
158            other
159        }
160    }
161    fn get_power(&self) -> i32 {
162        0
163    }
164
165    fn get_multiplier(&self) -> f64 {
166        *self
167    }
168
169    fn split_value(v: f64) -> (f64, i32) {
170        let power = v.abs().log10().floor() as i32;
171        let multiplier = v / 10f64.powi(power);
172        (multiplier, power)
173    }
174
175    fn is_close(&self, other: &Self, tolerance: &Self) -> bool {
176        (self - other).abs() < (*tolerance)
177    }
178
179    fn optimize(&mut self) {}
180
181    const INFINITY: Self = f64::INFINITY;
182    const NEG_INFINITY: Self = f64::NEG_INFINITY;
183}
184pub use crate::power;
185
186pub trait PhysicsUnit {
187    fn name(&self) -> &str;
188    fn base_per_x(&self) -> (f64, i32);
189}
190
191pub enum NoUnit {
192    no_unit,
193}
194
195impl PhysicsUnit for NoUnit {
196    fn name(&self) -> &str {
197        ""
198    }
199
200    fn base_per_x(&self) -> (f64, i32) {
201        (1., 0)
202    }
203}