use crate::def_package; use crate::parser::INT; use crate::result::EvalAltResult; use crate::token::Position; #[cfg(not(feature = "no_float"))] use crate::parser::FLOAT; use crate::stdlib::{boxed::Box, format, i32, i64}; #[cfg(feature = "only_i32")] pub const MAX_INT: INT = i32::MAX; #[cfg(not(feature = "only_i32"))] pub const MAX_INT: INT = i64::MAX; def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, { #[cfg(not(feature = "no_float"))] { // Advanced math functions lib.set_fn_1("sin", |x: FLOAT| Ok(x.to_radians().sin())); lib.set_fn_1("cos", |x: FLOAT| Ok(x.to_radians().cos())); lib.set_fn_1("tan", |x: FLOAT| Ok(x.to_radians().tan())); lib.set_fn_1("sinh", |x: FLOAT| Ok(x.to_radians().sinh())); lib.set_fn_1("cosh", |x: FLOAT| Ok(x.to_radians().cosh())); lib.set_fn_1("tanh", |x: FLOAT| Ok(x.to_radians().tanh())); lib.set_fn_1("asin", |x: FLOAT| Ok(x.asin().to_degrees())); lib.set_fn_1("acos", |x: FLOAT| Ok(x.acos().to_degrees())); lib.set_fn_1("atan", |x: FLOAT| Ok(x.atan().to_degrees())); lib.set_fn_1("asinh", |x: FLOAT| Ok(x.asinh().to_degrees())); lib.set_fn_1("acosh", |x: FLOAT| Ok(x.acosh().to_degrees())); lib.set_fn_1("atanh", |x: FLOAT| Ok(x.atanh().to_degrees())); lib.set_fn_1("sqrt", |x: FLOAT| Ok(x.sqrt())); lib.set_fn_1("exp", |x: FLOAT| Ok(x.exp())); lib.set_fn_1("ln", |x: FLOAT| Ok(x.ln())); lib.set_fn_2("log", |x: FLOAT, base: FLOAT| Ok(x.log(base))); lib.set_fn_1("log10", |x: FLOAT| Ok(x.log10())); lib.set_fn_1("floor", |x: FLOAT| Ok(x.floor())); lib.set_fn_1("ceiling", |x: FLOAT| Ok(x.ceil())); lib.set_fn_1("round", |x: FLOAT| Ok(x.ceil())); lib.set_fn_1("int", |x: FLOAT| Ok(x.trunc())); lib.set_fn_1("fraction", |x: FLOAT| Ok(x.fract())); lib.set_fn_1("is_nan", |x: FLOAT| Ok(x.is_nan())); lib.set_fn_1("is_finite", |x: FLOAT| Ok(x.is_finite())); lib.set_fn_1("is_infinite", |x: FLOAT| Ok(x.is_infinite())); // Register conversion functions lib.set_fn_1("to_float", |x: INT| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: f32| Ok(x as FLOAT)); #[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i64"))] { lib.set_fn_1("to_float", |x: i8| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: u8| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: i16| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: u16| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: i32| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: u32| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: i64| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: u64| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: i128| Ok(x as FLOAT)); lib.set_fn_1("to_float", |x: u128| Ok(x as FLOAT)); } } lib.set_fn_1("to_int", |ch: char| Ok(ch as INT)); #[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i64"))] { lib.set_fn_1("to_int", |x: i8| Ok(x as INT)); lib.set_fn_1("to_int", |x: u8| Ok(x as INT)); lib.set_fn_1("to_int", |x: i16| Ok(x as INT)); lib.set_fn_1("to_int", |x: u16| Ok(x as INT)); } #[cfg(not(feature = "only_i32"))] { lib.set_fn_1("to_int", |x: i32| Ok(x as INT)); lib.set_fn_1("to_int", |x: u64| Ok(x as INT)); #[cfg(feature = "only_i64")] lib.set_fn_1("to_int", |x: u32| Ok(x as INT)); } #[cfg(not(feature = "no_float"))] { #[cfg(not(feature = "unchecked"))] { lib.set_fn_1( "to_int", |x: f32| { if x > (MAX_INT as f32) { return Err(Box::new(EvalAltResult::ErrorArithmetic( format!("Integer overflow: to_int({})", x), Position::none(), ))); } Ok(x.trunc() as INT) }, ); lib.set_fn_1( "to_int", |x: FLOAT| { if x > (MAX_INT as FLOAT) { return Err(Box::new(EvalAltResult::ErrorArithmetic( format!("Integer overflow: to_int({})", x), Position::none(), ))); } Ok(x.trunc() as INT) }, ); } #[cfg(feature = "unchecked")] { lib.set_fn_1("to_int", |x: f32| Ok(x as INT)); lib.set_fn_1("to_int", |x: f64| Ok(x as INT)); } } });