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