diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index e5929256ce..cae0f0c3c7 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -414,6 +414,9 @@ pub fn create_default_context() -> EngineState { MathArcSin, MathArcCos, MathArcTan, + MathArcSinH, + MathArcCosH, + MathArcTanH, MathPi, MathEuler, }; diff --git a/crates/nu-command/src/math/arccosh.rs b/crates/nu-command/src/math/arccosh.rs new file mode 100644 index 0000000000..17ade19563 --- /dev/null +++ b/crates/nu-command/src/math/arccosh.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 arccosh" + } + + fn signature(&self) -> Signature { + Signature::build("math arccosh") + .input_output_types(vec![(Type::Number, Type::Float)]) + .vectorizes_over_list(true) + .category(Category::Math) + } + + fn usage(&self) -> &str { + "Returns the inverse of the hyperbolic cosine function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + 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 arccosh of 1", + example: "1 | math arccosh", + result: Some(Value::test_float(0.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 (1.0..).contains(&val) { + let val = val.acosh(); + + Value::Float { val, span } + } else { + Value::Error { + error: ShellError::UnsupportedInput( + "'arccosh' undefined for values below 1.".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/arcsinh.rs b/crates/nu-command/src/math/arcsinh.rs new file mode 100644 index 0000000000..edde4cad4b --- /dev/null +++ b/crates/nu-command/src/math/arcsinh.rs @@ -0,0 +1,86 @@ +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 arcsinh" + } + + fn signature(&self) -> Signature { + Signature::build("math arcsinh") + .input_output_types(vec![(Type::Number, Type::Float)]) + .vectorizes_over_list(true) + .category(Category::Math) + } + + fn usage(&self) -> &str { + "Returns the inverse of the hyperbolic sine function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + 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 arcsinh of 0", + example: "0 | math arcsinh", + result: Some(Value::test_float(0.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!(), + }; + + let val = val.asinh(); + + Value::Float { val, 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/arctanh.rs b/crates/nu-command/src/math/arctanh.rs new file mode 100644 index 0000000000..8ee966941d --- /dev/null +++ b/crates/nu-command/src/math/arctanh.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 arctanh" + } + + fn signature(&self) -> Signature { + Signature::build("math arctanh") + .input_output_types(vec![(Type::Number, Type::Float)]) + .vectorizes_over_list(true) + .category(Category::Math) + } + + fn usage(&self) -> &str { + "Returns the inverse of the hyperbolic tangent function." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["trigonometry", "inverse", "hyperbolic"] + } + + 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 arctanh of 1", + example: "1 | math arctanh", + result: Some(Value::test_float(f64::INFINITY)), + }] + } +} + +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 (-1.0..=1.0).contains(&val) { + let val = val.atanh(); + + Value::Float { val, span } + } else { + Value::Error { + error: ShellError::UnsupportedInput( + "'arctanh' undefined for values outside the open interval (-1, 1).".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 35bc35f014..e920d73725 100644 --- a/crates/nu-command/src/math/mod.rs +++ b/crates/nu-command/src/math/mod.rs @@ -1,7 +1,10 @@ mod abs; mod arccos; +mod arccosh; mod arcsin; +mod arcsinh; mod arctan; +mod arctanh; mod avg; mod ceil; mod cos; @@ -55,6 +58,9 @@ pub use tanh::SubCommand as MathTanH; pub use arccos::SubCommand as MathArcCos; pub use arccosh::SubCommand as MathArcCosH; pub use arcsin::SubCommand as MathArcSin; +pub use arcsinh::SubCommand as MathArcSinH; +pub use arctan::SubCommand as MathArcTan; +pub use arctanh::SubCommand as MathArcTanH; pub use euler::SubCommand as MathEuler; pub use pi::SubCommand as MathPi;