nu_cmd_extra/extra/math/
cos.rs1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct MathCos;
5
6impl Command for MathCos {
7 fn name(&self) -> &str {
8 "math cos"
9 }
10
11 fn signature(&self) -> Signature {
12 Signature::build("math cos")
13 .switch("degrees", "Use degrees instead of radians", Some('d'))
14 .input_output_types(vec![
15 (Type::Number, Type::Float),
16 (
17 Type::List(Box::new(Type::Number)),
18 Type::List(Box::new(Type::Float)),
19 ),
20 ])
21 .category(Category::Math)
22 }
23
24 fn description(&self) -> &str {
25 "Returns the cosine of the number."
26 }
27
28 fn search_terms(&self) -> Vec<&str> {
29 vec!["trigonometry"]
30 }
31
32 fn run(
33 &self,
34 engine_state: &EngineState,
35 stack: &mut Stack,
36 call: &Call,
37 input: PipelineData,
38 ) -> Result<PipelineData, ShellError> {
39 let head = call.head;
40 let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
41 if let PipelineData::Empty = input {
43 return Err(ShellError::PipelineEmpty { dst_span: head });
44 }
45 input.map(
46 move |value| operate(value, head, use_degrees),
47 engine_state.signals(),
48 )
49 }
50
51 fn examples(&self) -> Vec<Example<'_>> {
52 vec![
53 Example {
54 description: "Apply the cosine to π",
55 example: "3.141592 | math cos | math round --precision 4",
56 result: Some(Value::test_float(-1f64)),
57 },
58 Example {
59 description: "Apply the cosine to a list of angles in degrees",
60 example: "[0 90 180 270 360] | math cos --degrees",
61 result: Some(Value::list(
62 vec![
63 Value::test_float(1f64),
64 Value::test_float(0f64),
65 Value::test_float(-1f64),
66 Value::test_float(0f64),
67 Value::test_float(1f64),
68 ],
69 Span::test_data(),
70 )),
71 },
72 ]
73 }
74}
75
76fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
77 match value {
78 numeric @ (Value::Int { .. } | Value::Float { .. }) => {
79 let span = numeric.span();
80 let (val, span) = match numeric {
81 Value::Int { val, .. } => (val as f64, span),
82 Value::Float { val, .. } => (val, span),
83 _ => unreachable!(),
84 };
85
86 let val = if use_degrees { val.to_radians() } else { val };
87
88 Value::float(val.cos(), span)
89 }
90 Value::Error { .. } => value,
91 other => Value::error(
92 ShellError::OnlySupportsThisInputType {
93 exp_input_type: "numeric".into(),
94 wrong_type: other.get_type().to_string(),
95 dst_span: head,
96 src_span: other.span(),
97 },
98 head,
99 ),
100 }
101}
102
103#[cfg(test)]
104mod test {
105 use super::*;
106
107 #[test]
108 fn test_examples() {
109 use crate::test_examples;
110
111 test_examples(MathCos {})
112 }
113}