1#[macro_export]
2macro_rules! impl_quantity_vec_ops {
3 ($quantity:ident) =>
4 {
5 paste::paste!
6 {
7 use core::ops::{Mul, Div, Add, Sub, AddAssign, SubAssign, MulAssign, DivAssign };
8 impl Div<f64> for [<$quantity Vec>]
9 {
10 type Output = [<$quantity Vec>];
11
12 fn div(self, rhs: f64) -> Self::Output {
13 let mut result = self.clone();
14 for val in result.values.as_mut_slice()
15 {
16 *val /= rhs;
17 }
18 result
19 }
20 }
21
22
23 impl Mul<f64> for [<$quantity Vec>]
24 {
25 type Output = [<$quantity Vec>];
26
27 fn mul(self, rhs: f64) -> Self::Output {
28 let mut result = self.clone();
29 for val in result.values.as_mut_slice()
30 {
31 *val *= rhs;
32 }
33 result
34 }
35 }
36 impl DivAssign<f64> for [<$quantity Vec>]
37 {
38
39 fn div_assign(&mut self, rhs: f64) {
40 for val in self.values.as_mut_slice()
41 {
42 *val /= rhs;
43 }
44 }
45 }
46 impl MulAssign<f64> for [<$quantity Vec>]
47 {
48
49 fn mul_assign(&mut self, rhs: f64) {
50 for val in self.values.as_mut_slice()
51 {
52 *val *= rhs;
53 }
54 }
55 }
56 use $crate::traits::Unit;
57 impl AddAssign<[<$quantity Vec>]> for [<$quantity Vec>]
58 {
59
60 fn add_assign(&mut self, rhs: [<$quantity Vec>]) {
61 if rhs.values.len() != self.values.len()
62 {
63 panic!("Slice dimensions do not match: {} != {}", rhs.values.len(), self.values.len());
64 }
65 let factor = rhs.unit.definition().convert_unchecked(self.unit.definition());
66 for (val, &rhs) in self.values.as_mut_slice().iter_mut().zip(rhs.values.as_slice())
67 {
68 *val += rhs*factor;
69 }
70 }
71 }
72 impl SubAssign<[<$quantity Vec>]> for [<$quantity Vec>]
73 {
74
75 fn sub_assign(&mut self, rhs: [<$quantity Vec>]) {
76 if rhs.values.len() != self.values.len()
77 {
78 panic!("Slice dimensions do not match: {} != {}", rhs.values.len(), self.values.len());
79 }
80 let factor = rhs.unit.convert_unchecked(self.unit);
81 for (val, &rhs) in self.values.as_mut_slice().iter_mut().zip(rhs.values.as_slice())
82 {
83 *val -= rhs*factor;
84 }
85 }
86 }
87 }
88 }
89}
90
91#[macro_export]
92macro_rules! impl_quantity_array_ops {
93 ($quantity:ident) =>
94 {
95 paste::paste!
96 {
97 impl<const N: usize> Div<f64> for [<$quantity Array>]<N>
98 {
99 type Output = [<$quantity Array>]<N>;
100
101 fn div(self, rhs: f64) -> Self::Output {
102 let mut result = self.clone();
103 for val in result.values.as_mut_slice()
104 {
105 *val /= rhs;
106 }
107 result
108 }
109 }
110
111
112 impl<const N: usize> Mul<f64> for [<$quantity Array>]<N>
113 {
114 type Output = [<$quantity Array>]<N>;
115
116 fn mul(self, rhs: f64) -> Self::Output {
117 let mut result = self.clone();
118 for val in result.values.as_mut_slice()
119 {
120 *val *= rhs;
121 }
122 result
123 }
124 }
125 impl<const N: usize> DivAssign<f64> for [<$quantity Array>]<N>
126 {
127
128 fn div_assign(&mut self, rhs: f64) {
129 for val in self.values.as_mut_slice()
130 {
131 *val /= rhs;
132 }
133 }
134 }
135 impl<const N: usize> MulAssign<f64> for [<$quantity Array>]<N>
136 {
137
138 fn mul_assign(&mut self, rhs: f64) {
139 for val in self.values.as_mut_slice()
140 {
141 *val *= rhs;
142 }
143 }
144 }
145 impl<const N: usize> AddAssign<[<$quantity Array>]<N>> for [<$quantity Array>]<N>
146 {
147
148 fn add_assign(&mut self, rhs: [<$quantity Array>]<N>) {
149 if rhs.values.len() != self.values.len()
150 {
151 panic!("Slice dimensions do not match: {} != {}", rhs.values.len(), self.values.len());
152 }
153 let factor = rhs.unit.definition().convert_unchecked(self.unit.definition());
154 for (val, &rhs) in self.values.as_mut_slice().iter_mut().zip(rhs.values.as_slice())
155 {
156 *val += rhs*factor;
157 }
158 }
159 }
160 impl<const N: usize> SubAssign<[<$quantity Array>]<N>> for [<$quantity Array>]<N>
161 {
162
163 fn sub_assign(&mut self, rhs: [<$quantity Array>]<N>) {
164 if rhs.values.len() != self.values.len()
165 {
166 panic!("Slice dimensions do not match: {} != {}", rhs.values.len(), self.values.len());
167 }
168 let factor = rhs.unit.convert_unchecked(self.unit);
169 for (val, &rhs) in self.values.as_mut_slice().iter_mut().zip(rhs.values.as_slice())
170 {
171 *val -= rhs*factor;
172 }
173 }
174 }
175 }
176 }
177}
178
179#[macro_export]
180macro_rules! create_multivalue_quantities {
181 ($quantity:ident) =>
182 {
183 #[cfg(feature="serde")]
184 use serde_with::serde_as;
185 use std::ops::{Deref, DerefMut};
186 paste::paste!
187 {
188 #[cfg_attr(feature="serde", cfg_eval::cfg_eval, serde_as)]
189 #[derive(Copy, Clone, Debug, PartialEq)]
190 #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
191 #[cfg_attr(feature="utoipa", derive(ToSchema))]
192 #[doc = "Array storage for a series of values and [`" [<$quantity Unit>]"`]."]
193 pub struct [<$quantity Array>]<const N: usize>
194 {
195 pub(crate) unit: [<$quantity Unit>],
196 #[cfg_attr(feature="serde", serde_as(as = "[_; N]"))]
197 pub(crate) values: [f64; N],
198 }
199
200 impl<const N: usize> Default for [<$quantity Array>]<N>
201 {
202 fn default() -> Self {
203 [<$quantity Array>]{unit: [<$quantity Unit>]::default(), values: [0.0; N]}
204 }
205 }
206
207 impl<const N: usize> Deref for [<$quantity Array>]<N>
208 {
209 type Target = [f64; N];
210 fn deref(&self) -> &[f64; N] {
211 &self.values
212 }
213 }
214
215 impl<const N: usize> DerefMut for [<$quantity Array>]<N>
216 {
217 fn deref_mut(&mut self) -> &mut [f64; N] {
218 &mut self.values
219 }
220 }
221
222 #[derive(Default, Clone, Debug, PartialEq)]
223 #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
224 #[cfg_attr(feature="utoipa", derive(ToSchema))]
225 #[doc = "Vector storage for a series of values and [`" [<$quantity Unit>]"`]."]
226 pub struct [<$quantity Vec>]
227 {
228 pub(crate) unit: [<$quantity Unit>],
229 pub(crate) values: Vec<f64>
230 }
231
232 impl Deref for [<$quantity Vec>]
233 {
234 type Target = Vec<f64>;
235 fn deref(&self) -> &Vec<f64> {
236 &self.values
237 }
238 }
239 impl DerefMut for [<$quantity Vec>]
240 {
241 fn deref_mut(&mut self) -> &mut Vec<f64> {
242 &mut self.values
243 }
244 }
245
246 impl crate::traits::FixedSliceQuantity<[<$quantity Unit>], f64> for [<$quantity Vec>]
247 {
248 fn unit(&self) -> [<$quantity Unit>] {
249 self.unit
250 }
251
252 fn values(&self) -> &[f64] {
253 &self.values.as_slice()
254 }
255
256 fn values_mut(&mut self) -> &mut [f64] {
257 self.values.as_mut_slice()
258 }
259
260 fn len(&self) -> usize {
261 self.values.len()
262 }
263
264 fn convert(&self, unit: [<$quantity Unit>]) -> Self
265 {
266 let mut result = self.clone();
267 result.convert_mut(unit);
268 return result;
269 }
270
271 #[inline]
272 fn convert_mut(&mut self, unit: [<$quantity Unit>]) {
273 let factor = self.unit.definition().convert_unchecked(unit.definition());
274 for val in self.values.as_mut_slice().iter_mut()
275 {
276 *val *= factor;
277 }
278 self.unit = unit;
279 }
280
281 #[inline]
282 fn try_convert(&self, unit: $crate::Units) -> Result<Self, RuntimeUnitError> where Self: Sized
283 {
284 let destination_unit: [<$quantity Unit>] = unit.try_into()?;
285 Ok(self.convert(destination_unit))
286 }
287 }
288 impl<const N: usize> crate::traits::FixedSliceQuantity<[<$quantity Unit>], f64> for [<$quantity Array>]<N>
289 {
290 fn unit(&self) -> [<$quantity Unit>] {
291 self.unit
292 }
293
294 fn values(&self) -> &[f64] {
295 &self.values.as_slice()
296 }
297
298 fn values_mut(&mut self) -> &mut [f64] {
299 self.values.as_mut_slice()
300 }
301
302 fn len(&self) -> usize {
303 self.values.len()
304 }
305
306 fn convert(&self, unit: [<$quantity Unit>]) -> Self
307 {
308 let mut result = self.clone();
309 result.convert_mut(unit);
310 return result;
311 }
312
313 #[inline]
314 fn convert_mut(&mut self, unit: [<$quantity Unit>]) {
315 let factor = self.unit.definition().convert_unchecked(unit.definition());
316 for val in self.values.as_mut_slice().iter_mut()
317 {
318 *val *= factor;
319 }
320 self.unit = unit;
321 }
322
323 #[inline]
324 fn try_convert(&self, unit: $crate::Units) -> Result<Self, RuntimeUnitError> where Self: Sized
325 {
326 let destination_unit: [<$quantity Unit>] = unit.try_into()?;
327 Ok(self.convert(destination_unit))
328 }
329 }
330
331 }
332 }
333}
334
335#[macro_export]
336macro_rules! create_multivalue_quantities_vec_enum {
337 ($($quantity:ident),+) =>
338 {
339 paste::paste!{
340 #[derive(Clone, Debug, PartialEq)]
341 #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
342 #[cfg_attr(feature="utoipa", derive(ToSchema))]
343 pub enum QuantitiesVec
348 {
349 $(
350 #[cfg(any(feature = "" $quantity, feature="All"))]
351 #[cfg_attr(feature="utoipa", schema(title = "" $quantity))]
352 $quantity([<$quantity Vec>]),
353 )+
354 }
355 impl QuantitiesVec
356 {
357 pub fn unit(&self) -> Units
359 {
360 use crate::traits::FixedSliceQuantity;
361 match self
362 {
363 $(
364 #[cfg(any(feature = "" $quantity, feature="All"))]
365 QuantitiesVec::$quantity(x)=> $crate::Units::from(x.unit()),
366 )+
367 }
368 }
369 pub fn try_convert(&self, unit: Units) -> Result<QuantitiesVec, RuntimeUnitError>
371 {
372 use crate::traits::FixedSliceQuantity;
373 match self
374 {
375 $(
376 #[cfg(any(feature = "" $quantity, feature="All"))]
377 QuantitiesVec::$quantity(x)=> {
378 Ok(QuantitiesVec::$quantity(x.try_convert(unit)?))
379 },
380 )+
381 }
382 }
383
384 pub fn new(value: Vec<f64>, unit: Units) -> QuantitiesVec
386 {
387 match unit
388 {
389 $(
390 #[cfg(any(feature = "" $quantity, feature="All"))]
391 Units::$quantity(x)=> {
392 QuantitiesVec::$quantity([<$quantity Vec>]::new(value, x))
393 },
394 )+
395 }
396 }
397 pub fn values(&self) -> Vec<f64>
399 {
400 use crate::vector_quantity::VecQuantity;
401 VecQuantity::from(self.clone()).values
402 }
403 }
404 impl From<Units> for QuantitiesVec
406 {
407
408 fn from(value: Units) -> Self
409 {
410
411 match value
412 {
413 $(
414
415 #[cfg(any(feature = "" $quantity, feature="All"))]
416 Units::$quantity(x)=>
417 {
418 QuantitiesVec::new(vec![0.0], x.into())
419 },
420 )+
421 }
422
423 }
424 }
425 impl From<QuantitiesVec> for crate::vector_quantity::VecQuantity
426 {
427 fn from(value: QuantitiesVec) -> Self {
428 match value
429 {
430 $(
431 #[cfg(any(feature = "" $quantity, feature="All"))]
432 QuantitiesVec::$quantity(x)=>crate::vector_quantity::VecQuantity { values: x.values, unit: UnitDefinition{multiplier: x.unit.multiplier(), base: [<$quantity:snake>]::[<$quantity:upper _UNIT_BASE>]} },
433 )+
434 }
435 }
436 }
437 impl ToString for QuantitiesVec
438 {
439 fn to_string(&self) -> String
440 {
441 match self
442 {
443 $(
444 #[cfg(any(feature = "" $quantity, feature="All"))]
445 QuantitiesVec::$quantity(x) => format!("{:?} {}", x.values, x.unit.abbreviation()),
446 )+
447 }
448 }
449 }
450 }
451 }
452}
453
454#[macro_export]
455macro_rules! create_multivalue_quantities_array_enum {
456 ($($quantity:ident),+) =>
457 {
458 paste::paste!{
459 #[derive(Copy, Clone, Debug, PartialEq)]
460 #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
461 pub enum QuantitiesArray<const N: usize>
466 {
467 $(
468 #[cfg(any(feature = "" $quantity, feature="All"))]
469 $quantity([<$quantity Array>]<N>),
470 )+
471 }
472 impl<const N: usize> QuantitiesArray<N>
473 {
474 pub fn unit(&self) -> Units
476 {
477 match self
478 {
479 $(
480 #[cfg(any(feature = "" $quantity, feature="All"))]
481 QuantitiesArray::$quantity(x)=> $crate::Units::from(x.unit),
482 )+
483 }
484 }
485 pub fn try_convert(&self, unit: Units) -> Result<QuantitiesArray<N>, RuntimeUnitError>
487 {
488 use crate::traits::FixedSliceQuantity;
489 match self
490 {
491 $(
492 #[cfg(any(feature = "" $quantity, feature="All"))]
493 QuantitiesArray::$quantity(x)=> {
494 Ok(QuantitiesArray::$quantity(x.try_convert(unit)?))
495 },
496 )+
497 }
498 }
499
500 pub fn new(value: [f64; N], unit: Units) -> QuantitiesArray<N>
502 {
503 match unit
504 {
505 $(
506 #[cfg(any(feature = "" $quantity, feature="All"))]
507 Units::$quantity(x)=> {
508 QuantitiesArray::$quantity([<$quantity Array>]{values: value, unit:x})
509 },
510 )+
511 }
512 }
513 pub fn values(&self) -> [f64; N]
515 {
516 use crate::array_quantity::ArrayQuantity;
517 ArrayQuantity::from(*self).values
518 }
519 }
520 impl<const N: usize> From<Units> for QuantitiesArray<N>
522 {
523 fn from(value: Units) -> Self
524 {
525 match value
526 {
527 $(
528 #[cfg(any(feature = "" $quantity, feature="All"))]
529 Units::$quantity(x)=> QuantitiesArray::new([0.0; N], x.into()),
530 )+
531 }
532
533 }
534 }
535 impl<const N: usize> From<QuantitiesArray<N>> for crate::array_quantity::ArrayQuantity<N>
536 {
537 fn from(value: QuantitiesArray<N>) -> Self {
538 use crate::array_quantity::ArrayQuantity;
539 match value
540 {
541 $(
542 #[cfg(any(feature = "" $quantity, feature="All"))]
543 QuantitiesArray::$quantity(x)=>ArrayQuantity { values: x.values, unit: UnitDefinition{multiplier: x.unit.multiplier(), base: [<$quantity:snake>]::[<$quantity:upper _UNIT_BASE>]} },
544 )+
545 }
546 }
547 }
548 impl<const N: usize> ToString for QuantitiesArray<N>
549 {
550 fn to_string(&self) -> String
551 {
552 match self
553 {
554 $(
555 #[cfg(any(feature = "" $quantity, feature="All"))]
556 QuantitiesArray::$quantity(x) => format!("{:?} {}", x.values, x.unit.abbreviation()),
557 )+
558 }
559 }
560 }
561 }
562 }
563}