num_parser/function/
builtin.rs

1//!
2//! Contains functions to easily retrieve and set built-in functions and constants.
3//!
4
5use 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        // Math constants
24        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        // Literal values
30        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
74/// Returns `Some(Function)` if the identifier matches some.
75pub 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
82/// Returns `Some(Value)` if the identifier matches some.
83pub 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
90/// Returns all reserved keywords.
91pub 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
105/// Get a cloned vector of all built-in functions.
106pub fn get_built_in_functions_vec() -> Vec<Function> {
107    BUILT_IN_FUNCTIONS.read().unwrap().iter().cloned().collect()
108}
109
110/// Get a cloned vector of all built-in constants.
111pub 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
120/// Add a function to the built-in ones.
121pub fn add_built_in_function(func: Function) {
122    BUILT_IN_FUNCTIONS.write().unwrap().push(func)
123}
124
125/// Add a constant to the built-in ones.
126///
127/// If a constant with the same identifier didn't exist, `None` is returned.
128///
129/// If it existed, the value is updated and the old value is returned.
130pub fn add_built_in_const(identifier: &'static str, value: Value) -> Option<Value> {
131    CONSTANTS.write().unwrap().insert(identifier, value)
132}
133
134/// Removes a built-in function with a matching identifier.
135///
136/// If a function is found, it is removed and returned, otherwise `None` is returned.
137pub 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
150/// Removes a built-in constant with a matching identifier.
151///
152/// If a constant is found, it is removed and returned, otherwise `None` is returned.
153pub fn remove_built_in_const(const_identifier: &str) -> Option<Value> {
154    CONSTANTS.write().unwrap().remove(const_identifier)
155}
156
157// STD
158
159decl_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
262// LOGIC
263
264fn 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
273// TRIGONOMETRY
274
275decl_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
359// COMPLEX
360
361decl_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);