daisy/src/quantity/quantity.rs

268 lines
4.7 KiB
Rust

use std::ops::{
Add, Sub, Mul, Div,
Neg, Rem,
AddAssign, SubAssign,
MulAssign, DivAssign
};
use std::cmp::Ordering;
use crate::quantity::Unit;
use crate::quantity::BaseUnit;
use crate::quantity::Scalar;
#[derive(Debug)]
#[derive(Clone)]
pub struct Quantity {
v: Scalar,
u: Unit
}
impl ToString for Quantity {
fn to_string(&self) -> String {
let n = self.v.to_string();
if self.unitless() { return n; }
let u = self.u.to_string();
if self.is_one() { return u; };
return format!("{n} {u}");
}
}
impl Quantity {
pub fn to_string_outer(&self) -> String {
let n = self.v.to_string();
if self.unitless() { return n; }
let u = self.u.to_string();
return format!("{n} {u}");
}
pub fn new_float(f: f64) -> Option<Quantity> {
let v = Scalar::new_float(f);
if v.is_none() { return None; }
return Some(Quantity{
v: v.unwrap(),
u: Unit::new()
});
}
pub fn new_rational(f: f64) -> Option<Quantity> {
let v = Scalar::new_rational(f);
if v.is_none() { return None; }
return Some(Quantity{
v: v.unwrap(),
u: Unit::new()
});
}
pub fn new_float_from_string(s: &str) -> Option<Quantity> {
let v = Scalar::new_float_from_string(s);
if v.is_none() { return None; }
return Some(Quantity{
v: v.unwrap(),
u: Unit::new()
});
}
pub fn new_rational_from_string(s: &str) -> Option<Quantity> {
let v = Scalar::new_rational_from_string(s);
if v.is_none() { return None; }
return Some(Quantity{
v: v.unwrap(),
u: Unit::new()
});
}
pub fn insert_unit(&mut self, ui: BaseUnit, pi: f64) { self.u.insert(ui, pi) }
pub fn set_unit(&mut self, u: Unit) { self.u = u; }
}
macro_rules! quant_foward {
( $x:ident ) => {
pub fn $x(&self) -> Quantity {
if !self.unitless() { panic!() }
Quantity {
v: self.v.$x(),
u: self.u.clone()
}
}
}
}
impl Quantity {
pub fn is_zero(&self) -> bool { self.v.is_zero() }
pub fn is_one(&self) -> bool { self.v.is_one() }
pub fn is_nan(&self) -> bool { self.v.is_nan() }
pub fn is_negative(&self) -> bool { self.v.is_negative() }
pub fn is_positive(&self) -> bool { self.v.is_positive() }
pub fn unitless(&self) -> bool { self.u.unitless() }
quant_foward!(fract);
quant_foward!(abs);
quant_foward!(floor);
quant_foward!(ceil);
quant_foward!(round);
quant_foward!(sin);
quant_foward!(cos);
quant_foward!(tan);
quant_foward!(asin);
quant_foward!(acos);
quant_foward!(atan);
quant_foward!(sinh);
quant_foward!(cosh);
quant_foward!(tanh);
quant_foward!(asinh);
quant_foward!(acosh);
quant_foward!(atanh);
quant_foward!(exp);
quant_foward!(ln);
quant_foward!(log10);
quant_foward!(log2);
pub fn log(&self, base: Quantity) -> Quantity {
if !self.unitless() { panic!() }
Quantity {
v: self.v.log(base.v),
u: self.u.clone()
}
}
pub fn pow(&self, pwr: Quantity) -> Quantity {
Quantity {
v: self.v.pow(pwr.v),
u: self.u.pow(2f64)
}
}
}
impl Neg for Quantity where {
type Output = Self;
fn neg(self) -> Self::Output {
Quantity {
v: -self.v,
u: self.u
}
}
}
impl Add for Quantity {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
if self.u != other.u { panic!() }
Quantity {
v: self.v + other.v,
u: self.u
}
}
}
impl AddAssign for Quantity where {
fn add_assign(&mut self, other: Self) {
if self.u != other.u { panic!() }
self.v += other.v
}
}
impl Sub for Quantity {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
if self.u != other.u { panic!() }
Quantity {
v: self.v - other.v,
u: self.u
}
}
}
impl SubAssign for Quantity where {
fn sub_assign(&mut self, other: Self) {
if self.u != other.u { panic!() }
self.v -= other.v
}
}
impl Mul for Quantity {
type Output = Self;
fn mul(self, other: Self) -> Self::Output {
Quantity {
v: self.v * other.v,
u: self.u * other.u
}
}
}
impl MulAssign for Quantity where {
fn mul_assign(&mut self, other: Self) {
self.v *= other.v;
self.u *= other.u;
}
}
impl Div for Quantity {
type Output = Self;
fn div(self, other: Self) -> Self::Output {
Quantity {
v: self.v / other.v,
u: self.u / other.u
}
}
}
impl DivAssign for Quantity where {
fn div_assign(&mut self, other: Self) {
self.v /= other.v;
self.u /= other.u;
}
}
impl Rem<Quantity> for Quantity {
type Output = Self;
fn rem(self, other: Quantity) -> Self::Output {
if !self.u.unitless() { panic!() }
if !other.u.unitless() { panic!() }
Quantity {
v: self.v % other.v,
u: self.u
}
}
}
impl PartialEq for Quantity {
fn eq(&self, other: &Self) -> bool {
if self.u != other.u {false} else {
self.v == other.v
}
}
}
impl PartialOrd for Quantity {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.u != other.u { panic!() }
self.v.partial_cmp(&other.v)
}
}