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);