From 0fe6c7c55847dba9610b5f0a1641323ee2c30a28 Mon Sep 17 00:00:00 2001 From: Luccas Mateus Date: Thu, 1 Apr 2021 18:26:05 -0300 Subject: [PATCH] Mathsqrt (#3239) * Output error when ls into a file without permission * math sqrt * added test to check fails when ls into prohibited dir * fix lint * math sqrt with tests and doc * trigger wasm build * Update filesystem_shell.rs * always forgetting the linting * fix clippy complaining Co-authored-by: Jonathan Turner --- crates/nu-command/src/commands.rs | 3 +- .../src/commands/default_context.rs | 1 + crates/nu-command/src/commands/math/mod.rs | 2 + crates/nu-command/src/commands/math/sqrt.rs | 75 +++++++++++++++++++ crates/nu-command/tests/commands/math/mod.rs | 1 + crates/nu-command/tests/commands/math/sqrt.rs | 31 ++++++++ docs/commands/math.md | 10 +++ 7 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 crates/nu-command/src/commands/math/sqrt.rs create mode 100644 crates/nu-command/tests/commands/math/sqrt.rs diff --git a/crates/nu-command/src/commands.rs b/crates/nu-command/src/commands.rs index 9e742a4e0..bce150c55 100644 --- a/crates/nu-command/src/commands.rs +++ b/crates/nu-command/src/commands.rs @@ -218,7 +218,8 @@ pub(crate) use lines::Lines; pub(crate) use ls::Ls; pub(crate) use math::{ Math, MathAbs, MathAverage, MathCeil, MathEval, MathFloor, MathMaximum, MathMedian, - MathMinimum, MathMode, MathProduct, MathRound, MathStddev, MathSummation, MathVariance, + MathMinimum, MathMode, MathProduct, MathRound, MathSqrt, MathStddev, MathSummation, + MathVariance, }; pub(crate) use merge::Merge; pub(crate) use mkdir::Mkdir; diff --git a/crates/nu-command/src/commands/default_context.rs b/crates/nu-command/src/commands/default_context.rs index 06590f7e9..dd83bd929 100644 --- a/crates/nu-command/src/commands/default_context.rs +++ b/crates/nu-command/src/commands/default_context.rs @@ -188,6 +188,7 @@ pub fn create_default_context(interactive: bool) -> Result &str { + "math sqrt" + } + + fn signature(&self) -> Signature { + Signature::build("math sqrt") + } + + fn usage(&self) -> &str { + "Applies the square root function to a list of numbers" + } + + async fn run(&self, args: CommandArgs) -> Result { + operate(args).await + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Apply the square root function to a list of numbers", + example: "echo [9 16] | math sqrt", + result: Some(vec![ + UntaggedValue::int(3).into(), + UntaggedValue::int(4).into(), + ]), + }] + } +} + +async fn operate(args: CommandArgs) -> Result { + let mapped = args.input.map(move |val| match val.value { + UntaggedValue::Primitive(Primitive::Int(val)) => sqrt_big_decimal(BigDecimal::from(val)), + UntaggedValue::Primitive(Primitive::Decimal(val)) => sqrt_big_decimal(val), + other => sqrt_default(other), + }); + Ok(OutputStream::from_input(mapped)) +} + +fn sqrt_big_decimal(val: BigDecimal) -> Value { + let squared = val.sqrt(); + match squared { + None => UntaggedValue::Error(ShellError::unexpected("Cant square root a negative number")) + .into(), + Some(val) if !val.is_integer() => UntaggedValue::decimal(val.normalized()).into(), + Some(val) => UntaggedValue::int(val.with_scale(0).as_bigint_and_exponent().0).into(), + } +} + +fn sqrt_default(_: UntaggedValue) -> Value { + UntaggedValue::Error(ShellError::unexpected( + "Only numerical values are supported", + )) + .into() +} + +#[cfg(test)] +mod tests { + use super::ShellError; + use super::SubCommand; + + #[test] + fn examples_work_as_expected() -> Result<(), ShellError> { + use crate::examples::test as test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/tests/commands/math/mod.rs b/crates/nu-command/tests/commands/math/mod.rs index 3bbcc3ea1..3108c7fa0 100644 --- a/crates/nu-command/tests/commands/math/mod.rs +++ b/crates/nu-command/tests/commands/math/mod.rs @@ -2,6 +2,7 @@ mod avg; mod eval; mod median; mod round; +mod sqrt; mod sum; use nu_test_support::{nu, pipeline}; diff --git a/crates/nu-command/tests/commands/math/sqrt.rs b/crates/nu-command/tests/commands/math/sqrt.rs new file mode 100644 index 000000000..c8e7eb24a --- /dev/null +++ b/crates/nu-command/tests/commands/math/sqrt.rs @@ -0,0 +1,31 @@ +use nu_test_support::nu; + +#[test] +fn can_sqrt_numbers() { + let actual = nu!( + cwd: ".", + "echo [0.25 2 4] | math sqrt | math sum" + ); + + assert_eq!(actual.out, "3.914213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573"); +} + +#[test] +fn can_sqrt_irrational() { + let actual = nu!( + cwd: ".", + "echo 2 | math sqrt" + ); + + assert_eq!(actual.out, "1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573"); +} + +#[test] +fn can_sqrt_perfect_square() { + let actual = nu!( + cwd: ".", + "echo 4 | math sqrt" + ); + + assert_eq!(actual.out, "2"); +} diff --git a/docs/commands/math.md b/docs/commands/math.md index 078a7fadb..7d4230e5c 100644 --- a/docs/commands/math.md +++ b/docs/commands/math.md @@ -13,6 +13,7 @@ Currently the following functions are implemented: * `math min`: Finds the minimum within a list of numbers or tables * `math mode`: Finds the most frequent element(s) within a list of numbers or tables * `math round`: Applies the round function to a list of numbers +* `math sqrt`: Applies the square root function to a list of numbers * `math stddev`: Finds the standard deviation of a list of numbers or tables * `math sum`: Finds the sum of a list of numbers or tables * `math product`: Finds the product of a list of numbers or tables @@ -148,6 +149,15 @@ To get the average of the file sizes in a directory, simply pipe the size column ───┴──── ``` +```shell +> echo [4 16 0.25] | math sqrt +───┬──── + 0 │ 2 + 1 │ 4 + 2 │ 0.5 +───┴──── +``` + ```shell > echo [1 -2 -3.0] | math abs ───┬────────