maths_traits/analysis/
real.rs

1//!
2//!Traits for [Real] and [Complex] properties and representations
3//!
4
5use crate::algebra::*;
6use crate::analysis::*;
7
8///
9///Functions and constants for evaluative trigonometric values
10///
11///For the most part, these methods are meant for struct representing [real numbers](Real),
12///and so, for those, the included functions have their normal meaning. However, in order to
13///include the generalizations (such as the complex trig functions), the precise definitions are
14///defined in a more abstract way.
15///
16///Specifically, all of the included methods should satisfy the relevant differential equation definition
17///of its function. Specifically:
18/// * [Sine](Trig::sin) and [Cosine](Trig::cos) should satisfy
19///     * `d/dx cos(x) = -sin(x)`
20///     * `d/dx sin(x) = cos(x)`
21///     * `cos(0) = 1`
22///     * `sin(0) = 0`
23/// * [Tangent](Trig::tan) should satisfy
24///     * `d/dx tan(x) = 1 + tan²(x)`
25///     * `tan(0) = 0`
26/// * [Hyperbolic Sine](Trig::sinh) and [Hyperbolic Cosine](Trig::cosh) should satisfy
27///     * `d/dx cosh(x) = sinh(x)`
28///     * `d/dx sinh(x) = cosh(x)`
29///     * `cosh(0) = 1`
30///     * `sinh(0) = 0`
31/// * [Hyperbolic Tangent](Trig::tanh) should satisfy
32///     * `d/dx tanh(x) = 1 - tanh²(x)`
33///     * `tanh(0) = 0`
34///
35///Of course, for Real and Complex numbers, the standard infinite series definitions also apply
36///and are most likely the method of computation.
37///
38pub trait Trig: UnitalRing + Divisibility {
39
40    ///
41    ///Finds the Sine of the given value
42    ///
43    ///For more general inputs, this is defined as the solution to:
44    /// * `f"(x) = -f(x)`
45    /// * `f(0) = 0`
46    /// * `f'(0) = 1`
47    ///
48    fn sin(self) -> Self;
49
50    ///
51    ///Finds the Cosine of the given value
52    ///
53    ///For more general inputs, this is defined as the solution to:
54    /// * `f"(x) = -f(x)`
55    /// * `f(0) = 1`
56    /// * `f'(0) = 0`
57    ///
58    fn cos(self) -> Self;
59
60    ///
61    ///Finds the Tangent of the given value
62    ///
63    ///For more general inputs, this is defined as the solution to:
64    /// * `f'(x) = 1 + f(x)²`
65    /// * `f(0) = 0`
66    ///
67    fn tan(self) -> Self;
68
69    ///
70    ///Finds both the [Sine](Trig::sin) and [Cosine](Trig::cos) as a tuple
71    ///
72    ///This is supposed to mirror f32::sin_cos() and f64::sin_cos()
73    ///
74    #[inline] fn sin_cos(self) -> (Self, Self) {(self.clone().sin(), self.cos())}
75
76    ///
77    ///Finds the Hyperbolic Sine of the given value
78    ///
79    ///For more general inputs, this is defined as the solution to:
80    /// * `f"(x) = f(x)`
81    /// * `f(0) = 0`
82    /// * `f'(0) = 1`
83    ///
84    fn sinh(self) -> Self;
85
86    ///
87    ///Finds the Hyperbolic Cosine of the given value
88    ///
89    ///For more general inputs, this is defined as the solution to:
90    /// * `f"(x) = f(x)`
91    /// * `f(0) = 1`
92    /// * `f'(0) = 0`
93    ///
94    fn cosh(self) -> Self;
95
96    ///
97    ///Finds the Hyperbolic Tangent of the given value
98    ///
99    ///For more general inputs, this is defined as the solution to:
100    /// * `f'(x) = 1 - f(x)²`
101    /// * `f(0) = 0`
102    ///
103    fn tanh(self) -> Self;
104
105    ///
106    ///A continuous inverse function of [Sine](Trig::sin) such that `asin(1) = π/2` and `asin(-1) = -π/2`
107    ///
108    ///Returns a `None` value if and only if the inverse doesn't exist for the given input
109    fn try_asin(self) -> Option<Self>;
110
111    ///
112    ///A continuous inverse function of [Cosine](Trig::cos) such that `acos(1) = 0` and `asin(-1) = π`
113    ///
114    ///Returns a `None` value if and only if the inverse doesn't exist for the given input
115    fn try_acos(self) -> Option<Self>;
116
117    ///
118    ///A continuous inverse function of [Sine](Trig::sin) such that `asin(1) = π/2` and `asin(-1) = -π/2`
119    ///
120    ///If the inverse does not exist for the given input, then the implementation can
121    ///decide between a `panic!` or returning some form of error value (like `NaN`). In general though,
122    ///there is no guarrantee which of these will occur, so it is suggested to use [Trig::try_asin]
123    ///in such cases.
124    ///
125    #[inline] fn asin(self) -> Self {self.try_asin().unwrap()}
126
127    ///
128    ///A continuous inverse function of [Cosine](Trig::cos) such that `acos(1) = 0` and `asin(-1) = π`
129    ///
130    ///If the inverse does not exist for the given input, then the implementation can
131    ///decide between a `panic!` or returning some form of error value (like `NaN`). In general though,
132    ///there is no guarrantee which of these will occur, so it is suggested to use [Trig::try_acos]
133    ///in such cases.
134    ///
135    #[inline] fn acos(self) -> Self {self.try_acos().unwrap()}
136
137    ///A continuous inverse function of [Tangent](Trig::tan) such that `atan(0) = 0` and `atan(1) = π/4`
138    fn atan(self) -> Self;
139
140    ///
141    ///A continuous function of two variables where `tan(atan2(y,x)) = y/x` for `y!=0` and `atan2(0,1) = 0`
142    ///
143    ///This is particularly useful for real numbers, where this gives the angle a vector `(x,y)` makes
144    ///with the x-axis, without the singularities and ambiguity of computing [`atan(y/x)`](Trig::atan)
145    ///
146    fn atan2(y: Self, x: Self) -> Self;
147
148    ///
149    ///A continuous inverse function of [Hyperbolic Sine](Trig::sinh) such that `asinh(0)=0`
150    ///
151    ///Returns a `None` value if and only if the inverse doesn't exist for the given input
152    fn try_asinh(self) -> Option<Self>;
153
154    ///
155    ///A continuous inverse function of [Hyperbolic Cosine](Trig::cosh) such that `acosh(0)=1`
156    ///
157    ///Returns a `None` value if and only if the inverse doesn't exist for the given input
158    fn try_acosh(self) -> Option<Self>;
159
160    ///
161    ///A continuous inverse function of [Hyperbolic Tangent](Trig::tanh) such that `atanh(0)=0`
162    ///
163    ///Returns a `None` value if and only if the inverse doesn't exist for the given input
164    fn try_atanh(self) -> Option<Self>;
165
166    ///
167    ///A continuous inverse function of [Hyperbolic Sine](Trig::sinh) such that `asinh(0)=0`
168    ///
169    ///If the inverse does not exist for the given input, then the implementation can
170    ///decide between a `panic!` or returning some form of error value (like `NaN`). In general though,
171    ///there is no guarrantee which of these will occur, so it is suggested to use [Trig::try_asinh]
172    ///in such cases.
173    ///
174    #[inline] fn asinh(self) -> Self {self.try_asinh().unwrap()}
175
176    ///
177    ///A continuous inverse function of [Hyperbolic Cosine](Trig::cosh) such that `acosh(0)=1`
178    ///
179    ///If the inverse does not exist for the given input, then the implementation can
180    ///decide between a `panic!` or returning some form of error value (like `NaN`). In general though,
181    ///there is no guarrantee which of these will occur, so it is suggested to use [Trig::try_acosh]
182    ///in such cases.
183    ///
184    #[inline] fn acosh(self) -> Self {self.try_acosh().unwrap()}
185
186    ///
187    ///A continuous inverse function of [Hyperbolic Tangent](Trig::tanh) such that `atanh(0)=0`
188    ///
189    ///If the inverse does not exist for the given input, then the implementation can
190    ///decide between a `panic!` or returning some form of error value (like `NaN`). In general though,
191    ///there is no guarrantee which of these will occur, so it is suggested to use [Trig::try_atanh]
192    ///in such cases.
193    ///
194    #[inline] fn atanh(self) -> Self {self.try_atanh().unwrap()}
195
196    ///
197    ///The classic cicle constant
198    ///
199    ///For real-algebras, this should be exactly what you expect: the ratio of a circle's cicumferance
200    ///to its diameter. However, in keeping with the generalized trig function definitions, this should
201    ///give the value of [`acos(-1)`](Trig::acos) and be a zero of [Sine](Trig::sin) and [Tangent](Trig::tan)
202    ///regardless of if it is the circle constant for the euclidean metric
203    ///
204    fn pi() -> Self;
205
206    ///`2/π`. Mirrors [FRAC_2_PI](::core::f32::consts::FRAC_2_PI)
207    #[inline] fn frac_2_pi() -> Self {Self::one().mul_n(2u32).divide(Self::pi()).unwrap()}
208    ///`π/2`. Mirrors [FRAC_PI_2](::core::f32::consts::FRAC_PI_2)
209    #[inline] fn frac_pi_2() -> Self {Self::pi().divide(Self::one().mul_n(2u32)).unwrap()}
210    ///`π/3`. Mirrors [FRAC_PI_3](::core::f32::consts::FRAC_PI_3)
211    #[inline] fn frac_pi_3() -> Self {Self::pi().divide(Self::one().mul_n(3u32)).unwrap()}
212    ///`π/4`. Mirrors [FRAC_PI_4](::core::f32::consts::FRAC_PI_4)
213    #[inline] fn frac_pi_4() -> Self {Self::pi().divide(Self::one().mul_n(4u32)).unwrap()}
214    ///`π/6`. Mirrors [FRAC_PI_6](::core::f32::consts::FRAC_PI_6)
215    #[inline] fn frac_pi_6() -> Self {Self::pi().divide(Self::one().mul_n(6u32)).unwrap()}
216    ///`π/8`. Mirrors [FRAC_PI_8](::core::f32::consts::FRAC_PI_8)
217    #[inline] fn frac_pi_8() -> Self {Self::pi().divide(Self::one().mul_n(8u32)).unwrap()}
218
219    ///The length of the hypotenuse of a unit right-triangle. Mirrors [SQRT_2](::core::f32::consts::SQRT_2)
220    #[inline] fn pythag_const() -> Self {Self::one().mul_n(2u32) * Self::pythag_const_inv()}
221
222    ///The sine of [`π/4`](Trig::frac_pi_4()). Mirrors [FRAC_1_SQRT_2](::core::f32::consts::FRAC_1_SQRT_2)
223    #[inline] fn pythag_const_inv() -> Self {Self::frac_pi_4().sin()}
224
225    #[inline] fn to_degrees(self) -> Self {self * (Self::one().mul_n(180u32).divide(Self::pi()).unwrap())}
226    #[inline] fn to_radians(self) -> Self {self * (Self::pi().divide(Self::one().mul_n(180u32)).unwrap())}
227}
228
229pub use crate::algebra::Exponential;
230
231///
232///An exponential ring with Real-like properties
233///
234///Specifically, this trait should be implemented on any [Exponential Ring](ExponentialRing)
235///where the [natural logarithm](Exponential::try_ln) exists for any positive integer and is
236///continuous almost everywhere[*][1], the purpose being that the above property guarantees
237///a large number of [Real]-like behavior and functions for free utilizing only the exponential function.
238///
239///In particular, this property can be used to prove that:
240/// * This ring contains a form of the positive Rationals: `exp(-ln(x)) = 1/exp(ln(x)) = 1/x`
241/// * The logarithm of any positive rational exists: `ln(p/q) = ln(p) - ln(q)`
242/// * We can take the nth-root of any rational with `exp(ln(x)/n)`
243/// * We can raise any rational to the power of any other rational using `exp(ln(x)*y)`
244/// * Any of the above can be extended to all reals using the continuity of the logarithm
245///
246///Now, it is worth noting that this distinction between the "Real Exponential" and "Exponential"
247///is necessarily since certain exponential rings are only possible if they do not fit this description.
248///In particular, the [integers](Integer) have an exponential defined as `(-1)^n` which obviously
249///does not output any naturals besides 1
250///
251///[1]: https://en.wikipedia.org/wiki/Almost_everywhere
252///
253pub trait RealExponential: Exponential + UnitalRing + Divisibility {
254
255    ///This element raised to the given power as defined by `x^y = exp(ln(x)*y)`, if `ln(x)` exists
256    #[inline] fn try_pow(self, power:Self) -> Option<Self> { self.try_ln().map(move |x| (x * power).exp()) }
257    ///This element taken to the given root as defined as `root(x, y) = x^(1/y)`, if `ln(x)` and `1/y` exist
258    #[inline] fn try_root(self, index:Self) -> Option<Self> { index.inverse().and_then(move |x| self.try_pow(x)) }
259    ///The inverse of [pow()](RealExponential::try_pow), if it exists
260    #[inline] fn try_log(self, base: Self) -> Option<Self> {
261        self.try_ln().and_then(move |x| base.try_ln().and_then(move |y| x.divide(y)))
262    }
263
264    ///
265    ///The natural logarithm of `self`
266    ///
267    ///Do note that this function is allowed to panic or return an error value whenever
268    ///the desired logarithm does not exist. This exception is specifically to allow primitive
269    ///floats to implement this method as a wrapper for the intrinsic definition
270    ///
271    #[inline] fn ln(self) -> Self {self.try_ln().unwrap()}
272
273    ///
274    ///The logarithm of `self` over a specific base
275    ///
276    ///Do note that this function is allowed to panic or return an error value whenever
277    ///the desired logarithm does not exist. This exception is specifically to allow primitive
278    ///floats to implement this method as a wrapper for the intrinsic definition
279    ///
280    #[inline] fn log(self, base: Self) -> Self {self.try_log(base).unwrap()}
281
282    ///
283    ///The power of `self` over a specific exponent
284    ///
285    ///Do note that this function is allowed to panic or return an error value whenever
286    ///the desired power does not exist. This exception is specifically to allow primitive
287    ///floats to implement this method as a wrapper for the intrinsic definition
288    ///
289    #[inline] fn pow(self, p: Self) -> Self {self.try_pow(p).unwrap()}
290
291    ///
292    ///The root of `self` over a specific index
293    ///
294    ///Do note that this function is allowed to panic or return an error value whenever
295    ///the desired root does not exist. This exception is specifically to allow primitive
296    ///floats to implement this method as a wrapper for the intrinsic definition
297    ///
298    #[inline] fn root(self, r: Self) -> Self {self.try_root(r).unwrap()}
299
300    ///Raises 2 to the power of `self`
301    #[inline] fn exp2(self) -> Self {self.pow(Self::one().mul_n(2u32))}
302
303    ///Raises 10 to the power of `self`
304    #[inline] fn exp10(self) -> Self { self.pow(Self::one().mul_n(10u32)) }
305
306    ///The logarithm of base 2
307    #[inline] fn log2(self) -> Self {self.log(Self::one().mul_n(2u32))}
308
309    ///The logarithm of base 10
310    #[inline] fn log10(self) -> Self { self.log(Self::one().mul_n(10u32)) }
311
312    //Takes the square-root of `self`
313    #[inline] fn sqrt(self) -> Self {self.root(Self::one().mul_n(2u32))}
314
315    //Takes the cube-root of `self`
316    #[inline] fn cbrt(self) -> Self {self.root(Self::one().mul_n(3u32))}
317
318    ///
319    ///The natural logarithm of `self` plus 1.
320    ///
321    ///This is meant as a wrapper for f32::ln_1p and f64::ln_1p
322    ///
323    #[inline] fn ln_1p(self) -> Self {(self-Self::one()).ln()}
324
325    ///
326    ///The exponential of `self` minus 1.
327    ///
328    ///This is meant as a wrapper for f32::exp_m1 and f64::exp_m1
329    ///
330    #[inline] fn exp_m1(self) -> Self {self.exp()-Self::one()}
331
332    ///The exponential of 1. Mirrors [::core::f32::consts::E]
333    #[inline] fn e() -> Self {Self::one().exp()}
334
335    ///The natural logarithm of 2. Mirrors [::core::f32::consts::LN_2]
336    #[inline] fn ln_2() -> Self {Self::one().mul_n(2u32).ln()}
337
338    ///The natural logarithm of 10. Mirrors [::core::f32::consts::LN_10]
339    #[inline] fn ln_10() -> Self {Self::one().mul_n(10u32).ln()}
340
341    ///The logarithm base 2 of e. Mirrors [::core::f32::consts::LOG2_E]
342    #[inline] fn log2_e() -> Self {Self::ln_2().inverse().unwrap()}
343
344    ///The logarithm base 10 of e. Mirrors [::core::f32::consts::LOG10_E]
345    #[inline] fn log10_e() -> Self {Self::ln_10().inverse().unwrap()}
346
347    ///The logarithm base 2 of 10. Mirrors [::core::f32::consts::LOG2_10]
348    #[inline] fn log2_10() -> Self {Self::ln_10().divide(Self::ln_2()).unwrap()}
349
350    ///The logarithm base 10 of 2. Mirrors [::core::f32::consts::LOG10_2]
351    #[inline] fn log10_2() -> Self {Self::ln_2().divide(Self::ln_10()).unwrap()}
352
353    ///The square root of 2. Mirrors [::core::f32::consts::SQRT_2]
354    #[inline] fn sqrt_2() -> Self {Self::one().mul_n(2u32).sqrt()}
355
356    ///One over the square root of 2. Mirrors [::core::f32::consts::FRAC_1_SQRT_2]
357    #[inline] fn frac_1_sqrt_2() -> Self {Self::sqrt_2().inverse().unwrap()}
358}
359
360///
361///An algebraic stucture that is a subset of the [Complex] numbers
362///
363///This trait is both meant as an ensapsulation of the [naturals](Natural), [integers](Integer),
364///[real numbers](Real), and [complex numbers](Complex). This way, users can work with a particular
365///set of similar-precision numeric types abstractly similarly to how they would normally.
366///
367pub trait ComplexSubset: PartialEq + Clone + Semiring {
368    type Real: Real
369        + ComplexSubset<Natural = Self::Natural, Integer = Self::Integer, Real = Self::Real>;
370    type Natural: Natural
371        + IntegerSubset<Signed = Self::Integer, Unsigned = Self::Natural>
372        + ComplexSubset<Natural = Self::Natural, Integer = Self::Integer, Real = Self::Real>;
373    type Integer: Integer
374        + IntegerSubset<Signed = Self::Integer, Unsigned = Self::Natural>
375        + ComplexSubset<Natural = Self::Natural, Integer = Self::Integer, Real = Self::Real>;
376
377    ///Converts `self` to a real number, discarding any imaginary component, if complex.
378    fn as_real(self) -> Self::Real;
379
380    ///Converts `self` to a natural number, truncating when necessary.
381    fn as_natural(self) -> Self::Natural;
382
383    ///Converts `self` to an integer, truncating when necessary.
384    fn as_integer(self) -> Self::Integer;
385
386    ///Rounds the real and imaginary components of `self` to the closest integer downward
387    fn floor(self) -> Self;
388
389    ///Rounds the real and imaginary components of `self` to the closest integer upward
390    fn ceil(self) -> Self;
391
392    ///Rounds the real and imaginary components of `self` to the closest integer
393    fn round(self) -> Self;
394
395    ///Rounds the real and imaginary components of `self` by removing the factional parts
396    fn trunc(self) -> Self;
397
398    ///Removes the integral parts of the real and imaginary components of `self`
399    fn fract(self) -> Self;
400
401    ///Sets the real component of `self` to 0
402    fn im(self) -> Self;
403
404    ///Sets the imaginary component of `self` to 0
405    fn re(self) -> Self;
406
407    ///The complex conjugate of `self`
408    fn conj(self) -> Self;
409
410    ///
411    ///The square of the complex absolute value of `self`
412    ///
413    ///This is computed as `self * self.conj()` by default
414    ///
415    #[inline] fn modulus_sqrd(self) -> Self { self.clone() * self.conj()}
416
417    ///
418    ///The complex absolute value of `self`
419    ///
420    ///This is computed as the square root of [modulus_sqrd](ComplexSubset::modulus_sqrd) by default
421    ///
422    #[inline] fn modulus(self) -> Self::Real { (self.clone() * self.conj()).as_real().sqrt()}
423}
424
425///A commutative semiring that is also a subset of the Complex numbers
426pub trait ComplexSemiring = CommutativeSemiring + ComplexSubset;
427///A commutative ring that is also a subset of the Complex numbers
428pub trait ComplexRing = CommutativeRing + ComplexSubset;
429///A field that is also a subset of the Complex numbers
430pub trait ComplexField = Field + ComplexSubset;
431
432///
433///A type representing the real numbers
434///
435///Note that in order to accomidate the primitive floats, this trait does _technically_ allow for
436///special values such as [infinity](::core::f32::INFINITY) and [NaN](::core::f32::NAN)
437///to return from operations
438///as error codes, but usage of such values is discouraged in favor of alternative functions that return
439///[optional](::core::option::Option) values instead
440///
441pub trait Real: ArchField + ComplexSubset<Real=Self> + Trig + RealExponential {
442
443    ///
444    ///Approximates this real number as a 64-bit floating point
445    ///
446    ///This is meant as a convenient way to interface with code using primitives, and in most cases,
447    ///this will exactly represent the given value since most real representations are 32 or 64-bit floats
448    ///However, this is not always the case, and the returned value is only guaranteed to be within
449    ///the precision of an f64.
450    ///
451    fn approx(self) -> f64;
452
453    ///
454    ///Constructs a real number from a 64-bit floating point
455    ///
456    ///This is meant to be a convenient way to input constants into algorithms with generics and to
457    ///interface with code using primitives, and in most cases, this should constant fold and represent
458    ///the given value precisely. However, there is no guarantee of this as the representation returned
459    ///could have a different precision than the f64
460    ///
461    fn repr(f: f64) -> Self;
462}
463
464///A type representing the complex numbers
465pub trait Complex: ComplexField + Trig + RealExponential + From<<Self as ComplexSubset>::Real> {
466    ///The imaginary unit representing `√̅-̅1`
467    fn i() -> Self;
468
469    ///
470    ///Multiplies `self` by [`i`](Complex::i)
471    ///
472    ///This is meant both as convenience and to be potentially faster than normal multiplication
473    ///as this can be done using only data moves and negation
474    ///
475    fn mul_i(self) -> Self;
476
477    ///
478    ///Divides `self` by [`i`](Complex::i). This is also equivalent to multiplication by `-i`
479    ///
480    ///This is meant both as convenience and to be potentially faster than normal multiplication
481    ///as this can be done using only data moves and negation
482    ///
483    fn div_i(self) -> Self;
484}
485
486#[cfg(feature = "std")]
487macro_rules! float_to_option {
488    ($expr:expr) => {
489        {
490            let result = $expr;
491            if result.is_infinite() || result.is_nan() {
492                None
493            } else {
494                Some(result)
495            }
496        }
497    }
498}
499
500#[cfg(feature = "std")]
501macro_rules! impl_real {
502    ($($f:ident:$n:ident:$z:ident)*) => {$(
503        impl Trig for $f {
504            #[inline(always)] fn sin(self) -> Self {self.sin()}
505            #[inline(always)] fn cos(self) -> Self {self.cos()}
506            #[inline(always)] fn tan(self) -> Self {self.tan()}
507            #[inline(always)] fn sin_cos(self) -> (Self,Self) {self.sin_cos()}
508
509            #[inline(always)] fn sinh(self) -> Self {self.sinh()}
510            #[inline(always)] fn cosh(self) -> Self {self.cosh()}
511            #[inline(always)] fn tanh(self) -> Self {self.tanh()}
512
513            #[inline] fn try_asin(self) -> Option<Self> {float_to_option!(self.asin())}
514            #[inline] fn try_acos(self) -> Option<Self> {float_to_option!(self.acos())}
515            #[inline(always)] fn asin(self) -> Self {self.asin()}
516            #[inline(always)] fn acos(self) -> Self {self.acos()}
517            #[inline(always)] fn atan(self) -> Self {self.atan()}
518            #[inline(always)] fn atan2(y:Self, x:Self) -> Self {$f::atan2(y,x)}
519
520            #[inline] fn try_asinh(self) -> Option<Self> {float_to_option!(self.asinh())}
521            #[inline] fn try_acosh(self) -> Option<Self> {float_to_option!(self.acosh())}
522            #[inline] fn try_atanh(self) -> Option<Self> {float_to_option!(self.atanh())}
523            #[inline(always)] fn asinh(self) -> Self {self.asinh()}
524            #[inline(always)] fn acosh(self) -> Self {self.acosh()}
525            #[inline(always)] fn atanh(self) -> Self {self.atanh()}
526
527            #[inline(always)] fn pi() -> Self {::core::$f::consts::PI}
528            #[inline(always)] fn frac_2_pi() -> Self {::core::$f::consts::FRAC_2_PI}
529            #[inline(always)] fn frac_pi_2() -> Self {::core::$f::consts::FRAC_PI_2}
530            #[inline(always)] fn frac_pi_3() -> Self {::core::$f::consts::FRAC_PI_3}
531            #[inline(always)] fn frac_pi_4() -> Self {::core::$f::consts::FRAC_PI_4}
532            #[inline(always)] fn frac_pi_6() -> Self {::core::$f::consts::FRAC_PI_6}
533            #[inline(always)] fn frac_pi_8() -> Self {::core::$f::consts::FRAC_PI_8}
534
535            #[inline(always)] fn pythag_const() -> Self {::core::$f::consts::SQRT_2}
536            #[inline(always)] fn pythag_const_inv() -> Self {::core::$f::consts::FRAC_1_SQRT_2}
537
538            #[inline(always)] fn to_degrees(self) -> Self { self.to_degrees() }
539            #[inline(always)] fn to_radians(self) -> Self { self.to_radians() }
540        }
541
542        impl Exponential for $f {
543            #[inline(always)] fn exp(self) -> Self {self.exp()}
544            #[inline] fn try_ln(self) -> Option<Self> { float_to_option!(self.ln()) }
545        }
546
547        impl RealExponential for $f {
548            #[inline] fn try_pow(self, power:Self) -> Option<Self> { float_to_option!(self.pow(power)) }
549            #[inline] fn try_root(self, index:Self) -> Option<Self> { float_to_option!(self.root(index)) }
550            #[inline] fn try_log(self, base: Self) -> Option<Self> { float_to_option!(self.log(base)) }
551
552            #[inline(always)] fn pow(self, power:Self) -> Self { self.powf(power)}
553            #[inline(always)] fn exp2(self) -> Self {self.exp2()}
554            #[inline(always)] fn exp10(self) -> Self {$f::from(10.0).pow(self)}
555
556            #[inline(always)] fn log(self, base:Self) -> Self {self.log(base)}
557            #[inline(always)] fn ln(self) -> Self {self.ln()}
558            #[inline(always)] fn log2(self) -> Self {self.log2()}
559            #[inline(always)] fn log10(self) -> Self {self.log10()}
560
561            #[inline(always)] fn root(self, index:Self) -> Self {self.pow(index.recip())}
562            #[inline(always)] fn sqrt(self) -> Self {self.sqrt()}
563            #[inline(always)] fn cbrt(self) -> Self {self.cbrt()}
564
565            #[inline(always)] fn ln_1p(self) -> Self {self.ln_1p()}
566            #[inline(always)] fn exp_m1(self) -> Self {self.exp_m1()}
567
568            #[inline(always)] fn e() -> Self {::core::$f::consts::E}
569            #[inline(always)] fn ln_2() -> Self {::core::$f::consts::LN_2}
570            #[inline(always)] fn ln_10() -> Self {::core::$f::consts::LN_10}
571            #[inline(always)] fn log2_e() -> Self {::core::$f::consts::LOG2_E}
572            #[inline(always)] fn log10_e() -> Self {::core::$f::consts::LOG10_E}
573            #[inline(always)] fn log2_10() -> Self {::core::$f::consts::LOG2_10}
574            #[inline(always)] fn log10_2() -> Self {::core::$f::consts::LOG10_2}
575            #[inline(always)] fn sqrt_2() -> Self {::core::$f::consts::SQRT_2}
576            #[inline(always)] fn frac_1_sqrt_2() -> Self {::core::$f::consts::FRAC_1_SQRT_2}
577        }
578
579        impl ComplexSubset for $f {
580            type Real = $f;
581            type Natural = $n;
582            type Integer = $z;
583
584            #[inline(always)] fn as_real(self) -> Self::Real {self}
585            #[inline(always)] fn as_natural(self) -> Self::Natural {self as $n}
586            #[inline(always)] fn as_integer(self) -> Self::Integer {self as $z}
587
588            #[inline(always)] fn floor(self) -> Self { self.floor() }
589            #[inline(always)] fn ceil(self) -> Self {self.ceil()}
590            #[inline(always)] fn round(self) -> Self {self.round()}
591
592            #[inline(always)] fn trunc(self) -> Self {self.trunc()}
593            #[inline(always)] fn fract(self) -> Self {self.fract()}
594
595            #[inline(always)] fn im(self) -> Self {self}
596            #[inline(always)] fn re(self) -> Self {self}
597            #[inline(always)] fn conj(self) -> Self {self}
598
599            #[inline(always)] fn modulus_sqrd(self) -> Self { self * self }
600            #[inline(always)] fn modulus(self) -> Self::Real { self.abs() }
601        }
602
603        impl ComplexSubset for $n {
604            type Real = $f;
605            type Natural = $n;
606            type Integer = $z;
607
608            #[inline(always)] fn as_real(self) -> Self::Real {self as $f}
609            #[inline(always)] fn as_natural(self) -> Self::Natural {self}
610            #[inline(always)] fn as_integer(self) -> Self::Integer {self as $z}
611
612            #[inline(always)] fn floor(self) -> Self {self}
613            #[inline(always)] fn ceil(self) -> Self {self}
614            #[inline(always)] fn round(self) -> Self {self}
615
616            #[inline(always)] fn trunc(self) -> Self {self}
617            #[inline(always)] fn fract(self) -> Self {0}
618
619            #[inline(always)] fn im(self) -> Self {self}
620            #[inline(always)] fn re(self) -> Self {self}
621            #[inline(always)] fn conj(self) -> Self {self}
622
623            #[inline(always)] fn modulus_sqrd(self) -> Self { self * self }
624            #[inline(always)] fn modulus(self) -> Self::Real { self as $f }
625        }
626
627        impl ComplexSubset for $z {
628            type Real = $f;
629            type Natural = $n;
630            type Integer = $z;
631
632            #[inline(always)] fn as_real(self) -> Self::Real {self as $f}
633            #[inline(always)] fn as_natural(self) -> Self::Natural {self as $n}
634            #[inline(always)] fn as_integer(self) -> Self::Integer {self}
635
636            #[inline(always)] fn floor(self) -> Self {self}
637            #[inline(always)] fn ceil(self) -> Self {self}
638            #[inline(always)] fn round(self) -> Self {self}
639
640            #[inline(always)] fn trunc(self) -> Self {self}
641            #[inline(always)] fn fract(self) -> Self {0}
642
643            #[inline(always)] fn im(self) -> Self {self}
644            #[inline(always)] fn re(self) -> Self {self}
645            #[inline(always)] fn conj(self) -> Self {self}
646
647            #[inline(always)] fn modulus_sqrd(self) -> Self { self * self }
648            #[inline(always)] fn modulus(self) -> Self::Real { self.abs() as $f }
649        }
650
651        impl Real for $f {
652            #[inline(always)] fn approx(self) -> f64 {self as f64}
653            #[inline(always)] fn repr(f: f64) -> Self {f as $f}
654        }
655
656    )*}
657}
658
659// Necessary do to issue #60021
660#[cfg(feature = "std")] mod impls {
661    use super::{ Trig, Exponential, RealExponential, ComplexSubset, Real };
662    impl_real!(f32:u32:i32 f64:u64:i64);
663}
664
665macro_rules! int_exp {
666    ($($t:ident)*) => {
667        $(
668            impl Exponential for $t {
669                #[inline] fn exp(self) -> Self { if self.even() {1} else {-1} }
670                #[inline] fn try_ln(self) -> Option<Self> {
671                    match self {
672                         1 => Some(0),
673                        -1 => Some(1),
674                         _ => None
675                    }
676                }
677            }
678        )*
679    }
680}
681
682int_exp!(i8 i16 i32 i64 isize i128);