use crate::quantized::Quantized;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TEC {
pub(crate) tecu: Quantized,
pub(crate) rms: Option<Quantized>,
height: Option<Quantized>,
}
impl std::ops::Mul<f64> for TEC {
type Output = TEC;
fn mul(self, rhs: f64) -> Self::Output {
let tecu = self.tecu() * rhs;
let mut tec = TEC::from_tecu(tecu);
tec.rms = self.rms.clone();
tec.height = self.height.clone();
tec
}
}
impl std::ops::MulAssign<f64> for TEC {
fn mul_assign(&mut self, rhs: f64) {
let tecu = self.tecu() * rhs;
*self = self.with_tecu(tecu);
}
}
impl std::ops::Div<f64> for TEC {
type Output = TEC;
fn div(self, rhs: f64) -> Self::Output {
let tecu = self.tecu() / rhs;
let mut tec = TEC::from_tecu(tecu);
tec.rms = self.rms.clone();
tec.height = self.height.clone();
tec
}
}
impl std::ops::DivAssign<f64> for TEC {
fn div_assign(&mut self, rhs: f64) {
let tecu = self.tecu() / rhs;
*self = self.with_tecu(tecu);
}
}
impl TEC {
pub fn from_tecu(tecu: f64) -> Self {
Self {
rms: None,
height: None,
tecu: Quantized::auto_scaled(tecu),
}
}
pub fn with_tecu(mut self, tecu: f64) -> Self {
self.tecu = Quantized::auto_scaled(tecu);
self
}
pub fn from_tec_m2(tec: f64) -> Self {
let tecu = tec / 10.0E16;
Self {
rms: None,
height: None,
tecu: Quantized::auto_scaled(tecu),
}
}
pub fn with_tec_m2(mut self, tec: f64) -> Self {
let tecu = tec / 10.0E16;
self.tecu = Quantized::auto_scaled(tecu);
self
}
pub fn with_rms(mut self, rms: f64) -> Self {
self.rms = Some(Quantized::auto_scaled(rms));
self
}
pub(crate) fn from_quantized(tecu: i64, exponent: i8) -> Self {
Self {
rms: None,
height: None,
tecu: Quantized {
value: tecu,
exponent: -exponent,
},
}
}
pub(crate) fn set_quantized_root_mean_square(&mut self, rms: i64, exponent: i8) {
self.rms = Some(Quantized {
exponent: -exponent,
value: rms,
});
}
pub fn tecu(&self) -> f64 {
self.tecu.real_value()
}
pub fn tec(&self) -> f64 {
self.tecu() * 10.0E16
}
pub fn root_mean_square(&self) -> Option<f64> {
let rms = self.rms?;
Some(rms.real_value())
}
}
#[cfg(test)]
mod test {
use super::TEC;
#[test]
fn quantized_tec() {
let tec = TEC::from_quantized(30, -1);
assert_eq!(tec.tecu(), 3.0);
assert_eq!(tec.tec(), 3.0 * 10E16);
let tec = TEC::from_quantized(30, -2);
assert_eq!(tec.tecu(), 0.3);
assert_eq!(tec.tec(), 0.3 * 10E16);
let tec = TEC::from_tec_m2(1.0 * 10E16);
assert_eq!(tec.tecu(), 1.0);
assert_eq!(tec.tec(), 1.0 * 10E16);
assert_eq!(tec, TEC::from_tecu(1.0));
let tec = TEC::from_tec_m2(3.5 * 10E16);
assert_eq!(tec.tecu(), 3.5);
assert_eq!(tec.tec(), 3.5 * 10E16);
assert_eq!(tec, TEC::from_tecu(3.5));
let tec = TEC::from_tec_m2(190355078157525800.0);
assert_eq!(tec.tec(), 1.903550781575258e17);
}
#[test]
fn tec_arithmetics() {
let mut tec = TEC::from_tecu(9.0);
assert_eq!(tec.tecu(), 9.0);
assert_eq!((tec * 2.0).tecu(), 18.0);
assert_eq!((tec / 2.0).tecu(), 4.5);
tec *= 2.0;
assert_eq!(tec.tecu(), 18.0);
tec /= 2.0;
assert_eq!(tec.tecu(), 9.0);
tec /= 2.0;
assert_eq!(tec.tecu(), 4.5);
}
}