diff options
| author | Nathan Perry <np@nathanperry.dev> | 2024-08-07 09:19:57 -0400 |
|---|---|---|
| committer | Nathan Perry <np@nathanperry.dev> | 2024-08-07 09:19:57 -0400 |
| commit | 91c1dc86f9386e56c113f6b6981772fe4d2fd7e1 (patch) | |
| tree | c6b0f97483cde2350780cccf35120a70799dfbbc | |
| parent | d0ae07a93cb7c32f6af3def019403d9fc4f71d55 (diff) | |
nif: update calc to point to new thulani-rs crate
| -rw-r--r-- | native/thulani_calc/Cargo.lock | 101 | ||||
| -rw-r--r-- | native/thulani_calc/Cargo.toml | 10 | ||||
| -rw-r--r-- | native/thulani_calc/README.md | 19 | ||||
| -rw-r--r-- | native/thulani_calc/src/lib.rs | 214 |
4 files changed, 72 insertions, 272 deletions
diff --git a/native/thulani_calc/Cargo.lock b/native/thulani_calc/Cargo.lock index 3504dc8..c1fdc2c 100644 --- a/native/thulani_calc/Cargo.lock +++ b/native/thulani_calc/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -99,9 +99,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" [[package]] name = "lazy_static" @@ -122,15 +128,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] name = "matrixmultiply" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -171,7 +168,7 @@ checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -228,19 +225,20 @@ checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pest" -version = "2.5.1" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.5.1" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -248,26 +246,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.1" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] name = "pest_meta" -version = "2.5.1" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", - "sha1", + "sha2", ] [[package]] @@ -278,18 +276,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -359,32 +357,33 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "rustler" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61e8ddf75de20513455d7b6f17241a595abbb01b53a6340cecc798a1b13422d" +checksum = "e94bdfa68c0388cbd725f1ca54e975956482c262599e5cced04a903eec918b7f" dependencies = [ - "lazy_static", + "inventory", "rustler_codegen", "rustler_sys", ] [[package]] name = "rustler_codegen" -version = "0.26.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa2e45c0165272070f80ce93bcd7dd5407a3c84a1ef73ab9900e00f00ef3d36" +checksum = "996dc019acb78b91b4e0c1bd6fa2cd509a835d309de762dc15213b97eac399da" dependencies = [ "heck", + "inventory", "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] name = "rustler_sys" -version = "2.2.0" +version = "2.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff26a42e62d538f82913dd34f60105ecfdffbdb25abdc3c3580b0c622285332" +checksum = "ddd0e2c955cfc86ea4680067e1d5e711427b43f7befcb6e23c7807cf3dd90e97" dependencies = [ "regex", "unreachable", @@ -400,10 +399,10 @@ dependencies = [ ] [[package]] -name = "sha1" -version = "0.10.5" +name = "sha2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -448,6 +447,17 @@ dependencies = [ ] [[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "thiserror" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -464,19 +474,26 @@ checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", +] + +[[package]] +name = "thulani_calc" +version = "0.1.0" +dependencies = [ + "rustler", + "thulani_calc 0.1.0 (git+https://pub.npry.dev/thulani)", ] [[package]] name = "thulani_calc" version = "0.1.0" +source = "git+https://pub.npry.dev/thulani#ba827ea23b170365e86564912bf7c213af1b0c2f" dependencies = [ "lazy_static", - "log", "pest", "pest_derive", "rand", - "rustler", "statrs", "thiserror", ] diff --git a/native/thulani_calc/Cargo.toml b/native/thulani_calc/Cargo.toml index 8ba8a75..0bb638c 100644 --- a/native/thulani_calc/Cargo.toml +++ b/native/thulani_calc/Cargo.toml @@ -10,11 +10,5 @@ path = "src/lib.rs" crate-type = ["cdylib"] [dependencies] -rustler = "0.26.0" -pest = "2.5" -pest_derive = "2.5" -lazy_static = "1.4" -statrs = "0.16" -thiserror = "1.0" -rand = "0.8" -log = "0.4" +rustler = "0.34" +thulani_calc.git = "https://pub.npry.dev/thulani" diff --git a/native/thulani_calc/README.md b/native/thulani_calc/README.md index 03e1510..e8c1e8a 100644 --- a/native/thulani_calc/README.md +++ b/native/thulani_calc/README.md @@ -1,20 +1 @@ # NIF for Elixir.Thulani.Calc - -## To build the NIF module: - -- Your NIF will now build along with your project. - -## To load the NIF: - -```elixir -defmodule Thulani.Calc do - use Rustler, otp_app: :thulani, crate: "thulani_calc" - - # When your NIF is loaded, it will override this function. - def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded) -end -``` - -## Examples - -[This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust. diff --git a/native/thulani_calc/src/lib.rs b/native/thulani_calc/src/lib.rs index 75a6b37..23a8aea 100644 --- a/native/thulani_calc/src/lib.rs +++ b/native/thulani_calc/src/lib.rs @@ -1,215 +1,23 @@ -use log::error; -use rand::prelude::*; -use statrs; -use thiserror::Error; -use lazy_static::lazy_static; use rustler::Encoder; -mod atoms { - rustler::atoms! { - ok, - error, - inf, - ninf, - nan, - } +rustler::atoms! { + ok, + error, + inf, + ninf, + nan, } #[rustler::nif] pub fn eval<'a>(env: rustler::Env<'a>, args: String) -> Result<rustler::Term<'a>, String> { - Calc::eval(&args) + thulani_calc::Calc::eval(&args) .map(|x| match x { - f64::INFINITY => atoms::inf().encode(env), - f64::NEG_INFINITY => atoms::ninf().encode(env), - x if x.is_nan() => atoms::nan().encode(env), + x if x.is_infinite() && x.is_sign_positive() => inf().encode(env), + x if x.is_infinite() && x.is_sign_negative() => ninf().encode(env), + x if x.is_nan() => nan().encode(env), x => x.encode(env), }) .map_err(|e| e.to_string()) } -rustler::init!("Elixir.Thulani.Calc", [eval]); - - -#[derive(pest_derive::Parser)] -#[grammar = "calc.pest"] -struct Calc; - -#[derive(Copy, Clone, Error, Debug, PartialEq, Eq, Hash)] -pub(crate) enum CalcError { - #[error("pest was unable to parse the input")] - Pest, - - #[error("invalid number format")] - NumberFormat, - - #[error("bad argument count")] - ArgCount, -} - -impl Calc { - fn eval<S: AsRef<str>>(s: S) -> Result<f64, CalcError> { - use pest::{ - Parser, - prec_climber::PrecClimber, - iterators::{Pair, Pairs}, - }; - - use self::Rule::*; - - lazy_static! { - static ref CLIMBER: PrecClimber<self::Rule> = { - use pest::prec_climber::{ - Operator, - Assoc::*, - }; - - PrecClimber::new(vec![ - Operator::new(add, Left) | Operator::new(sub, Left) | Operator::new(modulo, Left), - Operator::new(mul, Left) | Operator::new(div, Left), - Operator::new(dice, Left), - Operator::new(pow, Right), - ]) - }; - } - - let result = Calc::parse(calc, s.as_ref()).map_err(|_| CalcError::Pest)?; - - fn eval_single_pair(pair: Pair<self::Rule>) -> Result<f64, CalcError> { - let result = match pair.as_rule() { - oct | hex | binary => { - let base = match pair.as_rule() { - hex => 16, - oct => 8, - binary => 2, - _ => unreachable!(), - }; - - u64::from_str_radix(&pair.as_str()[2..], base).map_err(|_| CalcError::NumberFormat)? as f64 - }, - float => pair.as_str().parse::<f64>().map_err(|_| CalcError::NumberFormat)?, - expr | num => eval_expr(pair.into_inner())?, - unary_expr => { - let mut p = pair.into_inner(); - - let op = p.next().ok_or(CalcError::ArgCount)?; - let arg = eval_expr(p)?; - - match op.as_rule() { - log => arg.ln(), - sqrt => arg.sqrt(), - sgn => arg.signum(), - - sin => arg.sin(), - cos => arg.cos(), - tan => arg.tan(), - asin => arg.asin(), - acos => arg.acos(), - atan => arg.atan(), - - sinh => arg.sinh(), - cosh => arg.cosh(), - tanh => arg.tanh(), - asinh => arg.asinh(), - acosh => arg.acosh(), - atanh => arg.atanh(), - - exp => arg.exp(), - abs => arg.abs(), - ceil => arg.ceil(), - floor => arg.floor(), - round => arg.round(), - _ => unreachable!(), - } - }, - binary_expr => { - let mut p = pair.into_inner(); - - let op = p.next().ok_or(CalcError::ArgCount)?; - - let arg1 = eval_single_pair(p.next().ok_or(CalcError::ArgCount)?)?; - let arg2 = eval_single_pair(p.next().ok_or(CalcError::ArgCount)?)?; - - assert!(p.next().is_none()); - - match op.as_rule() { - min => arg1.min(arg2), - max => arg1.max(arg2), - atan2 => arg1.atan2(arg2), - _ => unreachable!(), - } - }, - suffix_expr => { - let mut p = pair.into_inner(); - - let arg = eval_expr(p.next().ok_or(CalcError::ArgCount)?.into_inner())?; - let op = p.next().ok_or(CalcError::ArgCount)?; - - assert!(p.next().is_none()); - - match op.as_rule() { - factorial => statrs::function::gamma::gamma(arg + 1.), - _ => unreachable!(), - } - }, - _ => unreachable!(), - }; - - Ok(result) - } - - fn eval_expr(p: Pairs<self::Rule>) -> Result<f64, CalcError> { - CLIMBER.climb( - p, - eval_single_pair, - |lhs, op, rhs| { - let lhs = lhs?; - let rhs = rhs?; - - let result = match op.as_rule() { - add => lhs + rhs, - sub => lhs - rhs, - mul => lhs * rhs, - div => lhs / rhs, - pow => lhs.powf(rhs), - dice => { - let dice_count = lhs as usize; - let dice_faces = rhs as usize; - - let mut rng = thread_rng(); - (0..dice_count).map(|_| rng.gen_range(1..=dice_faces)).sum::<usize>() as f64 - }, - _ => unreachable!(), - }; - - Ok(result) - } - ) - } - - eval_expr(result) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_calc_basics() { - assert_eq!(3., Calc::eval("1 + 2").unwrap()); - assert_eq!(3.0f64.ln(), Calc::eval("log 3").unwrap()); - assert!(6. - Calc::eval("3!").unwrap() < 0.0001); - assert_eq!(3., Calc::eval("max 3 2").unwrap()); - } - - #[test] - fn test_binary_unary() { - assert_eq!(3.0f64.ln(), Calc::eval("max log 3 log 2").unwrap()); - } - - #[test] - fn test_prefix_suffix() { - assert!(6. - Calc::eval("abs 3!").unwrap() < 0.0001); - } -} - +rustler::init!("Elixir.Thulani.Calc"); |
