number_diff/lib.rs
1//! # Overview
2//! ## Number Diff - An all-purpose tool for calculus
3//!
4//!
5//!
6//! ### Functions
7//! Number Diff is built around a calculus-like function, that is, a function that takes an
8//! f64 as an argument, returning an f64 according to some specific rule. In the current state of
9//! the crate, functions are limited to ƒ: ℝ ⟶ ℝ (have a look at the [supported
10//! functions](#supported-functions) for which functions can be used).
11//! There are plans to expand to ƒ: ℂ ⟶ ℂ in the not so distant future.
12//!
13//! #### Usage
14//! Functions are represented by the Function struct. The Function struct can be created by either
15//! parsing a string or combining functions using standard operations. A Function
16//! instance can then be used with the call(x) method (or when using the nightly feature, Function
17//! instances can be called directly).
18//!
19//! Check out [some examples](https://github.com/HellFelix/number-diff/tree/main/examples)!
20//!
21//! ## Supported functions
22//! | Function | Parsing Identifier | In-code Function |
23//! |:----------:|:-------------------:|:-----------------:|
24//! | sin | "sin(_)" | [sin()](crate::sin) |
25//! | cos | "cos(_)" | [cos()](crate::cos) |
26//! | tan | "tan(_)" | [tan()](crate::tan) |
27//! | sec | "sec(_)" | [sec()](crate::sec) |
28//! | csc | "csc(_)" | [csc()](crate::csc) |
29//! | cot | "cot(_)" | [cot()](crate::cot) |
30//! | asin | "asin(_)" | [asin()](crate::asin) |
31//! | acos | "acos(_)" | [acos()](crate::acos) |
32//! | atan | "atan(_)" | [atan()](crate::atan) |
33//! | sinh | "sinh(_)" | [sinh()](crate::sinh) |
34//! | cosh | "cosh(_)" | [cosh()](crate::cosh) |
35//! | tanh | "tanh(_)" | [tanh()](crate::tanh) |
36//! | natural log|"ln(_)" | [ln()](crate::ln) |
37//! | absolute value|"abs(_)" | [abs()](crate::abs) |
38//! | square root|"sqrt(_)" | [sqrt()](crate::sqrt) |
39//! | factorial | "_!" | [factorial()](crate::factorial) |
40//! | addition | "_ + _ " | [+](core::ops::Add) |
41//! | subtraction| "_ - _" | [-](core::ops::Sub) |
42//! | multiplication| "_ * _" | [*](core::ops::Mul) |
43//! | division | "_ / _" | [/](core::ops::Div) |
44//! | contant | "1", "-12", "3.14", etc. | [f64](f64) |
45//! | independent variable | "x" | [Function::default()](crate::Function::default) |
46//!
47//! Note that "_" in the table above refers to any other function of the ones provided above. Note also that the
48//! operations (+, -, *, /) cannot be applied to each other. Attempting to apply an operation to
49//! another operation will make the parser return a [Parsing Error](crate::Error::ParseError).
50//!
51//! ### Derivatives
52//! All of the [supported functions](#supported-functions) are [smooth functions](https://en.wikipedia.org/wiki/Smoothness) which in turn
53//! means that once initialized, a [Function](crate::Function) is guaranteed to be a smooth function and so are all of its
54//! derivatives.
55//!
56//! Derivatives are calculated analytically. The provided derivative function will always be the
57//! the exact derivative of the original function (although not always in simplest form).
58//!
59//! Note that in its current state, differentiating might in some rare cases return NaN for
60//! certain input values where simplification fails to avoid a division by zero.
61//!
62//! Function instances can be differentiated using the [differentiate()
63//! method](crate::Function::differentiate) or using the [derivative_of()
64//! function](crate::derivative_of).
65//!
66//! ### Integrals
67//! Integration is stable for the most part. With a standard precision of 1000, integration uses
68//! Simpson's rule in order to find an approximate value of the integral.
69//!
70//! For usage examples, check out the [integration documentation](crate::Integrate)!
71//!
72//! Note that while integrating over an interval (including the bounds of integration) inside of which the value of the
73//! specified function is undefined, the resulting value might be [NaN](f64::NAN).
74//!
75//! Also, integrating over an interval (including the bounds of integration) inside of which the value of the
76//! specified function is infinit, the resulting value might be [inf](f64::INFINITY) even though
77//! the integral should converge.
78//!
79//! ### Series Expansions
80//! See [this article](https://en.wikipedia.org/wiki/Series_expansion) for an explanation of series
81//! expansions.
82//!
83//! #### Current stability of series expansions
84//!
85//! | Expansion Technique | Stability | Usage |
86//! |:-------------------:|:---------:|:-----------:|
87//! | Taylor series | Stable ✅ | [get_taylor_expansion()](crate::Function::get_taylor_expansion)|
88//! | Maclaurin series | Stable ✅ | [get_maclaurin_expansion()](crate::Function::get_maclaurin_expansion)|
89//! | Fourier series | Unimplemented ❌| N/A |
90
91#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
92#![cfg_attr(feature = "nightly", feature(fn_traits))]
93#![cfg_attr(feature = "nightly", feature(tuple_trait))]
94
95mod functions;
96pub use functions::calc::Elementary;
97
98mod utils;
99pub use utils::include::*;
100
101mod simplify;
102
103type Func = Box<dyn Fn(f64) -> f64 + 'static>;
104
105#[derive(Debug)]
106pub enum Error {
107 ParseError(String),
108 SimplifyError(Elementary, String),
109 InternalError(String),
110 ExpansionError(String),
111 InputError(String),
112}