1use anyhow::Result;
4
5use crate::{
6 errors::KclError,
7 execution::{
8 types::{ArrayLen, NumericType, RuntimeType},
9 ExecState, KclValue,
10 },
11 std::args::{Args, TyF64},
12 CompilationError,
13};
14
15pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
18 let n: TyF64 = args.get_unlabeled_kw_arg_typed("number to divide", &RuntimeType::num_any(), exec_state)?;
19 let d: TyF64 = args.get_kw_arg_typed("divisor", &RuntimeType::num_any(), exec_state)?;
20
21 let (n, d, ty) = NumericType::combine_div(n, d);
22 if ty == NumericType::Unknown {
23 exec_state.err(CompilationError::err(
24 args.source_range,
25 "Calling `rem` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`"
26 ));
27 }
28 let remainder = n % d;
29
30 Ok(args.make_user_val_from_f64_with_type(TyF64::new(remainder, ty)))
31}
32
33pub async fn cos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
35 let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
36 let num = num.to_radians();
37 Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.cos())))
38}
39
40pub async fn sin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
42 let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
43 let num = num.to_radians();
44 Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.sin())))
45}
46
47pub async fn tan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
49 let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
50 let num = num.to_radians();
51 Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.tan())))
52}
53
54pub async fn sqrt(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
56 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
57 let result = input.n.sqrt();
58
59 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
60}
61
62pub async fn abs(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
64 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
65 let result = input.n.abs();
66
67 Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
68}
69
70pub async fn round(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
72 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
73 let result = input.n.round();
74
75 Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
76}
77
78pub async fn floor(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
80 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
81 let result = input.n.floor();
82
83 Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
84}
85
86pub async fn ceil(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
88 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
89 let result = input.n.ceil();
90
91 Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
92}
93
94pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
96 let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
97 "input",
98 &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::NonEmpty),
99 exec_state,
100 )?;
101 let (nums, ty) = NumericType::combine_eq_array(&nums);
102 if ty == NumericType::Unknown {
103 exec_state.warn(CompilationError::err(
104 args.source_range,
105 "Calling `min` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`",
106 ));
107 }
108
109 let mut result = f64::MAX;
110 for num in nums {
111 if num < result {
112 result = num;
113 }
114 }
115
116 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
117}
118
119pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
121 let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
122 "input",
123 &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::NonEmpty),
124 exec_state,
125 )?;
126 let (nums, ty) = NumericType::combine_eq_array(&nums);
127 if ty == NumericType::Unknown {
128 exec_state.warn(CompilationError::err(
129 args.source_range,
130 "Calling `max` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`",
131 ));
132 }
133
134 let mut result = f64::MIN;
135 for num in nums {
136 if num > result {
137 result = num;
138 }
139 }
140
141 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
142}
143
144pub async fn pow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
146 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
147 let exp: TyF64 = args.get_kw_arg_typed("exp", &RuntimeType::count(), exec_state)?;
148 let result = input.n.powf(exp.n);
149
150 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
151}
152
153pub async fn acos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
155 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
156 let result = input.n.acos();
157
158 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
159}
160
161pub async fn asin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
163 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
164 let result = input.n.asin();
165
166 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
167}
168
169pub async fn atan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
171 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
172 let result = input.n.atan();
173
174 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
175}
176
177pub async fn atan2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
179 let y = args.get_kw_arg_typed("y", &RuntimeType::length(), exec_state)?;
180 let x = args.get_kw_arg_typed("x", &RuntimeType::length(), exec_state)?;
181 let (y, x, _) = NumericType::combine_eq_coerce(y, x);
182 let result = y.atan2(x);
183
184 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
185}
186
187pub async fn log(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
193 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
194 let base: TyF64 = args.get_kw_arg_typed("base", &RuntimeType::count(), exec_state)?;
195 let result = input.n.log(base.n);
196
197 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
198}
199
200pub async fn log2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
202 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
203 let result = input.n.log2();
204
205 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
206}
207
208pub async fn log10(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
210 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
211 let result = input.n.log10();
212
213 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
214}
215
216pub async fn ln(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
218 let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
219 let result = input.n.ln();
220
221 Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
222}