Compare commits
3 Commits
fa3371ec3b
...
9b682c5f3c
Author | SHA1 | Date | |
---|---|---|---|
9b682c5f3c | |||
dc608b3fad | |||
357d9af039 |
@ -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"
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
32
src/main.rs
32
src/main.rs
@ -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}");
|
||||||
}
|
}
|
||||||
|
@ -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![],
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user