1use std::collections::HashMap;
6
7use crate::{
8 create_func, decl_func, function::Function, function::*, out::ErrorType, read_vec_values,
9 value::Value, EvalResult, ValueType,
10};
11use lazy_static::*;
12use num::complex::ComplexFloat;
13use rand::Rng;
14use std::sync::RwLock;
15use tuple_conv::RepeatedTuple;
16
17lazy_static! {
18 #[derive(Debug, Clone)]
19 static ref CONSTANTS: RwLock<HashMap<&'static str, Value>> = RwLock::new
20 ({
21 let mut m = HashMap::new();
22 use std::f64::consts;
23 m.insert("pi", Value::Float(consts::PI));
25 m.insert("e", Value::Float(consts::E));
26 m.insert("tau", Value::Float(consts::TAU));
27 m.insert("phi", Value::Float(1.618_033_988_749_894));
28
29 m.insert("true", Value::Bool(true));
31 m.insert("false", Value::Bool(false));
32 m.insert("i", Value::Complex(num::Complex::i()));
33
34 m
35 });
36 #[derive(Debug, Clone)]
37 static ref BUILT_IN_FUNCTIONS: RwLock<Vec<Function>> = RwLock::new(vec![
38 create_func!(min, Arguments::Dynamic),
39 create_func!(max, Arguments::Dynamic),
40 create_func!(floor, Arguments::Const(1)),
41 create_func!(ceil, Arguments::Const(1)),
42 create_func!(round, Arguments::Const(1)),
43 create_func!(abs, Arguments::Const(1)),
44 create_func!(sqrt, Arguments::Const(1)),
45 create_func!(ln, Arguments::Const(1)),
46 create_func!(log, Arguments::Const(2)),
47 create_func!(exp, Arguments::Const(1)),
48 create_func!(rand, Arguments::Const(2)),
49
50 create_func!(branch, Arguments::Const(3)),
51
52 create_func!(sin, Arguments::Const(1)),
53 create_func!(cos, Arguments::Const(1)),
54 create_func!(tan, Arguments::Const(1)),
55 create_func!(asin, Arguments::Const(1)),
56 create_func!(acos, Arguments::Const(1)),
57 create_func!(atan, Arguments::Const(1)),
58 create_func!(sinh, Arguments::Const(1)),
59 create_func!(cosh, Arguments::Const(1)),
60 create_func!(tanh, Arguments::Const(1)),
61 create_func!(asinh, Arguments::Const(1)),
62 create_func!(acosh, Arguments::Const(1)),
63 create_func!(atanh, Arguments::Const(1)),
64
65 create_func!(re, Arguments::Const(1)),
66 create_func!(im, Arguments::Const(1)),
67 create_func!(polar, Arguments::Const(1)),
68 create_func!(arg, Arguments::Const(1)),
69 create_func!(norm, Arguments::Const(1)),
70
71 ]);
72}
73
74pub fn get_built_in_function(identifier: &str) -> Option<Function> {
76 get_built_in_functions_vec()
77 .iter()
78 .find(|x| x.func_identifier == identifier)
79 .cloned()
80}
81
82pub fn get_built_in_const(identifier: &str) -> Option<Value> {
84 get_built_in_consts_map()
85 .iter()
86 .find(|&x| x.0 == identifier)
87 .map(|x| x.1.clone())
88}
89
90pub fn reserved_keywords<'a>() -> Vec<&'a str> {
92 [
93 get_built_in_consts_map()
94 .iter()
95 .map(|x| x.0)
96 .collect::<Vec<&str>>(),
97 get_built_in_functions_vec()
98 .iter()
99 .map(|x| x.func_identifier)
100 .collect::<Vec<&str>>(),
101 ]
102 .concat()
103}
104
105pub fn get_built_in_functions_vec() -> Vec<Function> {
107 BUILT_IN_FUNCTIONS.read().unwrap().iter().cloned().collect()
108}
109
110pub fn get_built_in_consts_map() -> Vec<(&'static str, Value)> {
112 CONSTANTS
113 .read()
114 .unwrap()
115 .iter()
116 .map(|x| (x.0.clone(), x.1.clone()))
117 .collect()
118}
119
120pub fn add_built_in_function(func: Function) {
122 BUILT_IN_FUNCTIONS.write().unwrap().push(func)
123}
124
125pub fn add_built_in_const(identifier: &'static str, value: Value) -> Option<Value> {
131 CONSTANTS.write().unwrap().insert(identifier, value)
132}
133
134pub fn remove_built_in_function(func_identifier: &str) -> Option<Function> {
138 if let Some(index) = BUILT_IN_FUNCTIONS
139 .read()
140 .unwrap()
141 .iter()
142 .position(|x| x.func_identifier == func_identifier)
143 {
144 Some(BUILT_IN_FUNCTIONS.write().unwrap().swap_remove(index))
145 } else {
146 None
147 }
148}
149
150pub fn remove_built_in_const(const_identifier: &str) -> Option<Value> {
154 CONSTANTS.write().unwrap().remove(const_identifier)
155}
156
157decl_func!(
160 min,
161 FunctionType::Std,
162 |v| {
163 let vec = v.as_vector();
164 let mut min = vec[0].as_float()?;
165 for elem in vec {
166 if elem.as_float()? < min {
167 min = elem.as_float()?;
168 }
169 }
170 Ok(Value::Float(min))
171 },
172 ValueType::VectorType
173);
174
175decl_func!(
176 max,
177 FunctionType::Std,
178 |v| {
179 let vec = v.as_vector();
180 let mut max = vec[0].as_float()?;
181 for elem in vec {
182 if elem.as_float()? > max {
183 max = elem.as_float()?;
184 }
185 }
186 Ok(Value::Float(max))
187 },
188 ValueType::VectorType
189);
190
191decl_func!(
192 floor,
193 FunctionType::Std,
194 |v| Ok(v.as_float()?.floor()),
195 ValueType::FloatType
196);
197
198decl_func!(
199 ceil,
200 FunctionType::Std,
201 |v| Ok(v.as_float()?.ceil()),
202 ValueType::FloatType
203);
204
205decl_func!(
206 round,
207 FunctionType::Std,
208 |v| Ok(v.as_float()?.round()),
209 ValueType::FloatType
210);
211
212decl_func!(
213 abs,
214 FunctionType::Std,
215 |v: Value| Ok(Value::Float(v.as_complex()?.abs())),
216 ValueType::ComplexType
217);
218
219decl_func!(
220 sqrt,
221 FunctionType::Std,
222 |v: Value| Ok(Value::Complex(v.as_complex()?.sqrt())),
223 ValueType::ComplexType
224);
225
226decl_func!(
227 ln,
228 FunctionType::Std,
229 |v| Ok(v.as_complex()?.ln()),
230 ValueType::ComplexType
231);
232
233decl_func!(
234 log,
235 FunctionType::Std,
236 |v| {
237 read_vec_values!(v, base, argument);
238 Ok(argument.as_complex()?.log(base.as_float()?))
239 },
240 ValueType::VectorType
241);
242
243decl_func!(
244 exp,
245 FunctionType::Std,
246 |v| Ok(v.as_complex()?.exp()),
247 ValueType::ComplexType
248);
249
250decl_func!(
251 rand,
252 FunctionType::Std,
253 |v| {
254 read_vec_values!(v, min, max);
255 Ok(Value::Float(
256 rand::thread_rng().gen_range(min.as_float()?..max.as_float()?),
257 ))
258 },
259 ValueType::VectorType
260);
261
262fn branch(arguments: &Vec<Box<Expression>>, context: &Context, depth: u32) -> EvalResult<Value> {
265 let condition = arguments[0].eval(context, None, depth)?.as_bool()?;
266 if condition {
267 Ok(arguments[1].eval(context, None, depth)?)
268 } else {
269 Ok(arguments[2].eval(context, None, depth)?)
270 }
271}
272
273decl_func!(
276 sin,
277 FunctionType::Trig,
278 |v| Ok(v.as_complex()?.sin()),
279 ValueType::ComplexType
280);
281
282decl_func!(
283 cos,
284 FunctionType::Trig,
285 |v| Ok(v.as_complex()?.cos()),
286 ValueType::ComplexType
287);
288
289decl_func!(
290 tan,
291 FunctionType::Trig,
292 |v| Ok(v.as_complex()?.tan()),
293 ValueType::ComplexType
294);
295
296decl_func!(
297 asin,
298 FunctionType::InverseTrig,
299 |v| Ok(v.as_complex()?.asin()),
300 ValueType::ComplexType
301);
302
303decl_func!(
304 acos,
305 FunctionType::InverseTrig,
306 |v| Ok(v.as_complex()?.acos()),
307 ValueType::ComplexType
308);
309
310decl_func!(
311 atan,
312 FunctionType::InverseTrig,
313 |v| Ok(v.as_complex()?.atan()),
314 ValueType::ComplexType
315);
316
317decl_func!(
318 sinh,
319 FunctionType::Trig,
320 |v| Ok(v.as_complex()?.sinh()),
321 ValueType::ComplexType
322);
323
324decl_func!(
325 cosh,
326 FunctionType::Trig,
327 |v| Ok(v.as_complex()?.cosh()),
328 ValueType::ComplexType
329);
330
331decl_func!(
332 tanh,
333 FunctionType::Trig,
334 |v| Ok(v.as_complex()?.tanh()),
335 ValueType::ComplexType
336);
337
338decl_func!(
339 asinh,
340 FunctionType::InverseTrig,
341 |v| Ok(v.as_complex()?.asinh()),
342 ValueType::ComplexType
343);
344
345decl_func!(
346 acosh,
347 FunctionType::InverseTrig,
348 |v| Ok(v.as_complex()?.acosh()),
349 ValueType::ComplexType
350);
351
352decl_func!(
353 atanh,
354 FunctionType::InverseTrig,
355 |v| Ok(v.as_complex()?.atanh()),
356 ValueType::ComplexType
357);
358
359decl_func!(
362 re,
363 FunctionType::Std,
364 |v| Ok(v.as_complex()?.re),
365 ValueType::ComplexType
366);
367
368decl_func!(
369 im,
370 FunctionType::Std,
371 |v| Ok(v.as_complex()?.im),
372 ValueType::ComplexType
373);
374
375decl_func!(
376 polar,
377 FunctionType::Std,
378 |v| Ok(v.as_complex()?.to_polar().to_vec()),
379 ValueType::ComplexType
380);
381
382decl_func!(
383 arg,
384 FunctionType::Std,
385 |v| Ok(v.as_complex()?.arg()),
386 ValueType::ComplexType
387);
388
389decl_func!(
390 norm,
391 FunctionType::Std,
392 |v| Ok(v.as_complex()?.norm()),
393 ValueType::ComplexType
394);