Implement dynamic dispatch for different number types
This commit is contained in:
parent
c070ec8eae
commit
dde79520a1
@ -12,16 +12,18 @@ var numbers, election, opts, state, stageNum;
|
|||||||
|
|
||||||
onmessage = function(evt) {
|
onmessage = function(evt) {
|
||||||
if (evt.data.type === 'countElection') {
|
if (evt.data.type === 'countElection') {
|
||||||
|
numbers = 'DynNum';
|
||||||
|
|
||||||
if (evt.data.numbers === 'fixed') {
|
if (evt.data.numbers === 'fixed') {
|
||||||
numbers = 'Fixed';
|
wasm.dynnum_set_kind(wasm.NumKind.Fixed);
|
||||||
wasm.fixed_set_dps(evt.data.decimals);
|
wasm.fixed_set_dps(evt.data.decimals);
|
||||||
} else if (evt.data.numbers === 'gfixed') {
|
} else if (evt.data.numbers === 'gfixed') {
|
||||||
numbers = 'GuardedFixed';
|
wasm.dynnum_set_kind(wasm.NumKind.GuardedFixed);
|
||||||
wasm.gfixed_set_dps(evt.data.decimals);
|
wasm.gfixed_set_dps(evt.data.decimals);
|
||||||
} else if (evt.data.numbers === 'float64') {
|
} else if (evt.data.numbers === 'float64') {
|
||||||
numbers = 'NativeFloat64';
|
wasm.dynnum_set_kind(wasm.NumKind.NativeFloat64);
|
||||||
} else if (evt.data.numbers === 'rational') {
|
} else if (evt.data.numbers === 'rational') {
|
||||||
numbers = 'Rational';
|
wasm.dynnum_set_kind(wasm.NumKind.Rational);
|
||||||
} else {
|
} else {
|
||||||
throw 'Unknown --numbers';
|
throw 'Unknown --numbers';
|
||||||
}
|
}
|
||||||
|
30
src/main.rs
30
src/main.rs
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
use opentally::constraints::Constraints;
|
use opentally::constraints::Constraints;
|
||||||
use opentally::election::{Candidate, CandidateState, CountCard, CountState, Election};
|
use opentally::election::{Candidate, CandidateState, CountCard, CountState, Election};
|
||||||
use opentally::numbers::{Fixed, GuardedFixed, NativeFloat64, Number, Rational};
|
use opentally::numbers::{DynNum, Fixed, GuardedFixed, NativeFloat64, Number, NumKind, Rational};
|
||||||
use opentally::stv;
|
use opentally::stv;
|
||||||
|
|
||||||
use clap::{AppSettings, Clap};
|
use clap::{AppSettings, Clap};
|
||||||
@ -61,6 +61,10 @@ struct STV {
|
|||||||
#[clap(help_heading=Some("NUMBERS"), long, default_value="5", value_name="dps")]
|
#[clap(help_heading=Some("NUMBERS"), long, default_value="5", value_name="dps")]
|
||||||
decimals: usize,
|
decimals: usize,
|
||||||
|
|
||||||
|
/// Use dynamic dispatch for numbers
|
||||||
|
//#[clap(help_heading=Some("NUMBERS"), long)]
|
||||||
|
//dynnum: bool,
|
||||||
|
|
||||||
/// Convert ballots with value >1 to multiple ballots of value 1
|
/// Convert ballots with value >1 to multiple ballots of value 1
|
||||||
#[clap(help_heading=Some("NUMBERS"), long)]
|
#[clap(help_heading=Some("NUMBERS"), long)]
|
||||||
normalise_ballots: bool,
|
normalise_ballots: bool,
|
||||||
@ -195,27 +199,21 @@ fn main() {
|
|||||||
|
|
||||||
// Create and count election according to --numbers
|
// Create and count election according to --numbers
|
||||||
if cmd_opts.numbers == "rational" {
|
if cmd_opts.numbers == "rational" {
|
||||||
let mut election: Election<Rational> = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter());
|
DynNum::set_kind(NumKind::Rational);
|
||||||
maybe_load_constraints(&mut election, &cmd_opts.constraints);
|
|
||||||
|
|
||||||
// Must specify ::<N> here and in a few other places because ndarray causes E0275 otherwise
|
|
||||||
count_election::<Rational>(election, cmd_opts);
|
|
||||||
} else if cmd_opts.numbers == "float64" {
|
} else if cmd_opts.numbers == "float64" {
|
||||||
let mut election: Election<NativeFloat64> = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter());
|
DynNum::set_kind(NumKind::NativeFloat64);
|
||||||
maybe_load_constraints(&mut election, &cmd_opts.constraints);
|
|
||||||
count_election::<NativeFloat64>(election, cmd_opts);
|
|
||||||
} else if cmd_opts.numbers == "fixed" {
|
} else if cmd_opts.numbers == "fixed" {
|
||||||
Fixed::set_dps(cmd_opts.decimals);
|
Fixed::set_dps(cmd_opts.decimals);
|
||||||
let mut election: Election<Fixed> = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter());
|
DynNum::set_kind(NumKind::Fixed);
|
||||||
maybe_load_constraints(&mut election, &cmd_opts.constraints);
|
|
||||||
count_election::<Fixed>(election, cmd_opts);
|
|
||||||
} else if cmd_opts.numbers == "gfixed" {
|
} else if cmd_opts.numbers == "gfixed" {
|
||||||
GuardedFixed::set_dps(cmd_opts.decimals);
|
GuardedFixed::set_dps(cmd_opts.decimals);
|
||||||
|
DynNum::set_kind(NumKind::GuardedFixed);
|
||||||
let mut election: Election<GuardedFixed> = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter());
|
|
||||||
maybe_load_constraints(&mut election, &cmd_opts.constraints);
|
|
||||||
count_election::<GuardedFixed>(election, cmd_opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut election: Election<DynNum> = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter());
|
||||||
|
maybe_load_constraints(&mut election, &cmd_opts.constraints);
|
||||||
|
|
||||||
|
count_election::<DynNum>(election, cmd_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_load_constraints<N: Number>(election: &mut Election<N>, constraints: &Option<String>) {
|
fn maybe_load_constraints<N: Number>(election: &mut Election<N>, constraints: &Option<String>) {
|
||||||
|
503
src/numbers/dynnum.rs
Normal file
503
src/numbers/dynnum.rs
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
/* OpenTally: Open-source election vote counting
|
||||||
|
* Copyright © 2021 Lee Yingtong Li (RunasSudo)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::{Assign, Fixed, GuardedFixed, NativeFloat64, Number, Rational};
|
||||||
|
|
||||||
|
use num_traits::{Num, One, Zero};
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
|
use std::cmp::{Ord, Ordering};
|
||||||
|
use std::fmt;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::ops::{self, Deref, DerefMut};
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub enum NumKind {
|
||||||
|
Fixed,
|
||||||
|
GuardedFixed,
|
||||||
|
NativeFloat64,
|
||||||
|
Rational,
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut KIND: NumKind = NumKind::Fixed;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_kind() -> &'static NumKind {
|
||||||
|
unsafe {
|
||||||
|
return &KIND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub union DynNum {
|
||||||
|
fixed: ManuallyDrop<Fixed>,
|
||||||
|
gfixed: ManuallyDrop<GuardedFixed>,
|
||||||
|
float64: NativeFloat64,
|
||||||
|
rational: ManuallyDrop<Rational>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynNum {
|
||||||
|
pub fn set_kind(kind: NumKind) {
|
||||||
|
unsafe {
|
||||||
|
KIND = kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_1arg_nowrap {
|
||||||
|
($self:expr, $arg:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
$self.fixed.$func($arg)
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
$self.gfixed.$func($arg)
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
$self.float64.$func($arg)
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
$self.rational.$func($arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_assoc_nowrap {
|
||||||
|
($func:ident) => {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
Fixed::$func()
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
GuardedFixed::$func()
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
NativeFloat64::$func()
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
Rational::$func()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Number for DynNum {
|
||||||
|
fn new() -> Self {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
DynNum { fixed: ManuallyDrop::new(Fixed::new()) }
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
DynNum { gfixed: ManuallyDrop::new(GuardedFixed::new()) }
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
DynNum { float64: NativeFloat64::new() }
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
DynNum { rational: ManuallyDrop::new(Rational::new()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn describe() -> String { impl_assoc_nowrap!(describe) }
|
||||||
|
fn pow_assign(&mut self, exponent: i32) { impl_1arg_nowrap!(self, exponent, pow_assign) }
|
||||||
|
fn floor_mut(&mut self, dps: usize) { impl_1arg_nowrap!(self, dps, floor_mut) }
|
||||||
|
fn ceil_mut(&mut self, dps: usize) { impl_1arg_nowrap!(self, dps, ceil_mut) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DynNum {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
ManuallyDrop::drop(&mut self.fixed);
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
ManuallyDrop::drop(&mut self.gfixed);
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {}
|
||||||
|
NumKind::Rational => {
|
||||||
|
ManuallyDrop::drop(&mut self.rational);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_0arg_wrap {
|
||||||
|
($self:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
DynNum { fixed: ManuallyDrop::new($self.fixed.deref().$func()) }
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
DynNum { gfixed: ManuallyDrop::new($self.gfixed.deref().$func()) }
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
DynNum { float64: $self.float64.$func() }
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
DynNum { rational: ManuallyDrop::new($self.rational.deref().$func()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for DynNum {
|
||||||
|
fn clone(&self) -> Self { impl_0arg_wrap!(self, clone) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Num for DynNum {
|
||||||
|
type FromStrRadixErr = Self; // TODO
|
||||||
|
|
||||||
|
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
Ok(DynNum { fixed: ManuallyDrop::new(Fixed::from_str_radix(str, radix).unwrap()) })
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
Ok(DynNum { gfixed: ManuallyDrop::new(GuardedFixed::from_str_radix(str, radix).unwrap()) })
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
Ok(DynNum { float64: NativeFloat64::from_str_radix(str, radix).unwrap() })
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
Ok(DynNum { rational: ManuallyDrop::new(Rational::from_str_radix(str, radix).unwrap()) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_1other_nowrap {
|
||||||
|
($self:expr, $rhs:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
$self.fixed.deref().$func($rhs.fixed.deref())
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
$self.gfixed.deref().$func($rhs.gfixed.deref())
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
$self.float64.$func(&$rhs.float64)
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
$self.rational.deref().$func($rhs.rational.deref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_1other_nowrap_mut {
|
||||||
|
($self:expr, $rhs:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
$self.fixed.deref_mut().$func($rhs.fixed.deref())
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
$self.gfixed.deref_mut().$func($rhs.gfixed.deref())
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
$self.float64.$func(&$rhs.float64)
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
$self.rational.deref_mut().$func($rhs.rational.deref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Assign for DynNum {
|
||||||
|
fn assign(&mut self, src: Self) { impl_1other_nowrap_mut!(self, src, assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Assign<&Self> for DynNum {
|
||||||
|
fn assign(&mut self, src: &Self) { impl_1other_nowrap_mut!(self, src, assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<usize> for DynNum {
|
||||||
|
fn from(n: usize) -> Self {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
DynNum { fixed: ManuallyDrop::new(Fixed::from(n)) }
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
DynNum { gfixed: ManuallyDrop::new(GuardedFixed::from(n)) }
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
DynNum { float64: NativeFloat64::from(n) }
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
DynNum { rational: ManuallyDrop::new(Rational::from(n)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DynNum {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl_1arg_nowrap!(self, f, fmt) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for DynNum {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl_1arg_nowrap!(self, f, fmt) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DynNum {
|
||||||
|
fn eq(&self, other: &Self) -> bool { impl_1other_nowrap!(self, other, eq) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for DynNum {}
|
||||||
|
|
||||||
|
impl PartialOrd for DynNum {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { impl_1other_nowrap!(self, other, partial_cmp) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for DynNum {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering { impl_1other_nowrap!(self, other, cmp) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_assoc_wrap {
|
||||||
|
($func:ident) => {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
DynNum { fixed: ManuallyDrop::new(Fixed::$func()) }
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
DynNum { gfixed: ManuallyDrop::new(GuardedFixed::$func()) }
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
DynNum { float64: NativeFloat64::$func() }
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
DynNum { rational: ManuallyDrop::new(Rational::$func()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl One for DynNum {
|
||||||
|
fn one() -> Self { impl_assoc_wrap!(one) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_0arg_nowrap {
|
||||||
|
($self:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
$self.fixed.deref().$func()
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
$self.gfixed.deref().$func()
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
$self.float64.$func()
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
$self.rational.deref().$func()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Zero for DynNum {
|
||||||
|
fn zero() -> Self { impl_assoc_wrap!(zero) }
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool { impl_0arg_nowrap!(self, is_zero) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Neg for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn neg(self) -> Self::Output { impl_0arg_wrap!(self, neg) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_1other_wrap {
|
||||||
|
($self:expr, $rhs:expr, $func:ident) => {
|
||||||
|
// Safety: Access only correct union field
|
||||||
|
unsafe {
|
||||||
|
match get_kind() {
|
||||||
|
NumKind::Fixed => {
|
||||||
|
DynNum { fixed: ManuallyDrop::new($self.fixed.deref().$func($rhs.fixed.deref())) }
|
||||||
|
}
|
||||||
|
NumKind::GuardedFixed => {
|
||||||
|
DynNum { gfixed: ManuallyDrop::new($self.gfixed.deref().$func($rhs.gfixed.deref())) }
|
||||||
|
}
|
||||||
|
NumKind::NativeFloat64 => {
|
||||||
|
DynNum { float64: $self.float64.$func($rhs.float64) }
|
||||||
|
}
|
||||||
|
NumKind::Rational => {
|
||||||
|
DynNum { rational: ManuallyDrop::new($self.rational.deref().$func($rhs.rational.deref())) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, add) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Sub for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, sub) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, mul) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Div for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn div(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, div) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Rem for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn rem(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, rem) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add<&Self> for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: &Self) -> Self::Output { impl_1other_wrap!(self, rhs, add) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Sub<&Self> for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, rhs: &Self) -> Self::Output { impl_1other_wrap!(self, rhs, sub) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<&Self> for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn mul(self, rhs: &Self) -> Self::Output { impl_1other_wrap!(self, rhs, mul) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Div<&Self> for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn div(self, rhs: &Self) -> Self::Output { impl_1other_wrap!(self, rhs, div) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Rem<&Self> for DynNum {
|
||||||
|
type Output = Self;
|
||||||
|
fn rem(self, rhs: &Self) -> Self::Output { impl_1other_wrap!(self, rhs, rem) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::AddAssign for DynNum {
|
||||||
|
fn add_assign(&mut self, rhs: Self) { impl_1other_nowrap_mut!(self, rhs, add_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::SubAssign for DynNum {
|
||||||
|
fn sub_assign(&mut self, rhs: Self) { impl_1other_nowrap_mut!(self, rhs, sub_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::MulAssign for DynNum {
|
||||||
|
fn mul_assign(&mut self, rhs: Self) { impl_1other_nowrap_mut!(self, rhs, mul_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::DivAssign for DynNum {
|
||||||
|
fn div_assign(&mut self, rhs: Self) { impl_1other_nowrap_mut!(self, rhs, div_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::RemAssign for DynNum {
|
||||||
|
fn rem_assign(&mut self, rhs: Self) { impl_1other_nowrap_mut!(self, rhs, rem_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::AddAssign<&Self> for DynNum {
|
||||||
|
fn add_assign(&mut self, rhs: &Self) { impl_1other_nowrap_mut!(self, rhs, add_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::SubAssign<&Self> for DynNum {
|
||||||
|
fn sub_assign(&mut self, rhs: &Self) { impl_1other_nowrap_mut!(self, rhs, sub_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::MulAssign<&Self> for DynNum {
|
||||||
|
fn mul_assign(&mut self, rhs: &Self) { impl_1other_nowrap_mut!(self, rhs, mul_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::DivAssign<&Self> for DynNum {
|
||||||
|
fn div_assign(&mut self, rhs: &Self) { impl_1other_nowrap_mut!(self, rhs, div_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::RemAssign<&Self> for DynNum {
|
||||||
|
fn rem_assign(&mut self, rhs: &Self) { impl_1other_nowrap_mut!(self, rhs, rem_assign) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Neg for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn neg(self) -> Self::Output { impl_0arg_wrap!(self, neg) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add<Self> for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, add) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Sub<Self> for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, sub) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<Self> for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, mul) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Div<Self> for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn div(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, div) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Rem<Self> for &DynNum {
|
||||||
|
type Output = DynNum;
|
||||||
|
fn rem(self, rhs: Self) -> Self::Output { impl_1other_wrap!(self, rhs, rem) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl ops::Add<&&Rational> for &Rational {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Sub<&&Rational> for &Rational {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<&&Rational> for &Rational {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Div<&&Rational> for &Rational {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Rem<&&Rational> for &Rational {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
@ -281,8 +281,9 @@ impl ops::MulAssign<&Self> for Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&Self> for Fixed {
|
impl ops::DivAssign<&Self> for Fixed {
|
||||||
fn div_assign(&mut self, _rhs: &Self) {
|
fn div_assign(&mut self, rhs: &Self) {
|
||||||
todo!()
|
self.0 *= get_factor();
|
||||||
|
self.0 /= &rhs.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ impl Num for GuardedFixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for GuardedFixed {
|
impl PartialEq for GuardedFixed {
|
||||||
fn eq(&self, other: &GuardedFixed) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
if &(&self.0 - &other.0).abs() < get_factor_cmp() {
|
if &(&self.0 - &other.0).abs() < get_factor_cmp() {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -132,13 +132,13 @@ impl PartialEq for GuardedFixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for GuardedFixed {
|
impl PartialOrd for GuardedFixed {
|
||||||
fn partial_cmp(&self, other: &GuardedFixed) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
return Some(self.cmp(other));
|
return Some(self.cmp(other));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for GuardedFixed {
|
impl Ord for GuardedFixed {
|
||||||
fn cmp(&self, other: &GuardedFixed) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
if self.eq(other) {
|
if self.eq(other) {
|
||||||
return Ordering::Equal;
|
return Ordering::Equal;
|
||||||
} else {
|
} else {
|
||||||
@ -313,8 +313,9 @@ impl ops::MulAssign<&Self> for GuardedFixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&Self> for GuardedFixed {
|
impl ops::DivAssign<&Self> for GuardedFixed {
|
||||||
fn div_assign(&mut self, _rhs: &Self) {
|
fn div_assign(&mut self, rhs: &Self) {
|
||||||
todo!()
|
self.0 *= get_factor();
|
||||||
|
self.0 /= &rhs.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ mod rational_rug;
|
|||||||
//#[cfg(target_arch = "wasm32")]
|
//#[cfg(target_arch = "wasm32")]
|
||||||
mod rational_num;
|
mod rational_num;
|
||||||
|
|
||||||
|
//#[cfg(target_arch = "wasm32")]
|
||||||
|
mod dynnum;
|
||||||
|
|
||||||
use num_traits::{NumAssignRef, NumRef};
|
use num_traits::{NumAssignRef, NumRef};
|
||||||
|
|
||||||
use std::cmp::Ord;
|
use std::cmp::Ord;
|
||||||
@ -74,6 +77,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use self::dynnum::NumKind;
|
||||||
|
pub use self::dynnum::DynNum;
|
||||||
|
|
||||||
pub use self::fixed::Fixed;
|
pub use self::fixed::Fixed;
|
||||||
pub use self::gfixed::GuardedFixed;
|
pub use self::gfixed::GuardedFixed;
|
||||||
pub use self::native::NativeFloat64;
|
pub use self::native::NativeFloat64;
|
||||||
|
@ -26,7 +26,7 @@ use std::ops;
|
|||||||
type ImplType = f64;
|
type ImplType = f64;
|
||||||
|
|
||||||
/// Native 64-bit floating-point number
|
/// Native 64-bit floating-point number
|
||||||
#[derive(Clone, Debug, Display, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Display, PartialEq, PartialOrd)]
|
||||||
pub struct NativeFloat64(ImplType);
|
pub struct NativeFloat64(ImplType);
|
||||||
|
|
||||||
impl Number for NativeFloat64 {
|
impl Number for NativeFloat64 {
|
||||||
@ -183,9 +183,7 @@ impl ops::MulAssign<&NativeFloat64> for NativeFloat64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::DivAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
fn div_assign(&mut self, _rhs: &NativeFloat64) {
|
fn div_assign(&mut self, rhs: &NativeFloat64) { self.0 /= &rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
||||||
|
@ -251,9 +251,7 @@ impl ops::MulAssign<&Rational> for Rational {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&Rational> for Rational {
|
impl ops::DivAssign<&Rational> for Rational {
|
||||||
fn div_assign(&mut self, _rhs: &Rational) {
|
fn div_assign(&mut self, rhs: &Rational) { self.0 /= &rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&Rational> for Rational {
|
impl ops::RemAssign<&Rational> for Rational {
|
||||||
|
@ -250,9 +250,7 @@ impl ops::MulAssign<&Self> for Rational {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ops::DivAssign<&Self> for Rational {
|
impl ops::DivAssign<&Self> for Rational {
|
||||||
fn div_assign(&mut self, _rhs: &Self) {
|
fn div_assign(&mut self, rhs: &Self) { self.0 /= &rhs.0; }
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::RemAssign<&Self> for Rational {
|
impl ops::RemAssign<&Self> for Rational {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
use crate::constraints::Constraints;
|
use crate::constraints::Constraints;
|
||||||
use crate::election::{CandidateState, CountState, Election};
|
use crate::election::{CandidateState, CountState, Election};
|
||||||
use crate::numbers::{Fixed, GuardedFixed, NativeFloat64, Number, Rational};
|
use crate::numbers::{DynNum, Fixed, GuardedFixed, NumKind, Number};
|
||||||
use crate::stv;
|
use crate::stv;
|
||||||
|
|
||||||
extern crate console_error_panic_hook;
|
extern crate console_error_panic_hook;
|
||||||
@ -31,6 +31,12 @@ use std::cmp::max;
|
|||||||
|
|
||||||
// Init
|
// Init
|
||||||
|
|
||||||
|
/// Wrapper for [DynNum::set_kind]
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn dynnum_set_kind(kind: NumKind) {
|
||||||
|
DynNum::set_kind(kind);
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper for [Fixed::set_dps]
|
/// Wrapper for [Fixed::set_dps]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn fixed_set_dps(dps: usize) {
|
pub fn fixed_set_dps(dps: usize) {
|
||||||
@ -180,10 +186,12 @@ macro_rules! impl_type {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_type!(Fixed);
|
//impl_type!(Fixed);
|
||||||
impl_type!(GuardedFixed);
|
//impl_type!(GuardedFixed);
|
||||||
impl_type!(NativeFloat64);
|
//impl_type!(NativeFloat64);
|
||||||
impl_type!(Rational);
|
//impl_type!(Rational);
|
||||||
|
|
||||||
|
impl_type!(DynNum);
|
||||||
|
|
||||||
/// Wrapper for [stv::STVOptions]
|
/// Wrapper for [stv::STVOptions]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
Loading…
Reference in New Issue
Block a user