Skip to main content

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