More unit/integration tests
This commit is contained in:
parent
b05e0e06f2
commit
e1e347c255
@ -16,6 +16,7 @@ eval llvm-cov show target/coverage/debug/opentally -instr-profile=target/coverag
|
||||
-ignore-filename-regex="$HOME/." \
|
||||
-ignore-filename-regex=rustc \
|
||||
-ignore-filename-regex=numbers/rational_num.rs \
|
||||
-ignore-filename-regex=stv/gregory/prettytable_html.rs \
|
||||
-ignore-filename-regex=stv/wasm.rs \
|
||||
-ignore-filename-regex=tests \
|
||||
-format=html --show-instantiations=false --output-dir=target/coverage/html
|
||||
|
@ -18,7 +18,7 @@
|
||||
use super::{Assign, Number};
|
||||
|
||||
use ibig::{IBig, ops::Abs};
|
||||
use num_traits::{Num, One, Zero};
|
||||
use num_traits::{Num, One, Signed, Zero};
|
||||
|
||||
use std::cmp::{Ord, PartialEq, PartialOrd};
|
||||
use std::ops;
|
||||
@ -57,6 +57,9 @@ impl Number for Fixed {
|
||||
fn describe() -> String { format!("--numbers fixed --decimals {}", get_dps()) }
|
||||
|
||||
fn pow_assign(&mut self, exponent: i32) {
|
||||
if exponent < 0 {
|
||||
todo!();
|
||||
}
|
||||
self.0 = self.0.pow(exponent as usize) * get_factor() / get_factor().pow(exponent as usize);
|
||||
}
|
||||
|
||||
@ -83,13 +86,11 @@ impl Number for Fixed {
|
||||
fn round_mut(&mut self, dps: usize) {
|
||||
// Only do something if truncating
|
||||
if dps < get_dps() {
|
||||
// TODO: Streamline
|
||||
let mut factor = Self::from(10);
|
||||
factor.pow_assign(-(dps as i32));
|
||||
factor /= Self::from(2);
|
||||
let mut factor = IBig::from(10).pow(get_dps() - dps);
|
||||
factor /= IBig::from(2);
|
||||
|
||||
*self = self.clone() - factor;
|
||||
self.ceil_mut(dps);
|
||||
self.0 += factor;
|
||||
self.floor_mut(dps);
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +106,12 @@ impl Number for Fixed {
|
||||
Ok(value) => value,
|
||||
Err(_) => panic!("Syntax Error"),
|
||||
} * get_factor() / IBig::from(10).pow(decimal.len());
|
||||
return Self(whole + decimal);
|
||||
|
||||
if whole.is_negative() {
|
||||
return Self(whole - decimal);
|
||||
} else {
|
||||
return Self(whole + decimal);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse integer
|
||||
@ -117,6 +123,26 @@ impl Number for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
Fixed::set_dps(2);
|
||||
|
||||
let mut x = Fixed::parse("555.50"); x.floor_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.52"); x.floor_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.55"); x.floor_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.57"); x.floor_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
|
||||
let mut x = Fixed::parse("555.50"); x.ceil_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.52"); x.ceil_mut(1); assert_eq!(x, Fixed::parse("555.6"));
|
||||
let mut x = Fixed::parse("555.55"); x.ceil_mut(1); assert_eq!(x, Fixed::parse("555.6"));
|
||||
let mut x = Fixed::parse("555.57"); x.ceil_mut(1); assert_eq!(x, Fixed::parse("555.6"));
|
||||
|
||||
let mut x = Fixed::parse("555.50"); x.round_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.52"); x.round_mut(1); assert_eq!(x, Fixed::parse("555.5"));
|
||||
let mut x = Fixed::parse("555.55"); x.round_mut(1); assert_eq!(x, Fixed::parse("555.6"));
|
||||
let mut x = Fixed::parse("555.57"); x.round_mut(1); assert_eq!(x, Fixed::parse("555.6"));
|
||||
}
|
||||
|
||||
impl Num for Fixed {
|
||||
type FromStrRadixErr = ibig::error::ParseError;
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||
@ -199,9 +225,7 @@ impl ops::Add for Fixed {
|
||||
|
||||
impl ops::Sub for Fixed {
|
||||
type Output = Self;
|
||||
fn sub(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul for Fixed {
|
||||
@ -221,6 +245,18 @@ impl ops::Rem for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_owned() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + b.clone(), Fixed::parse("802.35"));
|
||||
assert_eq!(a.clone() - b.clone(), Fixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), Fixed::parse("83810.20")); // = 83810.205 rounds to 83810.20
|
||||
assert_eq!(a.clone() / b.clone(), Fixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for Fixed {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: &Self) -> Self::Output { Self(self.0 + &rhs.0) }
|
||||
@ -248,6 +284,18 @@ impl ops::Rem<&Self> for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_ref() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + &b, Fixed::parse("802.35"));
|
||||
assert_eq!(a.clone() - &b, Fixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, Fixed::parse("83810.20"));
|
||||
assert_eq!(a.clone() / &b, Fixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Fixed {
|
||||
fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; }
|
||||
}
|
||||
@ -276,6 +324,18 @@ impl ops::RemAssign for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_owned() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += b.clone(); assert_eq!(x, Fixed::parse("802.35"));
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, Fixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, Fixed::parse("83810.20"));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, Fixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for Fixed {
|
||||
fn add_assign(&mut self, rhs: &Self) { self.0 += &rhs.0; }
|
||||
}
|
||||
@ -304,6 +364,18 @@ impl ops::RemAssign<&Self> for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_ref() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += &b; assert_eq!(x, Fixed::parse("802.35"));
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, Fixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, Fixed::parse("83810.20"));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, Fixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::Neg for &Fixed {
|
||||
type Output = Fixed;
|
||||
fn neg(self) -> Self::Output { Fixed(-&self.0) }
|
||||
@ -336,6 +408,18 @@ impl ops::Rem<Self> for &Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_ref_ref() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
assert_eq!(&a + &b, Fixed::parse("802.35"));
|
||||
assert_eq!(&a - &b, Fixed::parse("-555.45"));
|
||||
assert_eq!(&a * &b, Fixed::parse("83810.20"));
|
||||
assert_eq!(&a / &b, Fixed::parse("0.18"));
|
||||
}
|
||||
|
||||
/*
|
||||
impl ops::Add<&&Rational> for &Rational {
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
use super::{Assign, Number};
|
||||
|
||||
use ibig::{IBig, ops::Abs};
|
||||
use num_traits::{Num, One, Zero};
|
||||
use num_traits::{Num, One, Signed, Zero};
|
||||
|
||||
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
||||
use std::ops;
|
||||
@ -64,6 +64,9 @@ impl Number for GuardedFixed {
|
||||
fn describe() -> String { format!("--numbers gfixed --decimals {}", get_dps()) }
|
||||
|
||||
fn pow_assign(&mut self, exponent: i32) {
|
||||
if exponent < 0 {
|
||||
todo!();
|
||||
}
|
||||
self.0 = self.0.pow(exponent as usize) * get_factor() / get_factor().pow(exponent as usize);
|
||||
}
|
||||
|
||||
@ -90,13 +93,11 @@ impl Number for GuardedFixed {
|
||||
fn round_mut(&mut self, dps: usize) {
|
||||
// Only do something if truncating
|
||||
if dps < get_dps() * 2 {
|
||||
// TODO: Streamline
|
||||
let mut factor = Self::from(10);
|
||||
factor.pow_assign(-(dps as i32));
|
||||
factor /= Self::from(2);
|
||||
let mut factor = IBig::from(10).pow(get_dps() * 2 - dps);
|
||||
factor /= IBig::from(2);
|
||||
|
||||
*self = self.clone() - factor;
|
||||
self.ceil_mut(dps);
|
||||
self.0 += factor;
|
||||
self.floor_mut(dps);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +113,12 @@ impl Number for GuardedFixed {
|
||||
Ok(value) => value,
|
||||
Err(_) => panic!("Syntax Error"),
|
||||
} * get_factor() / IBig::from(10).pow(decimal.len());
|
||||
return Self(whole + decimal);
|
||||
|
||||
if whole.is_negative() {
|
||||
return Self(whole - decimal);
|
||||
} else {
|
||||
return Self(whole + decimal);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse integer
|
||||
@ -124,6 +130,26 @@ impl Number for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
GuardedFixed::set_dps(2);
|
||||
|
||||
let mut x = GuardedFixed::parse("555.50"); x.floor_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.52"); x.floor_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.55"); x.floor_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.57"); x.floor_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
|
||||
let mut x = GuardedFixed::parse("555.50"); x.ceil_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.52"); x.ceil_mut(1); assert_eq!(x, GuardedFixed::parse("555.6"));
|
||||
let mut x = GuardedFixed::parse("555.55"); x.ceil_mut(1); assert_eq!(x, GuardedFixed::parse("555.6"));
|
||||
let mut x = GuardedFixed::parse("555.57"); x.ceil_mut(1); assert_eq!(x, GuardedFixed::parse("555.6"));
|
||||
|
||||
let mut x = GuardedFixed::parse("555.50"); x.round_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.52"); x.round_mut(1); assert_eq!(x, GuardedFixed::parse("555.5"));
|
||||
let mut x = GuardedFixed::parse("555.55"); x.round_mut(1); assert_eq!(x, GuardedFixed::parse("555.6"));
|
||||
let mut x = GuardedFixed::parse("555.57"); x.round_mut(1); assert_eq!(x, GuardedFixed::parse("555.6"));
|
||||
}
|
||||
|
||||
impl Num for GuardedFixed {
|
||||
type FromStrRadixErr = ibig::error::ParseError;
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||
@ -231,9 +257,7 @@ impl ops::Add for GuardedFixed {
|
||||
|
||||
impl ops::Sub for GuardedFixed {
|
||||
type Output = Self;
|
||||
fn sub(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul for GuardedFixed {
|
||||
@ -253,6 +277,18 @@ impl ops::Rem for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_owned() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + b.clone(), GuardedFixed::parse("802.35"));
|
||||
assert_eq!(a.clone() - b.clone(), GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), GuardedFixed::parse("83810.205")); // Must compare to 3 d.p.s as doesn't meet FACTOR_CMP
|
||||
assert_eq!(a.clone() / b.clone(), GuardedFixed::parse("0.18")); // Meets FACTOR_CMP so compare only 2 d.p.s
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for GuardedFixed {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: &Self) -> Self::Output { Self(self.0 + &rhs.0) }
|
||||
@ -280,6 +316,18 @@ impl ops::Rem<&Self> for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_ref() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + &b, GuardedFixed::parse("802.35"));
|
||||
assert_eq!(a.clone() - &b, GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, GuardedFixed::parse("83810.205"));
|
||||
assert_eq!(a.clone() / &b, GuardedFixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for GuardedFixed {
|
||||
fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; }
|
||||
}
|
||||
@ -308,6 +356,18 @@ impl ops::RemAssign for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_owned() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += b.clone(); assert_eq!(x, GuardedFixed::parse("802.35"));
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, GuardedFixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, GuardedFixed::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for GuardedFixed {
|
||||
fn add_assign(&mut self, rhs: &Self) { self.0 += &rhs.0; }
|
||||
}
|
||||
@ -336,6 +396,18 @@ impl ops::RemAssign<&Self> for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_ref() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += &b; assert_eq!(x, GuardedFixed::parse("802.35"));
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, GuardedFixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, GuardedFixed::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||
}
|
||||
|
||||
impl ops::Neg for &GuardedFixed {
|
||||
type Output = GuardedFixed;
|
||||
fn neg(self) -> Self::Output { GuardedFixed(-&self.0) }
|
||||
@ -368,6 +440,18 @@ impl ops::Rem<Self> for &GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_ref_ref() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
assert_eq!(&a + &b, GuardedFixed::parse("802.35"));
|
||||
assert_eq!(&a - &b, GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(&a * &b, GuardedFixed::parse("83810.205"));
|
||||
assert_eq!(&a / &b, GuardedFixed::parse("0.18"));
|
||||
}
|
||||
|
||||
/*
|
||||
impl ops::Add<&&Rational> for &Rational {
|
||||
|
||||
|
@ -54,6 +54,24 @@ impl Number for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
let mut x = NativeFloat64::parse("55.550"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.552"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.555"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.557"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
|
||||
let mut x = NativeFloat64::parse("55.550"); x.ceil_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.552"); x.ceil_mut(2); assert_eq!(x, NativeFloat64::parse("55.56"));
|
||||
let mut x = NativeFloat64::parse("55.555"); x.ceil_mut(2); assert_eq!(x, NativeFloat64::parse("55.56"));
|
||||
let mut x = NativeFloat64::parse("55.557"); x.ceil_mut(2); assert_eq!(x, NativeFloat64::parse("55.56"));
|
||||
|
||||
let mut x = NativeFloat64::parse("55.550"); x.round_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.552"); x.round_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
let mut x = NativeFloat64::parse("55.555"); x.round_mut(2); assert_eq!(x, NativeFloat64::parse("55.56"));
|
||||
let mut x = NativeFloat64::parse("55.557"); x.round_mut(2); assert_eq!(x, NativeFloat64::parse("55.56"));
|
||||
}
|
||||
|
||||
impl Num for NativeFloat64 {
|
||||
type FromStrRadixErr = ParseFloatError;
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||
@ -76,6 +94,10 @@ impl From<usize> for NativeFloat64 {
|
||||
fn from(n: usize) -> Self { Self(n as ImplType) }
|
||||
}
|
||||
|
||||
impl From<f64> for NativeFloat64 {
|
||||
fn from(n: f64) -> Self { Self(n as ImplType) }
|
||||
}
|
||||
|
||||
impl One for NativeFloat64 {
|
||||
fn one() -> Self { Self(1.0) }
|
||||
}
|
||||
@ -102,9 +124,7 @@ impl ops::Add for NativeFloat64 {
|
||||
|
||||
impl ops::Sub for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn sub(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul for NativeFloat64 {
|
||||
@ -124,6 +144,17 @@ impl ops::Rem for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_owned() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + b.clone(), NativeFloat64::from(123.45_f64 + 678.90_f64));
|
||||
assert_eq!(a.clone() - b.clone(), NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(a.clone() * b.clone(), NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(a.clone() / b.clone(), NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
}
|
||||
|
||||
impl ops::Add<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 + &rhs.0) }
|
||||
@ -151,6 +182,17 @@ impl ops::Rem<&NativeFloat64> for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_ref() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + &b, NativeFloat64::from(123.45_f64 + 678.90_f64));
|
||||
assert_eq!(a.clone() - &b, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(a.clone() * &b, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(a.clone() / &b, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for NativeFloat64 {
|
||||
fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; }
|
||||
}
|
||||
@ -173,6 +215,17 @@ impl ops::RemAssign for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_owned() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 + 678.90_f64));
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn add_assign(&mut self, rhs: &NativeFloat64) { self.0 += &rhs.0; }
|
||||
}
|
||||
@ -195,6 +248,17 @@ impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_ref() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += &b; assert_eq!(x, NativeFloat64::from(123.45_f64 + 678.90_f64));
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
}
|
||||
|
||||
impl ops::Neg for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn neg(self) -> Self::Output { NativeFloat64(-&self.0) }
|
||||
@ -227,6 +291,17 @@ impl ops::Rem<Self> for &NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_ref_ref() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
assert_eq!(&a + &b, NativeFloat64::from(123.45_f64 + 678.90_f64));
|
||||
assert_eq!(&a - &b, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(&a * &b, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(&a / &b, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
}
|
||||
|
||||
/*
|
||||
impl ops::Add<&&NativeFloat> for &NativeFloat {
|
||||
|
||||
|
@ -70,8 +70,8 @@ impl Number for Rational {
|
||||
factor.pow_assign(-(dps as i32));
|
||||
factor /= Self::from(2);
|
||||
|
||||
*self = self.clone() - factor;
|
||||
self.ceil_mut(dps);
|
||||
*self = self.clone() + factor;
|
||||
self.floor_mut(dps);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +87,12 @@ impl Number for Rational {
|
||||
Ok(value) => rug::Rational::from(value),
|
||||
Err(_) => panic!("Syntax Error"),
|
||||
} / rug::Rational::from(10).pow(decimal.len() as u32);
|
||||
return Self(whole + decimal);
|
||||
|
||||
if whole < rug::Rational::new() {
|
||||
return Self(whole - decimal);
|
||||
} else {
|
||||
return Self(whole + decimal);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse integer
|
||||
@ -99,6 +104,24 @@ impl Number for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
let mut x = Rational::parse("55.550"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.552"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.555"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.557"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
|
||||
let mut x = Rational::parse("55.550"); x.ceil_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.552"); x.ceil_mut(2); assert_eq!(x, Rational::parse("55.56"));
|
||||
let mut x = Rational::parse("55.555"); x.ceil_mut(2); assert_eq!(x, Rational::parse("55.56"));
|
||||
let mut x = Rational::parse("55.557"); x.ceil_mut(2); assert_eq!(x, Rational::parse("55.56"));
|
||||
|
||||
let mut x = Rational::parse("55.550"); x.round_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.552"); x.round_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
let mut x = Rational::parse("55.555"); x.round_mut(2); assert_eq!(x, Rational::parse("55.56"));
|
||||
let mut x = Rational::parse("55.557"); x.round_mut(2); assert_eq!(x, Rational::parse("55.56"));
|
||||
}
|
||||
|
||||
impl Num for Rational {
|
||||
type FromStrRadixErr = ParseRationalError;
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||
@ -178,9 +201,7 @@ impl ops::Add for Rational {
|
||||
|
||||
impl ops::Sub for Rational {
|
||||
type Output = Self;
|
||||
fn sub(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul for Rational {
|
||||
@ -200,6 +221,17 @@ impl ops::Rem for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_owned() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + b.clone(), Rational::parse("802.35"));
|
||||
assert_eq!(a.clone() - b.clone(), Rational::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), Rational::parse("83810.205"));
|
||||
assert_eq!((a.clone() / b.clone()) * b, a);
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for Rational {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: &Self) -> Self::Output { Self(self.0 + &rhs.0) }
|
||||
@ -227,6 +259,17 @@ impl ops::Rem<&Self> for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_owned_ref() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
assert_eq!(a.clone() + &b, Rational::parse("802.35"));
|
||||
assert_eq!(a.clone() - &b, Rational::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, Rational::parse("83810.205"));
|
||||
assert_eq!((a.clone() / &b) * b, a);
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Rational {
|
||||
fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; }
|
||||
}
|
||||
@ -249,6 +292,17 @@ impl ops::RemAssign for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_owned() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += b.clone(); assert_eq!(x, Rational::parse("802.35"));
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, Rational::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, Rational::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= b.clone(); x *= b; assert_eq!(x, a);
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for Rational {
|
||||
fn add_assign(&mut self, rhs: &Self) { self.0 += &rhs.0; }
|
||||
}
|
||||
@ -271,6 +325,17 @@ impl ops::RemAssign<&Self> for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithassign_ref() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x += &b; assert_eq!(x, Rational::parse("802.35"));
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, Rational::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, Rational::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= &b; x *= b; assert_eq!(x, a);
|
||||
}
|
||||
|
||||
impl ops::Neg for &Rational {
|
||||
type Output = Rational;
|
||||
fn neg(self) -> Self::Output { Rational(rug::Rational::from(-&self.0)) }
|
||||
@ -303,6 +368,17 @@ impl ops::Rem<Self> for &Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arith_ref_ref() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
assert_eq!(&a + &b, Rational::parse("802.35"));
|
||||
assert_eq!(&a - &b, Rational::parse("-555.45"));
|
||||
assert_eq!(&a * &b, Rational::parse("83810.205"));
|
||||
assert_eq!((&a / &b) * b, a);
|
||||
}
|
||||
|
||||
/*
|
||||
impl ops::Add<&&Rational> for &Rational {
|
||||
|
||||
|
24
tests/data/ers97_csv_output.csv
Normal file
24
tests/data/ers97_csv_output.csv
Normal file
@ -0,0 +1,24 @@
|
||||
"Election for","ERS Model - 1997 Edition"
|
||||
"Date"," / / "
|
||||
"Number to be elected",6
|
||||
"Valid votes",753
|
||||
"Invalid votes",0
|
||||
"Quota",107.58
|
||||
"OpenTally","VERSION"
|
||||
"Election rules","--round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 2 --quota droop_exact --quota-criterion geq --quota-mode ers97 --surplus eg --transferable-only --exclusion by_value --bulk-exclude --defer-surpluses"
|
||||
,,"Stage",2,"Stage",3,"Stage",4,"Stage",5,"Stage",6,"Stage",7,"Stage",8
|
||||
,"First","Surplus of",,"Exclusion of",,"Exclusion of",,"Exclusion of",,"Exclusion of",,"Surplus of",,"Exclusion of",
|
||||
"Candidates","Preferences","Smith",,"Monk",,"Monk",,"Glazier+Wright",,"Glazier+Wright",,"Carpenter",,"Abbot",
|
||||
"Smith",134,-26.42,107.58,,107.58,,107.58,,107.58,,107.58,,107.58,,107.58,"Elected"
|
||||
"Duke",105,+1.68,106.68,+2.00,108.68,,108.68,,108.68,,108.68,,108.68,,108.68,"Elected"
|
||||
"Prince",91,+0.63,91.63,+4.00,95.63,,95.63,+5.00,100.63,+1.68,102.31,+2.00,104.31,,104.31,"Elected"
|
||||
"Freeman",90,+2.94,92.94,+1.00,93.94,,93.94,+4.00,97.94,+1.68,99.62,+1.00,100.62,+1.00,101.62,"Elected"
|
||||
"Carpenter",81,+7.14,88.14,,88.14,+0.21,88.35,+34.00,122.35,,122.35,-14.77,107.58,,107.58,"Elected"
|
||||
"Baron",64,+0.21,64.21,,64.21,,64.21,+3.00,67.21,+1.05,68.26,+2.00,70.26,+12.00,82.26,
|
||||
"Abbot",59,+0.84,59.84,+5.00,64.84,,64.84,+1.00,65.84,+1.26,67.10,+1.00,68.10,-66.00,2.10,
|
||||
"Vicar",55,+0.21,55.21,+10.00,65.21,,65.21,+3.00,68.21,+2.10,70.31,+2.00,72.31,+41.00,113.31,"Elected"
|
||||
"Wright",27,+5.25,32.25,,32.25,,32.25,-27.00,5.25,-5.25,"-",,"-",,"-",
|
||||
"Glazier",24,+6.51,30.51,,30.51,,30.51,-24.00,6.51,-6.51,"-",,"-",,"-",
|
||||
"Monk",23,+0.42,23.42,-23.00,0.42,-0.42,"-",,"-",,"-",,"-",,"-",
|
||||
"Non-transferable",,+0.59,0.59,+1.00,1.59,+0.21,1.80,+1.00,2.80,+3.99,6.79,+6.77,13.56,+12.00,25.56,
|
||||
"Totals",753,,753.00,,753.00,,753.00,,753.00,,753.00,,753.00,,753.00
|
Can't render this file because it has a wrong number of fields in line 9.
|
@ -25,6 +25,13 @@ fn cli_ers97old() {
|
||||
.assert().success();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_ers97_transfers_detail() {
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["stv", "tests/data/ers97.blt", "--numbers", "fixed", "--decimals", "5", "--round-surplus-fractions", "2", "--round-values", "2", "--round-votes", "2", "--round-quota", "2", "--quota", "droop_exact", "--quota-criterion", "geq", "--quota-mode", "ers97", "--surplus", "eg", "--transferable-only", "--exclusion", "by_value", "--bulk-exclude", "--defer-surpluses", "--transfers-detail"])
|
||||
.assert().success();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_meekm_wigm_ties_prompt() {
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
|
@ -15,43 +15,41 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use opentally::election::Election;
|
||||
use opentally::numbers::Rational;
|
||||
use opentally::parser;
|
||||
use opentally::writer;
|
||||
use assert_cmd::Command;
|
||||
|
||||
use std::fs;
|
||||
|
||||
#[test]
|
||||
fn ers97_wd_conversions() {
|
||||
fn convert_ers97_blt_bin() {
|
||||
let blt_input = fs::read_to_string("tests/data/ers97_wd.blt").expect("IO Error");
|
||||
|
||||
let election: Election<Rational> = parser::blt::parse_path("tests/data/ers97_wd.blt").expect("Parse Error");
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["convert", "tests/data/ers97_wd.blt", "/tmp/opentally.bin"])
|
||||
.assert().success();
|
||||
|
||||
// Check BLT
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
writer::blt::write(election.clone(), &mut buf);
|
||||
assert_eq!(blt_input, std::str::from_utf8(&buf).expect("UTF-8 Error"));
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["convert", "/tmp/opentally.bin", "/tmp/opentally.blt"])
|
||||
.assert().success();
|
||||
|
||||
// Check BIN
|
||||
buf.clear();
|
||||
writer::bin::write(election.clone(), &mut buf);
|
||||
let election2: Election<Rational> = parser::bin::parse_bytes(&buf);
|
||||
|
||||
buf.clear();
|
||||
writer::blt::write(election2, &mut buf);
|
||||
assert_eq!(blt_input, std::str::from_utf8(&buf).expect("UTF-8 Error"));
|
||||
|
||||
// Check CSP
|
||||
buf.clear();
|
||||
writer::csp::write(election.clone(), &mut buf);
|
||||
let mut election2: Election<Rational> = parser::csp::parse_reader(&buf[..]);
|
||||
|
||||
election2.seats = election.seats;
|
||||
election2.name = election.name;
|
||||
election2.withdrawn_candidates = election.withdrawn_candidates.clone();
|
||||
|
||||
buf.clear();
|
||||
writer::blt::write(election2, &mut buf);
|
||||
assert_eq!(blt_input, std::str::from_utf8(&buf).expect("UTF-8 Error"));
|
||||
let blt_roundtrip = fs::read_to_string("/tmp/opentally.blt").expect("IO Error");
|
||||
assert_eq!(blt_input, blt_roundtrip);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_ers97_blt_csp() {
|
||||
// Withdrawn candidates not supported
|
||||
let blt_input = fs::read_to_string("tests/data/ers97_wd.blt").expect("IO Error")
|
||||
.replace(r#""ERS Model - 1997 Edition""#, r#""""#)
|
||||
.replace("-1 -2\n", "");
|
||||
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["convert", "tests/data/ers97_wd.blt", "/tmp/opentally.csp"])
|
||||
.assert().success();
|
||||
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["convert", "/tmp/opentally.csp", "/tmp/opentally.blt", "--seats", "6"])
|
||||
.assert().success();
|
||||
|
||||
let blt_roundtrip = fs::read_to_string("/tmp/opentally.blt").expect("IO Error");
|
||||
assert_eq!(blt_input, blt_roundtrip);
|
||||
}
|
||||
|
@ -20,6 +20,10 @@ use crate::utils;
|
||||
use opentally::numbers::Rational;
|
||||
use opentally::stv;
|
||||
|
||||
use assert_cmd::Command;
|
||||
|
||||
use std::fs;
|
||||
|
||||
#[test]
|
||||
fn ers97old_rational() {
|
||||
let stv_opts = stv::STVOptionsBuilder::default()
|
||||
@ -62,6 +66,20 @@ fn ers97_rational() {
|
||||
utils::read_validate_election::<Rational>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers97_rational_csv() {
|
||||
let cmd = Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["stv", "tests/data/ers97.blt", "--round-surplus-fractions", "2", "--round-values", "2", "--round-votes", "2", "--round-quota", "2", "--quota", "droop_exact", "--quota-criterion", "geq", "--quota-mode", "ers97", "--surplus", "eg", "--transferable-only", "--exclusion", "by_value", "--bulk-exclude", "--defer-surpluses", "--output", "csv"])
|
||||
.assert().success();
|
||||
|
||||
let output = std::str::from_utf8(&cmd.get_output().stdout).expect("Unicode Error")
|
||||
.replace(&format!(r#""{}""#, opentally::VERSION), r#""VERSION""#);
|
||||
|
||||
let expected = fs::read_to_string("tests/data/ers97_csv_output.csv").expect("IO Error");
|
||||
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers76_rational() {
|
||||
let stv_opts = stv::STVOptionsBuilder::default()
|
||||
|
Loading…
Reference in New Issue
Block a user