Compare commits

...

3 Commits

6 changed files with 768 additions and 26 deletions

View File

@ -6,5 +6,4 @@ edition = "2024"
[dependencies] [dependencies]
rand = "0.9.0" rand = "0.9.0"
paste = "1.0.15" paste = "1.0.15"
rust_decimal = "1.37" rust_decimal = { version = "1.37", features = ["macros", "maths"] }
rust_decimal_macros = "1.37"

View File

@ -22,13 +22,16 @@ pub mod macros {
macro_rules! make_instruction { macro_rules! make_instruction {
($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => {
paste::item! { 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) { 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; return;
} }
let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity);
for n in 1..=$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) { if let Some(result) = $fn_name(inputs) {
for _ in 0..$fn_arity { for _ in 0..$fn_arity {

View File

@ -2,12 +2,16 @@
//! //!
//! This file contains numeric instructions for int and float. //! 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 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::cmp::{max, min};
use std::ops::{Add, Div, Mul, Sub}; use std::ops::{Add, Div, Mul, Sub};
use super::utils::CheckedDiv; use super::utils::InstructionTrait;
/// Adds two addable values together. /// Adds two addable values together.
fn _add<T>(vals: Vec<T>) -> Option<T> fn _add<T>(vals: Vec<T>) -> Option<T>
@ -42,7 +46,7 @@ make_instruction!(float, float, _mult, Decimal, 2);
/// Divides two values from each other. /// Divides two values from each other.
fn _div<T>(vals: Vec<T>) -> Option<T> fn _div<T>(vals: Vec<T>) -> Option<T>
where where
T: Div<Output = T> + Copy + CheckedDiv, T: Div<Output = T> + Copy + InstructionTrait,
{ {
vals[1].checked_div(vals[0]) vals[1].checked_div(vals[0])
} }
@ -52,7 +56,7 @@ make_instruction!(float, float, _div, Decimal, 2);
/// Takes the remainder of two values /// Takes the remainder of two values
fn _rem<T>(vals: Vec<T>) -> Option<T> fn _rem<T>(vals: Vec<T>) -> Option<T>
where where
T: Div<Output = T> + Copy + CheckedDiv, T: Div<Output = T> + Copy + InstructionTrait,
{ {
vals[1].checked_mod(vals[0]) vals[1].checked_mod(vals[0])
} }
@ -66,6 +70,8 @@ where
{ {
Some(max(vals[1], vals[0])) 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 /// Takes the min of two values
fn _min<T>(vals: Vec<T>) -> Option<T> fn _min<T>(vals: Vec<T>) -> Option<T>
@ -74,11 +80,227 @@ where
{ {
Some(min(vals[1], vals[0])) 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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<bool>
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<T>(vals: Vec<T>) -> Option<bool>
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<T>(vals: Vec<T>) -> Option<bool>
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<T>(vals: Vec<T>) -> Option<bool>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<Decimal>) -> Option<i128> {
vals[0].to_i128()
}
make_instruction!(float, int, _to_int, Decimal, 1);
/// Converts the top float to an int.
fn _to_float(vals: Vec<i128>) -> Option<Decimal> {
Decimal::from_i128(vals[0])
}
make_instruction!(int, float, _to_float, i128, 1);
/// Converts a single number to a bool.
fn _to_bool<T>(vals: Vec<T>) -> Option<bool>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
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<T>(vals: Vec<T>) -> Option<T>
where
T: Copy + InstructionTrait,
{
Some(vals[0].square())
}
make_instruction!(int, int, _square, i128, 1);
make_instruction!(float, float, _square, Decimal, 1);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use rust_decimal_macros::dec;
/// Tests the _add function. /// Tests the _add function.
#[test] #[test]
@ -171,6 +393,95 @@ mod tests {
assert_eq!(Some(dec!(-1.1)), _min(vals)); assert_eq!(Some(dec!(-1.1)), _min(vals));
} }
/// Tests the _inc and _dec functions
#[test]
fn inc_dec_test() {
let vals: Vec<i128> = vec![2];
assert_eq!(Some(3), _inc(vals));
let vals: Vec<i128> = vec![10];
assert_eq!(Some(9), _dec(vals));
let vals: Vec<Decimal> = vec![dec!(2.2)];
assert_eq!(Some(dec!(3.2)), _inc(vals));
let vals: Vec<Decimal> = 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<i128> = vec![3, 2];
assert_eq!(Some(true), _lt(vals));
let vals: Vec<i128> = vec![1, 4];
assert_eq!(Some(false), _lt(vals));
let vals: Vec<i128> = vec![3, 3];
assert_eq!(Some(false), _lt(vals));
let vals: Vec<i128> = vec![2, 3];
assert_eq!(Some(true), _gt(vals));
let vals: Vec<i128> = vec![4, 1];
assert_eq!(Some(false), _gt(vals));
let vals: Vec<i128> = vec![3, 3];
assert_eq!(Some(false), _gt(vals));
let vals: Vec<i128> = vec![3, 2];
assert_eq!(Some(true), _lte(vals));
let vals: Vec<i128> = vec![1, 4];
assert_eq!(Some(false), _lte(vals));
let vals: Vec<i128> = vec![3, 3];
assert_eq!(Some(true), _lte(vals));
let vals: Vec<i128> = vec![2, 3];
assert_eq!(Some(true), _gte(vals));
let vals: Vec<i128> = vec![4, 1];
assert_eq!(Some(false), _gte(vals));
let vals: Vec<i128> = 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<i128> = vec![2];
assert_eq!(Some(dec!(2.0)), _to_float(vals));
}
/// Tests that the various addition functions. /// Tests that the various addition functions.
#[test] #[test]
fn state_add() { fn state_add() {
@ -262,4 +573,317 @@ mod tests {
float_rem(&mut test_state); float_rem(&mut test_state);
assert_eq!(vec![dec!(0.3)], test_state.float); 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<i128> = 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);
}
} }

View File

@ -1,26 +1,128 @@
use rust_decimal::Decimal; use rust_decimal::Decimal;
use rust_decimal_macros::dec; use rust_decimal::prelude::*;
use std::ops::Div; use std::ops::Div;
pub trait CheckedDiv: Sized + Div<Output = Self> { /// 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<Output = Self> {
fn checked_div(self, v: Self) -> Option<Self>; fn checked_div(self, v: Self) -> Option<Self>;
fn checked_mod(self, v: Self) -> Option<Self>; fn checked_mod(self, v: Self) -> Option<Self>;
fn increment(self) -> Self;
fn decrement(self) -> Self;
fn safe_sin(self) -> Option<Self>;
fn safe_cos(self) -> Option<Self>;
fn safe_tan(self) -> Option<Self>;
fn inverse(self) -> Option<Self>;
fn safe_exp(self) -> Option<Self>;
fn absolute(self) -> Self;
fn safe_log10(self) -> Option<Self>;
fn safe_sqrt(self) -> Option<Self>;
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<Self> { fn checked_div(self, v: Self) -> Option<Self> {
if v == dec!(0.0) { None } else { Some(self / v) } if v == dec!(0.0) { None } else { Some(self / v) }
} }
fn checked_mod(self, v: Self) -> Option<Self> { fn checked_mod(self, v: Self) -> Option<Self> {
if v == dec!(0.0) { None } else { Some(self % v) } 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> {
self.checked_sin()
}
fn safe_cos(self) -> Option<Self> {
self.checked_cos()
}
fn safe_tan(self) -> Option<Self> {
self.checked_tan()
}
fn inverse(self) -> Option<Self> {
dec!(1.0).checked_div(self)
}
fn safe_exp(self) -> Option<Self> {
self.checked_exp()
}
fn absolute(self) -> Self {
self.abs()
}
fn safe_log10(self) -> Option<Self> {
self.absolute().checked_log10()
}
fn safe_sqrt(self) -> Option<Self> {
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<Self> { fn checked_div(self, v: Self) -> Option<Self> {
if v == 0 { None } else { Some(self / v) } if v == 0 { None } else { Some(self / v) }
} }
fn checked_mod(self, v: Self) -> Option<Self> { fn checked_mod(self, v: Self) -> Option<Self> {
if v == 0 { None } else { Some(self % v) } 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<Self> {
Decimal::from_i128(self)?.checked_sin()?.to_i128()
}
fn safe_cos(self) -> Option<Self> {
Decimal::from_i128(self)?.checked_cos()?.to_i128()
}
fn safe_tan(self) -> Option<Self> {
Decimal::from_i128(self)?.checked_tan()?.to_i128()
}
fn inverse(self) -> Option<Self> {
if self == 0 { None } else { Some(1 / self) }
}
fn safe_exp(self) -> Option<Self> {
Decimal::from_i128(self)?.checked_exp()?.to_i128()
}
fn absolute(self) -> Self {
self.abs()
}
fn safe_log10(self) -> Option<Self> {
Decimal::from_i128(self)?
.absolute()
.checked_log10()?
.to_i128()
}
fn safe_sqrt(self) -> Option<Self> {
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
}
} }

View File

@ -1,18 +1,32 @@
use instructions::utils::InstructionTrait;
use rust_decimal::MathematicalOps;
use rust_decimal::prelude::*; use rust_decimal::prelude::*;
use rust_decimal_macros::dec;
mod instructions; mod instructions;
mod push; mod push;
fn test_func() {}
fn another_test_func() {}
fn main() { fn main() {
// let arr: Vec<i32> = vec![]; // let sixth_pi = Decimal::PI / dec!(6.0);
// let slice = &arr[..2]; // let result = dec!(1).sin();
// println!("{:?}", slice); // 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<Decimal> = vec![dec!(2.2), dec!(1.1)]; println!("{result:?}");
// println!("{arr:?}"); // println!("{sixth_pi}");
// let result = dec!(1.0) / dec!(0.0); // casting a function call to a usize is a way to
let result = dec!(2.7) % dec!(1.2); // test for function equality.
println!("{result}"); let test_func_result = test_func as usize == test_func as usize;
println!("{test_func_result}");
} }

View File

@ -9,12 +9,12 @@ pub struct PushState {
pub int: Vec<i128>, pub int: Vec<i128>,
pub float: Vec<Decimal>, pub float: Vec<Decimal>,
pub string: Vec<Vec<u8>>, pub string: Vec<Vec<u8>>,
pub bool: Vec<bool>, pub boolean: Vec<bool>,
pub char: Vec<u8>, pub char: Vec<u8>,
pub vector_int: Vec<Vec<i128>>, pub vector_int: Vec<Vec<i128>>,
pub vector_float: Vec<Vec<Decimal>>, pub vector_float: Vec<Vec<Decimal>>,
pub vector_string: Vec<Vec<Vec<u8>>>, pub vector_string: Vec<Vec<Vec<u8>>>,
pub vector_bool: Vec<Vec<bool>>, pub vector_boolean: Vec<Vec<bool>>,
pub vector_char: Vec<u8>, pub vector_char: Vec<u8>,
} }
@ -22,11 +22,11 @@ pub const EMPTY_STATE: PushState = PushState {
int: vec![], int: vec![],
float: vec![], float: vec![],
string: vec![], string: vec![],
bool: vec![], boolean: vec![],
char: vec![], char: vec![],
vector_int: vec![], vector_int: vec![],
vector_float: vec![], vector_float: vec![],
vector_string: vec![], vector_string: vec![],
vector_bool: vec![], vector_boolean: vec![],
vector_char: vec![], vector_char: vec![],
}; };