aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.rs')
-rw-r--r--src/eval.rs139
1 files changed, 66 insertions, 73 deletions
diff --git a/src/eval.rs b/src/eval.rs
index dce9d68..a72f271 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -1,4 +1,5 @@
use std::fmt::{Display, Formatter};
+use Num::{Float, Int};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Num {
@@ -6,25 +7,17 @@ pub enum Num {
Float(f64),
}
-pub fn int(i: i128) -> Num {
- Num::Int(i)
-}
-
-pub fn float(f: f64) -> Num {
- Num::Float(f)
-}
-
impl Num {
fn as_float(self) -> f64 {
match self {
- Num::Int(i) => i as f64,
- Num::Float(f) => f,
+ Int(i) => i as f64,
+ Float(f) => f,
}
}
fn powi(self, p: i128) -> Num {
if p == 0 {
- return int(1);
+ return Int(1);
}
if p == 1 {
return self;
@@ -37,106 +30,106 @@ impl Num {
pub fn pow(self, other: Num) -> Num {
match other {
- Num::Int(i) => {
+ Int(i) => {
if i >= 0 {
return self.powi(i);
}
if let Ok(i_32) = i32::try_from(i) {
- return float(self.as_float().powi(i_32));
+ return Float(self.as_float().powi(i_32));
}
- float(1.).div(self).powi(-i)
+ Float(1.).div(self).powi(-i)
}
- Num::Float(f) => float(self.as_float().powf(f)),
+ Float(f) => Float(self.as_float().powf(f)),
}
}
pub fn mul(self, other: Num) -> Num {
- if let (Num::Int(i1), Num::Int(i2)) = (self, other) {
+ if let (Int(i1), Int(i2)) = (self, other) {
if let Some(p) = i1.checked_mul(i2) {
- return int(p);
+ return Int(p);
}
}
- float(self.as_float() * other.as_float())
+ Float(self.as_float() * other.as_float())
}
pub fn div(self, other: Num) -> Num {
- float(self.as_float() / other.as_float())
+ Float(self.as_float() / other.as_float())
}
pub fn int_div(self, other: Num) -> Num {
- if let (Num::Int(i1), Num::Int(i2)) = (self, other) {
+ if let (Int(i1), Int(i2)) = (self, other) {
if let Some(q) = i1.checked_div(i2) {
- return int(q);
+ return Int(q);
}
}
- int((self.as_float() / other.as_float()) as i128)
+ Int((self.as_float() / other.as_float()) as i128)
}
pub fn modulo(self, other: Num) -> Num {
- if let (Num::Int(i1), Num::Int(i2)) = (self, other) {
+ if let (Int(i1), Int(i2)) = (self, other) {
if let Some(r) = i1.checked_rem(i2) {
if i2 > 0 && r < 0 || i2 < 0 && r > 0 {
- return int(r + i2);
+ return Int(r + i2);
}
- return int(r);
+ return Int(r);
}
}
let n1 = self.as_float();
let n2 = other.as_float();
let r = n1 % n2;
if n2 > 0. && r < 0. || n2 < 0. && r > 0. {
- return float(r + n2);
+ return Float(r + n2);
}
- float(r)
+ Float(r)
}
pub fn add(self, other: Num) -> Num {
- if let (Num::Int(i1), Num::Int(i2)) = (self, other) {
+ if let (Int(i1), Int(i2)) = (self, other) {
if let Some(s) = i1.checked_add(i2) {
- return int(s);
+ return Int(s);
}
}
- float(self.as_float() + other.as_float())
+ Float(self.as_float() + other.as_float())
}
pub fn sub(self, other: Num) -> Num {
- if let (Num::Int(i1), Num::Int(i2)) = (self, other) {
+ if let (Int(i1), Int(i2)) = (self, other) {
if let Some(d) = i1.checked_sub(i2) {
- return int(d);
+ return Int(d);
}
}
- float(self.as_float() - other.as_float())
+ Float(self.as_float() - other.as_float())
}
pub fn sin(self) -> Num {
- float(self.as_float().sin())
+ Float(self.as_float().sin())
}
pub fn cos(self) -> Num {
- float(self.as_float().cos())
+ Float(self.as_float().cos())
}
pub fn tan(self) -> Num {
- float(self.as_float().tan())
+ Float(self.as_float().tan())
}
pub fn asin(self) -> Num {
- float(self.as_float().asin())
+ Float(self.as_float().asin())
}
pub fn acos(self) -> Num {
- float(self.as_float().acos())
+ Float(self.as_float().acos())
}
pub fn atan(self) -> Num {
- float(self.as_float().atan())
+ Float(self.as_float().atan())
}
pub fn sqrt(self) -> Num {
match self {
- Num::Int(i) if i >= 0 => {
+ Int(i) if i >= 0 => {
if i <= 1 {
- return int(i);
+ return Int(i);
}
let mut x0 = i / 2;
let mut x1 = (x0 + i / x0) / 2;
@@ -145,51 +138,51 @@ impl Num {
x1 = (x0 + i / x0) / 2;
}
if x0 * x0 == i {
- return int(x0);
+ return Int(x0);
}
}
_ => (),
}
- float(self.as_float().sqrt())
+ Float(self.as_float().sqrt())
}
pub fn log(self) -> Num {
- float(self.as_float().ln())
+ Float(self.as_float().ln())
}
pub fn log10(self) -> Num {
- float(self.as_float().log10())
+ Float(self.as_float().log10())
}
pub fn log2(self) -> Num {
- float(self.as_float().log2())
+ Float(self.as_float().log2())
}
pub fn floor(self) -> Num {
match self {
- Num::Int(i) => int(i),
- Num::Float(f) => int(f.floor() as i128),
+ Int(i) => Int(i),
+ Float(f) => Int(f.floor() as i128),
}
}
pub fn ceil(self) -> Num {
match self {
- Num::Int(i) => int(i),
- Num::Float(f) => int(f.ceil() as i128),
+ Int(i) => Int(i),
+ Float(f) => Int(f.ceil() as i128),
}
}
pub fn round(self) -> Num {
match self {
- Num::Int(i) => int(i),
- Num::Float(f) => int(f.round_ties_even() as i128),
+ Int(i) => Int(i),
+ Float(f) => Int(f.round_ties_even() as i128),
}
}
pub fn abs(self) -> Num {
match self {
- Num::Int(i) => int(i.abs()),
- Num::Float(f) => float(f.abs()),
+ Int(i) => Int(i.abs()),
+ Float(f) => Float(f.abs()),
}
}
}
@@ -197,8 +190,8 @@ impl Num {
impl Display for Num {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
- Num::Int(n) => write!(f, "{n}"),
- Num::Float(n) => {
+ Int(n) => write!(f, "{n}"),
+ Float(n) => {
if !(-1e30..=1e30).contains(n) {
return write!(f, "{n:.7e}");
}
@@ -218,76 +211,76 @@ mod tests {
#[test]
fn pow_positive_int() {
- assert_eq!(int(2).pow(int(16)), int(65536));
+ assert_eq!(Int(2).pow(Int(16)), Int(65536));
}
#[test]
fn pow_negative_int() {
- assert_eq!(int(2).pow(int(-3)), float(0.125));
+ assert_eq!(Int(2).pow(Int(-3)), Float(0.125));
}
#[test]
fn pow_float() {
- assert_eq!(int(4).pow(float(0.5)), float(2.));
+ assert_eq!(Int(4).pow(Float(0.5)), Float(2.));
}
#[test]
fn pow_overflow() {
- assert_eq!(int(2).pow(int(1 << 126)), float(f64::INFINITY));
+ assert_eq!(Int(2).pow(Int(1 << 126)), Float(f64::INFINITY));
}
#[test]
fn pow_underflow() {
- assert_eq!(int(2).pow(int(-(1 << 126))), float(0.));
+ assert_eq!(Int(2).pow(Int(-(1 << 126))), Float(0.));
}
#[test]
fn modulo_pos() {
- assert_eq!(int(5).modulo(int(3)), int(2));
+ assert_eq!(Int(5).modulo(Int(3)), Int(2));
}
#[test]
fn modulo_pos_neg() {
- assert_eq!(int(5).modulo(int(-3)), int(-1));
+ assert_eq!(Int(5).modulo(Int(-3)), Int(-1));
}
#[test]
fn modulo_neg_pos() {
- assert_eq!(int(-5).modulo(int(3)), int(1));
+ assert_eq!(Int(-5).modulo(Int(3)), Int(1));
}
#[test]
fn modulo_neg() {
- assert_eq!(int(-5).modulo(int(-3)), int(-2));
+ assert_eq!(Int(-5).modulo(Int(-3)), Int(-2));
}
#[test]
fn modulo_float_pos() {
- assert_eq!(float(5.).modulo(int(3)), float(2.));
+ assert_eq!(Float(5.).modulo(Int(3)), Float(2.));
}
#[test]
fn modulo_float_pos_neg() {
- assert_eq!(float(5.).modulo(int(-3)), float(-1.));
+ assert_eq!(Float(5.).modulo(Int(-3)), Float(-1.));
}
#[test]
fn modulo_float_neg_pos() {
- assert_eq!(float(-5.).modulo(int(3)), float(1.));
+ assert_eq!(Float(-5.).modulo(Int(3)), Float(1.));
}
#[test]
fn modulo_float_neg() {
- assert_eq!(float(-5.).modulo(int(-3)), float(-2.));
+ assert_eq!(Float(-5.).modulo(Int(-3)), Float(-2.));
}
#[test]
fn sqrt() {
for n in 0..65536 {
assert_eq!(
- int(n * n).sqrt(),
- int(n),
- "int({}).sqrt() is not equal to {}",
+ Int(n * n).sqrt(),
+ Int(n),
+ "Int({}).sqrt() is not equal to {}",
n * n,
n
);
@@ -296,6 +289,6 @@ mod tests {
#[test]
fn sqrt_big() {
- assert_eq!(int(1 << 126).sqrt(), int(1 << 63));
+ assert_eq!(Int(1 << 126).sqrt(), Int(1 << 63));
}
}