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{
78 type Unit: PhysicsUnit;
79 fn new(value: f64, unit: Self::Unit) -> Self;
80 fn to(&self, unit: Self::Unit) -> f64;
81 fn zero() -> Self;
82 fn get_tuple(&self) -> (f64, i32);
83 fn abs(self) -> Self;
84 fn to_raw(&self) -> f64;
85 fn from_raw(value: f64) -> Self;
86 fn from_exponential(multiplier: f64, power: i32) -> Self;
87 fn min(self, other: Self) -> Self;
88 fn max(self, other: Self) -> Self;
89 fn get_value(&self) -> f64;
90 fn get_power(&self) -> i32;
91 fn get_multiplyer(&self) -> f64;
92 fn split_value(v: f64) -> (f64, i32);
93 const INFINITY: Self;
94 const NEG_INFINITY: Self;
95}
96
97pub trait Sqrt<T> {
98 fn sqrt(self) -> T;
99}
100
101impl PhysicsQuantity for f64 {
102 type Unit = NoUnit;
103
104 fn new(value: f64, _unit: Self::Unit) -> Self {
105 value
106 }
107
108 fn to(&self, _unit: Self::Unit) -> f64 {
109 self.to_raw()
110 }
111
112 fn zero() -> Self {
113 0.
114 }
115
116 fn get_tuple(&self) -> (f64, i32) {
117 (self.get_multiplyer() , self.get_power())
118 }
119
120 fn abs(self) -> Self {
121 self.abs()
122 }
123
124 fn to_raw(&self) -> f64 {
125 *self
126 }
127
128 fn from_raw(value: f64) -> Self {
129 value
130 }
131
132 fn from_exponential(multiplier: f64, power: i32) -> Self {
133 multiplier * 10_f64.powi(power)
134 }
135
136 fn min(self, other: Self) -> Self {
137 if self < other {
138 self
139 } else {
140 other
141 }
142 }
143
144 fn max(self, other: Self) -> Self {
145 if self > other {
146 self
147 } else {
148 other
149 }
150 }
151
152 fn get_value(&self) -> f64 {
153 *self
154 }
155
156 fn get_power(&self) -> i32 {
157 0
158 }
159
160 fn get_multiplyer(&self) -> f64 {
161 *self
162 }
163
164 fn split_value(v: f64) -> (f64, i32) {
165 let power = v.abs().log10().floor() as i32;
166 let multiplier = v / 10f64.powi(power);
167 (multiplier, power)
168 }
169
170 const INFINITY: Self = f64::INFINITY;
171 const NEG_INFINITY: Self = f64::NEG_INFINITY;
172}
173pub use crate::power;
174
175pub trait PhysicsUnit {
176 fn name(&self) -> &str;
177 fn base_per_x(&self) -> (f64, i32);
178}
179
180pub enum NoUnit {
181 no_unit,
182}
183
184impl PhysicsUnit for NoUnit {
185 fn name(&self) -> &str {
186 ""
187 }
188
189 fn base_per_x(&self) -> (f64, i32) {
190 (1., 0)
191 }
192}