Format code using 'cargo fmt'
This commit is contained in:
@@ -10,60 +10,66 @@ use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
|
||||
use prolog::ordered_float::*;
|
||||
use prolog::rug::{Assign, Integer, Rational};
|
||||
use prolog::rug::ops::PowAssign;
|
||||
use prolog::rug::{Assign, Integer, Rational};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::{Ordering, min, max};
|
||||
use std::cmp::{max, min, Ordering};
|
||||
use std::f64;
|
||||
use std::num::FpCategory;
|
||||
use std::ops::{Add, Sub, Div, Mul, Neg};
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use std::rc::Rc;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub struct ArithInstructionIterator<'a> {
|
||||
state_stack: Vec<TermIterState<'a>>
|
||||
state_stack: Vec<TermIterState<'a>>,
|
||||
}
|
||||
|
||||
pub type ArithCont = (Code, Option<ArithmeticTerm>);
|
||||
|
||||
impl<'a> ArithInstructionIterator<'a> {
|
||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
|
||||
self.state_stack
|
||||
.push(TermIterState::subterm_to_state(lvl, term));
|
||||
}
|
||||
|
||||
fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
|
||||
let state = match term {
|
||||
&Term::AnonVar =>
|
||||
return Err(ArithmeticError::UninstantiatedVar),
|
||||
&Term::Clause(ref cell, ref name, ref terms, ref fixity) =>
|
||||
&Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
|
||||
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
|
||||
match ClauseType::from(name.clone(), terms.len(), fixity.clone()) {
|
||||
ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) =>
|
||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)),
|
||||
ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) => {
|
||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
||||
}
|
||||
ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
|
||||
let ct = ClauseType::Named(clause_name!("float"), 1, CodeIndex::default());
|
||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
|
||||
},
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name.clone(),
|
||||
fixity.clone()),
|
||||
terms.len()))
|
||||
}?,
|
||||
&Term::Constant(ref cell, ref cons) =>
|
||||
TermIterState::Constant(Level::Shallow, cell, cons),
|
||||
&Term::Cons(_, _, _) =>
|
||||
return Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2)),
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
TermIterState::Var(Level::Shallow, cell, var.clone())
|
||||
}
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||
Constant::Atom(name.clone(), fixity.clone()),
|
||||
terms.len(),
|
||||
)),
|
||||
}?
|
||||
}
|
||||
&Term::Constant(ref cell, ref cons) => {
|
||||
TermIterState::Constant(Level::Shallow, cell, cons)
|
||||
}
|
||||
&Term::Cons(_, _, _) => {
|
||||
return Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))
|
||||
}
|
||||
&Term::Var(ref cell, ref var) => TermIterState::Var(Level::Shallow, cell, var.clone()),
|
||||
};
|
||||
|
||||
Ok(ArithInstructionIterator { state_stack: vec![state] })
|
||||
Ok(ArithInstructionIterator {
|
||||
state_stack: vec![state],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ArithTermRef<'a> {
|
||||
Constant(&'a Constant),
|
||||
Op(ClauseName, usize), // name, arity.
|
||||
Var(&'a Cell<VarReg>, Rc<Var>)
|
||||
Var(&'a Cell<VarReg>, Rc<Var>),
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||
@@ -72,24 +78,28 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(iter_state) = self.state_stack.pop() {
|
||||
match iter_state {
|
||||
TermIterState::AnonVar(_) =>
|
||||
return Some(Err(ArithmeticError::UninstantiatedVar)),
|
||||
TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
|
||||
TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
|
||||
let arity = subterms.len();
|
||||
|
||||
if child_num == arity {
|
||||
return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
|
||||
} else {
|
||||
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms));
|
||||
self.state_stack.push(TermIterState::Clause(
|
||||
lvl,
|
||||
child_num + 1,
|
||||
cell,
|
||||
ct,
|
||||
subterms,
|
||||
));
|
||||
self.push_subterm(lvl, subterms[child_num].as_ref());
|
||||
}
|
||||
},
|
||||
TermIterState::Constant(_, _, c) =>
|
||||
return Some(Ok(ArithTermRef::Constant(c))),
|
||||
TermIterState::Var(_, cell, var) =>
|
||||
return Some(Ok(ArithTermRef::Var(cell, var.clone()))),
|
||||
_ =>
|
||||
return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2)))
|
||||
}
|
||||
TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))),
|
||||
TermIterState::Var(_, cell, var) => {
|
||||
return Some(Ok(ArithTermRef::Var(cell, var.clone())))
|
||||
}
|
||||
_ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,11 +110,11 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||
pub struct ArithmeticEvaluator<'a> {
|
||||
bindings: &'a AllocVarDict,
|
||||
interm: Vec<ArithmeticTerm>,
|
||||
interm_c: usize
|
||||
interm_c: usize,
|
||||
}
|
||||
|
||||
pub trait ArithmeticTermIter<'a> {
|
||||
type Iter : Iterator<Item=Result<ArithTermRef<'a>, ArithmeticError>>;
|
||||
type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;
|
||||
|
||||
fn iter(self) -> Result<Self::Iter, ArithmeticError>;
|
||||
}
|
||||
@@ -117,15 +127,20 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArithmeticEvaluator<'a>
|
||||
{
|
||||
impl<'a> ArithmeticEvaluator<'a> {
|
||||
pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
|
||||
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
|
||||
ArithmeticEvaluator {
|
||||
bindings,
|
||||
interm: Vec::new(),
|
||||
interm_c: target_int,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
fn get_unary_instr(
|
||||
name: ClauseName,
|
||||
a1: ArithmeticTerm,
|
||||
t: usize,
|
||||
) -> Result<ArithmeticInstruction, ArithmeticError> {
|
||||
match name.as_str() {
|
||||
"abs" => Ok(ArithmeticInstruction::Abs(a1, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
|
||||
@@ -145,34 +160,43 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
"ceiling" => Ok(ArithmeticInstruction::Ceiling(a1, t)),
|
||||
"floor" => Ok(ArithmeticInstruction::Floor(a1, t)),
|
||||
"\\" => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)),
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), 1))
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||
Constant::Atom(name, None),
|
||||
1,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
fn get_binary_instr(
|
||||
name: ClauseName,
|
||||
a1: ArithmeticTerm,
|
||||
a2: ArithmeticTerm,
|
||||
t: usize,
|
||||
) -> Result<ArithmeticInstruction, ArithmeticError> {
|
||||
match name.as_str() {
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
|
||||
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
||||
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"max" => Ok(ArithmeticInstruction::Max(a1, a2, t)),
|
||||
"min" => Ok(ArithmeticInstruction::Min(a1, a2, t)),
|
||||
"div" => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
|
||||
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
||||
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"max" => Ok(ArithmeticInstruction::Max(a1, a2, t)),
|
||||
"min" => Ok(ArithmeticInstruction::Min(a1, a2, t)),
|
||||
"div" => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
|
||||
"rdiv" => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
|
||||
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
||||
"**" => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
|
||||
"^" => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
|
||||
">>" => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
|
||||
"<<" => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
|
||||
"/\\" => Ok(ArithmeticInstruction::And(a1, a2, t)),
|
||||
"\\/" => Ok(ArithmeticInstruction::Or(a1, a2, t)),
|
||||
"xor" => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
|
||||
"mod" => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
|
||||
"rem" => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
|
||||
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
||||
"**" => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
|
||||
"^" => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
|
||||
">>" => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
|
||||
"<<" => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
|
||||
"/\\" => Ok(ArithmeticInstruction::And(a1, a2, t)),
|
||||
"\\/" => Ok(ArithmeticInstruction::Or(a1, a2, t)),
|
||||
"xor" => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
|
||||
"mod" => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
|
||||
"rem" => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
|
||||
"atan2" => Ok(ArithmeticInstruction::ATan2(a1, a2, t)),
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), 2))
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||
Constant::Atom(name, None),
|
||||
2,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,9 +209,11 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
temp
|
||||
}
|
||||
|
||||
fn instr_from_clause(&mut self, name: ClauseName, arity: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
fn instr_from_clause(
|
||||
&mut self,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> Result<ArithmeticInstruction, ArithmeticError> {
|
||||
match arity {
|
||||
1 => {
|
||||
let a1 = self.interm.pop().unwrap();
|
||||
@@ -200,7 +226,7 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
};
|
||||
|
||||
Self::get_unary_instr(name, a1, ninterm)
|
||||
},
|
||||
}
|
||||
2 => {
|
||||
let a2 = self.interm.pop().unwrap();
|
||||
let a1 = self.interm.pop().unwrap();
|
||||
@@ -224,35 +250,44 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
};
|
||||
|
||||
Self::get_binary_instr(name, a1, a2, ninterm)
|
||||
},
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), arity))
|
||||
}
|
||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||
Constant::Atom(name, None),
|
||||
arity,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
|
||||
match c {
|
||||
&Constant::Integer(ref n) =>
|
||||
self.interm.push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
|
||||
&Constant::Float(ref n) =>
|
||||
self.interm.push(ArithmeticTerm::Number(Number::Float(n.clone()))),
|
||||
&Constant::Rational(ref n) =>
|
||||
self.interm.push(ArithmeticTerm::Number(Number::Rational(n.clone()))),
|
||||
&Constant::Atom(ref name, _) if name.as_str() == "pi" =>
|
||||
self.interm.push(ArithmeticTerm::Number(Number::Float(OrderedFloat(f64::consts::PI)))),
|
||||
_ =>
|
||||
return Err(ArithmeticError::NonEvaluableFunctor(c.clone(), 0))
|
||||
&Constant::Integer(ref n) => self
|
||||
.interm
|
||||
.push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
|
||||
&Constant::Float(ref n) => self
|
||||
.interm
|
||||
.push(ArithmeticTerm::Number(Number::Float(n.clone()))),
|
||||
&Constant::Rational(ref n) => self
|
||||
.interm
|
||||
.push(ArithmeticTerm::Number(Number::Rational(n.clone()))),
|
||||
&Constant::Atom(ref name, _) if name.as_str() == "pi" => {
|
||||
self.interm
|
||||
.push(ArithmeticTerm::Number(Number::Float(OrderedFloat(
|
||||
f64::consts::PI,
|
||||
))))
|
||||
}
|
||||
_ => return Err(ArithmeticError::NonEvaluableFunctor(c.clone(), 0)),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError>
|
||||
where Iter: ArithmeticTermIter<'a>
|
||||
where
|
||||
Iter: ArithmeticTermIter<'a>,
|
||||
{
|
||||
let mut code = vec![];
|
||||
|
||||
for term_ref in src.iter()?
|
||||
{
|
||||
for term_ref in src.iter()? {
|
||||
match term_ref? {
|
||||
ArithTermRef::Constant(c) => self.push_constant(c)?,
|
||||
ArithTermRef::Var(cell, name) => {
|
||||
@@ -260,14 +295,14 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
match self.bindings.get(&name) {
|
||||
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
|
||||
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
|
||||
_ => return Err(ArithmeticError::UninstantiatedVar)
|
||||
_ => return Err(ArithmeticError::UninstantiatedVar),
|
||||
}
|
||||
} else {
|
||||
cell.get().norm()
|
||||
};
|
||||
|
||||
self.interm.push(ArithmeticTerm::Reg(r));
|
||||
},
|
||||
}
|
||||
ArithTermRef::Op(name, arity) => {
|
||||
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
|
||||
}
|
||||
@@ -281,10 +316,10 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
// integer division rounding function -- 9.1.3.1.
|
||||
pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> {
|
||||
match n {
|
||||
&Number::Integer(ref n) =>
|
||||
RefOrOwned::Borrowed(n),
|
||||
&Number::Float(OrderedFloat(f)) =>
|
||||
RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0))),
|
||||
&Number::Integer(ref n) => RefOrOwned::Borrowed(n),
|
||||
&Number::Float(OrderedFloat(f)) => {
|
||||
RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)))
|
||||
}
|
||||
&Number::Rational(ref r) => {
|
||||
let r_ref = r.fract_floor_ref();
|
||||
let (mut fract, mut floor) = (Rational::new(), Integer::new());
|
||||
@@ -300,24 +335,25 @@ pub fn rnd_f(n: &Number) -> f64 {
|
||||
match n {
|
||||
&Number::Integer(ref n) => n.to_f64(),
|
||||
&Number::Float(OrderedFloat(f)) => f,
|
||||
&Number::Rational(ref r) => r.to_f64()
|
||||
&Number::Rational(ref r) => r.to_f64(),
|
||||
}
|
||||
}
|
||||
|
||||
// floating point result function -- 9.1.4.2.
|
||||
pub fn result_f<Round>(n: &Number, round: Round) -> Result<f64, EvalError>
|
||||
where Round: Fn(&Number) -> f64
|
||||
where
|
||||
Round: Fn(&Number) -> f64,
|
||||
{
|
||||
let f = rnd_f(n);
|
||||
classify_float(f, round)
|
||||
}
|
||||
|
||||
fn classify_float<Round>(f: f64, round: Round) -> Result<f64, EvalError>
|
||||
where Round: Fn(&Number) -> f64
|
||||
where
|
||||
Round: Fn(&Number) -> f64,
|
||||
{
|
||||
match f.classify() {
|
||||
FpCategory::Normal | FpCategory::Zero =>
|
||||
Ok(round(&Number::Float(OrderedFloat(f)))),
|
||||
FpCategory::Normal | FpCategory::Zero => Ok(round(&Number::Float(OrderedFloat(f)))),
|
||||
FpCategory::Infinite => {
|
||||
let f = round(&Number::Float(OrderedFloat(f)));
|
||||
|
||||
@@ -326,9 +362,9 @@ fn classify_float<Round>(f: f64, round: Round) -> Result<f64, EvalError>
|
||||
} else {
|
||||
Err(EvalError::FloatOverflow)
|
||||
}
|
||||
},
|
||||
}
|
||||
FpCategory::Nan => Err(EvalError::Undefined),
|
||||
_ => Ok(round(&Number::Float(OrderedFloat(f))))
|
||||
_ => Ok(round(&Number::Float(OrderedFloat(f)))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,21 +397,23 @@ impl Add<Number> for Number {
|
||||
|
||||
fn add(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(Number::Integer(n1 + n2)), // add_i
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
|
||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) =>
|
||||
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?)),
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Integer(n1), Number::Rational(n2))
|
||||
| (Number::Rational(n2), Number::Integer(n1)) =>
|
||||
Ok(Number::Rational(Rational::from(n1) + n2)),
|
||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||
Ok(Number::Rational(Rational::from(n1) + n2))
|
||||
}
|
||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) =>
|
||||
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?)),
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) =>
|
||||
Ok(Number::Float(add_f(f1, f2)?)),
|
||||
(Number::Rational(r1), Number::Rational(r2)) =>
|
||||
Ok(Number::Rational(r1 + r2))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||
Ok(Number::Float(add_f(f1, f2)?))
|
||||
}
|
||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,7 +425,7 @@ impl Neg for Number {
|
||||
match self {
|
||||
Number::Integer(n) => Number::Integer(-n),
|
||||
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
||||
Number::Rational(r) => Number::Rational(-r)
|
||||
Number::Rational(r) => Number::Rational(-r),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,21 +443,23 @@ impl Mul<Number> for Number {
|
||||
|
||||
fn mul(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(Number::Integer(n1 * n2)), // mul_i
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
|
||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) =>
|
||||
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?)),
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Integer(n1), Number::Rational(n2))
|
||||
| (Number::Rational(n2), Number::Integer(n1)) =>
|
||||
Ok(Number::Rational(Rational::from(n1) * n2)),
|
||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||
Ok(Number::Rational(Rational::from(n1) * n2))
|
||||
}
|
||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) =>
|
||||
Ok(Number::Float(mul_f(float_r_to_f(&n1)?, n2)?)),
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) =>
|
||||
Ok(Number::Float(mul_f(f1, f2)?)),
|
||||
(Number::Rational(r1), Number::Rational(r2)) =>
|
||||
Ok(Number::Rational(r1 * r2))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||
Ok(Number::Float(mul_f(float_r_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||
Ok(Number::Float(mul_f(f1, f2)?))
|
||||
}
|
||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,24 +469,37 @@ impl Div<Number> for Number {
|
||||
|
||||
fn div(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(Number::Float(div_f(float_i_to_f(&n1)?, float_i_to_f(&n2)?)?)),
|
||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) =>
|
||||
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?)),
|
||||
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) =>
|
||||
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?)),
|
||||
(Number::Integer(n1), Number::Rational(n2)) =>
|
||||
Ok(Number::Float(div_f(float_i_to_f(&n1)?, float_r_to_f(&n2)?)?)),
|
||||
(Number::Rational(n2), Number::Integer(n1)) =>
|
||||
Ok(Number::Float(div_f(float_r_to_f(&n2)?, float_i_to_f(&n1)?)?)),
|
||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) =>
|
||||
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?)),
|
||||
(Number::Float(OrderedFloat(n2)), Number::Rational(n1)) =>
|
||||
Ok(Number::Float(div_f(n2, float_r_to_f(&n1)?)?)),
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) =>
|
||||
Ok(Number::Float(div_f(f1, f2)?)),
|
||||
(Number::Rational(r1), Number::Rational(r2)) =>
|
||||
Ok(Number::Float(div_f(float_r_to_f(&r1)?, float_r_to_f(&r2)?)?))
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f(
|
||||
float_i_to_f(&n1)?,
|
||||
float_i_to_f(&n2)?,
|
||||
)?)),
|
||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) => {
|
||||
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
|
||||
}
|
||||
(Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f(
|
||||
float_i_to_f(&n1)?,
|
||||
float_r_to_f(&n2)?,
|
||||
)?)),
|
||||
(Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f(
|
||||
float_r_to_f(&n2)?,
|
||||
float_i_to_f(&n1)?,
|
||||
)?)),
|
||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => {
|
||||
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||
Ok(Number::Float(div_f(n2, float_r_to_f(&n1)?)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||
Ok(Number::Float(div_f(f1, f2)?))
|
||||
}
|
||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Float(div_f(
|
||||
float_r_to_f(&r1)?,
|
||||
float_r_to_f(&r2)?,
|
||||
)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,24 +507,15 @@ impl Div<Number> for Number {
|
||||
impl PartialOrd for Number {
|
||||
fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
|
||||
match (self, rhs) {
|
||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) =>
|
||||
Some(n1.cmp(n2)),
|
||||
(&Number::Integer(_), Number::Float(_)) =>
|
||||
Some(Ordering::Greater),
|
||||
(&Number::Float(_), &Number::Integer(_)) =>
|
||||
Some(Ordering::Less),
|
||||
(&Number::Integer(_), &Number::Rational(_)) =>
|
||||
Some(Ordering::Greater),
|
||||
(&Number::Rational(_), &Number::Integer(_)) =>
|
||||
Some(Ordering::Less),
|
||||
(&Number::Rational(_), Number::Float(_)) =>
|
||||
Some(Ordering::Greater),
|
||||
(&Number::Float(_), &Number::Rational(_)) =>
|
||||
Some(Ordering::Less),
|
||||
(&Number::Float(f1), &Number::Float(f2)) =>
|
||||
Some(f1.cmp(&f2)),
|
||||
(&Number::Rational(ref r1), &Number::Rational(ref r2)) =>
|
||||
Some(r1.cmp(&r2))
|
||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => Some(n1.cmp(n2)),
|
||||
(&Number::Integer(_), Number::Float(_)) => Some(Ordering::Greater),
|
||||
(&Number::Float(_), &Number::Integer(_)) => Some(Ordering::Less),
|
||||
(&Number::Integer(_), &Number::Rational(_)) => Some(Ordering::Greater),
|
||||
(&Number::Rational(_), &Number::Integer(_)) => Some(Ordering::Less),
|
||||
(&Number::Rational(_), Number::Float(_)) => Some(Ordering::Greater),
|
||||
(&Number::Float(_), &Number::Rational(_)) => Some(Ordering::Less),
|
||||
(&Number::Float(f1), &Number::Float(f2)) => Some(f1.cmp(&f2)),
|
||||
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => Some(r1.cmp(&r2)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,31 +523,21 @@ impl PartialOrd for Number {
|
||||
impl Ord for Number {
|
||||
fn cmp(&self, rhs: &Number) -> Ordering {
|
||||
match (self, rhs) {
|
||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) =>
|
||||
n1.cmp(n2),
|
||||
(&Number::Integer(_), Number::Float(_)) =>
|
||||
Ordering::Greater,
|
||||
(&Number::Float(_), &Number::Integer(_)) =>
|
||||
Ordering::Less,
|
||||
(&Number::Integer(_), &Number::Rational(_)) =>
|
||||
Ordering::Greater,
|
||||
(&Number::Rational(_), &Number::Integer(_)) =>
|
||||
Ordering::Less,
|
||||
(&Number::Rational(_), Number::Float(_)) =>
|
||||
Ordering::Greater,
|
||||
(&Number::Float(_), &Number::Rational(_)) =>
|
||||
Ordering::Less,
|
||||
(&Number::Float(f1), &Number::Float(f2)) =>
|
||||
f1.cmp(&f2),
|
||||
(&Number::Rational(ref r1), &Number::Rational(ref r2)) =>
|
||||
r1.cmp(&r2)
|
||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2),
|
||||
(&Number::Integer(_), Number::Float(_)) => Ordering::Greater,
|
||||
(&Number::Float(_), &Number::Integer(_)) => Ordering::Less,
|
||||
(&Number::Integer(_), &Number::Rational(_)) => Ordering::Greater,
|
||||
(&Number::Rational(_), &Number::Integer(_)) => Ordering::Less,
|
||||
(&Number::Rational(_), Number::Float(_)) => Ordering::Greater,
|
||||
(&Number::Float(_), &Number::Rational(_)) => Ordering::Less,
|
||||
(&Number::Float(f1), &Number::Float(f2)) => f1.cmp(&f2),
|
||||
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.cmp(&r2),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Computes n ^ power. Ignores the sign of power.
|
||||
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer
|
||||
{
|
||||
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
|
||||
let mut power = power.abs();
|
||||
|
||||
if power == 0 {
|
||||
|
||||
Reference in New Issue
Block a user