From 1f175d4c989a2984c67cd0f69752f5332604b761 Mon Sep 17 00:00:00 2001 From: sholderbach Date: Sun, 27 Nov 2022 21:16:53 +0100 Subject: [PATCH] Add natural logarithm (#7258) - `math ln` --- crates/nu-command/src/default_context.rs | 1 + crates/nu-command/src/math/ln.rs | 95 ++++++++++++++++++++++++ crates/nu-command/src/math/mod.rs | 3 + 3 files changed, 99 insertions(+) create mode 100644 crates/nu-command/src/math/ln.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index cae0f0c3c..8a82ded26 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -419,6 +419,7 @@ pub fn create_default_context() -> EngineState { MathArcTanH, MathPi, MathEuler, + MathLn, }; // Network diff --git a/crates/nu-command/src/math/ln.rs b/crates/nu-command/src/math/ln.rs new file mode 100644 index 000000000..95c33adcc --- /dev/null +++ b/crates/nu-command/src/math/ln.rs @@ -0,0 +1,95 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "math ln" + } + + fn signature(&self) -> Signature { + Signature::build("math ln") + .input_output_types(vec![(Type::Number, Type::Float)]) + .vectorizes_over_list(true) + .category(Category::Math) + } + + fn usage(&self) -> &str { + "Returns the natural logarithm. Base: (math e)" + } + + fn search_terms(&self) -> Vec<&str> { + vec!["natural", "logarithm", "inverse", "euler"] + } + + fn run( + &self, + engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let head = call.head; + input.map( + move |value| operate(value, head), + engine_state.ctrlc.clone(), + ) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Get the natural logarithm of e", + example: "math e | math ln", + result: Some(Value::test_float(1.0f64)), + }] + } +} + +fn operate(value: Value, head: Span) -> Value { + match value { + numeric @ (Value::Int { .. } | Value::Float { .. }) => { + let (val, span) = match numeric { + Value::Int { val, span } => (val as f64, span), + Value::Float { val, span } => (val, span), + _ => unreachable!(), + }; + + if val > 0.0 { + let val = val.ln(); + + Value::Float { val, span } + } else { + Value::Error { + error: ShellError::UnsupportedInput( + "'ln' undefined for values outside the open interval (0, Inf).".into(), + span, + ), + } + } + } + other => Value::Error { + error: ShellError::UnsupportedInput( + format!( + "Only numerical values are supported, input type: {:?}", + other.get_type() + ), + other.span().unwrap_or(head), + ), + }, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/math/mod.rs b/crates/nu-command/src/math/mod.rs index e920d7372..ed999b634 100644 --- a/crates/nu-command/src/math/mod.rs +++ b/crates/nu-command/src/math/mod.rs @@ -12,6 +12,7 @@ mod cosh; mod euler; mod eval; mod floor; +mod ln; pub mod math_; mod max; mod median; @@ -64,3 +65,5 @@ pub use arctanh::SubCommand as MathArcTanH; pub use euler::SubCommand as MathEuler; pub use pi::SubCommand as MathPi; + +pub use ln::SubCommand as MathLn;