From b2bfaa71a4736a55837d107d46261565bfdf915f Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Fri, 9 Feb 2024 11:51:59 -0500 Subject: [PATCH 01/30] Exposing internal rust functions to allow re-use for development of rhai-ml --- src/lib.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3cf175d..f21b1bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,28 +6,28 @@ #![doc = include_str!("../docs/highlight.html")] mod patterns; -use patterns::*; +pub use patterns::*; use rhai::{def_package, packages::Package, plugin::*, Engine, EvalAltResult}; mod matrices_and_arrays; -use matrices_and_arrays::matrix_functions; +pub use matrices_and_arrays::matrix_functions; mod statistics; -use statistics::stats; +pub use statistics::stats; mod misc; -use misc::misc_functions; +pub use misc::misc_functions; mod cumulative; -use cumulative::cum_functions; +pub use cumulative::cum_functions; mod integration_and_differentiation; -use integration_and_differentiation::int_and_diff; +pub use integration_and_differentiation::int_and_diff; mod assertions; -use assertions::assert_functions; +pub use assertions::assert_functions; mod constants; -use constants::constant_definitions; +pub use constants::constant_definitions; mod moving; -use moving::moving_functions; +pub use moving::moving_functions; mod sets; -use sets::set_functions; +pub use sets::set_functions; mod validate; -use validate::validation_functions; +pub use validate::validation_functions; def_package! { /// Package for scientific computing From d4ebda2505541f819f409dc0cbf9a2d8fbf4e95c Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sat, 17 Feb 2024 11:22:59 -0500 Subject: [PATCH 02/30] Added nnz --- src/matrices_and_arrays.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/matrices_and_arrays.rs b/src/matrices_and_arrays.rs index b308d00..7578622 100644 --- a/src/matrices_and_arrays.rs +++ b/src/matrices_and_arrays.rs @@ -5,7 +5,7 @@ use rhai::plugin::*; pub mod matrix_functions { use crate::{ if_int_convert_to_float_and_do, if_int_do_else_if_array_do, if_list_do, - if_matrix_convert_to_vec_array_and_do, + if_matrix_convert_to_vec_array_and_do, array_to_vec_float }; #[cfg(feature = "nalgebra")] use crate::{ @@ -357,6 +357,22 @@ pub mod matrix_functions { flatten(matrix).len() as INT } + /// Returns the number of non-zero elements in a matrix, passed by reference. + /// ```typescript + /// let matrix = ones(4, 6); + /// let n = nnz(matrix); + /// assert_eq(n, 24); + /// ``` + /// ```typescript + /// let matrix = eye(4); + /// let n = nnz(matrix); + /// assert_eq(n, 4); + /// ``` + #[rhai_fn(name = "nnz", pure)] + pub fn nnz_by_reference(matrix: &mut Array) -> INT { + array_to_vec_float(&mut flatten(matrix)).iter().filter(|&n| *n > 0.0).count() as INT + } + #[cfg(all(feature = "io"))] pub mod read_write { use polars::prelude::{CsvReader, DataType, SerReader}; From 406673e2e56169d0ccb1bf8aec0426d3b4e6463d Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sat, 17 Feb 2024 11:23:09 -0500 Subject: [PATCH 03/30] Adding some documentation for patterns --- src/patterns.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/patterns.rs b/src/patterns.rs index f0b8a70..5128efc 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -68,6 +68,7 @@ where } } +/// Does a function if the input is a list, otherwise throws an error. pub fn if_list_do(arr: &mut Array, mut f: F) -> Result> where F: FnMut(&mut Array) -> Result>, @@ -96,6 +97,8 @@ where .and_then(f) } +/// If the input is an int, convert to a float and do the function. if the input is a float already, +/// the function is still performed. pub fn if_int_convert_to_float_and_do(x: Dynamic, mut f: F) -> Result> where F: FnMut(FLOAT) -> Result>, @@ -182,6 +185,7 @@ where } } +/// If the input is a pub fn if_matrix_convert_to_vec_array_and_do( matrix: &mut Array, mut f: F, From 4ff907daf6b237879963ff07c2ded5c223ed840f Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 04:54:24 -0500 Subject: [PATCH 04/30] Added approximate equal assertion --- src/assertions.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/assertions.rs b/src/assertions.rs index 29552a3..d25660d 100644 --- a/src/assertions.rs +++ b/src/assertions.rs @@ -2,7 +2,7 @@ use rhai::plugin::*; #[export_module] pub mod assert_functions { - use rhai::{Dynamic, EvalAltResult, Position}; + use rhai::{FLOAT, Dynamic, EvalAltResult, Position}; /// Assert that a statement is true and throw an error if it is not. /// ```typescript @@ -88,4 +88,32 @@ pub mod assert_functions { .into()) } } + + + /// Assert that two floats are approximately equal and throw an error if they are not. + /// ```typescript + /// assert_approx_eq(2.0, 2.000000000000000001, 10e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(2.0, 2.000000000000000001); + /// ``` + #[rhai_fn(name = "assert_approx_eq", return_raw)] + pub fn assert_approx_eq(lhs: FLOAT, rhs: FLOAT, eps: FLOAT) -> Result> { + + if (lhs - rhs).abs() < eps { + Ok(true) + } else { + println!("LHS: {:?}", lhs); + println!("RHS: {:?}", rhs); + Err(EvalAltResult::ErrorArithmetic( + "The left-hand side and right-hand side are not equal".to_string(), + Position::NONE, + ) + .into()) + } + } + #[rhai_fn(name = "assert_approx_eq", return_raw)] + pub fn assert_approx_eq_with_default(lhs: FLOAT, rhs: FLOAT) -> Result> { + assert_approx_eq(lhs, rhs, 10e-10) + } } From 59a08bede9bc85219daba492c07930984a139352 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 04:54:41 -0500 Subject: [PATCH 05/30] Added new trig module --- build.rs | 2 ++ src/lib.rs | 4 ++++ src/trig.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/trig.rs diff --git a/build.rs b/build.rs index 6c73726..ebbd33d 100644 --- a/build.rs +++ b/build.rs @@ -63,6 +63,7 @@ fn main() { combine_with_exported_module!(&mut lib, "rhai_sci_sets", set_functions); combine_with_exported_module!(&mut lib, "rhai_sci_moving", moving_functions); combine_with_exported_module!(&mut lib, "rhai_sci_validate", validation_functions); + combine_with_exported_module!(&mut lib, "rhai_sci_trig", trig_functions); engine.register_global_module(rhai::Shared::new(lib)); // Extract metadata @@ -219,6 +220,7 @@ mod functions { include!("src/moving.rs"); include!("src/validate.rs"); include!("src/patterns.rs"); + include!("src/trig.rs"); } #[cfg(feature = "metadata")] diff --git a/src/lib.rs b/src/lib.rs index f21b1bb..c69588d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,9 @@ pub use sets::set_functions; mod validate; pub use validate::validation_functions; +mod trig; +pub use trig::trig_functions; + def_package! { /// Package for scientific computing pub SciPackage(lib) { @@ -43,6 +46,7 @@ def_package! { combine_with_exported_module!(lib, "rhai_sci_sets", set_functions); combine_with_exported_module!(lib, "rhai_sci_moving", moving_functions); combine_with_exported_module!(lib, "rhai_sci_validation", validation_functions); + combine_with_exported_module!(lib, "rhai_sci_trig", trig_functions); } } diff --git a/src/trig.rs b/src/trig.rs new file mode 100644 index 0000000..ef6ca91 --- /dev/null +++ b/src/trig.rs @@ -0,0 +1,64 @@ +use rhai::plugin::*; + +#[export_module] +pub mod trig_functions { + use crate::{ + if_int_convert_to_float_and_do + }; + use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT, INT}; + + + /// Returns the sine of an argument given in degrees + /// ```typescript + /// assert_eq(sind(0.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(sind(90.0), 1.0); + /// ``` + /// ```typescript + /// assert_approx_eq(sind(180.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(sind(270.0), -1.0); + /// ``` + #[rhai_fn(name = "sind")] + pub fn sind(x: FLOAT) -> FLOAT { + FLOAT::sin(x * std::f64::consts::PI / 180.0) + } + + // + /// Returns the cosine of an argument given in degrees + /// ```typescript + /// assert_eq(cosd(0.0), 1.0); + /// ``` + /// ```typescript + /// assert_approx_eq(cosd(90.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(cosd(180.0), -1.0); + /// ``` + /// ```typescript + /// assert_approx_eq(cosd(270.0), 0.0); + /// ``` + #[rhai_fn(name = "cosd")] + pub fn cosd(x: FLOAT) -> FLOAT { + FLOAT::cos(x * std::f64::consts::PI / 180.0) + } + + + /// Returns the tangent of an argument given in degrees + /// ```typescript + /// assert_approx_eq(tand(-45.0), -1.0); + /// ``` + /// ```typescript + /// assert_eq(tand(0.0), 0.0); + /// ``` + /// ```typescript + /// assert_approx_eq(tand(45.0), 1.0); + /// ``` + #[rhai_fn(name = "tand")] + pub fn tand(x: FLOAT) -> FLOAT { + FLOAT::tan(x * std::f64::consts::PI / 180.0) + } + +} From 7f332d3240df8d9f671412a85c180edca45996b8 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 05:16:17 -0500 Subject: [PATCH 06/30] Introduce and use conversion functions --- src/trig.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index ef6ca91..ca3dfa0 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -8,6 +8,26 @@ pub mod trig_functions { use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT, INT}; + + /// Converts the argument from degrees to radians + /// ```typescript + /// assert_eq(deg2rad(180.0), pi); + /// ``` + #[rhai_fn(name = "deg2rad")] + pub fn deg2rad(degrees: FLOAT) -> FLOAT { + degrees * std::f64::consts::PI / 180.0 + } + + + /// Converts the argument from radians to degrees + /// ```typescript + /// assert_eq(rad2deg(pi), 180.0); + /// ``` + #[rhai_fn(name = "rad2deg")] + pub fn rad2deg(radians: FLOAT) -> FLOAT { + radians * 180.0 / std::f64::consts::PI + } + /// Returns the sine of an argument given in degrees /// ```typescript /// assert_eq(sind(0.0), 0.0); @@ -23,7 +43,7 @@ pub mod trig_functions { /// ``` #[rhai_fn(name = "sind")] pub fn sind(x: FLOAT) -> FLOAT { - FLOAT::sin(x * std::f64::consts::PI / 180.0) + FLOAT::sin(deg2rad(x)) } // @@ -42,7 +62,7 @@ pub mod trig_functions { /// ``` #[rhai_fn(name = "cosd")] pub fn cosd(x: FLOAT) -> FLOAT { - FLOAT::cos(x * std::f64::consts::PI / 180.0) + FLOAT::cos(deg2rad(x)) } @@ -58,7 +78,7 @@ pub mod trig_functions { /// ``` #[rhai_fn(name = "tand")] pub fn tand(x: FLOAT) -> FLOAT { - FLOAT::tan(x * std::f64::consts::PI / 180.0) + FLOAT::tan(deg2rad(x)) } } From 3f314df66bee45fd561dc34c3564d6b931e6f961 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 05:26:27 -0500 Subject: [PATCH 07/30] Adding asind, acosd, atand --- src/trig.rs | 62 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index ca3dfa0..0cad253 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -2,13 +2,9 @@ use rhai::plugin::*; #[export_module] pub mod trig_functions { - use crate::{ - if_int_convert_to_float_and_do - }; + use crate::if_int_convert_to_float_and_do; use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT, INT}; - - /// Converts the argument from degrees to radians /// ```typescript /// assert_eq(deg2rad(180.0), pi); @@ -18,7 +14,6 @@ pub mod trig_functions { degrees * std::f64::consts::PI / 180.0 } - /// Converts the argument from radians to degrees /// ```typescript /// assert_eq(rad2deg(pi), 180.0); @@ -42,8 +37,23 @@ pub mod trig_functions { /// assert_eq(sind(270.0), -1.0); /// ``` #[rhai_fn(name = "sind")] - pub fn sind(x: FLOAT) -> FLOAT { - FLOAT::sin(deg2rad(x)) + pub fn sind(degrees: FLOAT) -> FLOAT { + FLOAT::sin(deg2rad(degrees)) + } + + /// Returns the inverse sine of an argument in degrees + /// ```typescript + /// assert_eq(asind(-1.0), -90.0); + /// ``` + /// ```typescript + /// assert_eq(asind(0.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(asind(1.0), 90.0); + /// ``` + #[rhai_fn(name = "asind")] + pub fn asind(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::asin(x)) } // @@ -61,10 +71,24 @@ pub mod trig_functions { /// assert_approx_eq(cosd(270.0), 0.0); /// ``` #[rhai_fn(name = "cosd")] - pub fn cosd(x: FLOAT) -> FLOAT { - FLOAT::cos(deg2rad(x)) + pub fn cosd(degrees: FLOAT) -> FLOAT { + FLOAT::cos(deg2rad(degrees)) } + /// Returns the inverse cosine of an argument in degrees + /// ```typescript + /// assert_eq(acosd(-1.0), 180.0); + /// ``` + /// ```typescript + /// assert_eq(acosd(0.0), 90.0); + /// ``` + /// ```typescript + /// assert_eq(acosd(1.0), 0.0); + /// ``` + #[rhai_fn(name = "acosd")] + pub fn acosd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::acos(x)) + } /// Returns the tangent of an argument given in degrees /// ```typescript @@ -77,8 +101,22 @@ pub mod trig_functions { /// assert_approx_eq(tand(45.0), 1.0); /// ``` #[rhai_fn(name = "tand")] - pub fn tand(x: FLOAT) -> FLOAT { - FLOAT::tan(deg2rad(x)) + pub fn tand(degrees: FLOAT) -> FLOAT { + FLOAT::tan(deg2rad(degrees)) } + /// Returns the tangent of an argument given in degrees + /// ```typescript + /// assert_approx_eq(atand(-1.0), -45.0); + /// ``` + /// ```typescript + /// assert_eq(atand(0.0), 0.0); + /// ``` + /// ```typescript + /// assert_approx_eq(atand(1.0), 45.0); + /// ``` + #[rhai_fn(name = "atand")] + pub fn atand(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::atan(x)) + } } From b29d1d565ce50a5e7285fda3074a24fb3fee4efb Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 05:29:34 -0500 Subject: [PATCH 08/30] Adding hypot --- src/trig.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index 0cad253..9bf36a6 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -119,4 +119,13 @@ pub mod trig_functions { pub fn atand(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atan(x)) } + + /// Returns the square root of the sum of squares of the arguments + /// ```typescript + /// assert_eq(hypot(3.0, 4.0), 5.0); + /// ``` + #[rhai_fn(name = "hypot")] + pub fn hypot(x: FLOAT, y: FLOAT) -> FLOAT { + x.hypot(y) + } } From ac8e54ba540d290a0e9ffe06a272379f767fd75e Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 05:31:37 -0500 Subject: [PATCH 09/30] Forget hypot, tis silly --- src/trig.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index 9bf36a6..0cad253 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -119,13 +119,4 @@ pub mod trig_functions { pub fn atand(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atan(x)) } - - /// Returns the square root of the sum of squares of the arguments - /// ```typescript - /// assert_eq(hypot(3.0, 4.0), 5.0); - /// ``` - #[rhai_fn(name = "hypot")] - pub fn hypot(x: FLOAT, y: FLOAT) -> FLOAT { - x.hypot(y) - } } From 79e31dc411396f49f62bb1279f90f65b8498c184 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 05:54:25 -0500 Subject: [PATCH 10/30] Added full function sets for cosecant, secant, and cotangent --- src/trig.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index 0cad253..9a6fea3 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -119,4 +119,148 @@ pub mod trig_functions { pub fn atand(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atan(x)) } + + /// Returns the cosecant of the argument given in radians + #[rhai_fn(name = "csc")] + pub fn csc(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::sin(radians) + } + + /// Returns the cosecant of the argument given in degrees + #[rhai_fn(name = "cscd")] + pub fn cscd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::sin(deg2rad(degrees)) + } + + /// Returns the inverse of the cosecant in radians + #[rhai_fn(name = "acsc")] + pub fn acsc(x: FLOAT) -> FLOAT { + FLOAT::asin(1.0 / x) + } + + /// Returns the inverse of the cosecant in degrees + #[rhai_fn(name = "acscd")] + pub fn acscd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::asin(1.0 / x)) + } + + /// Returns the hyperbolic cosecant of the argument given in radians + #[rhai_fn(name = "csch")] + pub fn csch(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::sinh(radians) + } + + /// Returns the hyperbolic cosecant of the argument given in degrees + #[rhai_fn(name = "cschd")] + pub fn cschd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::sinh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic cosecant of the argument in radians + #[rhai_fn(name = "acsch")] + pub fn acsch(x: FLOAT) -> FLOAT { + FLOAT::asinh(1.0 / x) + } + + /// Returns the inverse hyperbolic cosecant of the argument in degrees + #[rhai_fn(name = "acschd")] + pub fn acschd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::asinh(1.0 / x)) + } + + /// Returns the secant of the argument given in radians + #[rhai_fn(name = "sec")] + pub fn sec(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::cos(radians) + } + + /// Returns the secant of the argument given in degrees + #[rhai_fn(name = "secd")] + pub fn secd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::cos(deg2rad(degrees)) + } + + /// Returns the inverse of the secant in radians + #[rhai_fn(name = "asec")] + pub fn asec(x: FLOAT) -> FLOAT { + FLOAT::acos(1.0 / x) + } + + /// Returns the inverse of the secant in degrees + #[rhai_fn(name = "asecd")] + pub fn asecd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::acos(1.0 / x)) + } + + /// Returns the hyperbolic secant of the argument given in radians + #[rhai_fn(name = "sech")] + pub fn sech(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::cosh(radians) + } + + /// Returns the hyperbolic secant of the argument given in degrees + #[rhai_fn(name = "sechd")] + pub fn sechd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::cosh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic secant of the argument in radians + #[rhai_fn(name = "asech")] + pub fn asech(x: FLOAT) -> FLOAT { + FLOAT::acosh(1.0 / x) + } + + /// Returns the inverse hyperbolic secant of the argument in degrees + #[rhai_fn(name = "asechd")] + pub fn asechd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::acosh(1.0 / x)) + } + + /// Returns the cotangent of the argument given in radians + #[rhai_fn(name = "cot")] + pub fn cot(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::tan(radians) + } + + /// Returns the cotangent of the argument given in degrees + #[rhai_fn(name = "cotd")] + pub fn cotd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::tan(deg2rad(degrees)) + } + + /// Returns the inverse of the cotangent in radians + #[rhai_fn(name = "acot")] + pub fn acot(x: FLOAT) -> FLOAT { + FLOAT::atan(1.0 / x) + } + + /// Returns the inverse of the cotangent in degrees + #[rhai_fn(name = "acotd")] + pub fn acotd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::atan(1.0 / x)) + } + + /// Returns the hyperbolic cotangent of the argument given in radians + #[rhai_fn(name = "coth")] + pub fn coth(radians: FLOAT) -> FLOAT { + 1.0 / FLOAT::tanh(radians) + } + + /// Returns the hyperbolic cotangent of the argument given in degrees + #[rhai_fn(name = "cothd")] + pub fn cothd(degrees: FLOAT) -> FLOAT { + 1.0 / FLOAT::tanh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic cotangent of the argument in radians + #[rhai_fn(name = "acoth")] + pub fn acoth(x: FLOAT) -> FLOAT { + FLOAT::atanh(1.0 / x) + } + + /// Returns the inverse hyperbolic cotangent of the argument in degrees + #[rhai_fn(name = "acothd")] + pub fn acothd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::atanh(1.0 / x)) + } } From 0cec92bb9a199864151b65877b32ab918b1adcd3 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 06:55:20 -0500 Subject: [PATCH 11/30] Better documentation for assert_approx_eq --- src/assertions.rs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/assertions.rs b/src/assertions.rs index d25660d..80c2acc 100644 --- a/src/assertions.rs +++ b/src/assertions.rs @@ -2,7 +2,7 @@ use rhai::plugin::*; #[export_module] pub mod assert_functions { - use rhai::{FLOAT, Dynamic, EvalAltResult, Position}; + use rhai::{Dynamic, EvalAltResult, Position, FLOAT}; /// Assert that a statement is true and throw an error if it is not. /// ```typescript @@ -89,17 +89,17 @@ pub mod assert_functions { } } - - /// Assert that two floats are approximately equal and throw an error if they are not. + /// Assert that two floats are approximately equal and throw an error if they are not. Specify a + /// specific tolerance to use for the comparison /// ```typescript - /// assert_approx_eq(2.0, 2.000000000000000001, 10e-10); - /// ``` - /// ```typescript - /// assert_approx_eq(2.0, 2.000000000000000001); + /// assert_approx_eq(2.0, 2.000000000000000001, 1e-10); /// ``` #[rhai_fn(name = "assert_approx_eq", return_raw)] - pub fn assert_approx_eq(lhs: FLOAT, rhs: FLOAT, eps: FLOAT) -> Result> { - + pub fn assert_approx_eq( + lhs: FLOAT, + rhs: FLOAT, + eps: FLOAT, + ) -> Result> { if (lhs - rhs).abs() < eps { Ok(true) } else { @@ -109,11 +109,20 @@ pub mod assert_functions { "The left-hand side and right-hand side are not equal".to_string(), Position::NONE, ) - .into()) + .into()) } } + + /// Assert that two floats are approximately equal and throw an error if they are not. Use the + /// default tolerance of 1e-10 for the comparison. + /// ```typescript + /// assert_approx_eq(2.0, 2.000000000000000001); + /// ``` #[rhai_fn(name = "assert_approx_eq", return_raw)] - pub fn assert_approx_eq_with_default(lhs: FLOAT, rhs: FLOAT) -> Result> { - assert_approx_eq(lhs, rhs, 10e-10) + pub fn assert_approx_eq_with_default( + lhs: FLOAT, + rhs: FLOAT, + ) -> Result> { + assert_approx_eq(lhs, rhs, 1e-10) } } From d27ef645edd502a8da811f88c3c2d274754ad1a3 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 06:55:59 -0500 Subject: [PATCH 12/30] Added degree versions of hyperbolic sin, cos, and tan (along with inverses) --- src/trig.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/trig.rs b/src/trig.rs index 9a6fea3..6ee9471 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -56,7 +56,18 @@ pub mod trig_functions { rad2deg(FLOAT::asin(x)) } - // + /// Returns the hyperbolic sine of the argument given in degrees + #[rhai_fn(name = "sinhd")] + pub fn sinhd(degrees: FLOAT) -> FLOAT { + FLOAT::sinh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic sine of the argument given in degrees + #[rhai_fn(name = "asinhd")] + pub fn asinhd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::asinh(x)) + } + /// Returns the cosine of an argument given in degrees /// ```typescript /// assert_eq(cosd(0.0), 1.0); @@ -90,6 +101,18 @@ pub mod trig_functions { rad2deg(FLOAT::acos(x)) } + /// Returns the hyperbolic cosine of the argument given in degrees + #[rhai_fn(name = "coshd")] + pub fn coshd(degrees: FLOAT) -> FLOAT { + FLOAT::cosh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic cosine of the argument given in degrees + #[rhai_fn(name = "acoshd")] + pub fn acoshd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::acosh(x)) + } + /// Returns the tangent of an argument given in degrees /// ```typescript /// assert_approx_eq(tand(-45.0), -1.0); @@ -120,6 +143,18 @@ pub mod trig_functions { rad2deg(FLOAT::atan(x)) } + /// Returns the hyperbolic tangent of the argument given in degrees + #[rhai_fn(name = "tanhd")] + pub fn tanhd(degrees: FLOAT) -> FLOAT { + FLOAT::tanh(deg2rad(degrees)) + } + + /// Returns the inverse hyperbolic tangent of the argument given in degrees + #[rhai_fn(name = "atanhd")] + pub fn atanhd(x: FLOAT) -> FLOAT { + rad2deg(FLOAT::atanh(x)) + } + /// Returns the cosecant of the argument given in radians #[rhai_fn(name = "csc")] pub fn csc(radians: FLOAT) -> FLOAT { From 7b0a35abe59a4ee4ae9b34de137bf8d203ccce4c Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 07:01:04 -0500 Subject: [PATCH 13/30] Added degree versions of hyperbolic sin, cos, and tan (along with inverses) --- src/trig.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index 6ee9471..f72d2a2 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -128,7 +128,7 @@ pub mod trig_functions { FLOAT::tan(deg2rad(degrees)) } - /// Returns the tangent of an argument given in degrees + /// Returns the tangent in degrees of the given argument /// ```typescript /// assert_approx_eq(atand(-1.0), -45.0); /// ``` @@ -143,13 +143,28 @@ pub mod trig_functions { rad2deg(FLOAT::atan(x)) } + /// Returns the tangent in degrees of the given argument + /// ```typescript + /// assert_approx_eq(atand(-1.0, 1.0), -45.0); + /// ``` + /// ```typescript + /// assert_eq(atand(0.0, 1.0), 0.0); + /// ``` + /// ```typescript + /// assert_approx_eq(atand(1.0, 1.0), 45.0); + /// ``` + #[rhai_fn(name = "atand")] + pub fn atand2(x: FLOAT, y: FLOAT) -> FLOAT { + rad2deg(FLOAT::atan2(x, y)) + } + /// Returns the hyperbolic tangent of the argument given in degrees #[rhai_fn(name = "tanhd")] pub fn tanhd(degrees: FLOAT) -> FLOAT { FLOAT::tanh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic tangent of the argument given in degrees + /// Returns the inverse hyperbolic tangent in degrees of the given argument #[rhai_fn(name = "atanhd")] pub fn atanhd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atanh(x)) From 2937888db4e75726bcd85d527cb0c9a06e1522ad Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 07:06:42 -0500 Subject: [PATCH 14/30] Cleaning up documentation --- src/trig.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index f72d2a2..db4e2a3 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -41,7 +41,7 @@ pub mod trig_functions { FLOAT::sin(deg2rad(degrees)) } - /// Returns the inverse sine of an argument in degrees + /// Returns the inverse sine in degrees /// ```typescript /// assert_eq(asind(-1.0), -90.0); /// ``` @@ -62,7 +62,7 @@ pub mod trig_functions { FLOAT::sinh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic sine of the argument given in degrees + /// Returns the inverse hyperbolic sine in degrees #[rhai_fn(name = "asinhd")] pub fn asinhd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asinh(x)) @@ -86,7 +86,7 @@ pub mod trig_functions { FLOAT::cos(deg2rad(degrees)) } - /// Returns the inverse cosine of an argument in degrees + /// Returns the inverse cosine in degrees /// ```typescript /// assert_eq(acosd(-1.0), 180.0); /// ``` @@ -107,7 +107,7 @@ pub mod trig_functions { FLOAT::cosh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic cosine of the argument given in degrees + /// Returns the inverse hyperbolic cosine in degrees #[rhai_fn(name = "acoshd")] pub fn acoshd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::acosh(x)) @@ -128,7 +128,7 @@ pub mod trig_functions { FLOAT::tan(deg2rad(degrees)) } - /// Returns the tangent in degrees of the given argument + /// Returns the inverse tangent in degrees /// ```typescript /// assert_approx_eq(atand(-1.0), -45.0); /// ``` @@ -143,7 +143,7 @@ pub mod trig_functions { rad2deg(FLOAT::atan(x)) } - /// Returns the tangent in degrees of the given argument + /// Returns the inverse tangent in degrees , taking two arguments as input. /// ```typescript /// assert_approx_eq(atand(-1.0, 1.0), -45.0); /// ``` @@ -164,7 +164,7 @@ pub mod trig_functions { FLOAT::tanh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic tangent in degrees of the given argument + /// Returns the inverse hyperbolic tangent in degrees #[rhai_fn(name = "atanhd")] pub fn atanhd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atanh(x)) @@ -182,13 +182,13 @@ pub mod trig_functions { 1.0 / FLOAT::sin(deg2rad(degrees)) } - /// Returns the inverse of the cosecant in radians + /// Returns the inverse cosecant in radians #[rhai_fn(name = "acsc")] pub fn acsc(x: FLOAT) -> FLOAT { FLOAT::asin(1.0 / x) } - /// Returns the inverse of the cosecant in degrees + /// Returns the inverse cosecant in degrees #[rhai_fn(name = "acscd")] pub fn acscd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asin(1.0 / x)) @@ -206,13 +206,13 @@ pub mod trig_functions { 1.0 / FLOAT::sinh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic cosecant of the argument in radians + /// Returns the inverse hyperbolic cosecant in radians #[rhai_fn(name = "acsch")] pub fn acsch(x: FLOAT) -> FLOAT { FLOAT::asinh(1.0 / x) } - /// Returns the inverse hyperbolic cosecant of the argument in degrees + /// Returns the inverse hyperbolic cosecant in degrees #[rhai_fn(name = "acschd")] pub fn acschd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asinh(1.0 / x)) @@ -230,13 +230,13 @@ pub mod trig_functions { 1.0 / FLOAT::cos(deg2rad(degrees)) } - /// Returns the inverse of the secant in radians + /// Returns the inverse secant in radians #[rhai_fn(name = "asec")] pub fn asec(x: FLOAT) -> FLOAT { FLOAT::acos(1.0 / x) } - /// Returns the inverse of the secant in degrees + /// Returns the inverse secant in degrees #[rhai_fn(name = "asecd")] pub fn asecd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::acos(1.0 / x)) @@ -254,7 +254,7 @@ pub mod trig_functions { 1.0 / FLOAT::cosh(deg2rad(degrees)) } - /// Returns the inverse hyperbolic secant of the argument in radians + /// Returns the inverse hyperbolic secant in radians #[rhai_fn(name = "asech")] pub fn asech(x: FLOAT) -> FLOAT { FLOAT::acosh(1.0 / x) From cd9c01a04f62165dacbe7c34f36b159274db56fd Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 07:43:18 -0500 Subject: [PATCH 15/30] Conversion between coordinate systems --- src/trig.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index db4e2a3..6c600bc 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -23,6 +23,73 @@ pub mod trig_functions { radians * 180.0 / std::f64::consts::PI } + /// Convert the argument from 3D Cartesian coordinates to polar coordinates. + /// ```typescript + /// assert_eq(cart2pol(1.0, 1.0, 1.0), [pi/4, sqrt(2.0), 1.0]) + /// ``` + #[rhai_fn(name = "cart2pol")] + pub fn cart2pol3d(x: FLOAT, y: FLOAT, z: FLOAT) -> Array { + vec![ + Dynamic::from(y.atan2(x)), + Dynamic::from(y.hypot(x)), + Dynamic::from(z), + ] + } + + /// Convert the argument from 2D Cartesian coordinates to polar coordinates. + /// ```typescript + /// assert_eq(cart2pol(1.0, 1.0), [pi/4, sqrt(2.0)]) + /// ``` + #[rhai_fn(name = "cart2pol")] + pub fn cart2pol2d(x: FLOAT, y: FLOAT) -> Array { + vec![Dynamic::from(y.atan2(x)), Dynamic::from(y.hypot(x))] + } + + /// Convert the argument from 3D polar coordinates to Cartesian coordinates. + #[rhai_fn(name = "pol2cart")] + pub fn pol2cart3d(theta: FLOAT, r: FLOAT, z: FLOAT) -> Array { + vec![ + Dynamic::from(r * theta.cos()), + Dynamic::from(r * theta.sin()), + Dynamic::from(z), + ] + } + + /// Convert the argument from 2D polar coordinates to Cartesian coordinates. + #[rhai_fn(name = "pol2cart")] + pub fn pol2cart2d(theta: FLOAT, r: FLOAT) -> Array { + vec![ + Dynamic::from(r * theta.cos()), + Dynamic::from(r * theta.sin()), + ] + } + + /// Convert the argument from 3D Cartesian coordinates to spherical coordinates. + #[rhai_fn(name = "cart2sph")] + pub fn cart2sph(x: FLOAT, y: FLOAT, z: FLOAT) -> Array { + vec![ + Dynamic::from(y.atan2(x)), + Dynamic::from(z.atan2(y.hypot(x))), + Dynamic::from(hypot3(x, y, z)), + ] + } + + /// Convert the argument from spherical coordinates to 3D Cartesian coordinates. + #[rhai_fn(name = "sph2cart")] + pub fn sph2cart(azimuth: FLOAT, elevation: FLOAT, r: FLOAT) -> Array { + vec![ + Dynamic::from(r * elevation.cos() * azimuth.sin()), + Dynamic::from(r * elevation.cos() * azimuth.sin()), + Dynamic::from(r * elevation.sin()), + ] + } + + /// Extends the built-in hypot function to compute distance in 3D cartesian space + #[rhai_fn(name = "hypot")] + pub fn hypot3(x: FLOAT, y: FLOAT, z: FLOAT) -> FLOAT { + (x.powf(2.0) + y.powf(2.0) + z.powf(2.0)).sqrt() + } + /// Returns the sine of an argument given in degrees /// ```typescript /// assert_eq(sind(0.0), 0.0); From 130f163f75097873cfbdca581264163e31003d1e Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 08:08:10 -0500 Subject: [PATCH 16/30] Add approx_equal assertion type for lists --- src/assertions.rs | 51 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/assertions.rs b/src/assertions.rs index 80c2acc..487353a 100644 --- a/src/assertions.rs +++ b/src/assertions.rs @@ -2,7 +2,9 @@ use rhai::plugin::*; #[export_module] pub mod assert_functions { - use rhai::{Dynamic, EvalAltResult, Position, FLOAT}; + use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT}; + + use crate::if_list_convert_to_vec_float_and_do; /// Assert that a statement is true and throw an error if it is not. /// ```typescript @@ -89,8 +91,8 @@ pub mod assert_functions { } } - /// Assert that two floats are approximately equal and throw an error if they are not. Specify a - /// specific tolerance to use for the comparison + /// Assert that two floats are approximately equal (within `eps`) and return an error if they + /// are not. /// ```typescript /// assert_approx_eq(2.0, 2.000000000000000001, 1e-10); /// ``` @@ -113,8 +115,8 @@ pub mod assert_functions { } } - /// Assert that two floats are approximately equal and throw an error if they are not. Use the - /// default tolerance of 1e-10 for the comparison. + /// Assert that two floats are approximately equal and return an error if they + /// are not. Use the default tolerance of 1e-10 for the comparison. /// ```typescript /// assert_approx_eq(2.0, 2.000000000000000001); /// ``` @@ -125,4 +127,43 @@ pub mod assert_functions { ) -> Result> { assert_approx_eq(lhs, rhs, 1e-10) } + + /// Assert that two arrays are approximately equal (within `eps`) and return an error if they + /// are not. + /// ```typescript + /// assert_approx_eq([2.0, 2.0], [2.0, 2.000000000000000001], 1e-10); + /// ``` + #[rhai_fn(name = "assert_approx_eq", return_raw)] + pub fn assert_approx_eq_list( + lhs: Array, + rhs: Array, + eps: FLOAT, + ) -> Result> { + if_list_convert_to_vec_float_and_do(&mut rhs.clone(), |rhs_as_vec_float| { + if_list_convert_to_vec_float_and_do(&mut lhs.clone(), |lhs_as_vec_float| { + let mut result = Ok(true); + for i in 0..rhs_as_vec_float.len() { + result = result.and(assert_approx_eq( + lhs_as_vec_float[i], + rhs_as_vec_float[i], + eps, + )) + } + result + }) + }) + } + + /// Assert that two arrays are approximately equal and return an error if they + /// are not. Use the default tolerance of 1e-10 for the comparison. + /// ```typescript + /// assert_approx_eq([2.0, 2.0], [2.0, 2.000000000000000001]); + /// ``` + #[rhai_fn(name = "assert_approx_eq", return_raw)] + pub fn assert_approx_eq_list_with_default( + lhs: Array, + rhs: Array, + ) -> Result> { + assert_approx_eq_list(lhs, rhs, 1e-10) + } } From f75d44aff6ebf6403330ec3e8099c8de9225ab54 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 08:08:16 -0500 Subject: [PATCH 17/30] New tests --- src/trig.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index 6c600bc..eb90e50 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -46,6 +46,9 @@ pub mod trig_functions { } /// Convert the argument from 3D polar coordinates to Cartesian coordinates. + /// ```typescript + /// assert_approx_eq(pol2cart(pi/4, sqrt(2.0), 1.0), [1.0, 1.0, 1.0]) + /// ``` #[rhai_fn(name = "pol2cart")] pub fn pol2cart3d(theta: FLOAT, r: FLOAT, z: FLOAT) -> Array { vec![ @@ -56,6 +59,9 @@ pub mod trig_functions { } /// Convert the argument from 2D polar coordinates to Cartesian coordinates. + /// ```typescript + /// assert_approx_eq(pol2cart(pi/4, sqrt(2.0)), [1.0, 1.0]) + /// ``` #[rhai_fn(name = "pol2cart")] pub fn pol2cart2d(theta: FLOAT, r: FLOAT) -> Array { vec![ From b8233914846771344a723bc0b56b9d59bb4863f3 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 08:10:27 -0500 Subject: [PATCH 18/30] Added test for hypot --- src/trig.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index eb90e50..7abc256 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -91,6 +91,9 @@ pub mod trig_functions { } /// Extends the built-in hypot function to compute distance in 3D cartesian space + /// ```typescript + /// assert_eq(hypot(2.0, 3.0, 6.0), 7.0); + /// ``` #[rhai_fn(name = "hypot")] pub fn hypot3(x: FLOAT, y: FLOAT, z: FLOAT) -> FLOAT { (x.powf(2.0) + y.powf(2.0) + z.powf(2.0)).sqrt() From 35f7d30e0ba4aeac13a02fda3b17396891be211a Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 08:18:19 -0500 Subject: [PATCH 19/30] Tests for polar-cartesian conversions --- src/trig.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/trig.rs b/src/trig.rs index 7abc256..23689aa 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -71,6 +71,9 @@ pub mod trig_functions { } /// Convert the argument from 3D Cartesian coordinates to spherical coordinates. + /// ```typescript + /// assert_approx_eq(cart2sph(1.0, 0.0, 1.0), [0.0, pi/4, sqrt(2.0)]) + /// ``` #[rhai_fn(name = "cart2sph")] pub fn cart2sph(x: FLOAT, y: FLOAT, z: FLOAT) -> Array { vec![ @@ -81,10 +84,13 @@ pub mod trig_functions { } /// Convert the argument from spherical coordinates to 3D Cartesian coordinates. + /// ```typescript + /// assert_approx_eq(sph2cart(0.0, pi/4, sqrt(2.0)), [1.0, 0.0, 1.0]) + /// ``` #[rhai_fn(name = "sph2cart")] pub fn sph2cart(azimuth: FLOAT, elevation: FLOAT, r: FLOAT) -> Array { vec![ - Dynamic::from(r * elevation.cos() * azimuth.sin()), + Dynamic::from(r * elevation.cos() * azimuth.cos()), Dynamic::from(r * elevation.cos() * azimuth.sin()), Dynamic::from(r * elevation.sin()), ] From c95a9a65feb08d16cfdd688db236d97abc02aa99 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 18 Feb 2024 14:23:20 -0500 Subject: [PATCH 20/30] Cleanup --- src/matrices_and_arrays.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/matrices_and_arrays.rs b/src/matrices_and_arrays.rs index 7578622..12ae5c6 100644 --- a/src/matrices_and_arrays.rs +++ b/src/matrices_and_arrays.rs @@ -4,8 +4,8 @@ use rhai::plugin::*; #[export_module] pub mod matrix_functions { use crate::{ - if_int_convert_to_float_and_do, if_int_do_else_if_array_do, if_list_do, - if_matrix_convert_to_vec_array_and_do, array_to_vec_float + array_to_vec_float, if_int_convert_to_float_and_do, if_int_do_else_if_array_do, if_list_do, + if_matrix_convert_to_vec_array_and_do, }; #[cfg(feature = "nalgebra")] use crate::{ @@ -370,7 +370,10 @@ pub mod matrix_functions { /// ``` #[rhai_fn(name = "nnz", pure)] pub fn nnz_by_reference(matrix: &mut Array) -> INT { - array_to_vec_float(&mut flatten(matrix)).iter().filter(|&n| *n > 0.0).count() as INT + array_to_vec_float(&mut flatten(matrix)) + .iter() + .filter(|&n| *n > 0.0) + .count() as INT } #[cfg(all(feature = "io"))] @@ -769,7 +772,7 @@ pub mod matrix_functions { output } - /// Returns the contents of an multidimensional array as a 1-D array. + /// Returns the contents of a multidimensional array as a 1-D array. /// ```typescript /// let matrix = ones(3, 5); /// let flat = flatten(matrix); From a1d2036978d5d27cc619b8fc04aa780b3c58bb39 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 11:38:02 -0500 Subject: [PATCH 21/30] Added tests for tan, cos, and sin series. --- src/trig.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index 23689aa..ef3c4af 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -184,12 +184,24 @@ pub mod trig_functions { } /// Returns the hyperbolic cosine of the argument given in degrees + /// ```typescript + /// assert_eq(coshd(0.0), 1.0) + /// ``` + /// ```typescript + /// assert_eq(coshd(10.0), cosh(10.0*pi/180.0)) + /// ``` #[rhai_fn(name = "coshd")] pub fn coshd(degrees: FLOAT) -> FLOAT { FLOAT::cosh(deg2rad(degrees)) } /// Returns the inverse hyperbolic cosine in degrees + /// ```typescript + /// assert_eq(acoshd(1.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(acoshd(10.0), 180.0/pi*acosh(10.0)) + /// ``` #[rhai_fn(name = "acoshd")] pub fn acoshd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::acosh(x)) @@ -241,12 +253,24 @@ pub mod trig_functions { } /// Returns the hyperbolic tangent of the argument given in degrees + /// ```typescript + /// assert_eq(tanhd(0.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(tanhd(10.0), tanh(10.0*pi/180.0)) + /// ``` #[rhai_fn(name = "tanhd")] pub fn tanhd(degrees: FLOAT) -> FLOAT { FLOAT::tanh(deg2rad(degrees)) } /// Returns the inverse hyperbolic tangent in degrees + /// ```typescript + /// assert_eq(atanhd(0.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(atanhd(10.0), 180.0/pi*atanh(10.0)) + /// ``` #[rhai_fn(name = "atanhd")] pub fn atanhd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atanh(x)) From a6bcf1b77119d08c6173f861aadc52d2bfd03b90 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 11:59:56 -0500 Subject: [PATCH 22/30] Added tests for csc and cscd --- src/trig.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index ef3c4af..dab354b 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -277,12 +277,30 @@ pub mod trig_functions { } /// Returns the cosecant of the argument given in radians + /// ```typescript + /// assert_eq(csc(-pi/2), -1.0) + /// ``` + /// ```typescript + /// assert_eq(csc(0.0), 1.0/0.0) + /// ``` + /// ```typescript + /// assert_eq(csc(pi/2), 1.0) + /// ``` #[rhai_fn(name = "csc")] pub fn csc(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::sin(radians) } /// Returns the cosecant of the argument given in degrees + /// ```typescript + /// assert_eq(cscd(-90.0), -1.0) + /// ``` + /// ```typescript + /// assert_eq(cscd(0.0), 1.0/0.0) + /// ``` + /// ```typescript + /// assert_eq(cscd(90.0), 1.0) + /// ``` #[rhai_fn(name = "cscd")] pub fn cscd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::sin(deg2rad(degrees)) From c4c140fd1e2a2c2a15855fa1d7fcb546122b0187 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 16:46:03 -0500 Subject: [PATCH 23/30] Updated build system for better docs --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index ebbd33d..4c52a2a 100644 --- a/build.rs +++ b/build.rs @@ -85,7 +85,7 @@ fn main() { let function = function.clone(); // Pull out basic info let name = function.name; - if !name.starts_with("anon") && !name.starts_with("_") { + if !name.starts_with("anon") && !name.starts_with("_") && !name.starts_with("$CONSTANTS$"){ let signature = function .signature .replace("Result<", "") From 29d521ef76837599fb9085b851c0b1216a96a9b4 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 16:51:27 -0500 Subject: [PATCH 24/30] Added infinity --- src/misc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/misc.rs b/src/misc.rs index a648483..37c2b6a 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -5,6 +5,10 @@ pub mod misc_functions { use crate::{if_list_convert_to_vec_float_and_do, if_list_do_int_or_do_float}; use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT}; + /// Infinity + #[allow(non_upper_case_globals)] + pub const inf: FLOAT = FLOAT::INFINITY; + /// Returns a random number between zero and one. /// ```typescript /// let r = rand(); From b7e0960bf3e862fa2c9d08e980d898e93f31f4c6 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 16:51:38 -0500 Subject: [PATCH 25/30] Added acsc tests --- src/trig.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index dab354b..9a8d631 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -307,6 +307,15 @@ pub mod trig_functions { } /// Returns the inverse cosecant in radians + /// ```typescript + /// assert_eq(acsc(-1.0), -pi/2) + /// ``` + /// ```typescript + /// assert_eq(acsc(1.0/0.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(acsc(1.0), pi/2) + /// ``` #[rhai_fn(name = "acsc")] pub fn acsc(x: FLOAT) -> FLOAT { FLOAT::asin(1.0 / x) From 6ad636ee883b9297b7dacab92ac463a018868066 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 16:52:07 -0500 Subject: [PATCH 26/30] Replaced instances of 1.0/0.0 with inf in tests --- src/trig.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/trig.rs b/src/trig.rs index 9a8d631..cb37f06 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -281,7 +281,7 @@ pub mod trig_functions { /// assert_eq(csc(-pi/2), -1.0) /// ``` /// ```typescript - /// assert_eq(csc(0.0), 1.0/0.0) + /// assert_eq(csc(0.0), inf) /// ``` /// ```typescript /// assert_eq(csc(pi/2), 1.0) @@ -296,7 +296,7 @@ pub mod trig_functions { /// assert_eq(cscd(-90.0), -1.0) /// ``` /// ```typescript - /// assert_eq(cscd(0.0), 1.0/0.0) + /// assert_eq(cscd(0.0), inf) /// ``` /// ```typescript /// assert_eq(cscd(90.0), 1.0) @@ -311,7 +311,7 @@ pub mod trig_functions { /// assert_eq(acsc(-1.0), -pi/2) /// ``` /// ```typescript - /// assert_eq(acsc(1.0/0.0), 0.0) + /// assert_eq(acsc(inf), 0.0) /// ``` /// ```typescript /// assert_eq(acsc(1.0), pi/2) From ef97b1ea0edf5a5b0775b1d5bb7090eb239139ff Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Mon, 19 Feb 2024 17:01:10 -0500 Subject: [PATCH 27/30] So many trig tests --- src/trig.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/trig.rs b/src/trig.rs index cb37f06..970be30 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -139,12 +139,24 @@ pub mod trig_functions { } /// Returns the hyperbolic sine of the argument given in degrees + /// ```typescript + /// assert_eq(sinhd(0.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(sinhd(10.0), sinh(10.0*pi/180.0)) + /// ``` #[rhai_fn(name = "sinhd")] pub fn sinhd(degrees: FLOAT) -> FLOAT { FLOAT::sinh(deg2rad(degrees)) } /// Returns the inverse hyperbolic sine in degrees + /// ```typescript + /// assert_eq(asinhd(0.0), 0.0) + /// ``` + /// ```typescript + /// assert_eq(asinhd(10.0), 180.0/pi*asinh(10.0)) + /// ``` #[rhai_fn(name = "asinhd")] pub fn asinhd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asinh(x)) @@ -322,30 +334,51 @@ pub mod trig_functions { } /// Returns the inverse cosecant in degrees + /// ```typescript + /// assert_eq(acscd(-1.0), -90.0) + /// ``` + /// ```typescript + /// assert_eq(acscd(inf), 0.0) + /// ``` + /// ```typescript + /// assert_eq(acscd(1.0), 90.0) + /// ``` #[rhai_fn(name = "acscd")] pub fn acscd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asin(1.0 / x)) } /// Returns the hyperbolic cosecant of the argument given in radians + /// ```typescript + /// assert_eq(csch(0.0), inf) + /// ``` #[rhai_fn(name = "csch")] pub fn csch(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::sinh(radians) } /// Returns the hyperbolic cosecant of the argument given in degrees + /// ```typescript + /// assert_eq(cschd(0.0), inf) + /// ``` #[rhai_fn(name = "cschd")] pub fn cschd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::sinh(deg2rad(degrees)) } /// Returns the inverse hyperbolic cosecant in radians + /// ```typescript + /// assert_eq(acsch(inf), 0.0) + /// ``` #[rhai_fn(name = "acsch")] pub fn acsch(x: FLOAT) -> FLOAT { FLOAT::asinh(1.0 / x) } /// Returns the inverse hyperbolic cosecant in degrees + /// ```typescript + /// assert_eq(acschd(inf), 0.0) + /// ``` #[rhai_fn(name = "acschd")] pub fn acschd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asinh(1.0 / x)) From 0bf498b836e2f652716f142776dcbb5db6e823c3 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 26 Jan 2025 14:57:22 -0500 Subject: [PATCH 28/30] Updated to recent version of dependencies, passing tests --- Cargo.toml | 34 ++++++++++++------------ README.md | 24 +++++++---------- src/matrices_and_arrays.rs | 28 +++++++++++++------- src/patterns.rs | 54 -------------------------------------- src/statistics.rs | 6 ++--- 5 files changed, 48 insertions(+), 98 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71458f2..e9ef87b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,29 +22,29 @@ rand = ["randlib"] [dependencies] rhai = ">=1.8.0" -nalgebralib = { version = "0.32.1", optional = true, package = "nalgebra" } -polars = { version = "0.27.2", optional = true } -url = { version = "2.2.2", optional = true } -temp-file = { version = "0.1.6", optional = true } +nalgebralib = { version = "0.33.2", optional = true, package = "nalgebra" } +polars = { version = "0.45.1", optional = true } +url = { version = ">=2.0.0", optional = true } +temp-file = { version = "0.1.9", optional = true } csv-sniffer = { version = "0.3.1", optional = true } -minreq = { version = "2.6.0", features = ["json-using-serde", "https"], optional = true } -randlib = { version = "0.8", optional = true, package = "rand" } -smartstring = "1.0.1" +minreq = { version = "2.13.0", features = ["json-using-serde", "https"], optional = true } +randlib = { version = "0.8.5", optional = true, package = "rand" } +smartstring = ">=1.0" linregress = { version = "0.5.0", optional = true } [build-dependencies] rhai = ">=1.8.0" -nalgebralib = { version = "0.32.1", optional = true, package = "nalgebra" } -polars = { version = "0.27.2", optional = true } -url = { version = "2.2.2", optional = true } -temp-file = { version = "0.1.6", optional = true } +nalgebralib = { version = "0.33.2", optional = true, package = "nalgebra" } +polars = { version = "0.45.1", optional = true } +url = { version = ">=2.0.0", optional = true } +temp-file = { version = "0.1.9", optional = true } csv-sniffer = { version = "0.3.1", optional = true } -minreq = { version = "2.6.0", features = ["json-using-serde", "https"], optional = true } -randlib = { version = "0.8", optional = true, package = "rand" } -serde_json = "1.0.82" -serde = "1.0.140" -smartstring = "1.0.1" -linregress = { version = "0.5.0", optional = true } +minreq = { version = "2.13.0", features = ["json-using-serde", "https"], optional = true } +randlib = { version = "0.8.5", optional = true, package = "rand" } +serde_json = ">=1.0.0" +serde = ">=1.0.0" +smartstring = ">=1.0.0" +linregress = { version = "0.5.4", optional = true } [package.metadata.docs.rs] all-features = true diff --git a/README.md b/README.md index 06f890a..a647d6b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ # About `rhai-sci` -This crate provides some basic scientific computing utilities for the [`Rhai`](https://rhai.rs/) scripting language, inspired by languages +This crate provides some basic scientific computing utilities for the [`Rhai`](https://rhai.rs/) scripting language, +inspired by languages like MATLAB, Octave, and R. For a complete API reference, check [the docs](https://docs.rs/rhai-sci). # Install @@ -15,15 +16,10 @@ To use the latest released version of `rhai-sci`, add this to your `Cargo.toml`: rhai-sci = "0.2.1" ``` -To use the bleeding edge instead, add this: - -```toml -rhai-sci = { git = "https://github.com/cmccomb/rhai-sci" } -``` - # Usage -Using this crate is pretty simple! If you just want to evaluate a single line of [`Rhai`](https://rhai.rs/), then you only need: +Using this crate is pretty simple! If you just want to evaluate a single line of [`Rhai`](https://rhai.rs/), then you +only need: ```rust use rhai::INT; @@ -49,9 +45,9 @@ let value = engine.eval::("argmin([43, 42, -500])").unwrap(); # Features -| Feature | Default | Description | -| ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `metadata` | Disabled | Enables exporting function metadata and is ___necessary for running doc-tests on Rhai examples___. | -| `io` | Enabled | Enables the [`read_matrix`](#read_matrixfile_path-string---array) function but pulls in several additional dependencies (`polars`, `url`, `temp-file`, `csv-sniffer`, `minreq`). | -| `nalgebra` | Enabled | Enables several functions ([`regress`](#regressx-array-y-array---map), [`inv`](#invmatrix-array---array), [`mtimes`](#mtimesmatrix1-array-matrix2-array---array), [`horzcat`](#horzcatmatrix1-array-matrix2-array---array), [`vertcat`](#vertcatmatrix1-array-matrix2-array---array), [`repmat`](#repmatmatrix-array-nx-i64-ny-i64---array), [`svd`](#svdmatrix-array---map), [`hessenberg`](#hessenbergmatrix-array---map), and [`qr`](#qrmatrix-array---map)) but brings in the `nalgebra` and `linregress` crates. | -| `rand` | Enabled | Enables the [`rand`](#rand) function for generating random FLOAT values and random matrices, but brings in the `rand` crate. | +| Feature | Default | Description | +|------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `metadata` | Disabled | Enables exporting function metadata and is ___necessary for running doc-tests on Rhai examples___. | +| `io` | Enabled | Enables the [`read_matrix`](#read_matrixfile_path-string---array) function but pulls in several additional dependencies (`polars`, `url`, `temp-file`, `csv-sniffer`, `minreq`). | +| `nalgebra` | Enabled | Enables several functions ([`regress`](#regressx-array-y-array---map), [`inv`](#invmatrix-array---array), [`mtimes`](#mtimesmatrix1-array-matrix2-array---array), [`horzcat`](#horzcatmatrix1-array-matrix2-array---array), [`vertcat`](#vertcatmatrix1-array-matrix2-array---array), [`repmat`](#repmatmatrix-array-nx-i64-ny-i64---array), [`svd`](#svdmatrix-array---map), [`hessenberg`](#hessenbergmatrix-array---map), and [`qr`](#qrmatrix-array---map)) but brings in the `nalgebra` and `linregress` crates. | +| `rand` | Enabled | Enables the [`rand`](#rand) function for generating random FLOAT values and random matrices, but brings in the `rand` crate. | diff --git a/src/matrices_and_arrays.rs b/src/matrices_and_arrays.rs index 12ae5c6..c7f845b 100644 --- a/src/matrices_and_arrays.rs +++ b/src/matrices_and_arrays.rs @@ -378,7 +378,7 @@ pub mod matrix_functions { #[cfg(all(feature = "io"))] pub mod read_write { - use polars::prelude::{CsvReader, DataType, SerReader}; + use polars::prelude::{CsvReadOptions, DataType, SerReader}; use rhai::{Array, Dynamic, EvalAltResult, ImmutableString, FLOAT}; /// Reads a numeric csv file from a url @@ -406,11 +406,13 @@ pub mod matrix_functions { let file_path_as_str = file_path.as_str(); - match CsvReader::from_path(file_path_as_str) { - Ok(csv) => { - let x = csv - .infer_schema(Some(10)) - .has_header( + // Determine path is url + let path_is_url = url::Url::parse(file_path_as_str); + + match path_is_url { + Err(_) => { + let x = CsvReadOptions::default() + .with_has_header( csv_sniffer::Sniffer::new() .sniff_path(file_path_as_str) .map_err(|err| { @@ -423,14 +425,21 @@ pub mod matrix_functions { .header .has_header_row, ) - .finish() + .try_into_reader_with_file_path(Some(file_path_as_str.into())) .map_err(|err| { EvalAltResult::ErrorSystem( format!("Cannot read file as CSV: {file_path_as_str}"), err.into(), ) })? - .drop_nulls(None) + .finish() + .map_err(|err| { + EvalAltResult::ErrorSystem( + format!("Cannot read file: {file_path_as_str}"), + err.into(), + ) + })? + .drop_nulls::(None) .map_err(|err| { EvalAltResult::ErrorSystem( format!("Cannot remove null values from file: {file_path_as_str}"), @@ -439,7 +448,6 @@ pub mod matrix_functions { })?; // Convert into vec of vec - let mut final_output = vec![]; for series in x.get_columns() { let col: Vec = series @@ -473,7 +481,7 @@ pub mod matrix_functions { Ok(matrix_as_array) } - Err(_) => { + Ok(_) => { if let Ok(_) = url::Url::parse(file_path_as_str) { let file_contents = minreq::get(file_path_as_str).send().map_err(|err| { diff --git a/src/patterns.rs b/src/patterns.rs index 5128efc..baef622 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,8 +1,4 @@ use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT, INT}; -#[cfg(feature = "smartcore")] -use smartcorelib::linalg::basic::{ - arrays::Array as scArray, arrays::Array2 as scArray2, matrix::DenseMatrix, -}; /// Matrix compatibility conditions #[allow(dead_code)] @@ -208,42 +204,6 @@ where } } -#[cfg(feature = "smartcore")] -pub fn if_matrix_convert_to_dense_matrix_and_do( - matrix: &mut Array, - mut f: F, -) -> Result> -where - F: FnMut(DenseMatrix) -> Result>, -{ - if crate::validation_functions::is_matrix(matrix) { - let matrix_as_vec = matrix - .clone() - .iter() - .map(|x| { - x.clone() - .into_array() - .unwrap() - .iter() - .map(|y| { - if y.is::() { - y.clone().as_float().unwrap() - } else { - y.clone().as_int().unwrap() as FLOAT - } - }) - .collect::>() - }) - .collect::>>(); - f(DenseMatrix::from_2d_vec(&matrix_as_vec)) - } else { - Err( - EvalAltResult::ErrorArithmetic(format!("The input must be a matrix."), Position::NONE) - .into(), - ) - } -} - pub fn if_int_do_else_if_array_do( d: Dynamic, mut f_int: FA, @@ -272,20 +232,6 @@ pub fn array_to_vec_int(arr: &mut Array) -> Vec { .collect::>() } -#[cfg(feature = "smartcore")] -pub fn dense_matrix_to_vec_dynamic(dm: DenseMatrix) -> Vec { - let mut output = vec![]; - for idx in 0..dm.shape().0 { - output.push(Dynamic::from_array( - dm.get_row(idx) - .iterator(0) - .map(|x| Dynamic::from_float(x.clone())) - .collect::>(), - )); - } - output -} - pub fn array_to_vec_float(arr: &mut Array) -> Vec { arr.into_iter() .map(|el| el.as_float().unwrap()) diff --git a/src/statistics.rs b/src/statistics.rs index db7308c..4228785 100644 --- a/src/statistics.rs +++ b/src/statistics.rs @@ -542,9 +542,9 @@ pub mod stats { /// [0.8], /// [2.1]]; /// let b = regress(x, y); - /// assert_eq(b, #{"parameters": [5.551115123125783e-16, 1.0000000000000002], - /// "pvalues": [1.0, 0.1091825535092476], - /// "standard_errors": [0.1118033988749896, 0.17320508075688787]}); + /// assert_eq(b, #{"parameters": [-2.220446049250313e-16, 1.0000000000000002], + /// "pvalues": [1.0, 0.10918255350924745], + /// "standard_errors": [0.11180339887498947, 0.17320508075688767]}); /// ``` #[cfg(feature = "nalgebra")] #[rhai_fn(name = "regress", return_raw, pure)] From ca79468789e9d9c82acce9ccf733f59ba82cf843 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 26 Jan 2025 15:25:33 -0500 Subject: [PATCH 29/30] A whole bunch of tests for trig functions --- README.md | 4 +- src/lib.rs | 1 - src/trig.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 157 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a647d6b..6ecee8a 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ # About `rhai-sci` This crate provides some basic scientific computing utilities for the [`Rhai`](https://rhai.rs/) scripting language, -inspired by languages -like MATLAB, Octave, and R. For a complete API reference, check [the docs](https://docs.rs/rhai-sci). +inspired by languages like MATLAB, Octave, and R. For a complete API reference, +check [the docs](https://docs.rs/rhai-sci). # Install diff --git a/src/lib.rs b/src/lib.rs index c69588d..48228b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,6 @@ mod sets; pub use sets::set_functions; mod validate; pub use validate::validation_functions; - mod trig; pub use trig::trig_functions; diff --git a/src/trig.rs b/src/trig.rs index 970be30..3ca82ac 100644 --- a/src/trig.rs +++ b/src/trig.rs @@ -352,6 +352,12 @@ pub mod trig_functions { /// ```typescript /// assert_eq(csch(0.0), inf) /// ``` + /// ```typescript + /// assert_eq(csch(10.0), 1.0/sinh(10.0)) + /// ``` + /// ```typescript + /// assert_eq(csch(pi/2), 1.0/sinh(pi/2)) + /// ``` #[rhai_fn(name = "csch")] pub fn csch(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::sinh(radians) @@ -361,6 +367,12 @@ pub mod trig_functions { /// ```typescript /// assert_eq(cschd(0.0), inf) /// ``` + /// ```typescript + /// assert_eq(cschd(10.0), 1.0/sinhd(10.0)) + /// ``` + /// ```typescript + /// assert_eq(cschd(90.0), 1.0/sinhd(90.0)) + /// ``` #[rhai_fn(name = "cschd")] pub fn cschd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::sinh(deg2rad(degrees)) @@ -370,6 +382,12 @@ pub mod trig_functions { /// ```typescript /// assert_eq(acsch(inf), 0.0) /// ``` + /// ```typescript + /// assert_eq(acsch(1.0), asinh(1.0)) + /// ``` + /// ```typescript + /// assert_eq(acsch(-1.0), asinh(-1.0)) + /// ``` #[rhai_fn(name = "acsch")] pub fn acsch(x: FLOAT) -> FLOAT { FLOAT::asinh(1.0 / x) @@ -379,102 +397,238 @@ pub mod trig_functions { /// ```typescript /// assert_eq(acschd(inf), 0.0) /// ``` + /// ```typescript + /// assert_eq(acschd(1.0), asinhd(1.0)) + /// ``` + /// ```typescript + /// assert_eq(acschd(-1.0), asinhd(-1.0)) + /// ``` #[rhai_fn(name = "acschd")] pub fn acschd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::asinh(1.0 / x)) } /// Returns the secant of the argument given in radians + /// ```typescript + /// assert_eq(sec(0.0), 1.0); + /// ``` + /// ```typescript + /// assert_eq(sec(pi/2), 1/cos(pi/2)); + /// ``` + /// ```typescript + /// assert_eq(sec(pi), -1.0); #[rhai_fn(name = "sec")] pub fn sec(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::cos(radians) } /// Returns the secant of the argument given in degrees + /// ```typescript + /// assert_eq(secd(0.0), 1.0); + /// ``` + /// ```typescript + /// assert_eq(secd(90.0), 1/cosd(90.0)); + /// ``` + /// ```typescript + /// assert_eq(secd(180.0), -1.0); + /// ``` #[rhai_fn(name = "secd")] pub fn secd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::cos(deg2rad(degrees)) } /// Returns the inverse secant in radians + /// ```typescript + /// assert_eq(asec(1.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(asec(-1.0), pi); + /// ``` + /// ```typescript + /// assert_eq(asec(0.5), acos(2.0)); + /// ``` #[rhai_fn(name = "asec")] pub fn asec(x: FLOAT) -> FLOAT { FLOAT::acos(1.0 / x) } /// Returns the inverse secant in degrees + /// ```typescript + /// assert_eq(asecd(1.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(asecd(-1.0), 180.0); + /// ``` + /// ```typescript + /// assert_eq(asecd(0.5), acosd(2.0)); + /// ``` #[rhai_fn(name = "asecd")] pub fn asecd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::acos(1.0 / x)) } /// Returns the hyperbolic secant of the argument given in radians + /// ```typescript + /// assert_eq(sech(0.0), 1.0); + /// ``` + /// ```typescript + /// assert_eq(sech(10.0), 1.0/cosh(10.0)); + /// ``` + /// ```typescript + /// assert_eq(sech(pi/2), 1.0/cosh(pi/2)); + /// ``` #[rhai_fn(name = "sech")] pub fn sech(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::cosh(radians) } - /// Returns the hyperbolic secant of the argument given in degrees + /// ```typescript + /// assert_eq(sechd(0.0), 1.0); + /// ``` + /// ```typescript + /// assert_eq(sechd(10.0), 1.0/coshd(10.0)); + /// ``` + /// ```typescript + /// assert_eq(sechd(90.0), 1.0/coshd(90.0)); + /// ``` #[rhai_fn(name = "sechd")] pub fn sechd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::cosh(deg2rad(degrees)) } /// Returns the inverse hyperbolic secant in radians + /// ```typescript + /// assert_eq(asech(1.0), 0.0); + /// ``` + /// ```typescript + /// assert_eq(asech(0.5), acosh(2.0)); + /// ``` + /// ```typescript + /// assert_eq(asech(0.1), acosh(10.0)); + /// ``` #[rhai_fn(name = "asech")] pub fn asech(x: FLOAT) -> FLOAT { FLOAT::acosh(1.0 / x) } /// Returns the inverse hyperbolic secant of the argument in degrees + /// ```typescript + /// assert_eq(asechd(1.0), 0.0); + /// ``` #[rhai_fn(name = "asechd")] pub fn asechd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::acosh(1.0 / x)) } /// Returns the cotangent of the argument given in radians + /// ```typescript + /// assert_approx_eq(cot(pi/4), 1.0, 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cot(pi/2), 0.0, 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cot(3*pi/4), -1.0, 1e-10); + /// ``` #[rhai_fn(name = "cot")] pub fn cot(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::tan(radians) } /// Returns the cotangent of the argument given in degrees + /// ```typescript + /// assert_approx_eq(cotd(45.0), 1.0, 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cotd(90.0), 0.0, 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cotd(135.0), -1.0, 1e-10); + /// ``` #[rhai_fn(name = "cotd")] pub fn cotd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::tan(deg2rad(degrees)) } /// Returns the inverse of the cotangent in radians + /// ```typescript + /// assert_eq(acot(1.0), pi/4); + /// ``` + /// ```typescript + /// assert_eq(acot(-1.0), -pi/4); + /// ``` + /// ```typescript + /// assert_eq(acot(0.0), pi/2); + /// ``` #[rhai_fn(name = "acot")] pub fn acot(x: FLOAT) -> FLOAT { FLOAT::atan(1.0 / x) } /// Returns the inverse of the cotangent in degrees + /// ```typescript + /// assert_eq(acotd(1.0), 45.0); + /// ``` + /// ```typescript + /// assert_eq(acotd(-1.0), -45.0); + /// ``` + /// ```typescript + /// assert_eq(acotd(0.0), 90.0); + /// ``` #[rhai_fn(name = "acotd")] pub fn acotd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atan(1.0 / x)) } /// Returns the hyperbolic cotangent of the argument given in radians + /// ```typescript + /// assert_approx_eq(coth(1.0), cosh(1.0)/sinh(1.0), 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(coth(0.5), cosh(0.5)/sinh(0.5), 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(coth(0.1), cosh(0.1)/sinh(0.1), 1e-10); + /// ``` #[rhai_fn(name = "coth")] pub fn coth(radians: FLOAT) -> FLOAT { 1.0 / FLOAT::tanh(radians) } /// Returns the hyperbolic cotangent of the argument given in degrees + /// ```typescript + /// assert_approx_eq(cothd(1.0), coshd(1.0)/sinhd(1.0), 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cothd(0.5), coshd(0.5)/sinhd(0.5), 1e-10); + /// ``` + /// ```typescript + /// assert_approx_eq(cothd(0.1), coshd(0.1)/sinhd(0.1), 1e-10); + /// ``` #[rhai_fn(name = "cothd")] pub fn cothd(degrees: FLOAT) -> FLOAT { 1.0 / FLOAT::tanh(deg2rad(degrees)) } /// Returns the inverse hyperbolic cotangent of the argument in radians + /// ```typescript + /// assert_eq(acoth(1.0), atanh(1.0)); + /// ``` + /// ```typescript + /// assert_eq(acoth(-1.0), atanh(-1.0)); + /// ``` #[rhai_fn(name = "acoth")] pub fn acoth(x: FLOAT) -> FLOAT { FLOAT::atanh(1.0 / x) } /// Returns the inverse hyperbolic cotangent of the argument in degrees + /// ```typescript + /// assert_eq(acothd(1.0), atanhd(1.0)); + /// ``` + /// ```typescript + /// assert_eq(acothd(-1.0), atanhd(-1.0)); + /// ``` #[rhai_fn(name = "acothd")] pub fn acothd(x: FLOAT) -> FLOAT { rad2deg(FLOAT::atanh(1.0 / x)) From c34ca7dda192c1969935dc962d1080f0cf1920c9 Mon Sep 17 00:00:00 2001 From: Chris McComb Date: Sun, 26 Jan 2025 15:27:20 -0500 Subject: [PATCH 30/30] Bumping version number --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e9ef87b..c162822 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rhai-sci" -version = "0.2.1" +version = "0.2.2" edition = "2021" authors = ["Chris McComb "] description = "Scientific computing in the Rhai scripting language" diff --git a/README.md b/README.md index 6ecee8a..45be01d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ check [the docs](https://docs.rs/rhai-sci). To use the latest released version of `rhai-sci`, add this to your `Cargo.toml`: ```toml -rhai-sci = "0.2.1" +rhai-sci = "0.2.2" ``` # Usage