From 1baf772b1cd98e4e042953944f93715bb3071387 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 22 May 2019 19:48:34 -0400 Subject: [PATCH] pass Number's by reference when possible --- src/prolog/arithmetic.rs | 54 +++++++++++++----------- src/prolog/machine/machine_indices.rs | 14 ++++-- src/prolog/machine/machine_state_impl.rs | 24 +++++------ 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index cad6f04c..b9115793 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -10,7 +10,7 @@ use prolog::machine::machine_errors::*; use prolog::machine::machine_indices::*; use prolog::ordered_float::*; -use prolog::rug::{Integer, Rational}; +use prolog::rug::{Assign, Integer, Rational}; use prolog::rug::ops::PowAssign; use std::cell::Cell; @@ -279,35 +279,42 @@ impl<'a> ArithmeticEvaluator<'a> } // integer division rounding function -- 9.1.3.1. -pub fn rnd_i(n: Number) -> Integer { +pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> { match n { - Number::Integer(n) => n, - Number::Float(OrderedFloat(f)) => - Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)), - Number::Rational(r) => r.fract_floor(Integer::new()).1 + &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()); + + (&mut fract, &mut floor).assign(r_ref); + RefOrOwned::Owned(floor) + } } } // floating point rounding function -- 9.1.4.1. -pub fn rnd_f(n: Number) -> f64 { +pub fn rnd_f(n: &Number) -> f64 { match n { - Number::Integer(n) => n.to_f64(), - Number::Float(OrderedFloat(f)) => f, - Number::Rational(r) => r.to_f64() + &Number::Integer(ref n) => n.to_f64(), + &Number::Float(OrderedFloat(f)) => f, + &Number::Rational(ref r) => r.to_f64() } } // floating point result function -- 9.1.4.2. -pub fn result_f(n: Number, round: Round) -> Result - where Round: Fn(Number) -> f64 +pub fn result_f(n: &Number, round: Round) -> Result + where Round: Fn(&Number) -> f64 { let f = rnd_f(n); match f.classify() { FpCategory::Normal | FpCategory::Zero => - Ok(round(Number::Float(OrderedFloat(f)))), + Ok(round(&Number::Float(OrderedFloat(f)))), FpCategory::Infinite => { - let f = round(Number::Float(OrderedFloat(f))); + let f = round(&Number::Float(OrderedFloat(f))); if OrderedFloat(f) == OrderedFloat(f64::MAX) { Ok(f) @@ -316,31 +323,31 @@ pub fn result_f(n: Number, round: Round) -> Result } }, FpCategory::Nan => Err(EvalError::Undefined), - _ => Ok(round(Number::Float(OrderedFloat(f)))) + _ => Ok(round(&Number::Float(OrderedFloat(f)))) } } fn float_i_to_f(n: Integer) -> Result { - result_f(Number::Integer(n), rnd_f) + result_f(&Number::Integer(n), rnd_f) } fn float_r_to_f(r: Rational) -> Result { - result_f(Number::Rational(r), rnd_f) + result_f(&Number::Rational(r), rnd_f) } fn add_f(f1: f64, f2: f64) -> Result, EvalError> { - Ok(OrderedFloat(result_f(Number::Float(OrderedFloat(f1 + f2)), rnd_f)?)) + Ok(OrderedFloat(result_f(&Number::Float(OrderedFloat(f1 + f2)), rnd_f)?)) } fn mul_f(f1: f64, f2: f64) -> Result, EvalError> { - Ok(OrderedFloat(result_f(Number::Float(OrderedFloat(f1 * f2)), rnd_f)?)) + Ok(OrderedFloat(result_f(&Number::Float(OrderedFloat(f1 * f2)), rnd_f)?)) } fn div_f(f1: f64, f2: f64) -> Result, EvalError> { if FpCategory::Zero == f2.classify() { Err(EvalError::ZeroDivisor) } else { - Ok(OrderedFloat(result_f(Number::Float(OrderedFloat(f1 / f2)), rnd_f)?)) + Ok(OrderedFloat(result_f(&Number::Float(OrderedFloat(f1 / f2)), rnd_f)?)) } } @@ -492,12 +499,11 @@ impl Ord for Number { // Computes n ^ power. Ignores the sign of power. pub fn binary_pow(mut n: Integer, power: Integer) -> Integer { - let one = Integer::from(1); - + let one = Integer::from(1); let mut power = power.abs(); - if power == Integer::from(0) { - return Integer::from(1); + if power == 0 { + return one; } let mut oddand = Integer::from(1); diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index 45db2f92..99a91998 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -595,17 +595,25 @@ impl CompileTimeHook { } } -pub(super) enum RefOrOwned<'a, T: 'a> { +pub enum RefOrOwned<'a, T: 'a> { Borrowed(&'a T), Owned(T) } impl<'a, T> RefOrOwned<'a, T> { - pub(super) - fn as_ref(&'a self) -> &'a T { + pub fn as_ref(&'a self) -> &'a T { match self { &RefOrOwned::Borrowed(r) => r, &RefOrOwned::Owned(ref r) => r } } + + pub fn to_owned(self) -> T + where T: Clone + { + match self { + RefOrOwned::Borrowed(item) => item.clone(), + RefOrOwned::Owned(item) => item + } + } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 1cfbf9ad..486f2f0d 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -957,7 +957,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("(div)"), 2); match n1 / n2 { - Ok(result) => Ok(rnd_i(result)), + Ok(result) => Ok(rnd_i(&result).to_owned()), Err(e) => Err(self.error_form(MachineError::evaluation_error(e), stub)) } } @@ -1051,15 +1051,15 @@ impl MachineState { fn float_pow(&self, n1: Number, n2: Number) -> Result { - let f1 = result_f(n1, rnd_f); - let f2 = result_f(n2, rnd_f); + let f1 = result_f(&n1, rnd_f); + let f2 = result_f(&n2, rnd_f); let stub = MachineError::functor_stub(clause_name!("(**)"), 2); let f1 = try_numeric_result!(self, f1, stub.clone())?; let f2 = try_numeric_result!(self, f2, stub.clone())?; - let result = result_f(Number::Float(OrderedFloat(f1.powf(f2))), rnd_f); + let result = result_f(&Number::Float(OrderedFloat(f1.powf(f2))), rnd_f); Ok(Number::Float(OrderedFloat(try_numeric_result!(self, result, stub)?))) } @@ -1084,8 +1084,8 @@ impl MachineState { { let stub = MachineError::functor_stub(clause_name!("(is)"), 2); - let f1 = try_numeric_result!(self, result_f(n1, rnd_f), stub.clone())?; - let f1 = result_f(Number::Float(OrderedFloat(f(f1))), rnd_f); + let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?; + let f1 = result_f(&Number::Float(OrderedFloat(f(f1))), rnd_f); try_numeric_result!(self, f1, stub) } @@ -1143,12 +1143,12 @@ impl MachineState { fn float(&self, n: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(is)"), 2); - try_numeric_result!(self, result_f(n, rnd_f), stub) + try_numeric_result!(self, result_f(&n, rnd_f), stub) } fn floor(&self, n1: Number) -> Integer { - rnd_i(n1) + rnd_i(&n1).to_owned() } fn ceiling(&self, n1: Number) -> Integer @@ -1300,8 +1300,8 @@ impl MachineState { (n1, n2) => { let stub = MachineError::functor_stub(clause_name!("max"), 2); - let f1 = try_numeric_result!(self, result_f(n1, rnd_f), stub.clone())?; - let f2 = try_numeric_result!(self, result_f(n2, rnd_f), stub)?; + let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?; + let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?; Ok(Number::Float(max(OrderedFloat(f1), OrderedFloat(f2)))) } @@ -1319,8 +1319,8 @@ impl MachineState { (n1, n2) => { let stub = MachineError::functor_stub(clause_name!("max"), 2); - let f1 = try_numeric_result!(self, result_f(n1, rnd_f), stub.clone())?; - let f2 = try_numeric_result!(self, result_f(n2, rnd_f), stub)?; + let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?; + let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?; Ok(Number::Float(min(OrderedFloat(f1), OrderedFloat(f2)))) } -- 2.54.0