aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.rs')
-rw-r--r--src/eval.rs38
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 {