num_primitive/
float.rs

1use crate::{PrimitiveNumber, PrimitiveNumberRef, PrimitiveUnsigned};
2
3use core::cmp::Ordering;
4use core::f32::consts as f32_consts;
5use core::f64::consts as f64_consts;
6use core::num::FpCategory;
7
8struct SealedToken;
9
10/// Trait for all primitive [floating-point types], including the supertrait [`PrimitiveNumber`].
11///
12/// This encapsulates trait implementations, constants, and inherent methods that are common among
13/// the primitive floating-point types, [`f32`] and [`f64`]. Unstable types [`f16`] and [`f128`]
14/// will be added once they are stabilized.
15///
16/// See the corresponding items on the individual types for more documentation and examples.
17///
18/// This trait is sealed with a private trait to prevent downstream implementations, so we may
19/// continue to expand along with the standard library without worrying about breaking changes for
20/// implementors.
21///
22/// [floating-point types]: https://doc.rust-lang.org/reference/types/numeric.html#r-type.numeric.float
23///
24/// # Examples
25///
26/// This example requires the `std` feature for [`powi`][Self::powi] and [`sqrt`][Self::sqrt]:
27///
28#[cfg_attr(feature = "std", doc = "```")]
29#[cfg_attr(not(feature = "std"), doc = "```ignore")]
30/// use num_primitive::PrimitiveFloat;
31///
32/// // Euclidean distance, √(∑(aᵢ - bᵢ)²)
33/// fn distance<T: PrimitiveFloat>(a: &[T], b: &[T]) -> T {
34///     assert_eq!(a.len(), b.len());
35///     core::iter::zip(a, b).map(|(a, b)| (*a - b).powi(2)).sum::<T>().sqrt()
36/// }
37///
38/// assert_eq!(distance::<f32>(&[0., 0.], &[3., 4.]), 5.);
39/// assert_eq!(distance::<f64>(&[0., 1., 2.], &[1., 3., 0.]), 3.);
40/// ```
41///
42/// This example works without any features:
43///
44/// ```
45/// use num_primitive::PrimitiveFloat;
46///
47/// // Squared Euclidean distance, ∑(aᵢ - bᵢ)²
48/// fn distance_squared<T: PrimitiveFloat>(a: &[T], b: &[T]) -> T {
49///     assert_eq!(a.len(), b.len());
50///     core::iter::zip(a, b).map(|(a, b)| (*a - b)).map(|x| x * x).sum::<T>()
51/// }
52///
53/// assert_eq!(distance_squared::<f32>(&[0., 0.], &[3., 4.]), 25.);
54/// assert_eq!(distance_squared::<f64>(&[0., 1., 2.], &[1., 3., 0.]), 9.);
55/// ```
56pub trait PrimitiveFloat:
57    PrimitiveNumber
58    + PrimitiveFloatToInt<i8>
59    + PrimitiveFloatToInt<i16>
60    + PrimitiveFloatToInt<i32>
61    + PrimitiveFloatToInt<i64>
62    + PrimitiveFloatToInt<i128>
63    + PrimitiveFloatToInt<isize>
64    + PrimitiveFloatToInt<u8>
65    + PrimitiveFloatToInt<u16>
66    + PrimitiveFloatToInt<u32>
67    + PrimitiveFloatToInt<u64>
68    + PrimitiveFloatToInt<u128>
69    + PrimitiveFloatToInt<usize>
70    + core::convert::From<i8>
71    + core::convert::From<u8>
72    + core::ops::Neg<Output = Self>
73{
74    /// Approximate number of significant digits in base 10.
75    const DIGITS: u32;
76
77    /// Machine epsilon value.
78    const EPSILON: Self;
79
80    /// Infinity (∞).
81    const INFINITY: Self;
82
83    /// Number of significant digits in base 2.
84    const MANTISSA_DIGITS: u32;
85
86    /// Largest finite value.
87    const MAX: Self;
88
89    /// Maximum _x_ for which 10<sup>_x_</sup> is normal.
90    const MAX_10_EXP: i32;
91
92    /// Maximum possible power of 2 exponent.
93    const MAX_EXP: i32;
94
95    /// Smallest finite value.
96    const MIN: Self;
97
98    /// Minimum _x_ for which 10<sup>_x_</sup> is normal.
99    const MIN_10_EXP: i32;
100
101    /// One greater than the minimum possible normal power of 2 exponent.
102    const MIN_EXP: i32;
103
104    /// Smallest positive normal value.
105    const MIN_POSITIVE: Self;
106
107    /// Not a Number (NaN).
108    const NAN: Self;
109
110    /// Negative infinity (−∞).
111    const NEG_INFINITY: Self;
112
113    /// The radix or base of the internal representation.
114    const RADIX: u32;
115
116    // The following are not inherent consts, rather from `core::{float}::consts`.
117
118    /// Euler's number (e)
119    const E: Self;
120
121    /// 1/π
122    const FRAC_1_PI: Self;
123
124    /// 1/sqrt(2)
125    const FRAC_1_SQRT_2: Self;
126
127    /// 2/π
128    const FRAC_2_PI: Self;
129
130    /// 2/sqrt(π)
131    const FRAC_2_SQRT_PI: Self;
132
133    /// π/2
134    const FRAC_PI_2: Self;
135
136    /// π/3
137    const FRAC_PI_3: Self;
138
139    /// π/4
140    const FRAC_PI_4: Self;
141
142    /// π/6
143    const FRAC_PI_6: Self;
144
145    /// π/8
146    const FRAC_PI_8: Self;
147
148    /// ln(2)
149    const LN_2: Self;
150
151    /// ln(10)
152    const LN_10: Self;
153
154    /// log₂(10)
155    const LOG2_10: Self;
156
157    /// log₂(e)
158    const LOG2_E: Self;
159
160    /// log₁₀(2)
161    const LOG10_2: Self;
162
163    /// log₁₀(e)
164    const LOG10_E: Self;
165
166    /// Archimedes' constant (π)
167    const PI: Self;
168
169    /// sqrt(2)
170    const SQRT_2: Self;
171
172    /// The full circle constant (τ)
173    const TAU: Self;
174
175    /// An unsigned integer type used by methods [`from_bits`][Self::from_bits] and
176    /// [`to_bits`][Self::to_bits].
177    type Bits: PrimitiveUnsigned;
178
179    /// Computes the absolute value of `self`.
180    fn abs(self) -> Self;
181
182    /// Restrict a value to a certain interval unless it is NaN.
183    fn clamp(self, min: Self, max: Self) -> Self;
184
185    /// Returns the floating point category of the number. If only one property is going to be
186    /// tested, it is generally faster to use the specific predicate instead.
187    fn classify(self) -> FpCategory;
188
189    /// Returns a number composed of the magnitude of `self` and the sign of sign.
190    fn copysign(self, sign: Self) -> Self;
191
192    /// Raw transmutation from `Self::Bits`.
193    fn from_bits(value: Self::Bits) -> Self;
194
195    /// Returns `true` if this number is neither infinite nor NaN.
196    fn is_finite(self) -> bool;
197
198    /// Returns `true` if this value is positive infinity or negative infinity.
199    fn is_infinite(self) -> bool;
200
201    /// Returns `true` if this value is NaN.
202    fn is_nan(self) -> bool;
203
204    /// Returns `true` if the number is neither zero, infinite, subnormal, or NaN.
205    fn is_normal(self) -> bool;
206
207    /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with negative sign bit
208    /// and negative infinity.
209    fn is_sign_negative(self) -> bool;
210
211    /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with positive sign bit
212    /// and positive infinity.
213    fn is_sign_positive(self) -> bool;
214
215    /// Returns `true` if the number is subnormal.
216    fn is_subnormal(self) -> bool;
217
218    /// Returns the maximum of the two numbers, ignoring NaN.
219    fn max(self, other: Self) -> Self;
220
221    /// Returns the minimum of the two numbers, ignoring NaN.
222    fn min(self, other: Self) -> Self;
223
224    /// Returns the greatest number less than `self`.
225    fn next_down(self) -> Self;
226
227    /// Returns the least number greater than `self`.
228    fn next_up(self) -> Self;
229
230    /// Takes the reciprocal (inverse) of a number, `1/x`.
231    fn recip(self) -> Self;
232
233    /// Returns a number that represents the sign of `self`.
234    fn signum(self) -> Self;
235
236    /// Raw transmutation to `Self::Bits`.
237    fn to_bits(self) -> Self::Bits;
238
239    /// Converts radians to degrees.
240    fn to_degrees(self) -> Self;
241
242    /// Converts degrees to radians.
243    fn to_radians(self) -> Self;
244
245    /// Returns the ordering between `self` and `other`.
246    fn total_cmp(&self, other: &Self) -> Ordering;
247
248    /// Rounds toward zero and converts to any primitive integer type, assuming that the value is
249    /// finite and fits in that type.
250    ///
251    /// # Safety
252    ///
253    /// The value must:
254    ///
255    /// * Not be `NaN`
256    /// * Not be infinite
257    /// * Be representable in the return type `Int`, after truncating off its fractional part
258    unsafe fn to_int_unchecked<Int>(self) -> Int
259    where
260        Self: PrimitiveFloatToInt<Int>;
261
262    /// Computes the arccosine of a number. Return value is in radians in the range [0, pi] or NaN
263    /// if the number is outside the range [-1, 1].
264    #[cfg(feature = "std")]
265    fn acos(self) -> Self;
266
267    /// Inverse hyperbolic cosine function.
268    #[cfg(feature = "std")]
269    fn acosh(self) -> Self;
270
271    /// Computes the arcsine of a number. Return value is in radians in the range [-pi/2, pi/2] or
272    /// NaN if the number is outside the range [-1, 1].
273    #[cfg(feature = "std")]
274    fn asin(self) -> Self;
275
276    /// Inverse hyperbolic sine function.
277    #[cfg(feature = "std")]
278    fn asinh(self) -> Self;
279
280    /// Computes the arctangent of a number. Return value is in radians in the range [-pi/2, pi/2];
281    #[cfg(feature = "std")]
282    fn atan(self) -> Self;
283
284    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
285    #[cfg(feature = "std")]
286    fn atan2(self, other: Self) -> Self;
287
288    /// Inverse hyperbolic tangent function.
289    #[cfg(feature = "std")]
290    fn atanh(self) -> Self;
291
292    /// Returns the cube root of a number.
293    #[cfg(feature = "std")]
294    fn cbrt(self) -> Self;
295
296    /// Returns the smallest integer greater than or equal to `self`.
297    #[cfg(feature = "std")]
298    fn ceil(self) -> Self;
299
300    /// Computes the cosine of a number (in radians).
301    #[cfg(feature = "std")]
302    fn cos(self) -> Self;
303
304    /// Hyperbolic cosine function.
305    #[cfg(feature = "std")]
306    fn cosh(self) -> Self;
307
308    /// Calculates Euclidean division, the matching method for `rem_euclid`.
309    #[cfg(feature = "std")]
310    fn div_euclid(self, rhs: Self) -> Self;
311
312    /// Returns `e^(self)`, (the exponential function).
313    #[cfg(feature = "std")]
314    fn exp(self) -> Self;
315
316    /// Returns `2^(self)`.
317    #[cfg(feature = "std")]
318    fn exp2(self) -> Self;
319
320    /// Returns `e^(self) - 1` in a way that is accurate even if the number is close to zero.
321    #[cfg(feature = "std")]
322    fn exp_m1(self) -> Self;
323
324    /// Returns the largest integer less than or equal to `self`.
325    #[cfg(feature = "std")]
326    fn floor(self) -> Self;
327
328    /// Returns the fractional part of `self`.
329    #[cfg(feature = "std")]
330    fn fract(self) -> Self;
331
332    /// Compute the distance between the origin and a point (`x`, `y`) on the Euclidean plane.
333    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other
334    /// sides having length `x.abs()` and `y.abs()`.
335    #[cfg(feature = "std")]
336    fn hypot(self, other: Self) -> Self;
337
338    /// Returns the natural logarithm of the number.
339    #[cfg(feature = "std")]
340    fn ln(self) -> Self;
341
342    /// Returns `ln(1+n)` (natural logarithm) more accurately than if the operations were performed
343    /// separately.
344    #[cfg(feature = "std")]
345    fn ln_1p(self) -> Self;
346
347    /// Returns the logarithm of the number with respect to an arbitrary base.
348    #[cfg(feature = "std")]
349    fn log(self, base: Self) -> Self;
350
351    /// Returns the base 2 logarithm of the number.
352    #[cfg(feature = "std")]
353    fn log2(self) -> Self;
354
355    /// Returns the base 10 logarithm of the number.
356    #[cfg(feature = "std")]
357    fn log10(self) -> Self;
358
359    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error, yielding a more
360    /// accurate result than an unfused multiply-add.
361    #[cfg(feature = "std")]
362    fn mul_add(self, a: Self, b: Self) -> Self;
363
364    /// Raises a number to a floating point power.
365    #[cfg(feature = "std")]
366    fn powf(self, n: Self) -> Self;
367
368    /// Raises a number to an integer power.
369    #[cfg(feature = "std")]
370    fn powi(self, n: i32) -> Self;
371
372    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
373    #[cfg(feature = "std")]
374    fn rem_euclid(self, rhs: Self) -> Self;
375
376    /// Returns the nearest integer to `self`. If a value is half-way between two integers, round
377    /// away from `0.0`.
378    #[cfg(feature = "std")]
379    fn round(self) -> Self;
380
381    /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even
382    /// least significant digit.
383    #[cfg(feature = "std")]
384    fn round_ties_even(self) -> Self;
385
386    /// Computes the sine of a number (in radians).
387    #[cfg(feature = "std")]
388    fn sin(self) -> Self;
389
390    /// Simultaneously computes the sine and cosine of the number, `x`. Returns `(sin(x), cos(x))`.
391    #[cfg(feature = "std")]
392    fn sin_cos(self) -> (Self, Self);
393
394    /// Hyperbolic sine function.
395    #[cfg(feature = "std")]
396    fn sinh(self) -> Self;
397
398    /// Returns the square root of a number.
399    #[cfg(feature = "std")]
400    fn sqrt(self) -> Self;
401
402    /// Computes the tangent of a number (in radians).
403    #[cfg(feature = "std")]
404    fn tan(self) -> Self;
405
406    /// Hyperbolic tangent function.
407    #[cfg(feature = "std")]
408    fn tanh(self) -> Self;
409
410    /// Returns the integer part of `self`. This means that non-integer numbers are always
411    /// truncated towards zero.
412    #[cfg(feature = "std")]
413    fn trunc(self) -> Self;
414}
415
416/// Trait for references to primitive floating-point types ([`PrimitiveFloat`]).
417///
418/// This enables traits like the standard operators in generic code,
419/// e.g. `where &T: PrimitiveFloatRef<T>`.
420pub trait PrimitiveFloatRef<T>: PrimitiveNumberRef<T> + core::ops::Neg<Output = T> {}
421
422/// Trait for conversions supported by [`PrimitiveFloat::to_int_unchecked`].
423///
424/// This is effectively the same as the unstable [`core::convert::FloatToInt`], implemented for all
425/// combinations of [`PrimitiveFloat`] and [`PrimitiveInteger`][crate::PrimitiveInteger].
426///
427/// # Examples
428///
429/// `PrimitiveFloatToInt<{integer}>` is a supertrait of [`PrimitiveFloat`] for all primitive
430/// integers, so you do not need to use this trait directly with concrete integer types.
431///
432/// ```
433/// use num_primitive::PrimitiveFloat;
434///
435/// fn pi<Float: PrimitiveFloat>() -> i32 {
436///     // SAFETY: π is finite, and truncated to 3 fits any int
437///     unsafe { Float::PI.to_int_unchecked() }
438/// }
439///
440/// assert_eq!(pi::<f32>(), 3i32);
441/// assert_eq!(pi::<f64>(), 3i32);
442/// ```
443///
444/// However, if the integer type is also generic, an explicit type constraint is needed.
445///
446/// ```
447/// use num_primitive::{PrimitiveFloat, PrimitiveFloatToInt};
448///
449/// fn tau<Float, Int>() -> Int
450/// where
451///     Float: PrimitiveFloat + PrimitiveFloatToInt<Int>,
452/// {
453///     // SAFETY: τ is finite, and truncated to 6 fits any int
454///     unsafe { Float::TAU.to_int_unchecked() }
455/// }
456///
457/// assert_eq!(tau::<f32, i64>(), 6i64);
458/// assert_eq!(tau::<f64, u8>(), 6u8);
459/// ```
460///
461pub trait PrimitiveFloatToInt<Int> {
462    #[doc(hidden)]
463    #[expect(private_interfaces)]
464    unsafe fn __to_int_unchecked(x: Self, _: SealedToken) -> Int;
465}
466
467macro_rules! impl_float {
468    ($Float:ident, $consts:ident, $Bits:ty) => {
469        impl PrimitiveFloat for $Float {
470            use_consts!(Self::{
471                DIGITS: u32,
472                EPSILON: Self,
473                INFINITY: Self,
474                MANTISSA_DIGITS: u32,
475                MAX: Self,
476                MAX_10_EXP: i32,
477                MAX_EXP: i32,
478                MIN: Self,
479                MIN_10_EXP: i32,
480                MIN_EXP: i32,
481                MIN_POSITIVE: Self,
482                NAN: Self,
483                NEG_INFINITY: Self,
484                RADIX: u32,
485            });
486
487            use_consts!($consts::{
488                E: Self,
489                FRAC_1_PI: Self,
490                FRAC_1_SQRT_2: Self,
491                FRAC_2_PI: Self,
492                FRAC_2_SQRT_PI: Self,
493                FRAC_PI_2: Self,
494                FRAC_PI_3: Self,
495                FRAC_PI_4: Self,
496                FRAC_PI_6: Self,
497                FRAC_PI_8: Self,
498                LN_2: Self,
499                LN_10: Self,
500                LOG2_10: Self,
501                LOG2_E: Self,
502                LOG10_2: Self,
503                LOG10_E: Self,
504                PI: Self,
505                SQRT_2: Self,
506                TAU: Self,
507            });
508
509            type Bits = $Bits;
510
511            forward! {
512                fn from_bits(value: Self::Bits) -> Self;
513            }
514            forward! {
515                fn abs(self) -> Self;
516                fn clamp(self, min: Self, max: Self) -> Self;
517                fn classify(self) -> FpCategory;
518                fn copysign(self, sign: Self) -> Self;
519                fn is_finite(self) -> bool;
520                fn is_infinite(self) -> bool;
521                fn is_nan(self) -> bool;
522                fn is_normal(self) -> bool;
523                fn is_sign_negative(self) -> bool;
524                fn is_sign_positive(self) -> bool;
525                fn is_subnormal(self) -> bool;
526                fn max(self, other: Self) -> Self;
527                fn min(self, other: Self) -> Self;
528                fn next_down(self) -> Self;
529                fn next_up(self) -> Self;
530                fn recip(self) -> Self;
531                fn signum(self) -> Self;
532                fn to_bits(self) -> Self::Bits;
533                fn to_degrees(self) -> Self;
534                fn to_radians(self) -> Self;
535            }
536            forward! {
537                fn total_cmp(&self, other: &Self) -> Ordering;
538            }
539
540            // NOTE: This is still effectively forwarding, but we need some indirection
541            // to avoid naming the unstable `core::convert::FloatToInt`.
542            #[doc = forward_doc!(to_int_unchecked)]
543            #[inline]
544            unsafe fn to_int_unchecked<Int>(self) -> Int
545            where
546                Self: PrimitiveFloatToInt<Int>,
547            {
548                // SAFETY: we're just passing through here!
549                unsafe { <Self as PrimitiveFloatToInt<Int>>::__to_int_unchecked(self, SealedToken) }
550            }
551
552            // --- std-only methods ---
553
554            #[cfg(feature = "std")]
555            forward! {
556                fn acos(self) -> Self;
557                fn acosh(self) -> Self;
558                fn asin(self) -> Self;
559                fn asinh(self) -> Self;
560                fn atan(self) -> Self;
561                fn atan2(self, other: Self) -> Self;
562                fn atanh(self) -> Self;
563                fn cbrt(self) -> Self;
564                fn ceil(self) -> Self;
565                fn cos(self) -> Self;
566                fn cosh(self) -> Self;
567                fn div_euclid(self, rhs: Self) -> Self;
568                fn exp(self) -> Self;
569                fn exp2(self) -> Self;
570                fn exp_m1(self) -> Self;
571                fn floor(self) -> Self;
572                fn fract(self) -> Self;
573                fn hypot(self, other: Self) -> Self;
574                fn ln(self) -> Self;
575                fn ln_1p(self) -> Self;
576                fn log(self, base: Self) -> Self;
577                fn log2(self) -> Self;
578                fn log10(self) -> Self;
579                fn mul_add(self, a: Self, b: Self) -> Self;
580                fn powf(self, n: Self) -> Self;
581                fn powi(self, n: i32) -> Self;
582                fn rem_euclid(self, rhs: Self) -> Self;
583                fn round(self) -> Self;
584                fn round_ties_even(self) -> Self;
585                fn sin(self) -> Self;
586                fn sin_cos(self) -> (Self, Self);
587                fn sinh(self) -> Self;
588                fn sqrt(self) -> Self;
589                fn tan(self) -> Self;
590                fn tanh(self) -> Self;
591                fn trunc(self) -> Self;
592            }
593        }
594
595        impl PrimitiveFloatRef<$Float> for &$Float {}
596    }
597}
598
599impl_float!(f32, f32_consts, u32);
600impl_float!(f64, f64_consts, u64);
601
602// NOTE: the extra module level here is to make sure that `PrimitiveFloat` isn't in scope, so we
603// can be sure that we're not recursing. Elsewhere we rely on the normal `unconditional-recursion`
604// lint, but that doesn't see through this level of trait indirection.
605mod internal {
606    macro_rules! impl_float_to_int {
607        ($Float:ty => $($Int:ty),+) => {
608            $(
609                impl super::PrimitiveFloatToInt<$Int> for $Float {
610                    #[inline]
611                    #[expect(private_interfaces)]
612                    unsafe fn __to_int_unchecked(x: Self, _: super::SealedToken) -> $Int {
613                        // SAFETY: we're just passing through here!
614                        unsafe { <$Float>::to_int_unchecked::<$Int>(x) }
615                    }
616                }
617            )+
618        }
619    }
620
621    impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
622    impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
623}