diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 081d6a6..2008fa4 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -418,6 +418,8 @@ pub fn string_instructions() -> Vec { string_split_on, string_replace, string_remove, + string_insert, + string_insert_vector, // common.rs string_pop, ] @@ -480,6 +482,11 @@ pub fn vector_int_instructions() -> Vec { vector_int_split_on, vector_int_replace, vector_int_remove, + vector_int_iterate, + vector_int_sort, + vector_int_sort_reverse, + vector_int_insert, + vector_int_insert_vector, // common.rs vector_int_pop, ] @@ -521,6 +528,11 @@ pub fn vector_float_instructions() -> Vec { vector_float_split_on, vector_float_replace, vector_float_remove, + vector_float_iterate, + vector_float_sort, + vector_float_sort_reverse, + vector_float_insert, + vector_float_insert_vector, // common.rs vector_float_pop, ] @@ -561,6 +573,8 @@ pub fn vector_string_instructions() -> Vec { vector_string_split_on, vector_string_replace, vector_string_remove, + vector_string_insert, + vector_string_insert_vector, // common.rs vector_string_pop, ] @@ -602,6 +616,9 @@ pub fn vector_boolean_instructions() -> Vec { vector_boolean_split_on, vector_boolean_replace, vector_boolean_remove, + vector_boolean_iterate, + vector_boolean_insert, + vector_boolean_insert_vector, // common.rs vector_boolean_pop, ] @@ -643,6 +660,9 @@ pub fn vector_char_instructions() -> Vec { vector_char_split_on, vector_char_replace, vector_char_remove, + vector_char_iterate, + vector_char_insert, + vector_char_insert_vector, // common.rs vector_char_pop, ] diff --git a/src/instructions/utils.rs b/src/instructions/utils.rs index d27d490..572c11b 100644 --- a/src/instructions/utils.rs +++ b/src/instructions/utils.rs @@ -1,6 +1,6 @@ use rust_decimal::Decimal; use rust_decimal::prelude::*; -use std::ops::Div; +use std::ops::{Add, Div}; /// This trait houses various methods for making instructions /// more generic instead of declaring a separate function for each @@ -8,7 +8,7 @@ use std::ops::Div; /// /// Trig functions named safe rather than checked to not overlap /// with Decimal library's checked function names. -pub trait NumericTrait: Sized + Div + Ord { +pub trait NumericTrait: Sized + Add + Div + Ord { fn checked_div(self, v: Self) -> Option; fn checked_mod(self, v: Self) -> Option; fn increment(self) -> Self; @@ -23,6 +23,8 @@ pub trait NumericTrait: Sized + Div + Ord { fn safe_sqrt(self) -> Option; fn sign_reverse(self) -> Self; fn square(self) -> Self; + fn zero() -> Self; + fn from_usize(num: usize) -> Self; } impl NumericTrait for Decimal { @@ -68,6 +70,12 @@ impl NumericTrait for Decimal { fn square(self) -> Self { self * self } + fn zero() -> Self { + dec!(0.0) + } + fn from_usize(num: usize) -> Self { + Decimal::new(num as i64, 0) + } } impl NumericTrait for i128 { @@ -118,6 +126,12 @@ impl NumericTrait for i128 { fn square(self) -> Self { self * self } + fn zero() -> Self { + 0 + } + fn from_usize(num: usize) -> Self { + num as Self + } } /// A trait for types to implement logical functions that work diff --git a/src/instructions/vector.rs b/src/instructions/vector.rs index f8a4615..606b989 100644 --- a/src/instructions/vector.rs +++ b/src/instructions/vector.rs @@ -1,3 +1,4 @@ +use crate::instructions::utils::NumericTrait; use crate::push::state::{Gene, PushState}; use rust_decimal::Decimal; use std::collections::HashSet; @@ -1396,12 +1397,198 @@ make_iterate!(vector_boolean, boolean, GeneVectorBoolean); make_iterate!(vector_char, char, GeneVectorChar); //make_iterate!(string, string, GeneString); +/// Sorts a vector +pub fn _sort(mut vals: Vec>) -> Option> +where + T: NumericTrait + Clone, +{ + vals[0].sort(); + Some(vals[0].clone()) +} +make_instruction_clone!(vector_int, vector_int, _sort, Vec, 1); +make_instruction_clone!(vector_float, vector_float, _sort, Vec, 1); + +/// Sorts a vector and reverses it +pub fn _sort_reverse(mut vals: Vec>) -> Option> +where + T: NumericTrait + Clone, +{ + vals[0].sort(); + vals[0].reverse(); + Some(vals[0].clone()) +} +make_instruction_clone!(vector_int, vector_int, _sort_reverse, Vec, 1); +make_instruction_clone!(vector_float, vector_float, _sort_reverse, Vec, 1); + +/// Inserts a primitive into a vector at a given point from the int stack +pub fn _insert(mut vals: Vec>, auxs: Vec, auxs2: Vec) -> Option> +where + T: Clone, +{ + let vec_len = vals[0].len(); + vals[0].insert(bounded_idx(auxs2[0], vec_len), auxs[0].clone()); + Some(vals[0].clone()) +} +make_instruction_aux2!( + vector_int, + vector_int, + _insert, + Vec, + 1, + int, + 1, + i128, + int, + 1, + i128 +); +make_instruction_aux2!( + vector_float, + vector_float, + _insert, + Vec, + 1, + float, + 1, + Decimal, + int, + 1, + i128 +); +make_instruction_aux2!( + vector_string, + vector_string, + _insert, + Vec>, + 1, + string, + 1, + Vec, + int, + 1, + i128 +); +make_instruction_aux2!( + vector_boolean, + vector_boolean, + _insert, + Vec, + 1, + boolean, + 1, + bool, + int, + 1, + i128 +); +make_instruction_aux2!( + vector_char, + vector_char, + _insert, + Vec, + 1, + char, + 1, + char, + int, + 1, + i128 +); +make_instruction_aux2!( + string, + string, + _insert, + Vec, + 1, + char, + 1, + char, + int, + 1, + i128 +); + +/// Inserts one vector into another based on an index. +pub fn _insert_vector(mut vals: Vec>, auxs: Vec) -> Option> +where + T: Clone, +{ + let vec_len = vals[0].len(); + let idx = bounded_idx(auxs[0], vec_len); + let insert_list = vals[0].clone(); + vals[1].splice(idx..idx, insert_list); + Some(vals[1].clone()) +} +make_instruction_aux!( + vector_int, + vector_int, + _insert_vector, + Vec, + 2, + int, + 1, + i128 +); +make_instruction_aux!( + vector_float, + vector_float, + _insert_vector, + Vec, + 2, + int, + 1, + i128 +); +make_instruction_aux!( + vector_string, + vector_string, + _insert_vector, + Vec>, + 2, + int, + 1, + i128 +); +make_instruction_aux!( + vector_boolean, + vector_boolean, + _insert_vector, + Vec, + 2, + int, + 1, + i128 +); +make_instruction_aux!( + vector_char, + vector_char, + _insert_vector, + Vec, + 2, + int, + 1, + i128 +); +make_instruction_aux!(string, string, _insert_vector, Vec, 2, int, 1, i128); + +/// Takes the mean of a vector +pub fn _mean(vals: Vec>) -> Option { + let mut fin_num = T::zero(); + for num in vals[0].clone().into_iter() { + fin_num = fin_num + num; + } + Some(fin_num.div(T::from_usize(vals[0].len()))) +} +make_instruction_clone!(vector_int, int, _mean, Vec, 1); +make_instruction_clone!(vector_float, float, _mean, Vec, 1); + #[cfg(test)] mod tests { use super::*; use crate::instructions::numeric::int_inc; use crate::push::interpreter::interpret_program; use crate::push::state::EMPTY_STATE; + use rust_decimal::dec; #[test] fn vector_concat_test() { @@ -2041,7 +2228,106 @@ mod tests { Gene::StateFunc(vector_int_iterate), ]; interpret_program(&mut test_state, 1000, 1000); - println!("{:?}", test_state); assert_eq!(vec![1, 2, 3, 4, 5, 6, 3], test_state.int); } + + #[test] + fn sort_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2, 3, 4, 5, 2]]; + vector_int_sort(&mut test_state); + assert_eq!(vec![vec![0, 1, 2, 2, 3, 4, 5]], test_state.vector_int); + + test_state.vector_float = vec![vec![dec!(0.0), dec!(1.2), dec!(-3.4)]]; + vector_float_sort(&mut test_state); + assert_eq!( + vec![vec![dec!(-3.4), dec!(0.0), dec!(1.2)]], + test_state.vector_float + ); + + test_state.vector_int = vec![vec![]]; + vector_int_sort(&mut test_state); + assert_eq!(vec![Vec::::new()], test_state.vector_int); + } + + #[test] + fn sort_reverse_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2, 3, 4, 5, 2]]; + vector_int_sort_reverse(&mut test_state); + assert_eq!(vec![vec![5, 4, 3, 2, 2, 1, 0]], test_state.vector_int); + + test_state.vector_float = vec![vec![dec!(0.0), dec!(1.2), dec!(-3.4)]]; + vector_float_sort_reverse(&mut test_state); + assert_eq!( + vec![vec![dec!(1.2), dec!(0.0), dec!(-3.4)]], + test_state.vector_float + ); + + test_state.vector_int = vec![vec![]]; + vector_int_sort_reverse(&mut test_state); + assert_eq!(vec![Vec::::new()], test_state.vector_int); + } + + #[test] + fn insert_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2, 3]]; + test_state.int = vec![9, 1]; + vector_int_insert(&mut test_state); + assert_eq!(vec![vec![0, 9, 1, 2, 3]], test_state.vector_int); + + test_state.vector_boolean = vec![vec![false, true, false]]; + test_state.int = vec![0]; + test_state.boolean = vec![false]; + vector_boolean_insert(&mut test_state); + assert_eq!( + vec![vec![false, false, true, false]], + test_state.vector_boolean + ); + + test_state.vector_int = vec![vec![0, 1, 2, 3]]; + test_state.int = vec![9, 5]; + vector_int_insert(&mut test_state); + assert_eq!(vec![vec![0, 9, 1, 2, 3]], test_state.vector_int); + } + + #[test] + fn insert_vector_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![0, 1, 2, 3], vec![69, 69]]; + test_state.int = vec![1]; + vector_int_insert_vector(&mut test_state); + assert_eq!(vec![vec![0, 69, 69, 1, 2, 3]], test_state.vector_int); + + test_state.vector_boolean = vec![vec![false, true, false], vec![false, true]]; + test_state.int = vec![0]; + vector_boolean_insert_vector(&mut test_state); + assert_eq!( + vec![vec![false, true, false, true, false]], + test_state.vector_boolean + ); + + test_state.vector_int = vec![vec![0, 1, 2, 3], vec![69, 69]]; + test_state.int = vec![5]; + vector_int_insert_vector(&mut test_state); + assert_eq!(vec![vec![0, 69, 69, 1, 2, 3]], test_state.vector_int); + } + + #[test] + fn mean_test() { + let mut test_state = EMPTY_STATE; + + test_state.vector_int = vec![vec![6, 5, 4]]; + vector_int_mean(&mut test_state); + assert_eq!(vec![5], test_state.int); + + test_state.vector_float = vec![vec![dec!(6.0), dec!(5.0), dec!(4.0)]]; + vector_float_mean(&mut test_state); + assert_eq!(vec![dec!(5.0)], test_state.float); + } }