From 9b682c5f3cea8b79a1e38829eb7b1c0bb9ade21e Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Sat, 5 Apr 2025 20:04:06 -0500 Subject: [PATCH] numeric instructions tested and done --- src/instructions/mod.rs | 7 +- src/instructions/numeric.rs | 634 +++++++++++++++++++++++++++++++++++- src/instructions/utils.rs | 110 ++++++- src/main.rs | 32 +- src/push/state.rs | 8 +- 5 files changed, 767 insertions(+), 24 deletions(-) diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index fac2c62..3ff98c7 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -22,13 +22,16 @@ pub mod macros { macro_rules! make_instruction { ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { paste::item! { + /// Runs the $fn_name function on the top $fn_arity items from + /// the $in_stack and places the calculated value on the $out_stack. fn [< $in_stack $fn_name >] (state: &mut PushState) { - if state.$in_stack.len() < $fn_arity { + let in_stack_len = state.$in_stack.len(); + if in_stack_len < $fn_arity { return; } let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); for n in 1..=$fn_arity { - inputs.push(state.$in_stack[state.$in_stack.len() - n]); + inputs.push(state.$in_stack[in_stack_len - n]); } if let Some(result) = $fn_name(inputs) { for _ in 0..$fn_arity { diff --git a/src/instructions/numeric.rs b/src/instructions/numeric.rs index 924e121..4ba4fe8 100644 --- a/src/instructions/numeric.rs +++ b/src/instructions/numeric.rs @@ -2,12 +2,16 @@ //! //! This file contains numeric instructions for int and float. +// There has to be a better way to declare these functions. +// Just don't know enough Rust yet ig. + use crate::push::state::{EMPTY_STATE, PushState}; -use rust_decimal::Decimal; +use rust_decimal::prelude::{FromPrimitive, ToPrimitive}; +use rust_decimal::{Decimal, MathematicalOps, dec}; use std::cmp::{max, min}; use std::ops::{Add, Div, Mul, Sub}; -use super::utils::CheckedDiv; +use super::utils::InstructionTrait; /// Adds two addable values together. fn _add(vals: Vec) -> Option @@ -42,7 +46,7 @@ make_instruction!(float, float, _mult, Decimal, 2); /// Divides two values from each other. fn _div(vals: Vec) -> Option where - T: Div + Copy + CheckedDiv, + T: Div + Copy + InstructionTrait, { vals[1].checked_div(vals[0]) } @@ -52,7 +56,7 @@ make_instruction!(float, float, _div, Decimal, 2); /// Takes the remainder of two values fn _rem(vals: Vec) -> Option where - T: Div + Copy + CheckedDiv, + T: Div + Copy + InstructionTrait, { vals[1].checked_mod(vals[0]) } @@ -66,6 +70,8 @@ where { Some(max(vals[1], vals[0])) } +make_instruction!(int, int, _max, i128, 2); +make_instruction!(float, float, _max, Decimal, 2); /// Takes the min of two values fn _min(vals: Vec) -> Option @@ -74,11 +80,227 @@ where { Some(min(vals[1], vals[0])) } +make_instruction!(int, int, _min, i128, 2); +make_instruction!(float, float, _min, Decimal, 2); + +/// Increments a single value by 1 +fn _inc(vals: Vec) -> Option +where + T: InstructionTrait + Copy, +{ + Some(vals[0].increment()) +} +make_instruction!(int, int, _inc, i128, 1); +make_instruction!(float, float, _inc, Decimal, 1); + +/// Decrements a single value by 1 +fn _dec(vals: Vec) -> Option +where + T: InstructionTrait + Copy, +{ + Some(vals[0].decrement()) +} +make_instruction!(int, int, _dec, i128, 1); +make_instruction!(float, float, _dec, Decimal, 1); + +/// Checks if the 2nd to top value is less than the top value +fn _lt(vals: Vec) -> Option +where + T: Ord + Copy, +{ + Some(vals[1] < vals[0]) +} +make_instruction!(int, boolean, _lt, i128, 2); +make_instruction!(float, boolean, _lt, Decimal, 2); + +/// Checks if the 2nd to top value is greater than the top value +fn _gt(vals: Vec) -> Option +where + T: Ord + Copy, +{ + Some(vals[1] > vals[0]) +} +make_instruction!(int, boolean, _gt, i128, 2); +make_instruction!(float, boolean, _gt, Decimal, 2); + +/// Checks if the 2nd to top value is less than or equal to the top value +fn _lte(vals: Vec) -> Option +where + T: Ord + Copy, +{ + Some(vals[1] <= vals[0]) +} +make_instruction!(int, boolean, _lte, i128, 2); +make_instruction!(float, boolean, _lte, Decimal, 2); + +/// Checks if the 2nd to top value is greater than or equal to the top value +fn _gte(vals: Vec) -> Option +where + T: Ord + Copy, +{ + Some(vals[1] >= vals[0]) +} +make_instruction!(int, boolean, _gte, i128, 2); +make_instruction!(float, boolean, _gte, Decimal, 2); + +/// Runs sin on a single item. +fn _sin(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_sin() +} +make_instruction!(int, int, _sin, i128, 1); +make_instruction!(float, float, _sin, Decimal, 1); + +/// Runs arcsin on a single item. +fn _arcsin(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_sin()?.inverse() +} +make_instruction!(int, int, _arcsin, i128, 1); +make_instruction!(float, float, _arcsin, Decimal, 1); + +/// Runs cos on a single item. +fn _cos(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_cos() +} +make_instruction!(int, int, _cos, i128, 1); +make_instruction!(float, float, _cos, Decimal, 1); + +/// Runs arcsin on a single item. +fn _arccos(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_cos()?.inverse() +} +make_instruction!(int, int, _arccos, i128, 1); +make_instruction!(float, float, _arccos, Decimal, 1); + +/// Runs tan on a single item. +fn _tan(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_tan() +} +make_instruction!(int, int, _tan, i128, 1); +make_instruction!(float, float, _tan, Decimal, 1); + +/// Runs arctan on a single item. +fn _arctan(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_tan()?.inverse() +} +make_instruction!(int, int, _arctan, i128, 1); +make_instruction!(float, float, _arctan, Decimal, 1); + +/// Converts the top int to a float. +fn _to_int(vals: Vec) -> Option { + vals[0].to_i128() +} +make_instruction!(float, int, _to_int, Decimal, 1); + +/// Converts the top float to an int. +fn _to_float(vals: Vec) -> Option { + Decimal::from_i128(vals[0]) +} +make_instruction!(int, float, _to_float, i128, 1); + +/// Converts a single number to a bool. +fn _to_bool(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + Some(vals[0].to_bool()) +} +make_instruction!(int, boolean, _to_bool, i128, 1); +make_instruction!(float, boolean, _to_bool, Decimal, 1); + +/// Takes the log base 10 of a single Decimal. Acts as a +/// NoOp if the value is 0. If the value is negative, takes +/// the absolute value of the number. +fn _log(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].absolute().safe_log10() +} +make_instruction!(int, int, _log, i128, 1); +make_instruction!(float, float, _log, Decimal, 1); + +/// Takes the exp of a single value. Ints get truncated. +fn _exp(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_exp() +} +make_instruction!(int, int, _exp, i128, 1); +make_instruction!(float, float, _exp, Decimal, 1); + +/// Takes the square root of the absolute value of a single value. +fn _sqrt(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].safe_sqrt() +} +make_instruction!(int, int, _sqrt, i128, 1); +make_instruction!(float, float, _sqrt, Decimal, 1); + +/// Takes the inverse of a single value. If the number is 0, +/// does nothing (returns None). Truncates an int to 0. +fn _inv(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + vals[0].inverse() +} +make_instruction!(int, int, _inv, i128, 1); +make_instruction!(float, float, _inv, Decimal, 1); + +/// Takes the absolute value of the top number +fn _abs(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + Some(vals[0].absolute()) +} +make_instruction!(int, int, _abs, i128, 1); +make_instruction!(float, float, _abs, Decimal, 1); + +/// Reverses the sign of the top number +fn _sign_reverse(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + Some(vals[0].sign_reverse()) +} +make_instruction!(int, int, _sign_reverse, i128, 1); +make_instruction!(float, float, _sign_reverse, Decimal, 1); + +/// Squares the top number +fn _square(vals: Vec) -> Option +where + T: Copy + InstructionTrait, +{ + Some(vals[0].square()) +} +make_instruction!(int, int, _square, i128, 1); +make_instruction!(float, float, _square, Decimal, 1); #[cfg(test)] mod tests { use super::*; - use rust_decimal_macros::dec; /// Tests the _add function. #[test] @@ -171,6 +393,95 @@ mod tests { assert_eq!(Some(dec!(-1.1)), _min(vals)); } + /// Tests the _inc and _dec functions + #[test] + fn inc_dec_test() { + let vals: Vec = vec![2]; + assert_eq!(Some(3), _inc(vals)); + + let vals: Vec = vec![10]; + assert_eq!(Some(9), _dec(vals)); + + let vals: Vec = vec![dec!(2.2)]; + assert_eq!(Some(dec!(3.2)), _inc(vals)); + + let vals: Vec = vec![dec!(5.6)]; + assert_eq!(Some(dec!(4.6)), _dec(vals)); + } + + /// Tests the _lt, _gt, _lte, and _gte functions + #[test] + fn lt_gt_lte_gte_test() { + let vals: Vec = vec![3, 2]; + assert_eq!(Some(true), _lt(vals)); + + let vals: Vec = vec![1, 4]; + assert_eq!(Some(false), _lt(vals)); + + let vals: Vec = vec![3, 3]; + assert_eq!(Some(false), _lt(vals)); + + let vals: Vec = vec![2, 3]; + assert_eq!(Some(true), _gt(vals)); + + let vals: Vec = vec![4, 1]; + assert_eq!(Some(false), _gt(vals)); + + let vals: Vec = vec![3, 3]; + assert_eq!(Some(false), _gt(vals)); + + let vals: Vec = vec![3, 2]; + assert_eq!(Some(true), _lte(vals)); + + let vals: Vec = vec![1, 4]; + assert_eq!(Some(false), _lte(vals)); + + let vals: Vec = vec![3, 3]; + assert_eq!(Some(true), _lte(vals)); + + let vals: Vec = vec![2, 3]; + assert_eq!(Some(true), _gte(vals)); + + let vals: Vec = vec![4, 1]; + assert_eq!(Some(false), _gte(vals)); + + let vals: Vec = vec![3, 3]; + assert_eq!(Some(true), _gte(vals)); + } + + /// Tests the various trig functions. + #[test] + fn trig_tests() { + let vals = vec![Decimal::PI]; + assert_eq!(Some(dec!(0.0)), _sin(vals)); + + let vals = vec![Decimal::QUARTER_PI]; + assert_eq!(Some(dec!(1.4142135623869512272301701717)), _arcsin(vals)); + + let vals = vec![Decimal::PI]; + assert_eq!(Some(dec!(-1.0)), _cos(vals)); + + let vals = vec![Decimal::QUARTER_PI]; + assert_eq!(Some(dec!(1.4142135626023406165042434783)), _arccos(vals)); + + let vals = vec![Decimal::PI]; + assert_eq!(Some(dec!(0.0)), _tan(vals)); + + let vals = vec![Decimal::QUARTER_PI]; + assert_eq!(Some(dec!(1.0000000043184676055890307049)), _arctan(vals)); + } + + /// Tests the functions that cast from one numeric type + /// to another + #[test] + fn cast_tests() { + let vals = vec![dec!(1.2)]; + assert_eq!(Some(1), _to_int(vals)); + + let vals: Vec = vec![2]; + assert_eq!(Some(dec!(2.0)), _to_float(vals)); + } + /// Tests that the various addition functions. #[test] fn state_add() { @@ -262,4 +573,317 @@ mod tests { float_rem(&mut test_state); assert_eq!(vec![dec!(0.3)], test_state.float); } + + /// Tests the min and max functions in the state + #[test] + fn state_min_max() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![0]; + int_max(&mut test_state); + assert_eq!(vec![0], test_state.int); + + test_state.int = vec![0]; + int_min(&mut test_state); + assert_eq!(vec![0], test_state.int); + + test_state.int = vec![1, 2, 3]; + int_max(&mut test_state); + assert_eq!(vec![1, 3], test_state.int); + + test_state.int = vec![1, 2, 3]; + int_min(&mut test_state); + assert_eq!(vec![1, 2], test_state.int); + + test_state.float = vec![dec!(1.2), dec!(4.6)]; + float_max(&mut test_state); + assert_eq!(vec![dec!(4.6)], test_state.float); + + test_state.float = vec![dec!(0.0), dec!(1.2), dec!(4.6)]; + float_min(&mut test_state); + assert_eq!(vec![dec!(0.0), dec!(1.2)], test_state.float); + } + + /// Tests the inc and dec functions in the state + #[test] + fn state_inc_dec() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![]; + int_inc(&mut test_state); + let empty_vec: Vec = vec![]; + assert_eq!(empty_vec, test_state.int); + + drop(empty_vec); + + test_state.int = vec![-2, 1]; + int_inc(&mut test_state); + assert_eq!(vec![-2, 2], test_state.int); + + test_state.int = vec![-2, 1]; + int_dec(&mut test_state); + assert_eq!(vec![-2, 0], test_state.int); + + test_state.float = vec![dec!(1.1)]; + float_inc(&mut test_state); + assert_eq!(vec![dec!(2.1)], test_state.float); + + test_state.float = vec![dec!(1.1)]; + float_dec(&mut test_state); + assert_eq!(vec![dec!(0.1)], test_state.float); + } + + /// Tests the lt, gt, lte, gte functions in the state + #[test] + fn state_lt_gt_lte_gte() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![2, 3]; + int_lt(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + + test_state.int = vec![4, 1]; + test_state.boolean = vec![]; + int_lt(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![3, 3]; + test_state.boolean = vec![]; + int_lt(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![3, 2]; + test_state.boolean = vec![]; + int_gt(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + + test_state.int = vec![1, 4]; + test_state.boolean = vec![]; + int_gt(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![3, 3]; + test_state.boolean = vec![]; + int_gt(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![2, 3]; + test_state.boolean = vec![]; + int_lte(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + + test_state.int = vec![4, 1]; + test_state.boolean = vec![]; + int_lte(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![3, 3]; + test_state.boolean = vec![]; + int_lte(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + + test_state.int = vec![3, 2]; + test_state.boolean = vec![]; + int_gte(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + + test_state.int = vec![1, 4]; + test_state.boolean = vec![]; + int_gte(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + + test_state.int = vec![3, 3]; + test_state.boolean = vec![]; + int_gte(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + } + + /// Tests the various trig functions when they should revert. + #[test] + fn state_trig() { + let mut test_state = EMPTY_STATE; + + test_state.float = vec![Decimal::HALF_PI]; + float_tan(&mut test_state); + assert_eq!(vec![Decimal::HALF_PI], test_state.float); + + test_state.float = vec![Decimal::HALF_PI]; + float_arccos(&mut test_state); + assert_eq!(vec![Decimal::HALF_PI], test_state.float); + + test_state.float = vec![dec!(3.4), Decimal::PI]; + float_arcsin(&mut test_state); + assert_eq!(vec![dec!(3.4), Decimal::PI], test_state.float); + } + + /// Tests the int and float casting functions + #[test] + fn state_cast() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![0, 1]; + int_to_float(&mut test_state); + assert_eq!(vec![dec!(1.0)], test_state.float); + + test_state.int.clear(); + test_state.float = vec![dec!(2.1)]; + float_to_int(&mut test_state); + assert_eq!(vec![2], test_state.int); + + test_state.int = vec![1]; + int_to_bool(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + test_state.boolean.clear(); + + test_state.int = vec![0]; + int_to_bool(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + test_state.boolean.clear(); + + test_state.float = vec![dec!(2.0)]; + float_to_bool(&mut test_state); + assert_eq!(vec![true], test_state.boolean); + test_state.boolean.clear(); + + test_state.float = vec![dec!(0.0)]; + float_to_bool(&mut test_state); + assert_eq!(vec![false], test_state.boolean); + } + + /// Tests the log function + #[test] + fn state_log() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![1]; + int_log(&mut test_state); + assert_eq!(vec![0], test_state.int); + test_state.int.clear(); + + test_state.float = vec![dec!(2)]; + float_log(&mut test_state); + assert_eq!(vec![dec!(0.3010299956639811952137388949)], test_state.float); + test_state.float.clear(); + + test_state.int = vec![6, 7, 0]; + int_log(&mut test_state); + assert_eq!(vec![6, 7, 0], test_state.int); + + test_state.float = vec![dec!(-4.5)]; + float_log(&mut test_state); + assert_eq!(vec![dec!(0.6532125137753436793763169119)], test_state.float); + } + + /// Tests the exp function + #[test] + fn state_exp() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![0]; + int_exp(&mut test_state); + assert_eq!(vec![1], test_state.int); + + test_state.int = vec![0, 2]; + int_exp(&mut test_state); + assert_eq!(vec![0, 7], test_state.int); + + test_state.int.clear(); + test_state.float = vec![dec!(1.2)]; + float_exp(&mut test_state); + assert_eq!(vec![dec!(3.3201169022444051948051948052)], test_state.float); + } + + /// Tests the sqrt function + #[test] + fn state_sqrt() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![4]; + int_sqrt(&mut test_state); + assert_eq!(vec![2], test_state.int); + + test_state.int = vec![5]; + int_sqrt(&mut test_state); + assert_eq!(vec![2], test_state.int); + + test_state.float = vec![dec!(4.84)]; + float_sqrt(&mut test_state); + assert_eq!(vec![dec!(2.2)], test_state.float); + + test_state.int = vec![-1]; + int_sqrt(&mut test_state); + assert_eq!(vec![1], test_state.int); + + test_state.float = vec![dec!(-1.0)]; + float_sqrt(&mut test_state); + assert_eq!(vec![dec!(1.0)], test_state.float); + } + + /// Tests the inv function + #[test] + fn state_inv() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![-1, 10]; + int_inv(&mut test_state); + assert_eq!(vec![-1, 0], test_state.int); + + test_state.float = vec![dec!(-10)]; + float_inv(&mut test_state); + assert_eq!(vec![dec!(-0.1)], test_state.float); + + test_state.int = vec![0]; + int_inv(&mut test_state); + assert_eq!(vec![0], test_state.int); + } + + /// Tests the abs function + #[test] + fn state_abs() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![-1]; + int_abs(&mut test_state); + assert_eq!(vec![1], test_state.int); + + test_state.float = vec![dec!(-2.7)]; + float_abs(&mut test_state); + assert_eq!(vec![dec!(2.7)], test_state.float); + } + + /// Tests the sign reverse function + #[test] + fn state_sign_reverse() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![-2]; + int_sign_reverse(&mut test_state); + assert_eq!(vec![2], test_state.int); + + test_state.int = vec![3]; + int_sign_reverse(&mut test_state); + assert_eq!(vec![-3], test_state.int); + + test_state.float = vec![dec!(3.0), dec!(-2.0)]; + float_sign_reverse(&mut test_state); + assert_eq!(vec![dec!(3.0), dec!(2.0)], test_state.float); + + test_state.float = vec![dec!(3.0)]; + float_sign_reverse(&mut test_state); + assert_eq!(vec![dec!(-3.0)], test_state.float); + } + + /// Tests the square function + #[test] + fn state_square() { + let mut test_state = EMPTY_STATE; + + test_state.int = vec![2, 3]; + int_square(&mut test_state); + assert_eq!(vec![2, 9], test_state.int); + + test_state.float = vec![dec!(-4.0)]; + float_square(&mut test_state); + assert_eq!(vec![dec!(16.0)], test_state.float); + } } diff --git a/src/instructions/utils.rs b/src/instructions/utils.rs index 8596275..9b9dd45 100644 --- a/src/instructions/utils.rs +++ b/src/instructions/utils.rs @@ -1,26 +1,128 @@ use rust_decimal::Decimal; -use rust_decimal_macros::dec; +use rust_decimal::prelude::*; use std::ops::Div; -pub trait CheckedDiv: Sized + Div { +/// This trait houses various methods for making instructions +/// more generic instead of declaring a separate function for each +/// stack. In a way I'm doing that here, but in a more Rusty way. +/// +/// Trig functions named safe rather than checked to not overlap +/// with Decimal library's checked function names. +pub trait InstructionTrait: Sized + Div { fn checked_div(self, v: Self) -> Option; fn checked_mod(self, v: Self) -> Option; + fn increment(self) -> Self; + fn decrement(self) -> Self; + fn safe_sin(self) -> Option; + fn safe_cos(self) -> Option; + fn safe_tan(self) -> Option; + fn inverse(self) -> Option; + fn safe_exp(self) -> Option; + fn absolute(self) -> Self; + fn safe_log10(self) -> Option; + fn safe_sqrt(self) -> Option; + fn to_bool(self) -> bool; + fn sign_reverse(self) -> Self; + fn square(self) -> Self; } -impl CheckedDiv for Decimal { +impl InstructionTrait for Decimal { fn checked_div(self, v: Self) -> Option { if v == dec!(0.0) { None } else { Some(self / v) } } fn checked_mod(self, v: Self) -> Option { if v == dec!(0.0) { None } else { Some(self % v) } } + fn increment(self) -> Self { + self + dec!(1.0) + } + fn decrement(self) -> Self { + self - dec!(1.0) + } + fn safe_sin(self) -> Option { + self.checked_sin() + } + fn safe_cos(self) -> Option { + self.checked_cos() + } + fn safe_tan(self) -> Option { + self.checked_tan() + } + fn inverse(self) -> Option { + dec!(1.0).checked_div(self) + } + fn safe_exp(self) -> Option { + self.checked_exp() + } + fn absolute(self) -> Self { + self.abs() + } + fn safe_log10(self) -> Option { + self.absolute().checked_log10() + } + fn safe_sqrt(self) -> Option { + self.absolute().sqrt() + } + fn to_bool(self) -> bool { + if self == dec!(0.0) { false } else { true } + } + fn sign_reverse(self) -> Self { + self * dec!(-1) + } + fn square(self) -> Self { + self * self + } } -impl CheckedDiv for i128 { +impl InstructionTrait for i128 { fn checked_div(self, v: Self) -> Option { if v == 0 { None } else { Some(self / v) } } fn checked_mod(self, v: Self) -> Option { if v == 0 { None } else { Some(self % v) } } + fn increment(self) -> Self { + self + 1 + } + fn decrement(self) -> Self { + self - 1 + } + /// Casts the i128 to a Decimal and takes the checked_sin + /// of the value. Casts the calculated value back to an i128. + fn safe_sin(self) -> Option { + Decimal::from_i128(self)?.checked_sin()?.to_i128() + } + fn safe_cos(self) -> Option { + Decimal::from_i128(self)?.checked_cos()?.to_i128() + } + fn safe_tan(self) -> Option { + Decimal::from_i128(self)?.checked_tan()?.to_i128() + } + fn inverse(self) -> Option { + if self == 0 { None } else { Some(1 / self) } + } + fn safe_exp(self) -> Option { + Decimal::from_i128(self)?.checked_exp()?.to_i128() + } + fn absolute(self) -> Self { + self.abs() + } + fn safe_log10(self) -> Option { + Decimal::from_i128(self)? + .absolute() + .checked_log10()? + .to_i128() + } + fn safe_sqrt(self) -> Option { + Decimal::from_i128(self)?.absolute().sqrt()?.to_i128() + } + fn to_bool(self) -> bool { + if self == 0 { false } else { true } + } + fn sign_reverse(self) -> Self { + -1 * self + } + fn square(self) -> Self { + self * self + } } diff --git a/src/main.rs b/src/main.rs index 26c103c..80e509f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,32 @@ +use instructions::utils::InstructionTrait; +use rust_decimal::MathematicalOps; use rust_decimal::prelude::*; -use rust_decimal_macros::dec; mod instructions; mod push; +fn test_func() {} +fn another_test_func() {} + fn main() { - // let arr: Vec = vec![]; - // let slice = &arr[..2]; - // println!("{:?}", slice); + // let sixth_pi = Decimal::PI / dec!(6.0); + // let result = dec!(1).sin(); + // let result = Decimal::PI.sin().checked_div(Decimal::PI.cos()); + // let result = dec!(1.0) / Decimal::HALF_PI.sin(); + // let result = sixth_pi.sin(); + // let result = Decimal::HALF_PI.cos(); + // let result = Decimal::PI.sin(); + // let result = Decimal::PI.tan(); + // let result = dec!(1.0) / Decimal::QUARTER_PI.tan(); + // let result = dec!(1.0) / Decimal::QUARTER_PI.cos(); + // let result = dec!(1.2).checked_exp(); + let result = dec!(2).log10(); - // let arr: Vec = vec![dec!(2.2), dec!(1.1)]; - // println!("{arr:?}"); + println!("{result:?}"); + // println!("{sixth_pi}"); - // let result = dec!(1.0) / dec!(0.0); - let result = dec!(2.7) % dec!(1.2); - println!("{result}"); + // casting a function call to a usize is a way to + // test for function equality. + let test_func_result = test_func as usize == test_func as usize; + println!("{test_func_result}"); } diff --git a/src/push/state.rs b/src/push/state.rs index c4aee36..5c75d91 100644 --- a/src/push/state.rs +++ b/src/push/state.rs @@ -9,12 +9,12 @@ pub struct PushState { pub int: Vec, pub float: Vec, pub string: Vec>, - pub bool: Vec, + pub boolean: Vec, pub char: Vec, pub vector_int: Vec>, pub vector_float: Vec>, pub vector_string: Vec>>, - pub vector_bool: Vec>, + pub vector_boolean: Vec>, pub vector_char: Vec, } @@ -22,11 +22,11 @@ pub const EMPTY_STATE: PushState = PushState { int: vec![], float: vec![], string: vec![], - bool: vec![], + boolean: vec![], char: vec![], vector_int: vec![], vector_float: vec![], vector_string: vec![], - vector_bool: vec![], + vector_boolean: vec![], vector_char: vec![], };