More work on unit/integration tests
This commit is contained in:
parent
f12db205b9
commit
a641b97d1f
|
@ -9,10 +9,11 @@ export CARGO_TARGET_DIR=target/coverage
|
||||||
cargo test
|
cargo test
|
||||||
|
|
||||||
llvm-profdata merge -sparse target/coverage/prof/*.profraw -o target/coverage/opentally.profdata
|
llvm-profdata merge -sparse target/coverage/prof/*.profraw -o target/coverage/opentally.profdata
|
||||||
|
for file in $(cargo test --no-run --message-format=json 2>/dev/null | jq -r "select(.profile.test == true) | .filenames[]"); do echo -n --object '"'$file'" '; done > target/coverage/objects
|
||||||
|
|
||||||
# Need "eval" to correctly parse arguments
|
# Need "eval" to correctly parse arguments
|
||||||
eval llvm-cov show target/coverage/debug/opentally -instr-profile=target/coverage/opentally.profdata -Xdemangler="$HOME/.cargo/bin/rustfilt" \
|
eval llvm-cov show target/coverage/debug/opentally -instr-profile=target/coverage/opentally.profdata -Xdemangler="$HOME/.cargo/bin/rustfilt" \
|
||||||
$(for file in $(cargo test --no-run --message-format=json 2>/dev/null | jq -r "select(.profile.test == true) | .filenames[]"); do echo -n --object '"'$file'" '; done) \
|
$(cat target/coverage/objects) \
|
||||||
-ignore-filename-regex="$HOME/." \
|
-ignore-filename-regex="$HOME/." \
|
||||||
-ignore-filename-regex=rustc \
|
-ignore-filename-regex=rustc \
|
||||||
-ignore-filename-regex=numbers/rational_num.rs \
|
-ignore-filename-regex=numbers/rational_num.rs \
|
||||||
|
|
|
@ -35,7 +35,6 @@ use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// An election to be counted
|
/// An election to be counted
|
||||||
#[derive(Clone)]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||||
pub struct Election<N> {
|
pub struct Election<N> {
|
||||||
/// Name of the election
|
/// Name of the election
|
||||||
|
@ -93,7 +92,7 @@ impl<N: Number> Election<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A candidate in an [Election]
|
/// A candidate in an [Election]
|
||||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
#[derive(Eq, Hash, PartialEq)]
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||||
pub struct Candidate {
|
pub struct Candidate {
|
||||||
/// Name of the candidate
|
/// Name of the candidate
|
||||||
|
@ -465,7 +464,6 @@ impl<'a, N> Vote<'a, N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A record of a voter's preferences
|
/// A record of a voter's preferences
|
||||||
#[derive(Clone)]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||||
pub struct Ballot<N> {
|
pub struct Ballot<N> {
|
||||||
/// Original value/weight of the ballot
|
/// Original value/weight of the ballot
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// Smart logger used in election counts
|
/// Smart logger used in election counts
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Logger<'a> {
|
pub struct Logger<'a> {
|
||||||
/// [Vec] of log entries for the current stage
|
/// [Vec] of log entries for the current stage
|
||||||
pub entries: Vec<LogEntry<'a>>,
|
pub entries: Vec<LogEntry<'a>>,
|
||||||
|
@ -72,7 +71,6 @@ impl<'a> Logger<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents either a literal or smart log entry
|
/// Represents either a literal or smart log entry
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum LogEntry<'a> {
|
pub enum LogEntry<'a> {
|
||||||
/// Smart log entry - see [SmartLogEntry]
|
/// Smart log entry - see [SmartLogEntry]
|
||||||
Smart(SmartLogEntry<'a>),
|
Smart(SmartLogEntry<'a>),
|
||||||
|
@ -81,7 +79,6 @@ pub enum LogEntry<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Smart log entry
|
/// Smart log entry
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct SmartLogEntry<'a> {
|
pub struct SmartLogEntry<'a> {
|
||||||
template1: &'a str,
|
template1: &'a str,
|
||||||
template2: &'a str,
|
template2: &'a str,
|
||||||
|
|
|
@ -176,6 +176,16 @@ impl Assign<&Self> for Fixed {
|
||||||
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign() {
|
||||||
|
Fixed::set_dps(2);
|
||||||
|
let a = Fixed::parse("123.45");
|
||||||
|
let b = Fixed::parse("678.90");
|
||||||
|
|
||||||
|
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||||
|
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||||
|
}
|
||||||
|
|
||||||
impl From<usize> for Fixed {
|
impl From<usize> for Fixed {
|
||||||
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
||||||
}
|
}
|
||||||
|
@ -219,6 +229,13 @@ impl fmt::Display for Fixed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_debug() {
|
||||||
|
Fixed::set_dps(2);
|
||||||
|
let x = Fixed::parse("123.4"); assert_eq!(format!("{}", x), "123.40");
|
||||||
|
let x = Fixed::parse("123.4"); assert_eq!(format!("{:?}", x), "Fixed(12340)");
|
||||||
|
}
|
||||||
|
|
||||||
impl One for Fixed {
|
impl One for Fixed {
|
||||||
fn one() -> Self { Self(get_factor().clone()) }
|
fn one() -> Self { Self(get_factor().clone()) }
|
||||||
}
|
}
|
||||||
|
@ -255,9 +272,7 @@ impl ops::Div for Fixed {
|
||||||
|
|
||||||
impl ops::Rem for Fixed {
|
impl ops::Rem for Fixed {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -270,6 +285,7 @@ fn arith_owned_owned() {
|
||||||
assert_eq!(a.clone() - b.clone(), Fixed::parse("-555.45"));
|
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("83810.20")); // = 83810.205 rounds to 83810.20
|
||||||
assert_eq!(a.clone() / b.clone(), Fixed::parse("0.18"));
|
assert_eq!(a.clone() / b.clone(), Fixed::parse("0.18"));
|
||||||
|
assert_eq!(b.clone() % a.clone(), Fixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Add<&Self> for Fixed {
|
impl ops::Add<&Self> for Fixed {
|
||||||
|
@ -294,9 +310,7 @@ impl ops::Div<&Self> for Fixed {
|
||||||
|
|
||||||
impl ops::Rem<&Self> for Fixed {
|
impl ops::Rem<&Self> for Fixed {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
fn rem(self, rhs: &Self) -> Self::Output { Self(self.0 % &rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -309,6 +323,7 @@ fn arith_owned_ref() {
|
||||||
assert_eq!(a.clone() - &b, Fixed::parse("-555.45"));
|
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("83810.20"));
|
||||||
assert_eq!(a.clone() / &b, Fixed::parse("0.18"));
|
assert_eq!(a.clone() / &b, Fixed::parse("0.18"));
|
||||||
|
assert_eq!(b.clone() % &a, Fixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign for Fixed {
|
impl ops::AddAssign for Fixed {
|
||||||
|
@ -334,9 +349,7 @@ impl ops::DivAssign for Fixed {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign for Fixed {
|
impl ops::RemAssign for Fixed {
|
||||||
fn rem_assign(&mut self, _rhs: Self) {
|
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -349,6 +362,7 @@ fn arithassign_owned() {
|
||||||
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("-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("83810.20"));
|
||||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, Fixed::parse("0.18"));
|
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, Fixed::parse("0.18"));
|
||||||
|
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, Fixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign<&Self> for Fixed {
|
impl ops::AddAssign<&Self> for Fixed {
|
||||||
|
@ -374,9 +388,7 @@ impl ops::DivAssign<&Self> for Fixed {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&Self> for Fixed {
|
impl ops::RemAssign<&Self> for Fixed {
|
||||||
fn rem_assign(&mut self, _rhs: &Self) {
|
fn rem_assign(&mut self, rhs: &Self) { self.0 %= &rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -389,6 +401,7 @@ fn arithassign_ref() {
|
||||||
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("-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("83810.20"));
|
||||||
let mut x = a.clone(); x /= &b; assert_eq!(x, Fixed::parse("0.18"));
|
let mut x = a.clone(); x /= &b; assert_eq!(x, Fixed::parse("0.18"));
|
||||||
|
let mut x = b.clone(); x %= &a; assert_eq!(x, Fixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Neg for &Fixed {
|
impl ops::Neg for &Fixed {
|
||||||
|
@ -418,9 +431,7 @@ impl ops::Div<Self> for &Fixed {
|
||||||
|
|
||||||
impl ops::Rem<Self> for &Fixed {
|
impl ops::Rem<Self> for &Fixed {
|
||||||
type Output = Fixed;
|
type Output = Fixed;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output { Fixed(&self.0 % &rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -433,6 +444,7 @@ fn arith_ref_ref() {
|
||||||
assert_eq!(&a - &b, Fixed::parse("-555.45"));
|
assert_eq!(&a - &b, Fixed::parse("-555.45"));
|
||||||
assert_eq!(&a * &b, Fixed::parse("83810.20"));
|
assert_eq!(&a * &b, Fixed::parse("83810.20"));
|
||||||
assert_eq!(&a / &b, Fixed::parse("0.18"));
|
assert_eq!(&a / &b, Fixed::parse("0.18"));
|
||||||
|
assert_eq!(&b % &a, Fixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -220,6 +220,16 @@ impl Assign<&Self> for GuardedFixed {
|
||||||
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign() {
|
||||||
|
GuardedFixed::set_dps(2);
|
||||||
|
let a = GuardedFixed::parse("123.45");
|
||||||
|
let b = GuardedFixed::parse("678.90");
|
||||||
|
|
||||||
|
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||||
|
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||||
|
}
|
||||||
|
|
||||||
impl From<usize> for GuardedFixed {
|
impl From<usize> for GuardedFixed {
|
||||||
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
||||||
}
|
}
|
||||||
|
@ -262,6 +272,13 @@ impl fmt::Display for GuardedFixed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_debug() {
|
||||||
|
GuardedFixed::set_dps(2);
|
||||||
|
let x = GuardedFixed::parse("123.4"); assert_eq!(format!("{}", x), "123.40");
|
||||||
|
let x = GuardedFixed::parse("123.4"); assert_eq!(format!("{:?}", x), "GuardedFixed(1234000)");
|
||||||
|
}
|
||||||
|
|
||||||
impl One for GuardedFixed {
|
impl One for GuardedFixed {
|
||||||
fn one() -> Self { Self(get_factor().clone()) }
|
fn one() -> Self { Self(get_factor().clone()) }
|
||||||
}
|
}
|
||||||
|
@ -298,9 +315,7 @@ impl ops::Div for GuardedFixed {
|
||||||
|
|
||||||
impl ops::Rem for GuardedFixed {
|
impl ops::Rem for GuardedFixed {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -313,6 +328,7 @@ fn arith_owned_owned() {
|
||||||
assert_eq!(a.clone() - b.clone(), GuardedFixed::parse("-555.45"));
|
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("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
|
assert_eq!(a.clone() / b.clone(), GuardedFixed::parse("0.18")); // Meets FACTOR_CMP so compare only 2 d.p.s
|
||||||
|
assert_eq!(b.clone() % a.clone(), GuardedFixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Add<&Self> for GuardedFixed {
|
impl ops::Add<&Self> for GuardedFixed {
|
||||||
|
@ -337,9 +353,7 @@ impl ops::Div<&Self> for GuardedFixed {
|
||||||
|
|
||||||
impl ops::Rem<&Self> for GuardedFixed {
|
impl ops::Rem<&Self> for GuardedFixed {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
fn rem(self, rhs: &Self) -> Self::Output { Self(self.0 % &rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -352,6 +366,7 @@ fn arith_owned_ref() {
|
||||||
assert_eq!(a.clone() - &b, GuardedFixed::parse("-555.45"));
|
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("83810.205"));
|
||||||
assert_eq!(a.clone() / &b, GuardedFixed::parse("0.18"));
|
assert_eq!(a.clone() / &b, GuardedFixed::parse("0.18"));
|
||||||
|
assert_eq!(b.clone() % &a, GuardedFixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign for GuardedFixed {
|
impl ops::AddAssign for GuardedFixed {
|
||||||
|
@ -377,9 +392,7 @@ impl ops::DivAssign for GuardedFixed {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign for GuardedFixed {
|
impl ops::RemAssign for GuardedFixed {
|
||||||
fn rem_assign(&mut self, _rhs: Self) {
|
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -392,6 +405,7 @@ fn arithassign_owned() {
|
||||||
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("-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("83810.205"));
|
||||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, GuardedFixed::parse("0.18"));
|
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||||
|
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, GuardedFixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign<&Self> for GuardedFixed {
|
impl ops::AddAssign<&Self> for GuardedFixed {
|
||||||
|
@ -417,9 +431,7 @@ impl ops::DivAssign<&Self> for GuardedFixed {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&Self> for GuardedFixed {
|
impl ops::RemAssign<&Self> for GuardedFixed {
|
||||||
fn rem_assign(&mut self, _rhs: &Self) {
|
fn rem_assign(&mut self, rhs: &Self) { self.0 %= &rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -432,6 +444,7 @@ fn arithassign_ref() {
|
||||||
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("-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("83810.205"));
|
||||||
let mut x = a.clone(); x /= &b; assert_eq!(x, GuardedFixed::parse("0.18"));
|
let mut x = a.clone(); x /= &b; assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||||
|
let mut x = b.clone(); x %= &a; assert_eq!(x, GuardedFixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Neg for &GuardedFixed {
|
impl ops::Neg for &GuardedFixed {
|
||||||
|
@ -461,9 +474,7 @@ impl ops::Div<Self> for &GuardedFixed {
|
||||||
|
|
||||||
impl ops::Rem<Self> for &GuardedFixed {
|
impl ops::Rem<Self> for &GuardedFixed {
|
||||||
type Output = GuardedFixed;
|
type Output = GuardedFixed;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output { GuardedFixed(&self.0 % &rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -476,6 +487,7 @@ fn arith_ref_ref() {
|
||||||
assert_eq!(&a - &b, GuardedFixed::parse("-555.45"));
|
assert_eq!(&a - &b, GuardedFixed::parse("-555.45"));
|
||||||
assert_eq!(&a * &b, GuardedFixed::parse("83810.205"));
|
assert_eq!(&a * &b, GuardedFixed::parse("83810.205"));
|
||||||
assert_eq!(&a / &b, GuardedFixed::parse("0.18"));
|
assert_eq!(&a / &b, GuardedFixed::parse("0.18"));
|
||||||
|
assert_eq!(&b % &a, GuardedFixed::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -54,6 +54,12 @@ impl Number for NativeFloat64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_debug() {
|
||||||
|
let x = NativeFloat64::parse("123.4"); assert_eq!(format!("{}", x), format!("{}", 123.40_f64));
|
||||||
|
let x = NativeFloat64::parse("123.4"); assert_eq!(format!("{:?}", x), format!("NativeFloat64({})", 123.40_f64));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rounding() {
|
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.550"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||||
|
@ -90,6 +96,15 @@ impl Assign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn assign(&mut self, src: &NativeFloat64) { self.0 = src.0; }
|
fn assign(&mut self, src: &NativeFloat64) { self.0 = src.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign() {
|
||||||
|
let a = NativeFloat64::parse("123.45");
|
||||||
|
let b = NativeFloat64::parse("678.90");
|
||||||
|
|
||||||
|
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||||
|
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||||
|
}
|
||||||
|
|
||||||
impl From<usize> for NativeFloat64 {
|
impl From<usize> for NativeFloat64 {
|
||||||
fn from(n: usize) -> Self { Self(n as ImplType) }
|
fn from(n: usize) -> Self { Self(n as ImplType) }
|
||||||
}
|
}
|
||||||
|
@ -139,9 +154,7 @@ impl ops::Div for NativeFloat64 {
|
||||||
|
|
||||||
impl ops::Rem for NativeFloat64 {
|
impl ops::Rem for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -153,33 +166,32 @@ fn arith_owned_owned() {
|
||||||
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));
|
||||||
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!(b.clone() % a.clone(), NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Add<&NativeFloat64> for NativeFloat64 {
|
impl ops::Add<&NativeFloat64> for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 + &rhs.0) }
|
fn add(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 + rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Sub<&NativeFloat64> for NativeFloat64 {
|
impl ops::Sub<&NativeFloat64> for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 - &rhs.0) }
|
fn sub(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 - rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Mul<&NativeFloat64> for NativeFloat64 {
|
impl ops::Mul<&NativeFloat64> for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * &rhs.0) }
|
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Div<&NativeFloat64> for NativeFloat64 {
|
impl ops::Div<&NativeFloat64> for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / &rhs.0) }
|
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Rem<&NativeFloat64> for NativeFloat64 {
|
impl ops::Rem<&NativeFloat64> for NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn rem(self, _rhs: &NativeFloat64) -> Self::Output {
|
fn rem(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 % rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -191,6 +203,7 @@ fn arith_owned_ref() {
|
||||||
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));
|
||||||
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!(b.clone() % &a, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign for NativeFloat64 {
|
impl ops::AddAssign for NativeFloat64 {
|
||||||
|
@ -206,13 +219,11 @@ impl ops::MulAssign for NativeFloat64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign for NativeFloat64 {
|
impl ops::DivAssign for NativeFloat64 {
|
||||||
fn div_assign(&mut self, rhs: Self) { self.0 /= &rhs.0; }
|
fn div_assign(&mut self, rhs: Self) { self.0 /= rhs.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign for NativeFloat64 {
|
impl ops::RemAssign for NativeFloat64 {
|
||||||
fn rem_assign(&mut self, _rhs: Self) {
|
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -224,28 +235,27 @@ fn arithassign_owned() {
|
||||||
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));
|
||||||
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 = b.clone(); x %= a.clone(); assert_eq!(x, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::AddAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn add_assign(&mut self, rhs: &NativeFloat64) { self.0 += &rhs.0; }
|
fn add_assign(&mut self, rhs: &NativeFloat64) { self.0 += rhs.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::SubAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::SubAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn sub_assign(&mut self, rhs: &NativeFloat64) { self.0 -= &rhs.0; }
|
fn sub_assign(&mut self, rhs: &NativeFloat64) { self.0 -= rhs.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::MulAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::MulAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn mul_assign(&mut self, rhs: &NativeFloat64) { self.0 *= &rhs.0; }
|
fn mul_assign(&mut self, rhs: &NativeFloat64) { self.0 *= rhs.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::DivAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn div_assign(&mut self, rhs: &NativeFloat64) { self.0 /= &rhs.0; }
|
fn div_assign(&mut self, rhs: &NativeFloat64) { self.0 /= rhs.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn rem_assign(&mut self, _rhs: &NativeFloat64) {
|
fn rem_assign(&mut self, rhs: &NativeFloat64) { self.0 %= rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -257,38 +267,37 @@ fn arithassign_ref() {
|
||||||
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));
|
||||||
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 = b.clone(); x %= &a; assert_eq!(x, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Neg for &NativeFloat64 {
|
impl ops::Neg for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn neg(self) -> Self::Output { NativeFloat64(-&self.0) }
|
fn neg(self) -> Self::Output { NativeFloat64(-self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Add<Self> for &NativeFloat64 {
|
impl ops::Add<Self> for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 + &rhs.0) }
|
fn add(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 + rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Sub<Self> for &NativeFloat64 {
|
impl ops::Sub<Self> for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 - &rhs.0) }
|
fn sub(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 - rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Mul<Self> for &NativeFloat64 {
|
impl ops::Mul<Self> for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 * &rhs.0) }
|
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Div<Self> for &NativeFloat64 {
|
impl ops::Div<Self> for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 / &rhs.0) }
|
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / rhs.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Rem<Self> for &NativeFloat64 {
|
impl ops::Rem<Self> for &NativeFloat64 {
|
||||||
type Output = NativeFloat64;
|
type Output = NativeFloat64;
|
||||||
fn rem(self, _rhs: &NativeFloat64) -> Self::Output {
|
fn rem(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 % rhs.0) }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -300,6 +309,7 @@ fn arith_ref_ref() {
|
||||||
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));
|
||||||
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!(&b % &a, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -104,6 +104,12 @@ impl Number for Rational {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn describe() {
|
||||||
|
// Never executed - just for the sake of code coverage
|
||||||
|
assert_eq!(Rational::describe(), "--numbers rational");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rounding() {
|
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.550"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||||
|
@ -140,6 +146,15 @@ impl Assign<&Self> for Rational {
|
||||||
fn assign(&mut self, src: &Self) { self.0.assign(&src.0) }
|
fn assign(&mut self, src: &Self) { self.0.assign(&src.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign() {
|
||||||
|
let a = Rational::parse("123.45");
|
||||||
|
let b = Rational::parse("678.90");
|
||||||
|
|
||||||
|
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||||
|
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||||
|
}
|
||||||
|
|
||||||
impl From<usize> for Rational {
|
impl From<usize> for Rational {
|
||||||
fn from(n: usize) -> Self { Self(rug::Rational::from(n)) }
|
fn from(n: usize) -> Self { Self(rug::Rational::from(n)) }
|
||||||
}
|
}
|
||||||
|
@ -175,6 +190,13 @@ impl fmt::Display for Rational {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_debug() {
|
||||||
|
let x = Rational::parse("123.4"); assert_eq!(format!("{}", x), "617/5");
|
||||||
|
let x = Rational::parse("123.4"); assert_eq!(format!("{:.2}", x), "123.40");
|
||||||
|
let x = Rational::parse("123.4"); assert_eq!(format!("{:?}", x), "Rational(617/5)");
|
||||||
|
}
|
||||||
|
|
||||||
impl One for Rational {
|
impl One for Rational {
|
||||||
fn one() -> Self { Self(rug::Rational::from(1)) }
|
fn one() -> Self { Self(rug::Rational::from(1)) }
|
||||||
}
|
}
|
||||||
|
@ -216,8 +238,12 @@ impl ops::Div for Rational {
|
||||||
|
|
||||||
impl ops::Rem for Rational {
|
impl ops::Rem for Rational {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output {
|
||||||
todo!()
|
// TODO: Is there a cleaner way of implementing this?
|
||||||
|
let mut quotient = self.0 / &rhs.0;
|
||||||
|
quotient.rem_trunc_mut();
|
||||||
|
quotient *= rhs.0;
|
||||||
|
return Self(quotient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +255,8 @@ fn arith_owned_owned() {
|
||||||
assert_eq!(a.clone() + b.clone(), Rational::parse("802.35"));
|
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("-555.45"));
|
||||||
assert_eq!(a.clone() * b.clone(), Rational::parse("83810.205"));
|
assert_eq!(a.clone() * b.clone(), Rational::parse("83810.205"));
|
||||||
assert_eq!((a.clone() / b.clone()) * b, a);
|
assert_eq!((a.clone() / b.clone()) * b.clone(), a);
|
||||||
|
assert_eq!(b.clone() % a.clone(), Rational::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Add<&Self> for Rational {
|
impl ops::Add<&Self> for Rational {
|
||||||
|
@ -254,8 +281,11 @@ impl ops::Div<&Self> for Rational {
|
||||||
|
|
||||||
impl ops::Rem<&Self> for Rational {
|
impl ops::Rem<&Self> for Rational {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
fn rem(self, rhs: &Self) -> Self::Output {
|
||||||
todo!()
|
let mut quotient = self.0 / &rhs.0;
|
||||||
|
quotient.rem_trunc_mut();
|
||||||
|
quotient *= &rhs.0;
|
||||||
|
return Self(quotient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +297,8 @@ fn arith_owned_ref() {
|
||||||
assert_eq!(a.clone() + &b, Rational::parse("802.35"));
|
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("-555.45"));
|
||||||
assert_eq!(a.clone() * &b, Rational::parse("83810.205"));
|
assert_eq!(a.clone() * &b, Rational::parse("83810.205"));
|
||||||
assert_eq!((a.clone() / &b) * b, a);
|
assert_eq!((a.clone() / &b) * &b, a);
|
||||||
|
assert_eq!(b.clone() % &a, Rational::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign for Rational {
|
impl ops::AddAssign for Rational {
|
||||||
|
@ -287,8 +318,10 @@ impl ops::DivAssign for Rational {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign for Rational {
|
impl ops::RemAssign for Rational {
|
||||||
fn rem_assign(&mut self, _rhs: Self) {
|
fn rem_assign(&mut self, rhs: Self) {
|
||||||
todo!()
|
self.0 /= &rhs.0;
|
||||||
|
self.0.rem_trunc_mut();
|
||||||
|
self.0 *= rhs.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +333,8 @@ fn arithassign_owned() {
|
||||||
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("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("-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(); assert_eq!(x, Rational::parse("83810.205"));
|
||||||
let mut x = a.clone(); x /= b.clone(); x *= b; assert_eq!(x, a);
|
let mut x = a.clone(); x /= b.clone(); x *= &b; assert_eq!(x, a);
|
||||||
|
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, Rational::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::AddAssign<&Self> for Rational {
|
impl ops::AddAssign<&Self> for Rational {
|
||||||
|
@ -320,8 +354,10 @@ impl ops::DivAssign<&Self> for Rational {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&Self> for Rational {
|
impl ops::RemAssign<&Self> for Rational {
|
||||||
fn rem_assign(&mut self, _rhs: &Self) {
|
fn rem_assign(&mut self, rhs: &Self) {
|
||||||
todo!()
|
self.0 /= &rhs.0;
|
||||||
|
self.0.rem_trunc_mut();
|
||||||
|
self.0 *= &rhs.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +369,8 @@ fn arithassign_ref() {
|
||||||
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("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("-555.45"));
|
||||||
let mut x = a.clone(); x *= &b; assert_eq!(x, Rational::parse("83810.205"));
|
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);
|
let mut x = a.clone(); x /= &b; x *= &b; assert_eq!(x, a);
|
||||||
|
let mut x = b.clone(); x %= &a; assert_eq!(x, Rational::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Neg for &Rational {
|
impl ops::Neg for &Rational {
|
||||||
|
@ -363,8 +400,11 @@ impl ops::Div<Self> for &Rational {
|
||||||
|
|
||||||
impl ops::Rem<Self> for &Rational {
|
impl ops::Rem<Self> for &Rational {
|
||||||
type Output = Rational;
|
type Output = Rational;
|
||||||
fn rem(self, _rhs: Self) -> Self::Output {
|
fn rem(self, rhs: Self) -> Self::Output {
|
||||||
todo!()
|
let mut quotient = rug::Rational::from(&self.0 / &rhs.0);
|
||||||
|
quotient.rem_trunc_mut();
|
||||||
|
quotient *= &rhs.0;
|
||||||
|
return Rational(quotient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +416,8 @@ fn arith_ref_ref() {
|
||||||
assert_eq!(&a + &b, Rational::parse("802.35"));
|
assert_eq!(&a + &b, Rational::parse("802.35"));
|
||||||
assert_eq!(&a - &b, Rational::parse("-555.45"));
|
assert_eq!(&a - &b, Rational::parse("-555.45"));
|
||||||
assert_eq!(&a * &b, Rational::parse("83810.205"));
|
assert_eq!(&a * &b, Rational::parse("83810.205"));
|
||||||
assert_eq!((&a / &b) * b, a);
|
assert_eq!((&a / &b) * &b, a);
|
||||||
|
assert_eq!(&b % &a, Rational::parse("61.65"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -19,7 +19,6 @@ use ibig::UBig;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
/// Deterministic random number generator using SHA256
|
/// Deterministic random number generator using SHA256
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct SHARandom<'r> {
|
pub struct SHARandom<'r> {
|
||||||
seed: &'r str,
|
seed: &'r str,
|
||||||
counter: usize,
|
counter: usize,
|
||||||
|
|
|
@ -460,15 +460,15 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render table as plain text
|
/// Render table as plain text
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
//#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn render_text(&self, opts: &STVOptions) -> String {
|
pub fn render_text(&self, opts: &STVOptions) -> String {
|
||||||
return self.render(opts).to_string();
|
return self.render(opts).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render table as HTML
|
// Render table as HTML
|
||||||
pub fn render_html(&self, opts: &STVOptions) -> String {
|
//pub fn render_html(&self, opts: &STVOptions) -> String {
|
||||||
return self.render(opts).to_string();
|
// return self.render(opts).to_string();
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Column in a [TransferTable]
|
/// Column in a [TransferTable]
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub struct STVOptions {
|
||||||
pub sum_surplus_transfers: SumSurplusTransfersMode,
|
pub sum_surplus_transfers: SumSurplusTransfersMode,
|
||||||
|
|
||||||
/// (Meek STV) Limit for stopping iteration of surplus distribution
|
/// (Meek STV) Limit for stopping iteration of surplus distribution
|
||||||
#[builder(default)]
|
#[builder(default=r#"String::from("0.001%")"#)]
|
||||||
pub meek_surplus_tolerance: String,
|
pub meek_surplus_tolerance: String,
|
||||||
|
|
||||||
/// Convert ballots with value >1 to multiple ballots of value 1 (used only for [STVOptions::describe])
|
/// Convert ballots with value >1 to multiple ballots of value 1 (used only for [STVOptions::describe])
|
||||||
|
@ -88,7 +88,7 @@ pub struct STVOptions {
|
||||||
pub quota_mode: QuotaMode,
|
pub quota_mode: QuotaMode,
|
||||||
|
|
||||||
/// Tie-breaking method
|
/// Tie-breaking method
|
||||||
#[builder(default)]
|
#[builder(default="vec![TieStrategy::Prompt]")]
|
||||||
pub ties: Vec<TieStrategy>,
|
pub ties: Vec<TieStrategy>,
|
||||||
|
|
||||||
/// Method of surplus distributions
|
/// Method of surplus distributions
|
||||||
|
@ -180,12 +180,12 @@ impl STVOptions {
|
||||||
if self.normalise_ballots { flags.push("--normalise-ballots".to_string()); }
|
if self.normalise_ballots { flags.push("--normalise-ballots".to_string()); }
|
||||||
if self.quota != QuotaType::Droop { flags.push(self.quota.describe()); }
|
if self.quota != QuotaType::Droop { flags.push(self.quota.describe()); }
|
||||||
if self.quota_criterion != QuotaCriterion::Greater { flags.push(self.quota_criterion.describe()); }
|
if self.quota_criterion != QuotaCriterion::Greater { flags.push(self.quota_criterion.describe()); }
|
||||||
if self.surplus != SurplusMethod::Meek && self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); }
|
if self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); }
|
||||||
let ties_str = self.ties.iter().map(|t| t.describe()).join(" ");
|
let ties_str = self.ties.iter().map(|t| t.describe()).join(" ");
|
||||||
if ties_str != "prompt" { flags.push(format!("--ties {}", ties_str)); }
|
if ties_str != "prompt" { flags.push(format!("--ties {}", ties_str)); }
|
||||||
for t in self.ties.iter() { if let TieStrategy::Random(seed) = t { flags.push(format!("--random-seed {}", seed)); } }
|
for t in self.ties.iter() { if let TieStrategy::Random(seed) = t { flags.push(format!("--random-seed {}", seed)); } }
|
||||||
if self.surplus != SurplusMethod::WIG { flags.push(self.surplus.describe()); }
|
if self.surplus != SurplusMethod::WIG { flags.push(self.surplus.describe()); }
|
||||||
if self.surplus == SurplusMethod::WIG || self.surplus == SurplusMethod::UIG || self.surplus == SurplusMethod::EG {
|
if self.surplus != SurplusMethod::Meek {
|
||||||
if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); }
|
if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); }
|
||||||
if self.transferable_only { flags.push("--transferable-only".to_string()); }
|
if self.transferable_only { flags.push("--transferable-only".to_string()); }
|
||||||
if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); }
|
if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); }
|
||||||
|
|
|
@ -177,7 +177,7 @@ macro_rules! impl_type {
|
||||||
/// Call [render_html](crate::stv::transfers::TransferTable::render_html) on [CountState::transfer_table]
|
/// Call [render_html](crate::stv::transfers::TransferTable::render_html) on [CountState::transfer_table]
|
||||||
pub fn transfer_table_render_html(&self, opts: &STVOptions) -> Option<String> {
|
pub fn transfer_table_render_html(&self, opts: &STVOptions) -> Option<String> {
|
||||||
return match &self.0.transfer_table {
|
return match &self.0.transfer_table {
|
||||||
Some(tt) => Some(tt.render_html(&opts.0)), // TODO
|
Some(tt) => Some(tt.render_text(&opts.0)), // TODO
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,5 +33,7 @@ fn act_kurrajong20_rational() {
|
||||||
.early_bulk_elect(false)
|
.early_bulk_elect(false)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 6 --round-quota 0 --quota-criterion geq --surplus eg --surplus-order by_order --transferable-only --exclusion by_value --no-early-bulk-elect");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/ACT2020Kurrajong.csv", "tests/data/ACT2020Kurrajong.blt", stv_opts, Some(6), &["exhausted", "lbf"]);
|
utils::read_validate_election::<Rational>("tests/data/ACT2020Kurrajong.csv", "tests/data/ACT2020Kurrajong.blt", stv_opts, Some(6), &["exhausted", "lbf"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,5 +70,7 @@ fn aec_tas19_rational() {
|
||||||
.bulk_exclude(true)
|
.bulk_exclude(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --quota-criterion geq --surplus uig --surplus-order by_order --exclusion by_value --bulk-exclude");
|
||||||
|
|
||||||
utils::validate_election::<Rational>(stages, records, election, stv_opts, None, &["exhausted", "lbf"]);
|
utils::validate_election::<Rational>(stages, records, election, stv_opts, None, &["exhausted", "lbf"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,5 +34,7 @@ fn cambridge_cc03_rational() {
|
||||||
.min_threshold("49".to_string())
|
.min_threshold("49".to_string())
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-quota 0 --normalise-ballots --quota-criterion geq --surplus cincinnati --transferable-only --sample nth_ballot --sample-per-ballot --no-early-bulk-elect --min-threshold 49");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/CambCC2003.csv", "tests/data/CambCC2003.blt", stv_opts, None, &["exhausted"]);
|
utils::read_validate_election::<Rational>("tests/data/CambCC2003.csv", "tests/data/CambCC2003.blt", stv_opts, None, &["exhausted"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,14 @@ use assert_cmd::Command;
|
||||||
use predicates::prelude::*;
|
use predicates::prelude::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cli_ers97old() {
|
fn cli_ers97old_fixed5() {
|
||||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||||
.args(&["stv", "tests/data/ers97old.blt", "--numbers", "fixed", "--decimals", "5", "--round-tvs", "2", "--round-weights", "2", "--round-votes", "2", "--round-quota", "2", "--quota", "droop_exact", "--quota-mode", "ers97", "--surplus", "eg", "--transferable-only", "--exclusion", "by_value"])
|
.args(&["stv", "tests/data/ers97old.blt", "--numbers", "fixed", "--decimals", "5", "--round-tvs", "2", "--round-weights", "2", "--round-votes", "2", "--round-quota", "2", "--quota", "droop_exact", "--quota-mode", "ers97", "--surplus", "eg", "--transferable-only", "--exclusion", "by_value"])
|
||||||
.assert().success();
|
.assert().success();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cli_ers97_transfers_detail() {
|
fn cli_ers97_fixed5_transfers_detail() {
|
||||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
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"])
|
.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();
|
.assert().success();
|
||||||
|
|
|
@ -35,5 +35,7 @@ fn ers97_coe_rational() {
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 2 --sum-surplus-transfers per_ballot --quota-criterion geq --surplus eg --transferable-only --exclusion by_value --defer-surpluses");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/ers97_coe.csv", "tests/data/ers97.blt", stv_opts, None, &["nt"]);
|
utils::read_validate_election::<Rational>("tests/data/ers97_coe.csv", "tests/data/ers97.blt", stv_opts, None, &["nt"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,5 +30,7 @@ fn csm15_float64() {
|
||||||
.bulk_exclude(true)
|
.bulk_exclude(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --round-quota 0 --quota-criterion geq --exclusion wright --no-early-bulk-elect --bulk-exclude");
|
||||||
|
|
||||||
utils::read_validate_election::<NativeFloat64>("tests/data/CSM15.csv", "tests/data/CSM15.blt", stv_opts, Some(6), &["quota"]);
|
utils::read_validate_election::<NativeFloat64>("tests/data/CSM15.csv", "tests/data/CSM15.blt", stv_opts, Some(6), &["quota"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
|
||||||
use opentally::numbers::Rational;
|
use opentally::numbers::{Fixed, GuardedFixed, NativeFloat64, Rational};
|
||||||
use opentally::stv;
|
use opentally::stv;
|
||||||
|
|
||||||
use assert_cmd::Command;
|
use assert_cmd::Command;
|
||||||
|
@ -42,6 +42,8 @@ fn ers97old_rational() {
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/ers97old.csv", "tests/data/ers97old.blt", stv_opts, None, &["nt", "vre"]);
|
utils::read_validate_election::<Rational>("tests/data/ers97old.csv", "tests/data/ers97old.blt", stv_opts, None, &["nt", "vre"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +65,84 @@ fn ers97_rational() {
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
utils::read_validate_election::<Rational>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ers97_fixed9() {
|
||||||
|
let stv_opts = stv::STVOptionsBuilder::default()
|
||||||
|
.round_surplus_fractions(Some(2))
|
||||||
|
.round_values(Some(2))
|
||||||
|
.round_votes(Some(2))
|
||||||
|
.round_quota(Some(2))
|
||||||
|
.quota(stv::QuotaType::DroopExact)
|
||||||
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
|
.quota_mode(stv::QuotaMode::ERS97)
|
||||||
|
.surplus(stv::SurplusMethod::EG)
|
||||||
|
.transferable_only(true)
|
||||||
|
.exclusion(stv::ExclusionMethod::ByValue)
|
||||||
|
.early_bulk_elect(false)
|
||||||
|
.bulk_exclude(true)
|
||||||
|
.defer_surpluses(true)
|
||||||
|
.build().unwrap();
|
||||||
|
|
||||||
|
Fixed::set_dps(9);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 9 --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
|
utils::read_validate_election::<Fixed>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ers97_gfixed5() {
|
||||||
|
let stv_opts = stv::STVOptionsBuilder::default()
|
||||||
|
.round_surplus_fractions(Some(2))
|
||||||
|
.round_values(Some(2))
|
||||||
|
.round_votes(Some(2))
|
||||||
|
.round_quota(Some(2))
|
||||||
|
.quota(stv::QuotaType::DroopExact)
|
||||||
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
|
.quota_mode(stv::QuotaMode::ERS97)
|
||||||
|
.surplus(stv::SurplusMethod::EG)
|
||||||
|
.transferable_only(true)
|
||||||
|
.exclusion(stv::ExclusionMethod::ByValue)
|
||||||
|
.early_bulk_elect(false)
|
||||||
|
.bulk_exclude(true)
|
||||||
|
.defer_surpluses(true)
|
||||||
|
.build().unwrap();
|
||||||
|
|
||||||
|
GuardedFixed::set_dps(5);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<GuardedFixed>(), "--numbers gfixed --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
|
utils::read_validate_election::<GuardedFixed>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ers97_float64() {
|
||||||
|
let stv_opts = stv::STVOptionsBuilder::default()
|
||||||
|
.round_surplus_fractions(Some(2))
|
||||||
|
.round_values(Some(2))
|
||||||
|
.round_votes(Some(2))
|
||||||
|
.round_quota(Some(2))
|
||||||
|
.quota(stv::QuotaType::DroopExact)
|
||||||
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
|
.quota_mode(stv::QuotaMode::ERS97)
|
||||||
|
.surplus(stv::SurplusMethod::EG)
|
||||||
|
.transferable_only(true)
|
||||||
|
.exclusion(stv::ExclusionMethod::ByValue)
|
||||||
|
.early_bulk_elect(false)
|
||||||
|
.bulk_exclude(true)
|
||||||
|
.defer_surpluses(true)
|
||||||
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
|
utils::read_validate_election::<NativeFloat64>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, Some(2), &["nt", "vre"]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ers97_rational_csv() {
|
fn ers97_rational_csv() {
|
||||||
let cmd = Command::cargo_bin("opentally").expect("Cargo Error")
|
let cmd = Command::cargo_bin("opentally").expect("Cargo Error")
|
||||||
|
@ -98,5 +175,7 @@ fn ers76_rational() {
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 0 --quota droop_exact --quota-criterion geq --quota-mode ers76 --surplus eg --transferable-only --exclusion by_value --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/ers76.csv", "tests/data/ers76.blt", stv_opts, None, &["nt", "vre"]);
|
utils::read_validate_election::<Rational>("tests/data/ers76.csv", "tests/data/ers76.blt", stv_opts, None, &["nt", "vre"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ use opentally::stv;
|
||||||
#[test]
|
#[test]
|
||||||
fn meek87_ers97old_float64() {
|
fn meek87_ers97old_float64() {
|
||||||
let stv_opts = stv::STVOptionsBuilder::default()
|
let stv_opts = stv::STVOptionsBuilder::default()
|
||||||
.meek_surplus_tolerance("0.001%".to_string())
|
//.meek_surplus_tolerance("0.001%".to_string())
|
||||||
.quota(stv::QuotaType::DroopExact)
|
.quota(stv::QuotaType::DroopExact)
|
||||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
.quota_mode(stv::QuotaMode::DynamicByTotal)
|
.quota_mode(stv::QuotaMode::DynamicByTotal)
|
||||||
|
@ -34,6 +34,8 @@ fn meek87_ers97old_float64() {
|
||||||
.immediate_elect(false)
|
.immediate_elect(false)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --quota droop_exact --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --no-immediate-elect");
|
||||||
|
|
||||||
utils::read_validate_election::<NativeFloat64>("tests/data/ers97old_meek.csv", "tests/data/ers97old.blt", stv_opts, Some(2), &["exhausted", "quota"]);
|
utils::read_validate_election::<NativeFloat64>("tests/data/ers97old_meek.csv", "tests/data/ers97old.blt", stv_opts, Some(2), &["exhausted", "quota"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +56,8 @@ fn meek06_ers97old_fixed12() {
|
||||||
|
|
||||||
Fixed::set_dps(12);
|
Fixed::set_dps(12);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 12 --round-surplus-fractions 9 --round-values 9 --round-votes 9 --round-quota 9 --meek-surplus-tolerance 0.0001 --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --defer-surpluses");
|
||||||
|
|
||||||
// Read BLT
|
// Read BLT
|
||||||
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
||||||
|
|
||||||
|
@ -114,6 +118,8 @@ fn meeknz_ers97old_fixed12() {
|
||||||
|
|
||||||
Fixed::set_dps(12);
|
Fixed::set_dps(12);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 12 --round-surplus-fractions 9 --round-values 9 --round-votes 9 --round-quota 9 --meek-surplus-tolerance 0.0001 --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --meek-nz-exclusion --defer-surpluses");
|
||||||
|
|
||||||
// Read BLT
|
// Read BLT
|
||||||
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,14 @@ fn minneapolis_boe09_rational() {
|
||||||
.round_surplus_fractions(Some(4))
|
.round_surplus_fractions(Some(4))
|
||||||
.round_quota(Some(0))
|
.round_quota(Some(0))
|
||||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
.early_bulk_elect(true)
|
//.early_bulk_elect(true)
|
||||||
.bulk_exclude(true)
|
.bulk_exclude(true)
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.immediate_elect(false)
|
.immediate_elect(false)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 4 --round-quota 0 --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/Mppls-2009-BOE-full.csv", "tests/data/Mppls-2009-BOE-full.blt", stv_opts, Some(4), &[]);
|
utils::read_validate_election::<Rational>("tests/data/Mppls-2009-BOE-full.csv", "tests/data/Mppls-2009-BOE-full.blt", stv_opts, Some(4), &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +43,13 @@ fn minneapolis_pal13_rational() {
|
||||||
.round_surplus_fractions(Some(4))
|
.round_surplus_fractions(Some(4))
|
||||||
.round_quota(Some(0))
|
.round_quota(Some(0))
|
||||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
.early_bulk_elect(true)
|
//.early_bulk_elect(true)
|
||||||
.bulk_exclude(true)
|
.bulk_exclude(true)
|
||||||
.defer_surpluses(true)
|
.defer_surpluses(true)
|
||||||
.immediate_elect(false)
|
.immediate_elect(false)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 4 --round-quota 0 --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/2013-Park-At-Large-CVR.csv", "tests/data/2013-Park-At-Large-CVR.blt", stv_opts, Some(4), &[]);
|
utils::read_validate_election::<Rational>("tests/data/2013-Park-At-Large-CVR.csv", "tests/data/2013-Park-At-Large-CVR.blt", stv_opts, Some(4), &[]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,7 @@ fn prsa1_rational() {
|
||||||
.early_bulk_elect(false)
|
.early_bulk_elect(false)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 3 --round-values 3 --round-votes 3 --round-quota 3 --quota-criterion geq --surplus eg --surplus-order by_order --transferable-only --exclusion parcels_by_order --no-early-bulk-elect");
|
||||||
|
|
||||||
utils::read_validate_election::<Rational>("tests/data/prsa1.csv", "tests/data/prsa1.blt", stv_opts, None, &["exhausted", "lbf"]);
|
utils::read_validate_election::<Rational>("tests/data/prsa1.csv", "tests/data/prsa1.blt", stv_opts, None, &["exhausted", "lbf"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,15 @@ fn scotland_linn07_fixed5() {
|
||||||
//.round_votes(Some(5))
|
//.round_votes(Some(5))
|
||||||
.round_quota(Some(0))
|
.round_quota(Some(0))
|
||||||
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
||||||
//.normalise_ballots(true)
|
|
||||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
.early_bulk_elect(false)
|
.early_bulk_elect(false)
|
||||||
.pp_decimals(5)
|
.pp_decimals(5)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
Fixed::set_dps(5);
|
Fixed::set_dps(5);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 5 --round-surplus-fractions 5 --round-quota 0 --sum-surplus-transfers per_ballot --quota-criterion geq --no-early-bulk-elect --pp-decimals 5");
|
||||||
|
|
||||||
scotland_linn07::<Fixed>(stv_opts);
|
scotland_linn07::<Fixed>(stv_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,13 +53,15 @@ fn scotland_linn07_gfixed5() {
|
||||||
.round_votes(Some(5))
|
.round_votes(Some(5))
|
||||||
.round_quota(Some(0))
|
.round_quota(Some(0))
|
||||||
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
||||||
//.normalise_ballots(true)
|
|
||||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
.early_bulk_elect(false)
|
.early_bulk_elect(false)
|
||||||
.pp_decimals(5)
|
.pp_decimals(5)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
GuardedFixed::set_dps(5);
|
GuardedFixed::set_dps(5);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<GuardedFixed>(), "--numbers gfixed --decimals 5 --round-surplus-fractions 5 --round-values 5 --round-votes 5 --round-quota 0 --sum-surplus-transfers per_ballot --quota-criterion geq --no-early-bulk-elect --pp-decimals 5");
|
||||||
|
|
||||||
scotland_linn07::<GuardedFixed>(stv_opts);
|
scotland_linn07::<GuardedFixed>(stv_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue