number_diff/functions/calc.rs
1use crate::{gamma_function, polygamma_function, Elementary::*, Factorial};
2use std::{f64::consts::E, sync::Arc};
3
4use crate::{Error, Func};
5
6use super::series_expansions::SeriesExpansion;
7
8// unit function f(x) -> x
9fn f() -> Func {
10 Box::new(move |x| x)
11}
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum Elementary {
15 // Standard trig functions
16 Sin(Arc<Elementary>), // of the type sin(f(x))
17 Cos(Arc<Elementary>), // of the type cos(f(x))
18 Tan(Arc<Elementary>), // of the type tan(f(x))
19
20 Sec(Arc<Elementary>), // of the tyoe sec(f(x))
21 Csc(Arc<Elementary>), // of the type csc(f(x))
22 Cot(Arc<Elementary>), // of the type cot(f(x))
23
24 // Standard arcus functions
25 Asin(Arc<Elementary>), // of the type arcsin(f(x))
26 Acos(Arc<Elementary>), // of the type arccos(f(x))
27 Atan(Arc<Elementary>), // of the type arctan(f(x))
28
29 // hyperbolic trig functions
30 Sinh(Arc<Elementary>), // of the type sinh(f(x))
31 Cosh(Arc<Elementary>), // of the type cosh(f(x))
32 Tanh(Arc<Elementary>), // of the type tanh(f(x))
33
34 // Standard operations
35 Add(Arc<Elementary>, Arc<Elementary>), // of the type f(x) + g(x)
36 Sub(Arc<Elementary>, Arc<Elementary>), // of the type f(x) - g(x)
37 Mul(Arc<Elementary>, Arc<Elementary>), // of the type f(x) * g(x)
38 Div(Arc<Elementary>, Arc<Elementary>), // of the type f(x) / g(x)
39 Pow(Arc<Elementary>, Arc<Elementary>), // of the type f(x)^g(x)
40 Log(Arc<Elementary>, Arc<Elementary>), // of the type logb(f(x)) where b = g(x)
41
42 // special functions
43 Factorial(Arc<Elementary>),
44 // gamma function
45 Gamma(Arc<Elementary>), // of the type 𝜞(f(x))
46 Polygamma(Arc<Elementary>, usize), // Of the type 𝝍m(f(x))
47
48 // Absolute value function
49 Abs(Arc<Elementary>),
50 // Constant function
51 Con(f64), // of the type c
52
53 X, // unit function f(x) = x. Any function dependant on a variable must include this
54 // function as it returns a function of type Func which returns the input value.
55 // X will represent the independant variable in each function
56}
57impl Elementary {
58 pub fn call(self) -> Func {
59 Box::new(move |x| match self.clone() {
60 Sin(func) => (*func).clone().call()(x).sin(),
61 Cos(func) => (*func).clone().call()(x).cos(),
62 Tan(func) => (*func).clone().call()(x).tan(),
63
64 Sec(func) => 1. / (*func).clone().call()(x).cos(),
65 Csc(func) => 1. / (*func).clone().call()(x).sin(),
66 Cot(func) => 1. / (*func).clone().call()(x).tan(),
67
68 Asin(func) => (*func).clone().call()(x).asin(),
69 Acos(func) => (*func).clone().call()(x).acos(),
70 Atan(func) => (*func).clone().call()(x).atan(),
71
72 Sinh(func) => {
73 (E.powf((*func).clone().call()(x)) - E.powf(-(*func).clone().call()(x))) / 2.
74 }
75 Cosh(func) => {
76 (E.powf((*func).clone().call()(x)) + E.powf(-(*func).clone().call()(x))) / 2.
77 }
78 Tanh(func) => Sinh(func.clone()).call()(x) / Cosh(func).call()(x),
79
80 Add(func1, func2) => (*func1).clone().call()(x) + (*func2).clone().call()(x),
81 Sub(func1, func2) => (*func1).clone().call()(x) - (*func2).clone().call()(x),
82 Mul(func1, func2) => (*func1).clone().call()(x) * (*func2).clone().call()(x),
83 Div(func1, func2) => (*func1).clone().call()(x) / (*func2).clone().call()(x),
84
85 Pow(func1, func2) => (*func1).clone().call()(x).powf((*func2).clone().call()(x)),
86 Log(func1, func2) => (*func2).clone().call()(x).log((*func1).clone().call()(x)),
87
88 Factorial(func) => (*func).clone().call()(x).factorial(),
89
90 Gamma(func) => gamma_function((*func).clone().call()(x)),
91 Polygamma(func, order) => polygamma_function((*func).clone().call()(x), order),
92
93 Abs(func) => (*func).clone().call()(x).abs(),
94
95 Con(numb) => numb,
96
97 X => f()(x),
98 })
99 }
100}
101
102// returns the inner Elementary value of the Arc or returns a clone
103pub fn force_unwrap(element: &Arc<Elementary>) -> Elementary {
104 if let Ok(inner) = Arc::try_unwrap(element.clone()) {
105 inner
106 } else {
107 (**element).clone()
108 }
109}
110
111// basic trig functions
112/// Creates a [Function](crate::Function) equal to the sine of the passed [Function](crate::Function)
113///
114/// i.e f(x) ⟹ sin(f(x))
115///
116/// Example:
117/// ```rust
118/// let x = Function::default();
119/// let sin_of_x = sin(x);
120/// assert_eq!(sin_of_x.call(PI / 2.), 1.);
121/// ```
122pub fn sin(func: Function) -> Function {
123 let new_function = Sin(Arc::new(func.elementary()));
124 Function::from(new_function)
125}
126
127/// Creates a [Function](crate::Function) equal to the cosine of the passed [Function](crate::Function)
128///
129/// i.e f(x) ⟹ cos(f(x))
130///
131/// Example:
132/// ```rust
133/// let x = Function::default();
134/// let cos_of_x = cos(x);
135/// assert_eq!(cos_of_x.call(0.), 1.);
136/// ```
137pub fn cos(func: Function) -> Function {
138 let new_function = Cos(Arc::new(func.elementary()));
139 Function::from(new_function)
140}
141
142/// Creates a [Function](crate::Function) equal to the tangent of the passed [Function](crate::Function)
143///
144/// i.e f(x) ⟹ tan(f(x))
145///
146/// Example:
147/// ```rust
148/// let x = Function::default();
149/// let tan_of_x = tan(x);
150/// assert_eq!(tan_of_x.call(PI / 4.), 1.);
151/// ```
152pub fn tan(func: Function) -> Function {
153 let new_function = Tan(Arc::new(func.elementary()));
154 Function::from(new_function)
155}
156
157/// Creates a [Function](crate::Function) equal to the secant of the passed [Function](crate::Function)
158///
159/// i.e f(x) ⟹ sec(f(x))
160///
161/// Example:
162/// ```rust
163/// let x = Function::default();
164/// let sec_of_x = sec(x);
165/// assert_eq!(sec_of_x.call(PI), -1.);
166/// ```
167pub fn sec(func: Function) -> Function {
168 let new_function = Sec(Arc::new(func.elementary()));
169 Function::from(new_function)
170}
171
172/// Creates a [Function](crate::Function) equal to the cosecant of the passed [Function](crate::Function)
173///
174/// i.e f(x) ⟹ csc(f(x))
175///
176/// Example:
177/// ```rust
178/// let x = Function::default();
179/// let csc_of_x = csc(x);
180/// assert_eq!(csc_of_x.call(3./2. * PI), -1.);
181/// ```
182pub fn csc(func: Function) -> Function {
183 let new_function = Csc(Arc::new(func.elementary()));
184 Function::from(new_function)
185}
186
187/// Creates a [Function](crate::Function) equal to the cotangent of the passed [Function](crate::Function)
188///
189/// i.e f(x) ⟹ cot(f(x))
190///
191/// Example:
192/// ```rust
193/// let x = Function::default();
194/// let cot_of_x = cot(x);
195/// assert_eq!(cot_of_x.call(PI/2.), 0.);
196/// ```
197pub fn cot(func: Function) -> Function {
198 let new_function = Cot(Arc::new(func.elementary()));
199 Function::from(new_function)
200}
201
202// basic arcus functions
203/// Creates a [Function](crate::Function) equal to the arcsine of the passed [Function](crate::Function)
204///
205/// i.e f(x) ⟹ asin(f(x))
206///
207/// Example:
208/// ```rust
209/// let x = function::default();
210/// let asin_of_x = asin(x);
211/// assert_eq!(asin_of_x.call(1.), PI/2.);
212/// ```
213pub fn asin(func: Function) -> Function {
214 let new_function = Asin(Arc::new(func.elementary()));
215 Function::from(new_function)
216}
217
218/// Creates a [Function](crate::Function) equal to the arccosine of the passed [Function](crate::Function)
219///
220/// i.e f(x) ⟹ acos(f(x))
221///
222/// Example:
223/// ```rust
224/// let x = function::default();
225/// let acos_of_x = acos(x);
226/// assert_eq!(acos_of_x.call(1.), 0.);
227/// ```
228pub fn acos(func: Function) -> Function {
229 let new_function = Acos(Arc::new(func.elementary()));
230 Function::from(new_function)
231}
232
233/// Creates a [Function](crate::Function) equal to the arctangent of the passed [Function](crate::Function)
234///
235/// i.e f(x) ⟹ atan(f(x))
236///
237/// Example:
238/// ```rust
239/// let x = function::default();
240/// let atan_of_x = atan(x);
241/// assert_eq!(atan_of_x.call(1.), PI/4.);
242/// ```
243pub fn atan(func: Function) -> Function {
244 let new_function = Atan(Arc::new(func.elementary()));
245 Function::from(new_function)
246}
247
248// hyperbolic functions
249
250/// Creates a [Function](crate::Function) equal to the hyperbolic sine of the passed [Function](crate::Function)
251///
252/// i.e f(x) ⟹ sinh(f(x))
253///
254/// Example:
255/// ```rust
256/// let x = function::default();
257/// let sinh_of_x = sinh(x);
258/// assert_eq!(sinh_of_x.call(0.), 0.);
259/// ```
260pub fn sinh(func: Function) -> Function {
261 let new_function = Sinh(Arc::new(func.elementary()));
262 Function::from(new_function)
263}
264
265/// Creates a [Function](crate::Function) equal to the hyperbolic cosine of the passed [Function](crate::Function)
266///
267/// i.e f(x) ⟹ cosh(f(x))
268///
269/// Example:
270/// ```rust
271/// let x = function::default();
272/// let cosh_of_x = cosh(x);
273/// assert_eq!(cosh_of_x.call(0.), 1.);
274/// ```
275pub fn cosh(func: Function) -> Function {
276 let new_function = Cosh(Arc::new(func.elementary()));
277 Function::from(new_function)
278}
279
280/// Creates a [Function](crate::Function) equal to the hyperbolic tangent of the passed [Function](crate::Function)
281///
282/// i.e f(x) ⟹ tanh(f(x))
283///
284/// Example:
285/// ```rust
286/// let x = function::default();
287/// let tanh_of_x = tanh(x);
288/// assert_eq!(tanh_of_x.call(0.), 0.);
289/// ```
290pub fn tanh(func: Function) -> Function {
291 let new_function = Tanh(Arc::new(func.elementary()));
292 Function::from(new_function)
293}
294// abs function
295/// Creates a [Function](crate::Function) equal to the absolute value of the passed [Function](crate::Function)
296///
297/// i.e f(x) ⟹ |f(x)|
298///
299/// Example:
300/// ```rust
301/// let x = function::default();
302/// let abs_of_x = abs(x);
303/// assert_eq!(abs_of_x.call(-1.), 1.);
304/// ```
305pub fn abs(func: Function) -> Function {
306 let new_function = Abs(Arc::new(func.elementary()));
307 Function::from(new_function)
308}
309
310// ln function
311/// Creates a [Function](crate::Function) equal to the natural logarithm (base e) of the passed [Function](crate::Function)
312///
313/// i.e f(x) ⟹ ln(f(x))
314///
315/// Example:
316/// ```rust
317/// let x = function::default();
318/// let ln_of_x = ln(x);
319/// assert_eq!(ln_of_x.call(E), 1.);
320/// ```
321pub fn ln(func: Function) -> Function {
322 let new_function = Log(Con(E).into(), func.elementary().into());
323 Function::from(new_function)
324}
325
326/// Creates a [Function](crate::Function) equal to the square root of the passed [Function](crate::Function)
327///
328/// i.e f(x) ⟹ √f(x)
329///
330/// Example:
331/// ```rust
332/// let x = function::default();
333/// let sqrt_of_x = sqrt(x);
334/// assert_eq!(sqrt_of_x.call(4.), 2.);
335/// ```
336pub fn sqrt(func: Function) -> Function {
337 let new_function = Pow(Arc::new(func.elementary()), Arc::new(Con(0.5)));
338 Function::from(new_function)
339}
340
341/// Creates a [Function](crate::Function) equal to the factorial of the passed [Function](crate::Function)
342///
343/// i.e f(x) ⟹ f(x)!
344///
345/// Example:
346/// ```rust
347/// let x = function::default();
348/// let factorial_of_x = factorial(x);
349/// assert_eq!(factorial_of_x.call(4.), 2.);
350/// ```
351pub fn factorial(func: Function) -> Function {
352 let new_function = Factorial(func.elementary().into());
353 Function::from(new_function)
354}
355
356/// Creates a [Function](crate::Function) equal to the nth root of the passed [Function](crate::Function)
357///
358/// i.e f(x) ⟹ √f(x)
359///
360/// Example:
361/// ```rust
362/// let x = function::default();
363/// let nth_root_of_x = nth_root(x, 3);
364/// assert_eq!(nth_root_of_x.call(8.), 2.);
365/// ```
366pub fn nth_root(func: Function, n: f64) -> Function {
367 let new_function = Pow(Arc::new(func.elementary()), Arc::new(Con(1.) / n));
368 Function::from(new_function)
369}
370
371pub struct Function {
372 func: Elementary,
373}
374
375impl Function {
376 /// Returns the Elementary absraction of the Function instance
377 pub fn elementary(&self) -> Elementary {
378 self.func.clone()
379 }
380
381 /// Sets the function to represent the provided Elementary abstraction
382 pub fn set_function(&mut self, element: Elementary) {
383 self.func = element;
384 }
385
386 /// Turns self into the derivative of self
387 ///
388 /// i.e. f(x) ⟹ f'(x)
389 ///
390 /// Example:
391 /// ```rust
392 /// let mut function = Function::from("cosh(x)");
393 ///
394 /// // take derivative
395 /// function.differentiate();
396 /// // cosh(x)' = sinh(x)
397 /// // sinh(0) = 0
398 /// assert_eq!(function.call(0.), 0.);
399 /// ```
400 ///
401 /// Do also note that differentiating a function will not simplify the result. This is to make
402 /// sure that this method can never fail, but it does also mean that there are instances where
403 /// the resulting derivative will return [NaN](f64::NAN) for certain values.
404 pub fn differentiate(&mut self) {
405 self.func = self.elementary().to_owned().derivative_unsimplified();
406 }
407
408 /// Turns the given [Function](crate::Function) instance into a Taylor series expansion centered around the value
409 /// of a.
410 ///
411 /// If the conversion fails, an [Error::ExpansionError](Error) is returned.
412 pub fn as_taylor_expansion(&mut self, order: u8, a: f64) -> Result<(), Error> {
413 self.func = self.func.expand_taylor(order, a)?.get_elementary();
414 Ok(())
415 }
416
417 /// Returns a Taylor expansion of the provided order of the function centered around the provided value a.
418 pub fn get_taylor_expansion(&self, order: u8, a: f64) -> Result<SeriesExpansion, Error> {
419 self.func.expand_taylor(order, a)
420 }
421
422 /// Returns a Maclaurin expansion of the provided order.
423 pub fn get_maclaurin_expansion(&self, order: u8) -> Result<SeriesExpansion, Error> {
424 self.func.expand_maclaurin(order)
425 }
426}
427impl Default for Function {
428 /// The default() method returns the unit function f(x) = x, returning the independant variable
429 /// for each input value.
430 fn default() -> Self {
431 Self { func: X }
432 }
433}
434
435/// A [Function](crate::Function) instance can be parsed from any string type using the from method.
436///
437/// Example:
438/// ```rust
439/// let func = Function::from("sin(ln(x))");
440///
441/// assert_eq!(func.call(1.), 0.);
442/// // ...or using the nightly feature
443/// // assert_eq!(func(1.), 0.);
444/// ```
445impl<'a> From<&'a str> for Function {
446 fn from(value: &'a str) -> Self {
447 let func = Elementary::from(value);
448 Self { func }
449 }
450}
451impl From<String> for Function {
452 fn from(value: String) -> Self {
453 let func = Elementary::from(&value[..]);
454 Self { func }
455 }
456}
457impl<'a> From<&'a String> for Function {
458 fn from(value: &'a String) -> Self {
459 let func = Elementary::from(&value[..]);
460 Self { func }
461 }
462}
463impl From<Elementary> for Function {
464 fn from(value: Elementary) -> Self {
465 Self { func: value }
466 }
467}
468/// A [Function](crate::Function) instance can be obtained from a SeriesExpansion instance using the from method.
469///
470/// Example:
471/// ```rust
472/// // create the Function instance
473/// let func = Function::from("sin(x)");
474///
475/// // Get the SeriesExpansion
476/// // In this instance we're creating a Taylor expansion of order 5 centered around 0
477/// let expansion = func.get_taylor_expansion(5, 0.);
478///
479/// // Convert the SeriesExpansion into a Function using the from method
480/// let func_expansion = Function::from(expansion);
481/// // Note that this could also be done using the get_function method:
482/// // let func_expansion = expansion.get_function()
483/// //
484/// // ... or using the as_taylor_expansion method to convert the original Function instance into a
485/// // Taylor expansion without creating the SeriesExpansion instance seperatly:
486/// // func.as_taylor_expansion()
487///
488/// ```
489impl From<SeriesExpansion> for Function {
490 fn from(value: SeriesExpansion) -> Self {
491 value.get_function()
492 }
493}
494impl From<&SeriesExpansion> for Function {
495 fn from(value: &SeriesExpansion) -> Self {
496 (*value).clone().get_function()
497 }
498}