diff options
| -rw-r--r-- | src/eval.rs | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/src/eval.rs b/src/eval.rs index 7c6ef5d..f8f4c53 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -22,28 +22,32 @@ impl Num { } } + fn powi(self, p: u64) -> Num { + if p == 0 { + return int(1); + } + if p == 1 { + return self; + } + if p % 2 == 0 { + return self.mul(self).powi(p / 2); + } + self.mul(self).powi(p / 2).mul(self) + } + pub fn pow(self, other: Num) -> Num { - match (self, other) { - (_, Num::Int(0)) => return int(1), - (Num::Int(-1), Num::Int(i2)) => { - if i2 % 2 == 0 { - return int(1); - } else { - return int(-1); + match other { + Num::Int(i) => { + if let Ok(u) = u64::try_from(i) { + return self.powi(u); } - } - (Num::Int(0), _) => return int(0), - (Num::Int(1), _) => return int(1), - (Num::Int(i1), Num::Int(i2)) => { - if let Ok(u) = u32::try_from(i2) { - if let Some(p) = i1.checked_pow(u) { - return int(p); - } + if let Ok(i_32) = i32::try_from(i) { + return float(self.as_float().powi(i_32)); } + float(1.).div(self).powi(-i as u64) } - _ => (), + Num::Float(f) => float(self.as_float().powf(f)), } - float(self.as_float().powf(other.as_float())) } pub fn mul(self, other: Num) -> Num { |
