1use core::cmp::Ordering;
2use core::num::FpCategory;
3use core::ops::{Add, Div, Neg};
4
5use core::f32;
6use core::f64;
7
8use crate::{Num, NumCast, ToPrimitive};
9
10pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
14 fn infinity() -> Self;
30
31 fn neg_infinity() -> Self;
47
48 fn nan() -> Self;
64
65 fn neg_zero() -> Self;
83
84 fn min_value() -> Self;
100
101 fn min_positive_value() -> Self;
117
118 fn epsilon() -> Self;
134
135 fn max_value() -> Self;
151
152 #[inline]
170 #[allow(clippy::eq_op)]
171 fn is_nan(self) -> bool {
172 self != self
173 }
174
175 #[inline]
195 fn is_infinite(self) -> bool {
196 self == Self::infinity() || self == Self::neg_infinity()
197 }
198
199 #[inline]
218 fn is_finite(self) -> bool {
219 !(self.is_nan() || self.is_infinite())
220 }
221
222 #[inline]
241 fn is_normal(self) -> bool {
242 self.classify() == FpCategory::Normal
243 }
244
245 #[inline]
267 fn is_subnormal(self) -> bool {
268 self.classify() == FpCategory::Subnormal
269 }
270
271 fn classify(self) -> FpCategory;
294
295 #[inline]
318 fn floor(self) -> Self {
319 let f = self.fract();
320 if f.is_nan() || f.is_zero() {
321 self
322 } else if self < Self::zero() {
323 self - f - Self::one()
324 } else {
325 self - f
326 }
327 }
328
329 #[inline]
352 fn ceil(self) -> Self {
353 let f = self.fract();
354 if f.is_nan() || f.is_zero() {
355 self
356 } else if self > Self::zero() {
357 self - f + Self::one()
358 } else {
359 self - f
360 }
361 }
362
363 #[inline]
385 fn round(self) -> Self {
386 let one = Self::one();
387 let h = Self::from(0.5).expect("Unable to cast from 0.5");
388 let f = self.fract();
389 if f.is_nan() || f.is_zero() {
390 self
391 } else if self > Self::zero() {
392 if f < h {
393 self - f
394 } else {
395 self - f + one
396 }
397 } else if -f < h {
398 self - f
399 } else {
400 self - f - one
401 }
402 }
403
404 #[inline]
427 fn trunc(self) -> Self {
428 let f = self.fract();
429 if f.is_nan() {
430 self
431 } else {
432 self - f
433 }
434 }
435
436 #[inline]
459 fn fract(self) -> Self {
460 if self.is_zero() {
461 Self::zero()
462 } else {
463 self % Self::one()
464 }
465 }
466
467 #[inline]
488 fn abs(self) -> Self {
489 if self.is_sign_positive() {
490 return self;
491 }
492 if self.is_sign_negative() {
493 return -self;
494 }
495 Self::nan()
496 }
497
498 #[inline]
522 fn signum(self) -> Self {
523 if self.is_nan() {
524 Self::nan()
525 } else if self.is_sign_negative() {
526 -Self::one()
527 } else {
528 Self::one()
529 }
530 }
531
532 #[inline]
555 fn is_sign_positive(self) -> bool {
556 !self.is_sign_negative()
557 }
558
559 #[inline]
582 fn is_sign_negative(self) -> bool {
583 let (_, _, sign) = self.integer_decode();
584 sign < 0
585 }
586
587 #[inline]
607 fn min(self, other: Self) -> Self {
608 if self.is_nan() {
609 return other;
610 }
611 if other.is_nan() {
612 return self;
613 }
614 if self < other {
615 self
616 } else {
617 other
618 }
619 }
620
621 #[inline]
641 fn max(self, other: Self) -> Self {
642 if self.is_nan() {
643 return other;
644 }
645 if other.is_nan() {
646 return self;
647 }
648 if self > other {
649 self
650 } else {
651 other
652 }
653 }
654
655 fn clamp(self, min: Self, max: Self) -> Self {
682 crate::clamp(self, min, max)
683 }
684
685 #[inline]
704 fn recip(self) -> Self {
705 Self::one() / self
706 }
707
708 #[inline]
728 fn powi(mut self, mut exp: i32) -> Self {
729 if exp < 0 {
730 exp = exp.wrapping_neg();
731 self = self.recip();
732 }
733 super::pow(self, (exp as u32).to_usize().unwrap())
737 }
738
739 fn to_degrees(self) -> Self;
757
758 fn to_radians(self) -> Self;
776
777 fn integer_decode(self) -> (u64, i16, i8);
799}
800
801impl FloatCore for f32 {
802 constant! {
803 infinity() -> f32::INFINITY;
804 neg_infinity() -> f32::NEG_INFINITY;
805 nan() -> f32::NAN;
806 neg_zero() -> -0.0;
807 min_value() -> f32::MIN;
808 min_positive_value() -> f32::MIN_POSITIVE;
809 epsilon() -> f32::EPSILON;
810 max_value() -> f32::MAX;
811 }
812
813 #[inline]
814 fn integer_decode(self) -> (u64, i16, i8) {
815 integer_decode_f32(self)
816 }
817
818 forward! {
819 Self::is_nan(self) -> bool;
820 Self::is_infinite(self) -> bool;
821 Self::is_finite(self) -> bool;
822 Self::is_normal(self) -> bool;
823 Self::is_subnormal(self) -> bool;
824 Self::clamp(self, min: Self, max: Self) -> Self;
825 Self::classify(self) -> FpCategory;
826 Self::is_sign_positive(self) -> bool;
827 Self::is_sign_negative(self) -> bool;
828 Self::min(self, other: Self) -> Self;
829 Self::max(self, other: Self) -> Self;
830 Self::recip(self) -> Self;
831 Self::to_degrees(self) -> Self;
832 Self::to_radians(self) -> Self;
833 }
834
835 #[cfg(feature = "std")]
836 forward! {
837 Self::floor(self) -> Self;
838 Self::ceil(self) -> Self;
839 Self::round(self) -> Self;
840 Self::trunc(self) -> Self;
841 Self::fract(self) -> Self;
842 Self::abs(self) -> Self;
843 Self::signum(self) -> Self;
844 Self::powi(self, n: i32) -> Self;
845 }
846
847 #[cfg(all(not(feature = "std"), feature = "libm"))]
848 forward! {
849 libm::floorf as floor(self) -> Self;
850 libm::ceilf as ceil(self) -> Self;
851 libm::roundf as round(self) -> Self;
852 libm::truncf as trunc(self) -> Self;
853 libm::fabsf as abs(self) -> Self;
854 }
855
856 #[cfg(all(not(feature = "std"), feature = "libm"))]
857 #[inline]
858 fn fract(self) -> Self {
859 self - libm::truncf(self)
860 }
861}
862
863impl FloatCore for f64 {
864 constant! {
865 infinity() -> f64::INFINITY;
866 neg_infinity() -> f64::NEG_INFINITY;
867 nan() -> f64::NAN;
868 neg_zero() -> -0.0;
869 min_value() -> f64::MIN;
870 min_positive_value() -> f64::MIN_POSITIVE;
871 epsilon() -> f64::EPSILON;
872 max_value() -> f64::MAX;
873 }
874
875 #[inline]
876 fn integer_decode(self) -> (u64, i16, i8) {
877 integer_decode_f64(self)
878 }
879
880 forward! {
881 Self::is_nan(self) -> bool;
882 Self::is_infinite(self) -> bool;
883 Self::is_finite(self) -> bool;
884 Self::is_normal(self) -> bool;
885 Self::is_subnormal(self) -> bool;
886 Self::clamp(self, min: Self, max: Self) -> Self;
887 Self::classify(self) -> FpCategory;
888 Self::is_sign_positive(self) -> bool;
889 Self::is_sign_negative(self) -> bool;
890 Self::min(self, other: Self) -> Self;
891 Self::max(self, other: Self) -> Self;
892 Self::recip(self) -> Self;
893 Self::to_degrees(self) -> Self;
894 Self::to_radians(self) -> Self;
895 }
896
897 #[cfg(feature = "std")]
898 forward! {
899 Self::floor(self) -> Self;
900 Self::ceil(self) -> Self;
901 Self::round(self) -> Self;
902 Self::trunc(self) -> Self;
903 Self::fract(self) -> Self;
904 Self::abs(self) -> Self;
905 Self::signum(self) -> Self;
906 Self::powi(self, n: i32) -> Self;
907 }
908
909 #[cfg(all(not(feature = "std"), feature = "libm"))]
910 forward! {
911 libm::floor as floor(self) -> Self;
912 libm::ceil as ceil(self) -> Self;
913 libm::round as round(self) -> Self;
914 libm::trunc as trunc(self) -> Self;
915 libm::fabs as abs(self) -> Self;
916 }
917
918 #[cfg(all(not(feature = "std"), feature = "libm"))]
919 #[inline]
920 fn fract(self) -> Self {
921 self - libm::trunc(self)
922 }
923}
924
925#[cfg(any(feature = "std", feature = "libm"))]
932pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
933 fn nan() -> Self;
943 fn infinity() -> Self;
956 fn neg_infinity() -> Self;
969 fn neg_zero() -> Self;
983
984 fn min_value() -> Self;
995
996 fn min_positive_value() -> Self;
1007
1008 fn epsilon() -> Self {
1024 Self::from(f32::EPSILON).expect("Unable to cast from f32::EPSILON")
1025 }
1026
1027 fn max_value() -> Self;
1037
1038 fn is_nan(self) -> bool;
1051
1052 fn is_infinite(self) -> bool;
1071
1072 fn is_finite(self) -> bool;
1090
1091 fn is_normal(self) -> bool;
1114
1115 #[inline]
1137 fn is_subnormal(self) -> bool {
1138 self.classify() == FpCategory::Subnormal
1139 }
1140
1141 fn classify(self) -> FpCategory;
1157
1158 fn floor(self) -> Self;
1170
1171 fn ceil(self) -> Self;
1183
1184 fn round(self) -> Self;
1197
1198 fn trunc(self) -> Self;
1210
1211 fn fract(self) -> Self;
1225
1226 fn abs(self) -> Self;
1245
1246 fn signum(self) -> Self;
1264
1265 fn is_sign_positive(self) -> bool;
1284
1285 fn is_sign_negative(self) -> bool;
1304
1305 fn mul_add(self, a: Self, b: Self) -> Self;
1324 fn recip(self) -> Self;
1335
1336 fn powi(self, n: i32) -> Self;
1349
1350 fn powf(self, n: Self) -> Self;
1361
1362 fn sqrt(self) -> Self;
1378
1379 fn exp(self) -> Self;
1394
1395 fn exp2(self) -> Self;
1408
1409 fn ln(self) -> Self;
1424
1425 fn log(self, base: Self) -> Self;
1443
1444 fn log2(self) -> Self;
1457
1458 fn log10(self) -> Self;
1471
1472 #[inline]
1484 fn to_degrees(self) -> Self {
1485 let halfpi = Self::zero().acos();
1486 let ninety = Self::from(90u8).unwrap();
1487 self * ninety / halfpi
1488 }
1489
1490 #[inline]
1502 fn to_radians(self) -> Self {
1503 let halfpi = Self::zero().acos();
1504 let ninety = Self::from(90u8).unwrap();
1505 self * halfpi / ninety
1506 }
1507
1508 fn max(self, other: Self) -> Self;
1519
1520 fn min(self, other: Self) -> Self;
1531
1532 fn clamp(self, min: Self, max: Self) -> Self {
1546 crate::clamp(self, min, max)
1547 }
1548
1549 fn abs_sub(self, other: Self) -> Self;
1567
1568 fn cbrt(self) -> Self;
1581
1582 fn hypot(self, other: Self) -> Self;
1597
1598 fn sin(self) -> Self;
1611
1612 fn cos(self) -> Self;
1625
1626 fn tan(self) -> Self;
1638
1639 fn asin(self) -> Self;
1655
1656 fn acos(self) -> Self;
1672
1673 fn atan(self) -> Self;
1687
1688 fn atan2(self, other: Self) -> Self;
1716
1717 fn sin_cos(self) -> (Self, Self);
1734
1735 fn exp_m1(self) -> Self;
1749
1750 fn ln_1p(self) -> Self;
1765
1766 fn sinh(self) -> Self;
1783
1784 fn cosh(self) -> Self;
1801
1802 fn tanh(self) -> Self;
1819
1820 fn asinh(self) -> Self;
1833
1834 fn acosh(self) -> Self;
1847
1848 fn atanh(self) -> Self;
1862
1863 fn integer_decode(self) -> (u64, i16, i8);
1883
1884 fn copysign(self, sign: Self) -> Self {
1906 if self.is_sign_negative() == sign.is_sign_negative() {
1907 self
1908 } else {
1909 self.neg()
1910 }
1911 }
1912}
1913
1914#[cfg(feature = "std")]
1915macro_rules! float_impl_std {
1916 ($T:ident $decode:ident) => {
1917 impl Float for $T {
1918 constant! {
1919 nan() -> $T::NAN;
1920 infinity() -> $T::INFINITY;
1921 neg_infinity() -> $T::NEG_INFINITY;
1922 neg_zero() -> -0.0;
1923 min_value() -> $T::MIN;
1924 min_positive_value() -> $T::MIN_POSITIVE;
1925 epsilon() -> $T::EPSILON;
1926 max_value() -> $T::MAX;
1927 }
1928
1929 #[inline]
1930 #[allow(deprecated)]
1931 fn abs_sub(self, other: Self) -> Self {
1932 <$T>::abs_sub(self, other)
1933 }
1934
1935 #[inline]
1936 fn integer_decode(self) -> (u64, i16, i8) {
1937 $decode(self)
1938 }
1939
1940 forward! {
1941 Self::is_nan(self) -> bool;
1942 Self::is_infinite(self) -> bool;
1943 Self::is_finite(self) -> bool;
1944 Self::is_normal(self) -> bool;
1945 Self::is_subnormal(self) -> bool;
1946 Self::classify(self) -> FpCategory;
1947 Self::clamp(self, min: Self, max: Self) -> Self;
1948 Self::floor(self) -> Self;
1949 Self::ceil(self) -> Self;
1950 Self::round(self) -> Self;
1951 Self::trunc(self) -> Self;
1952 Self::fract(self) -> Self;
1953 Self::abs(self) -> Self;
1954 Self::signum(self) -> Self;
1955 Self::is_sign_positive(self) -> bool;
1956 Self::is_sign_negative(self) -> bool;
1957 Self::mul_add(self, a: Self, b: Self) -> Self;
1958 Self::recip(self) -> Self;
1959 Self::powi(self, n: i32) -> Self;
1960 Self::powf(self, n: Self) -> Self;
1961 Self::sqrt(self) -> Self;
1962 Self::exp(self) -> Self;
1963 Self::exp2(self) -> Self;
1964 Self::ln(self) -> Self;
1965 Self::log(self, base: Self) -> Self;
1966 Self::log2(self) -> Self;
1967 Self::log10(self) -> Self;
1968 Self::to_degrees(self) -> Self;
1969 Self::to_radians(self) -> Self;
1970 Self::max(self, other: Self) -> Self;
1971 Self::min(self, other: Self) -> Self;
1972 Self::cbrt(self) -> Self;
1973 Self::hypot(self, other: Self) -> Self;
1974 Self::sin(self) -> Self;
1975 Self::cos(self) -> Self;
1976 Self::tan(self) -> Self;
1977 Self::asin(self) -> Self;
1978 Self::acos(self) -> Self;
1979 Self::atan(self) -> Self;
1980 Self::atan2(self, other: Self) -> Self;
1981 Self::sin_cos(self) -> (Self, Self);
1982 Self::exp_m1(self) -> Self;
1983 Self::ln_1p(self) -> Self;
1984 Self::sinh(self) -> Self;
1985 Self::cosh(self) -> Self;
1986 Self::tanh(self) -> Self;
1987 Self::asinh(self) -> Self;
1988 Self::acosh(self) -> Self;
1989 Self::atanh(self) -> Self;
1990 Self::copysign(self, sign: Self) -> Self;
1991 }
1992 }
1993 };
1994}
1995
1996#[cfg(all(not(feature = "std"), feature = "libm"))]
1997macro_rules! float_impl_libm {
1998 ($T:ident $decode:ident) => {
1999 constant! {
2000 nan() -> $T::NAN;
2001 infinity() -> $T::INFINITY;
2002 neg_infinity() -> $T::NEG_INFINITY;
2003 neg_zero() -> -0.0;
2004 min_value() -> $T::MIN;
2005 min_positive_value() -> $T::MIN_POSITIVE;
2006 epsilon() -> $T::EPSILON;
2007 max_value() -> $T::MAX;
2008 }
2009
2010 #[inline]
2011 fn integer_decode(self) -> (u64, i16, i8) {
2012 $decode(self)
2013 }
2014
2015 #[inline]
2016 fn fract(self) -> Self {
2017 self - Float::trunc(self)
2018 }
2019
2020 #[inline]
2021 fn log(self, base: Self) -> Self {
2022 self.ln() / base.ln()
2023 }
2024
2025 forward! {
2026 Self::is_nan(self) -> bool;
2027 Self::is_infinite(self) -> bool;
2028 Self::is_finite(self) -> bool;
2029 Self::is_normal(self) -> bool;
2030 Self::is_subnormal(self) -> bool;
2031 Self::clamp(self, min: Self, max: Self) -> Self;
2032 Self::classify(self) -> FpCategory;
2033 Self::is_sign_positive(self) -> bool;
2034 Self::is_sign_negative(self) -> bool;
2035 Self::min(self, other: Self) -> Self;
2036 Self::max(self, other: Self) -> Self;
2037 Self::recip(self) -> Self;
2038 Self::to_degrees(self) -> Self;
2039 Self::to_radians(self) -> Self;
2040 }
2041
2042 forward! {
2043 FloatCore::signum(self) -> Self;
2044 FloatCore::powi(self, n: i32) -> Self;
2045 }
2046 };
2047}
2048
2049fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
2050 let bits: u32 = f.to_bits();
2051 let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
2052 let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
2053 let mantissa = if exponent == 0 {
2054 (bits & 0x7fffff) << 1
2055 } else {
2056 (bits & 0x7fffff) | 0x800000
2057 };
2058 exponent -= 127 + 23;
2060 (mantissa as u64, exponent, sign)
2061}
2062
2063fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
2064 let bits: u64 = f.to_bits();
2065 let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
2066 let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
2067 let mantissa = if exponent == 0 {
2068 (bits & 0xfffffffffffff) << 1
2069 } else {
2070 (bits & 0xfffffffffffff) | 0x10000000000000
2071 };
2072 exponent -= 1023 + 52;
2074 (mantissa, exponent, sign)
2075}
2076
2077#[cfg(feature = "std")]
2078float_impl_std!(f32 integer_decode_f32);
2079#[cfg(feature = "std")]
2080float_impl_std!(f64 integer_decode_f64);
2081
2082#[cfg(all(not(feature = "std"), feature = "libm"))]
2083impl Float for f32 {
2084 float_impl_libm!(f32 integer_decode_f32);
2085
2086 #[inline]
2087 #[allow(deprecated)]
2088 fn abs_sub(self, other: Self) -> Self {
2089 libm::fdimf(self, other)
2090 }
2091
2092 forward! {
2093 libm::floorf as floor(self) -> Self;
2094 libm::ceilf as ceil(self) -> Self;
2095 libm::roundf as round(self) -> Self;
2096 libm::truncf as trunc(self) -> Self;
2097 libm::fabsf as abs(self) -> Self;
2098 libm::fmaf as mul_add(self, a: Self, b: Self) -> Self;
2099 libm::powf as powf(self, n: Self) -> Self;
2100 libm::sqrtf as sqrt(self) -> Self;
2101 libm::expf as exp(self) -> Self;
2102 libm::exp2f as exp2(self) -> Self;
2103 libm::logf as ln(self) -> Self;
2104 libm::log2f as log2(self) -> Self;
2105 libm::log10f as log10(self) -> Self;
2106 libm::cbrtf as cbrt(self) -> Self;
2107 libm::hypotf as hypot(self, other: Self) -> Self;
2108 libm::sinf as sin(self) -> Self;
2109 libm::cosf as cos(self) -> Self;
2110 libm::tanf as tan(self) -> Self;
2111 libm::asinf as asin(self) -> Self;
2112 libm::acosf as acos(self) -> Self;
2113 libm::atanf as atan(self) -> Self;
2114 libm::atan2f as atan2(self, other: Self) -> Self;
2115 libm::sincosf as sin_cos(self) -> (Self, Self);
2116 libm::expm1f as exp_m1(self) -> Self;
2117 libm::log1pf as ln_1p(self) -> Self;
2118 libm::sinhf as sinh(self) -> Self;
2119 libm::coshf as cosh(self) -> Self;
2120 libm::tanhf as tanh(self) -> Self;
2121 libm::asinhf as asinh(self) -> Self;
2122 libm::acoshf as acosh(self) -> Self;
2123 libm::atanhf as atanh(self) -> Self;
2124 libm::copysignf as copysign(self, other: Self) -> Self;
2125 }
2126}
2127
2128#[cfg(all(not(feature = "std"), feature = "libm"))]
2129impl Float for f64 {
2130 float_impl_libm!(f64 integer_decode_f64);
2131
2132 #[inline]
2133 #[allow(deprecated)]
2134 fn abs_sub(self, other: Self) -> Self {
2135 libm::fdim(self, other)
2136 }
2137
2138 forward! {
2139 libm::floor as floor(self) -> Self;
2140 libm::ceil as ceil(self) -> Self;
2141 libm::round as round(self) -> Self;
2142 libm::trunc as trunc(self) -> Self;
2143 libm::fabs as abs(self) -> Self;
2144 libm::fma as mul_add(self, a: Self, b: Self) -> Self;
2145 libm::pow as powf(self, n: Self) -> Self;
2146 libm::sqrt as sqrt(self) -> Self;
2147 libm::exp as exp(self) -> Self;
2148 libm::exp2 as exp2(self) -> Self;
2149 libm::log as ln(self) -> Self;
2150 libm::log2 as log2(self) -> Self;
2151 libm::log10 as log10(self) -> Self;
2152 libm::cbrt as cbrt(self) -> Self;
2153 libm::hypot as hypot(self, other: Self) -> Self;
2154 libm::sin as sin(self) -> Self;
2155 libm::cos as cos(self) -> Self;
2156 libm::tan as tan(self) -> Self;
2157 libm::asin as asin(self) -> Self;
2158 libm::acos as acos(self) -> Self;
2159 libm::atan as atan(self) -> Self;
2160 libm::atan2 as atan2(self, other: Self) -> Self;
2161 libm::sincos as sin_cos(self) -> (Self, Self);
2162 libm::expm1 as exp_m1(self) -> Self;
2163 libm::log1p as ln_1p(self) -> Self;
2164 libm::sinh as sinh(self) -> Self;
2165 libm::cosh as cosh(self) -> Self;
2166 libm::tanh as tanh(self) -> Self;
2167 libm::asinh as asinh(self) -> Self;
2168 libm::acosh as acosh(self) -> Self;
2169 libm::atanh as atanh(self) -> Self;
2170 libm::copysign as copysign(self, sign: Self) -> Self;
2171 }
2172}
2173
2174macro_rules! float_const_impl {
2175 ($(#[$doc:meta] $constant:ident,)+) => (
2176 #[allow(non_snake_case)]
2177 pub trait FloatConst {
2178 $(#[$doc] fn $constant() -> Self;)+
2179 #[doc = "Return the full circle constant `τ`."]
2180 #[inline]
2181 fn TAU() -> Self where Self: Sized + Add<Self, Output = Self> {
2182 Self::PI() + Self::PI()
2183 }
2184 #[doc = "Return `log10(2.0)`."]
2185 #[inline]
2186 fn LOG10_2() -> Self where Self: Sized + Div<Self, Output = Self> {
2187 Self::LN_2() / Self::LN_10()
2188 }
2189 #[doc = "Return `log2(10.0)`."]
2190 #[inline]
2191 fn LOG2_10() -> Self where Self: Sized + Div<Self, Output = Self> {
2192 Self::LN_10() / Self::LN_2()
2193 }
2194 }
2195 float_const_impl! { @float f32, $($constant,)+ }
2196 float_const_impl! { @float f64, $($constant,)+ }
2197 );
2198 (@float $T:ident, $($constant:ident,)+) => (
2199 impl FloatConst for $T {
2200 constant! {
2201 $( $constant() -> $T::consts::$constant; )+
2202 TAU() -> 6.28318530717958647692528676655900577;
2203 LOG10_2() -> 0.301029995663981195213738894724493027;
2204 LOG2_10() -> 3.32192809488736234787031942948939018;
2205 }
2206 }
2207 );
2208}
2209
2210float_const_impl! {
2211 #[doc = "Return Euler’s number."]
2212 E,
2213 #[doc = "Return `1.0 / π`."]
2214 FRAC_1_PI,
2215 #[doc = "Return `1.0 / sqrt(2.0)`."]
2216 FRAC_1_SQRT_2,
2217 #[doc = "Return `2.0 / π`."]
2218 FRAC_2_PI,
2219 #[doc = "Return `2.0 / sqrt(π)`."]
2220 FRAC_2_SQRT_PI,
2221 #[doc = "Return `π / 2.0`."]
2222 FRAC_PI_2,
2223 #[doc = "Return `π / 3.0`."]
2224 FRAC_PI_3,
2225 #[doc = "Return `π / 4.0`."]
2226 FRAC_PI_4,
2227 #[doc = "Return `π / 6.0`."]
2228 FRAC_PI_6,
2229 #[doc = "Return `π / 8.0`."]
2230 FRAC_PI_8,
2231 #[doc = "Return `ln(10.0)`."]
2232 LN_10,
2233 #[doc = "Return `ln(2.0)`."]
2234 LN_2,
2235 #[doc = "Return `log10(e)`."]
2236 LOG10_E,
2237 #[doc = "Return `log2(e)`."]
2238 LOG2_E,
2239 #[doc = "Return Archimedes’ constant `π`."]
2240 PI,
2241 #[doc = "Return `sqrt(2.0)`."]
2242 SQRT_2,
2243}
2244
2245pub trait TotalOrder {
2249 fn total_cmp(&self, other: &Self) -> Ordering;
2300}
2301macro_rules! totalorder_impl {
2302 ($T:ident, $I:ident, $U:ident, $bits:expr) => {
2303 impl TotalOrder for $T {
2304 #[inline]
2305 #[cfg(has_total_cmp)]
2306 fn total_cmp(&self, other: &Self) -> Ordering {
2307 Self::total_cmp(&self, other)
2309 }
2310 #[inline]
2311 #[cfg(not(has_total_cmp))]
2312 fn total_cmp(&self, other: &Self) -> Ordering {
2313 let mut left = self.to_bits() as $I;
2315 let mut right = other.to_bits() as $I;
2316
2317 left ^= (((left >> ($bits - 1)) as $U) >> 1) as $I;
2318 right ^= (((right >> ($bits - 1)) as $U) >> 1) as $I;
2319
2320 left.cmp(&right)
2321 }
2322 }
2323 };
2324}
2325totalorder_impl!(f64, i64, u64, 64);
2326totalorder_impl!(f32, i32, u32, 32);
2327
2328#[cfg(test)]
2329mod tests {
2330 use core::f64::consts;
2331
2332 const DEG_RAD_PAIRS: [(f64, f64); 7] = [
2333 (0.0, 0.),
2334 (22.5, consts::FRAC_PI_8),
2335 (30.0, consts::FRAC_PI_6),
2336 (45.0, consts::FRAC_PI_4),
2337 (60.0, consts::FRAC_PI_3),
2338 (90.0, consts::FRAC_PI_2),
2339 (180.0, consts::PI),
2340 ];
2341
2342 #[test]
2343 fn convert_deg_rad() {
2344 use crate::float::FloatCore;
2345
2346 for &(deg, rad) in &DEG_RAD_PAIRS {
2347 assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
2348 assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
2349
2350 let (deg, rad) = (deg as f32, rad as f32);
2351 assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-5);
2352 assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-5);
2353 }
2354 }
2355
2356 #[cfg(any(feature = "std", feature = "libm"))]
2357 #[test]
2358 fn convert_deg_rad_std() {
2359 for &(deg, rad) in &DEG_RAD_PAIRS {
2360 use crate::Float;
2361
2362 assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
2363 assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
2364
2365 let (deg, rad) = (deg as f32, rad as f32);
2366 assert!((Float::to_degrees(rad) - deg).abs() < 1e-5);
2367 assert!((Float::to_radians(deg) - rad).abs() < 1e-5);
2368 }
2369 }
2370
2371 #[test]
2372 fn to_degrees_rounding() {
2373 use crate::float::FloatCore;
2374
2375 assert_eq!(
2376 FloatCore::to_degrees(1_f32),
2377 57.2957795130823208767981548141051703
2378 );
2379 }
2380
2381 #[test]
2382 #[cfg(any(feature = "std", feature = "libm"))]
2383 fn extra_logs() {
2384 use crate::float::{Float, FloatConst};
2385
2386 fn check<F: Float + FloatConst>(diff: F) {
2387 let _2 = F::from(2.0).unwrap();
2388 assert!((F::LOG10_2() - F::log10(_2)).abs() < diff);
2389 assert!((F::LOG10_2() - F::LN_2() / F::LN_10()).abs() < diff);
2390
2391 let _10 = F::from(10.0).unwrap();
2392 assert!((F::LOG2_10() - F::log2(_10)).abs() < diff);
2393 assert!((F::LOG2_10() - F::LN_10() / F::LN_2()).abs() < diff);
2394 }
2395
2396 check::<f32>(1e-6);
2397 check::<f64>(1e-12);
2398 }
2399
2400 #[test]
2401 #[cfg(any(feature = "std", feature = "libm"))]
2402 fn copysign() {
2403 use crate::float::Float;
2404 test_copysign_generic(2.0_f32, -2.0_f32, f32::nan());
2405 test_copysign_generic(2.0_f64, -2.0_f64, f64::nan());
2406 test_copysignf(2.0_f32, -2.0_f32, f32::nan());
2407 }
2408
2409 #[cfg(any(feature = "std", feature = "libm"))]
2410 fn test_copysignf(p: f32, n: f32, nan: f32) {
2411 use crate::float::Float;
2412 use core::ops::Neg;
2413
2414 assert!(p.is_sign_positive());
2415 assert!(n.is_sign_negative());
2416 assert!(nan.is_nan());
2417
2418 assert_eq!(p, Float::copysign(p, p));
2419 assert_eq!(p.neg(), Float::copysign(p, n));
2420
2421 assert_eq!(n, Float::copysign(n, n));
2422 assert_eq!(n.neg(), Float::copysign(n, p));
2423
2424 assert!(Float::copysign(nan, p).is_sign_positive());
2425 assert!(Float::copysign(nan, n).is_sign_negative());
2426 }
2427
2428 #[cfg(any(feature = "std", feature = "libm"))]
2429 fn test_copysign_generic<F: crate::float::Float + ::core::fmt::Debug>(p: F, n: F, nan: F) {
2430 assert!(p.is_sign_positive());
2431 assert!(n.is_sign_negative());
2432 assert!(nan.is_nan());
2433 assert!(!nan.is_subnormal());
2434
2435 assert_eq!(p, p.copysign(p));
2436 assert_eq!(p.neg(), p.copysign(n));
2437
2438 assert_eq!(n, n.copysign(n));
2439 assert_eq!(n.neg(), n.copysign(p));
2440
2441 assert!(nan.copysign(p).is_sign_positive());
2442 assert!(nan.copysign(n).is_sign_negative());
2443 }
2444
2445 #[cfg(any(feature = "std", feature = "libm"))]
2446 fn test_subnormal<F: crate::float::Float + ::core::fmt::Debug>() {
2447 let min_positive = F::min_positive_value();
2448 let lower_than_min = min_positive / F::from(2.0f32).unwrap();
2449 assert!(!min_positive.is_subnormal());
2450 assert!(lower_than_min.is_subnormal());
2451 }
2452
2453 #[test]
2454 #[cfg(any(feature = "std", feature = "libm"))]
2455 fn subnormal() {
2456 test_subnormal::<f64>();
2457 test_subnormal::<f32>();
2458 }
2459
2460 #[test]
2461 fn total_cmp() {
2462 use crate::float::TotalOrder;
2463 use core::cmp::Ordering;
2464 use core::{f32, f64};
2465
2466 fn check_eq<T: TotalOrder>(x: T, y: T) {
2467 assert_eq!(x.total_cmp(&y), Ordering::Equal);
2468 }
2469 fn check_lt<T: TotalOrder>(x: T, y: T) {
2470 assert_eq!(x.total_cmp(&y), Ordering::Less);
2471 }
2472 fn check_gt<T: TotalOrder>(x: T, y: T) {
2473 assert_eq!(x.total_cmp(&y), Ordering::Greater);
2474 }
2475
2476 check_eq(f64::NAN, f64::NAN);
2477 check_eq(f32::NAN, f32::NAN);
2478
2479 check_lt(-0.0_f64, 0.0_f64);
2480 check_lt(-0.0_f32, 0.0_f32);
2481
2482 #[cfg(not(target_arch = "x86"))]
2485 {
2486 let s_nan = f64::from_bits(0x7ff4000000000000);
2487 let q_nan = f64::from_bits(0x7ff8000000000000);
2488 check_lt(s_nan, q_nan);
2489
2490 let neg_s_nan = f64::from_bits(0xfff4000000000000);
2491 let neg_q_nan = f64::from_bits(0xfff8000000000000);
2492 check_lt(neg_q_nan, neg_s_nan);
2493
2494 let s_nan = f32::from_bits(0x7fa00000);
2495 let q_nan = f32::from_bits(0x7fc00000);
2496 check_lt(s_nan, q_nan);
2497
2498 let neg_s_nan = f32::from_bits(0xffa00000);
2499 let neg_q_nan = f32::from_bits(0xffc00000);
2500 check_lt(neg_q_nan, neg_s_nan);
2501 }
2502
2503 check_lt(-f64::NAN, f64::NEG_INFINITY);
2504 check_gt(1.0_f64, -f64::NAN);
2505 check_lt(f64::INFINITY, f64::NAN);
2506 check_gt(f64::NAN, 1.0_f64);
2507
2508 check_lt(-f32::NAN, f32::NEG_INFINITY);
2509 check_gt(1.0_f32, -f32::NAN);
2510 check_lt(f32::INFINITY, f32::NAN);
2511 check_gt(f32::NAN, 1.0_f32);
2512 }
2513}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4