1#[cfg(feature = "approx")]
2use approx::{AbsDiffEq, RelativeEq, UlpsEq};
3use core::cmp::Ordering;
4use core::fmt::{self, Debug, Display, Formatter, LowerExp, UpperExp};
5use core::hash::{Hash, Hasher};
6use core::iter::{Product, Sum};
7use core::marker::PhantomData;
8use core::mem;
9use core::num::FpCategory;
10use core::ops::{
11 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
12};
13use core::str::FromStr;
14#[cfg(not(feature = "std"))]
15use num_traits::float::FloatCore as Float;
16#[cfg(feature = "std")]
17use num_traits::Float;
18use num_traits::{
19 Bounded, FloatConst, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero,
20};
21#[cfg(feature = "serde")]
22use serde_derive::{Deserialize, Serialize};
23
24use crate::cmp::{CanonicalEq, CanonicalOrd, EmptyInhabitant, EmptyOrd};
25use crate::constraint::{
26 Constraint, ExpectConstrained, InfinitySet, IsExtendedReal, IsFloat, IsReal, Member, NanSet,
27 SubsetOf, SupersetOf,
28};
29use crate::divergence::{self, Divergence, NonResidual};
30use crate::expression::Expression;
31use crate::hash::CanonicalHash;
32use crate::proxy::Proxy;
33#[cfg(feature = "serde")]
34use crate::proxy::Serde;
35use crate::real::{BinaryRealFunction, Function, Sign, UnaryRealFunction};
36use crate::sealed::StaticDebug;
37use crate::{
38 with_binary_operations, with_primitives, BaseEncoding, ExtendedReal, InfinityEncoding,
39 NanEncoding, Primitive, Real, ToCanonical, Total,
40};
41
42pub type OutputFor<P> = divergence::OutputFor<DivergenceFor<P>, P, ErrorFor<P>>;
43pub type ConstraintFor<P> = <P as ConstrainedProxy>::Constraint;
44pub type DivergenceFor<P> = <ConstraintFor<P> as Constraint>::Divergence;
45pub type ErrorFor<P> = <ConstraintFor<P> as Constraint>::Error;
46pub type ExpressionFor<P> = Expression<P, ErrorFor<P>>;
47
48pub trait ConstrainedProxy: Proxy {
50 type Constraint: Constraint;
51}
52
53#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
67#[cfg_attr(
68 feature = "serde",
69 serde(
70 bound(
71 deserialize = "T: serde::Deserialize<'de> + Primitive, \
72 C: Constraint, \
73 C::Error: Display",
74 serialize = "T: Primitive + serde::Serialize, \
75 C: Constraint"
76 ),
77 try_from = "Serde<T>",
78 into = "Serde<T>"
79 )
80)]
81#[repr(transparent)]
82pub struct Constrained<T, C> {
83 inner: T,
84 #[cfg_attr(feature = "serde", serde(skip))]
85 phantom: PhantomData<fn() -> C>,
86}
87
88impl<T, C> Constrained<T, C> {
89 pub(crate) const fn unchecked(inner: T) -> Self {
90 Constrained {
91 inner,
92 phantom: PhantomData,
93 }
94 }
95
96 pub(crate) fn with_inner<U, F>(self, f: F) -> U
97 where
98 F: FnOnce(T) -> U,
99 {
100 f(self.inner)
101 }
102}
103
104impl<T, C> Constrained<T, C>
105where
106 T: Copy,
107{
108 pub const fn into_inner(self) -> T {
126 self.inner
127 }
128
129 pub(crate) fn map_unchecked<F>(self, f: F) -> Self
130 where
131 F: FnOnce(T) -> T,
132 {
133 Constrained::unchecked(f(self.into_inner()))
134 }
135}
136
137impl<T, C> Constrained<T, C>
138where
139 T: Debug,
140 C: StaticDebug,
141{
142 pub fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
149 write!(formatter, "Constrained<")?;
150 C::fmt(formatter)?;
151 write!(formatter, ">({:?})", self.inner)
152 }
153
154 pub const fn debug(&self) -> impl '_ + Copy + Debug {
163 struct Formatted<'a, T, C>(&'a Constrained<T, C>);
164
165 impl<T, C> Clone for Formatted<'_, T, C> {
166 fn clone(&self) -> Self {
167 *self
168 }
169 }
170
171 impl<T, C> Copy for Formatted<'_, T, C> {}
172
173 impl<T, C> Debug for Formatted<'_, T, C>
174 where
175 T: Debug,
176 C: StaticDebug,
177 {
178 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
179 Constrained::fmt(self.0, formatter)
180 }
181 }
182
183 Formatted(self)
184 }
185}
186
187impl<T, C> Constrained<T, C>
188where
189 T: Primitive,
190 C: Constraint,
191{
192 pub fn new(inner: T) -> OutputFor<Self> {
246 C::map(inner, |inner| Constrained {
247 inner,
248 phantom: PhantomData,
249 })
250 }
251
252 pub fn try_new(inner: T) -> Result<Self, C::Error> {
298 C::check(inner).map(|_| Constrained {
299 inner,
300 phantom: PhantomData,
301 })
302 }
303
304 pub fn assert(inner: T) -> Self {
347 Self::try_new(inner).expect_constrained()
348 }
349
350 pub fn try_from_slice<'a>(slice: &'a [T]) -> Result<&'a [Self], C::Error> {
363 slice.iter().try_for_each(|inner| C::check(*inner))?;
364 Ok(unsafe { mem::transmute::<&'a [T], &'a [Self]>(slice) })
368 }
369
370 pub fn try_from_mut_slice<'a>(slice: &'a mut [T]) -> Result<&'a mut [Self], C::Error> {
384 slice.iter().try_for_each(|inner| C::check(*inner))?;
385 Ok(unsafe { mem::transmute::<&'a mut [T], &'a mut [Self]>(slice) })
389 }
390
391 pub fn from_subset<C2>(other: Constrained<T, C2>) -> Self
405 where
406 C2: Constraint + SubsetOf<C>,
407 {
408 Self::unchecked(other.into_inner())
409 }
410
411 pub fn into_superset<C2>(self) -> Constrained<T, C2>
424 where
425 C2: Constraint + SupersetOf<C>,
426 {
427 Constrained::unchecked(self.into_inner())
428 }
429
430 pub fn into_expression(self) -> ExpressionFor<Self> {
436 Expression::from(self)
437 }
438
439 pub(crate) fn map<F>(self, f: F) -> OutputFor<Self>
440 where
441 F: FnOnce(T) -> T,
442 {
443 Self::new(f(self.into_inner()))
444 }
445
446 pub(crate) fn zip_map<C2, F>(self, other: Constrained<T, C2>, f: F) -> OutputFor<Self>
447 where
448 C2: Constraint,
449 F: FnOnce(T, T) -> T,
450 {
451 Self::new(f(self.into_inner(), other.into_inner()))
452 }
453}
454
455impl<T> Total<T>
456where
457 T: Primitive,
458{
459 pub fn from_slice<'a>(slice: &'a [T]) -> &'a [Self] {
466 unsafe { mem::transmute::<&'a [T], &'a [Self]>(slice) }
470 }
471
472 pub fn from_mut_slice<'a>(slice: &'a mut [T]) -> &'a mut [Self] {
480 unsafe { mem::transmute::<&'a mut [T], &'a mut [Self]>(slice) }
484 }
485}
486
487#[cfg(feature = "approx")]
488impl<T, C> AbsDiffEq for Constrained<T, C>
489where
490 T: AbsDiffEq<Epsilon = T> + Primitive,
491 C: Constraint,
492{
493 type Epsilon = Self;
494
495 fn default_epsilon() -> Self::Epsilon {
496 Self::assert(T::default_epsilon())
497 }
498
499 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
500 self.into_inner()
501 .abs_diff_eq(&other.into_inner(), epsilon.into_inner())
502 }
503}
504
505impl<T, C> Add for Constrained<T, C>
506where
507 T: Primitive,
508 C: Constraint,
509{
510 type Output = OutputFor<Self>;
511
512 fn add(self, other: Self) -> Self::Output {
513 self.zip_map(other, Add::add)
514 }
515}
516
517impl<T, C> Add<T> for Constrained<T, C>
518where
519 T: Primitive,
520 C: Constraint,
521{
522 type Output = OutputFor<Self>;
523
524 fn add(self, other: T) -> Self::Output {
525 self.map(|inner| inner + other)
526 }
527}
528
529impl<T, C, E> AddAssign for Constrained<T, C>
530where
531 T: Primitive,
532 C: Constraint<Error = E>,
533 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
534{
535 fn add_assign(&mut self, other: Self) {
536 *self = *self + other;
537 }
538}
539
540impl<T, C, E> AddAssign<T> for Constrained<T, C>
541where
542 T: Primitive,
543 C: Constraint<Error = E>,
544 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
545{
546 fn add_assign(&mut self, other: T) {
547 *self = self.map(|inner| inner + other);
548 }
549}
550
551impl<T, C> AsRef<T> for Constrained<T, C> {
552 fn as_ref(&self) -> &T {
553 &self.inner
554 }
555}
556
557impl<T, C> BinaryRealFunction for Constrained<T, C>
558where
559 T: Primitive,
560 C: Constraint,
561{
562 #[cfg(feature = "std")]
563 fn div_euclid(self, n: Self) -> Self::Codomain {
564 self.zip_map(n, BinaryRealFunction::div_euclid)
565 }
566
567 #[cfg(feature = "std")]
568 fn rem_euclid(self, n: Self) -> Self::Codomain {
569 self.zip_map(n, BinaryRealFunction::rem_euclid)
570 }
571
572 #[cfg(feature = "std")]
573 fn pow(self, n: Self) -> Self::Codomain {
574 self.zip_map(n, BinaryRealFunction::pow)
575 }
576
577 #[cfg(feature = "std")]
578 fn log(self, base: Self) -> Self::Codomain {
579 self.zip_map(base, BinaryRealFunction::log)
580 }
581
582 #[cfg(feature = "std")]
583 fn hypot(self, other: Self) -> Self::Codomain {
584 self.zip_map(other, BinaryRealFunction::hypot)
585 }
586
587 #[cfg(feature = "std")]
588 fn atan2(self, other: Self) -> Self::Codomain {
589 self.zip_map(other, BinaryRealFunction::atan2)
590 }
591}
592
593impl<T, C> BinaryRealFunction<T> for Constrained<T, C>
594where
595 T: Primitive,
596 C: Constraint,
597{
598 #[cfg(feature = "std")]
599 fn div_euclid(self, n: T) -> Self::Codomain {
600 self.map(|inner| BinaryRealFunction::div_euclid(inner, n))
601 }
602
603 #[cfg(feature = "std")]
604 fn rem_euclid(self, n: T) -> Self::Codomain {
605 self.map(|inner| BinaryRealFunction::rem_euclid(inner, n))
606 }
607
608 #[cfg(feature = "std")]
609 fn pow(self, n: T) -> Self::Codomain {
610 self.map(|inner| BinaryRealFunction::pow(inner, n))
611 }
612
613 #[cfg(feature = "std")]
614 fn log(self, base: T) -> Self::Codomain {
615 self.map(|inner| BinaryRealFunction::log(inner, base))
616 }
617
618 #[cfg(feature = "std")]
619 fn hypot(self, other: T) -> Self::Codomain {
620 self.map(|inner| BinaryRealFunction::hypot(inner, other))
621 }
622
623 #[cfg(feature = "std")]
624 fn atan2(self, other: T) -> Self::Codomain {
625 self.map(|inner| BinaryRealFunction::atan2(inner, other))
626 }
627}
628
629impl<T, C> Bounded for Constrained<T, C>
630where
631 T: Primitive,
632{
633 fn min_value() -> Self {
634 BaseEncoding::MIN_FINITE
635 }
636
637 fn max_value() -> Self {
638 BaseEncoding::MAX_FINITE
639 }
640}
641
642impl<T, C> Clone for Constrained<T, C>
643where
644 T: Clone,
645{
646 fn clone(&self) -> Self {
647 Constrained {
648 inner: self.inner.clone(),
649 phantom: PhantomData,
650 }
651 }
652}
653
654impl<T, C> ConstrainedProxy for Constrained<T, C>
655where
656 T: Primitive,
657 C: Constraint,
658{
659 type Constraint = C;
660}
661
662impl<T, C> Function for Constrained<T, C>
663where
664 T: Primitive,
665 C: Constraint,
666{
667 type Codomain = OutputFor<Self>;
668}
669
670impl<T, C> Copy for Constrained<T, C> where T: Copy {}
671
672impl<T, D> Debug for Constrained<T, IsExtendedReal<D>>
673where
674 T: Debug,
675 D: Divergence,
676{
677 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
678 formatter
679 .debug_tuple("ExtendedReal")
680 .field(self.as_ref())
681 .finish()
682 }
683}
684
685impl<T> Debug for Constrained<T, IsFloat>
686where
687 T: Debug,
688{
689 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
690 formatter.debug_tuple("Total").field(self.as_ref()).finish()
691 }
692}
693
694impl<T, D> Debug for Constrained<T, IsReal<D>>
695where
696 T: Debug,
697 D: Divergence,
698{
699 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
700 formatter.debug_tuple("Real").field(self.as_ref()).finish()
701 }
702}
703
704impl<T, C> Default for Constrained<T, C>
705where
706 T: Primitive,
707 C: Constraint,
708{
709 fn default() -> Self {
710 Self::unchecked(T::ZERO)
712 }
713}
714
715impl<T, C> Display for Constrained<T, C>
716where
717 T: Display,
718{
719 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
720 self.as_ref().fmt(f)
721 }
722}
723
724impl<T, C> Div for Constrained<T, C>
725where
726 T: Primitive,
727 C: Constraint,
728{
729 type Output = OutputFor<Self>;
730
731 fn div(self, other: Self) -> Self::Output {
732 self.zip_map(other, Div::div)
733 }
734}
735
736impl<T, C> Div<T> for Constrained<T, C>
737where
738 T: Primitive,
739 C: Constraint,
740{
741 type Output = OutputFor<Self>;
742
743 fn div(self, other: T) -> Self::Output {
744 self.map(|inner| inner / other)
745 }
746}
747
748impl<T, C, E> DivAssign for Constrained<T, C>
749where
750 T: Primitive,
751 C: Constraint<Error = E>,
752 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
753{
754 fn div_assign(&mut self, other: Self) {
755 *self = *self / other
756 }
757}
758
759impl<T, C, E> DivAssign<T> for Constrained<T, C>
760where
761 T: Primitive,
762 C: Constraint<Error = E>,
763 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
764{
765 fn div_assign(&mut self, other: T) {
766 *self = self.map(|inner| inner / other);
767 }
768}
769
770impl<T, C> BaseEncoding for Constrained<T, C>
771where
772 T: Primitive,
773{
774 const MAX_FINITE: Self = Constrained::unchecked(T::MAX_FINITE);
775 const MIN_FINITE: Self = Constrained::unchecked(T::MIN_FINITE);
776 const MIN_POSITIVE_NORMAL: Self = Constrained::unchecked(T::MIN_POSITIVE_NORMAL);
777 const EPSILON: Self = Constrained::unchecked(T::EPSILON);
778
779 fn classify(self) -> FpCategory {
780 T::classify(self.into_inner())
781 }
782
783 fn is_normal(self) -> bool {
784 T::is_normal(self.into_inner())
785 }
786
787 fn is_sign_positive(self) -> bool {
788 self.into_inner().is_sign_positive()
789 }
790
791 fn is_sign_negative(self) -> bool {
792 self.into_inner().is_sign_negative()
793 }
794
795 #[cfg(feature = "std")]
796 fn signum(self) -> Self {
797 self.map_unchecked(|inner| inner.signum())
798 }
799
800 fn integer_decode(self) -> (u64, i16, i8) {
801 T::integer_decode(self.into_inner())
802 }
803}
804
805impl<T, C> Eq for Constrained<T, C> where T: Primitive {}
806
807impl<T, C, E> Float for Constrained<T, C>
808where
809 T: Float + Primitive,
810 C: Constraint<Error = E> + Member<InfinitySet> + Member<NanSet>,
811 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
812{
813 fn infinity() -> Self {
814 InfinityEncoding::INFINITY
815 }
816
817 fn neg_infinity() -> Self {
818 InfinityEncoding::NEG_INFINITY
819 }
820
821 fn is_infinite(self) -> bool {
822 self.with_inner(Float::is_infinite)
823 }
824
825 fn is_finite(self) -> bool {
826 self.with_inner(Float::is_finite)
827 }
828
829 fn nan() -> Self {
830 <Self as NanEncoding>::NAN
831 }
832
833 fn is_nan(self) -> bool {
834 self.with_inner(Float::is_nan)
835 }
836
837 fn max_value() -> Self {
838 BaseEncoding::MAX_FINITE
839 }
840
841 fn min_value() -> Self {
842 BaseEncoding::MIN_FINITE
843 }
844
845 fn min_positive_value() -> Self {
846 BaseEncoding::MIN_POSITIVE_NORMAL
847 }
848
849 fn epsilon() -> Self {
850 BaseEncoding::EPSILON
851 }
852
853 fn min(self, other: Self) -> Self {
854 self.zip_map(other, Float::min)
855 }
856
857 fn max(self, other: Self) -> Self {
858 self.zip_map(other, Float::max)
859 }
860
861 fn neg_zero() -> Self {
862 -Self::ZERO
863 }
864
865 fn is_sign_positive(self) -> bool {
866 self.with_inner(Float::is_sign_positive)
867 }
868
869 fn is_sign_negative(self) -> bool {
870 self.with_inner(Float::is_sign_negative)
871 }
872
873 fn signum(self) -> Self {
874 self.map(Float::signum)
875 }
876
877 fn abs(self) -> Self {
878 self.map(Float::abs)
879 }
880
881 fn classify(self) -> FpCategory {
882 self.with_inner(Float::classify)
883 }
884
885 fn is_normal(self) -> bool {
886 self.with_inner(Float::is_normal)
887 }
888
889 fn integer_decode(self) -> (u64, i16, i8) {
890 self.with_inner(Float::integer_decode)
891 }
892
893 fn floor(self) -> Self {
894 self.map(Float::floor)
895 }
896
897 fn ceil(self) -> Self {
898 self.map(Float::ceil)
899 }
900
901 fn round(self) -> Self {
902 self.map(Float::round)
903 }
904
905 fn trunc(self) -> Self {
906 self.map(Float::trunc)
907 }
908
909 fn fract(self) -> Self {
910 self.map(Float::fract)
911 }
912
913 fn recip(self) -> Self {
914 self.map(Float::recip)
915 }
916
917 #[cfg(feature = "std")]
918 fn mul_add(self, a: Self, b: Self) -> Self {
919 let a = a.into_inner();
920 let b = b.into_inner();
921 self.map(|inner| Float::mul_add(inner, a, b))
925 }
926
927 #[cfg(feature = "std")]
928 fn abs_sub(self, other: Self) -> Self {
929 self.zip_map(other, Float::abs_sub)
930 }
931
932 #[cfg(feature = "std")]
933 fn powi(self, n: i32) -> Self {
934 self.map(|inner| Float::powi(inner, n))
935 }
936
937 #[cfg(feature = "std")]
938 fn powf(self, n: Self) -> Self {
939 self.zip_map(n, Float::powf)
940 }
941
942 #[cfg(feature = "std")]
943 fn sqrt(self) -> Self {
944 self.map(Float::sqrt)
945 }
946
947 #[cfg(feature = "std")]
948 fn cbrt(self) -> Self {
949 self.map(Float::cbrt)
950 }
951
952 #[cfg(feature = "std")]
953 fn exp(self) -> Self {
954 self.map(Float::exp)
955 }
956
957 #[cfg(feature = "std")]
958 fn exp2(self) -> Self {
959 self.map(Float::exp2)
960 }
961
962 #[cfg(feature = "std")]
963 fn exp_m1(self) -> Self {
964 self.map(Float::exp_m1)
965 }
966
967 #[cfg(feature = "std")]
968 fn log(self, base: Self) -> Self {
969 self.zip_map(base, Float::log)
970 }
971
972 #[cfg(feature = "std")]
973 fn ln(self) -> Self {
974 self.map(Float::ln)
975 }
976
977 #[cfg(feature = "std")]
978 fn log2(self) -> Self {
979 self.map(Float::log2)
980 }
981
982 #[cfg(feature = "std")]
983 fn log10(self) -> Self {
984 self.map(Float::log10)
985 }
986
987 #[cfg(feature = "std")]
988 fn ln_1p(self) -> Self {
989 self.map(Float::ln_1p)
990 }
991
992 #[cfg(feature = "std")]
993 fn hypot(self, other: Self) -> Self {
994 BinaryRealFunction::hypot(self, other)
995 }
996
997 #[cfg(feature = "std")]
998 fn sin(self) -> Self {
999 self.map(Float::sin)
1000 }
1001
1002 #[cfg(feature = "std")]
1003 fn cos(self) -> Self {
1004 self.map(Float::cos)
1005 }
1006
1007 #[cfg(feature = "std")]
1008 fn tan(self) -> Self {
1009 self.map(Float::tan)
1010 }
1011
1012 #[cfg(feature = "std")]
1013 fn asin(self) -> Self {
1014 self.map(Float::asin)
1015 }
1016
1017 #[cfg(feature = "std")]
1018 fn acos(self) -> Self {
1019 self.map(Float::acos)
1020 }
1021
1022 #[cfg(feature = "std")]
1023 fn atan(self) -> Self {
1024 self.map(Float::atan)
1025 }
1026
1027 #[cfg(feature = "std")]
1028 fn atan2(self, other: Self) -> Self {
1029 BinaryRealFunction::atan2(self, other)
1030 }
1031
1032 #[cfg(feature = "std")]
1033 fn sin_cos(self) -> (Self, Self) {
1034 let (sin, cos) = Float::sin_cos(self.into_inner());
1035 (Constrained::<_, C>::new(sin), Constrained::<_, C>::new(cos))
1036 }
1037
1038 #[cfg(feature = "std")]
1039 fn sinh(self) -> Self {
1040 self.map(Float::sinh)
1041 }
1042
1043 #[cfg(feature = "std")]
1044 fn cosh(self) -> Self {
1045 self.map(Float::cosh)
1046 }
1047
1048 #[cfg(feature = "std")]
1049 fn tanh(self) -> Self {
1050 self.map(Float::tanh)
1051 }
1052
1053 #[cfg(feature = "std")]
1054 fn asinh(self) -> Self {
1055 self.map(Float::asinh)
1056 }
1057
1058 #[cfg(feature = "std")]
1059 fn acosh(self) -> Self {
1060 self.map(Float::acosh)
1061 }
1062
1063 #[cfg(feature = "std")]
1064 fn atanh(self) -> Self {
1065 self.map(Float::atanh)
1066 }
1067
1068 #[cfg(not(feature = "std"))]
1069 fn to_degrees(self) -> Self {
1070 self.map(Float::to_degrees)
1071 }
1072
1073 #[cfg(not(feature = "std"))]
1074 fn to_radians(self) -> Self {
1075 self.map(Float::to_radians)
1076 }
1077}
1078
1079impl<T, C> FloatConst for Constrained<T, C>
1080where
1081 T: Primitive,
1082 C: Constraint,
1083{
1084 fn E() -> Self {
1085 <Self as UnaryRealFunction>::E
1086 }
1087
1088 fn PI() -> Self {
1089 <Self as UnaryRealFunction>::PI
1090 }
1091
1092 fn SQRT_2() -> Self {
1093 <Self as UnaryRealFunction>::SQRT_2
1094 }
1095
1096 fn FRAC_1_PI() -> Self {
1097 <Self as UnaryRealFunction>::FRAC_1_PI
1098 }
1099
1100 fn FRAC_2_PI() -> Self {
1101 <Self as UnaryRealFunction>::FRAC_2_PI
1102 }
1103
1104 fn FRAC_1_SQRT_2() -> Self {
1105 <Self as UnaryRealFunction>::FRAC_1_SQRT_2
1106 }
1107
1108 fn FRAC_2_SQRT_PI() -> Self {
1109 <Self as UnaryRealFunction>::FRAC_2_SQRT_PI
1110 }
1111
1112 fn FRAC_PI_2() -> Self {
1113 <Self as UnaryRealFunction>::FRAC_PI_2
1114 }
1115
1116 fn FRAC_PI_3() -> Self {
1117 <Self as UnaryRealFunction>::FRAC_PI_3
1118 }
1119
1120 fn FRAC_PI_4() -> Self {
1121 <Self as UnaryRealFunction>::FRAC_PI_4
1122 }
1123
1124 fn FRAC_PI_6() -> Self {
1125 <Self as UnaryRealFunction>::FRAC_PI_6
1126 }
1127
1128 fn FRAC_PI_8() -> Self {
1129 <Self as UnaryRealFunction>::FRAC_PI_8
1130 }
1131
1132 fn LN_10() -> Self {
1133 <Self as UnaryRealFunction>::LN_10
1134 }
1135
1136 fn LN_2() -> Self {
1137 <Self as UnaryRealFunction>::LN_2
1138 }
1139
1140 fn LOG10_E() -> Self {
1141 <Self as UnaryRealFunction>::LOG10_E
1142 }
1143
1144 fn LOG2_E() -> Self {
1145 <Self as UnaryRealFunction>::LOG2_E
1146 }
1147}
1148
1149impl<T> From<Real<T>> for ExtendedReal<T>
1150where
1151 T: Primitive,
1152{
1153 fn from(other: Real<T>) -> Self {
1154 Self::from_subset(other)
1155 }
1156}
1157
1158impl<'a, T> From<&'a T> for &'a Total<T>
1159where
1160 T: Primitive,
1161{
1162 fn from(inner: &'a T) -> Self {
1163 unsafe { &*(inner as *const T as *const Total<T>) }
1167 }
1168}
1169
1170impl<'a, T> From<&'a mut T> for &'a mut Total<T>
1171where
1172 T: Primitive,
1173{
1174 fn from(inner: &'a mut T) -> Self {
1175 unsafe { &mut *(inner as *mut T as *mut Total<T>) }
1179 }
1180}
1181
1182impl<T> From<Real<T>> for Total<T>
1183where
1184 T: Primitive,
1185{
1186 fn from(other: Real<T>) -> Self {
1187 Self::from_subset(other)
1188 }
1189}
1190
1191impl<T> From<ExtendedReal<T>> for Total<T>
1192where
1193 T: Primitive,
1194{
1195 fn from(other: ExtendedReal<T>) -> Self {
1196 Self::from_subset(other)
1197 }
1198}
1199
1200impl<C> From<Constrained<f32, C>> for f32 {
1201 fn from(proxy: Constrained<f32, C>) -> Self {
1202 proxy.into_inner()
1203 }
1204}
1205
1206impl<C> From<Constrained<f64, C>> for f64 {
1207 fn from(proxy: Constrained<f64, C>) -> Self {
1208 proxy.into_inner()
1209 }
1210}
1211
1212#[cfg(feature = "serde")]
1213impl<T, C> From<Constrained<T, C>> for Serde<T>
1214where
1215 T: Copy,
1216{
1217 fn from(proxy: Constrained<T, C>) -> Self {
1218 Serde {
1219 inner: proxy.into_inner(),
1220 }
1221 }
1222}
1223
1224impl<T> From<T> for Total<T>
1225where
1226 T: Primitive,
1227{
1228 fn from(inner: T) -> Self {
1229 Self::unchecked(inner)
1230 }
1231}
1232
1233impl<T, C> FromPrimitive for Constrained<T, C>
1234where
1235 T: FromPrimitive + Primitive,
1236 C: Constraint,
1237{
1238 fn from_i8(value: i8) -> Option<Self> {
1239 T::from_i8(value).and_then(|inner| Constrained::try_new(inner).ok())
1240 }
1241
1242 fn from_u8(value: u8) -> Option<Self> {
1243 T::from_u8(value).and_then(|inner| Constrained::try_new(inner).ok())
1244 }
1245
1246 fn from_i16(value: i16) -> Option<Self> {
1247 T::from_i16(value).and_then(|inner| Constrained::try_new(inner).ok())
1248 }
1249
1250 fn from_u16(value: u16) -> Option<Self> {
1251 T::from_u16(value).and_then(|inner| Constrained::try_new(inner).ok())
1252 }
1253
1254 fn from_i32(value: i32) -> Option<Self> {
1255 T::from_i32(value).and_then(|inner| Constrained::try_new(inner).ok())
1256 }
1257
1258 fn from_u32(value: u32) -> Option<Self> {
1259 T::from_u32(value).and_then(|inner| Constrained::try_new(inner).ok())
1260 }
1261
1262 fn from_i64(value: i64) -> Option<Self> {
1263 T::from_i64(value).and_then(|inner| Constrained::try_new(inner).ok())
1264 }
1265
1266 fn from_u64(value: u64) -> Option<Self> {
1267 T::from_u64(value).and_then(|inner| Constrained::try_new(inner).ok())
1268 }
1269
1270 fn from_isize(value: isize) -> Option<Self> {
1271 T::from_isize(value).and_then(|inner| Constrained::try_new(inner).ok())
1272 }
1273
1274 fn from_usize(value: usize) -> Option<Self> {
1275 T::from_usize(value).and_then(|inner| Constrained::try_new(inner).ok())
1276 }
1277
1278 fn from_f32(value: f32) -> Option<Self> {
1279 T::from_f32(value).and_then(|inner| Constrained::try_new(inner).ok())
1280 }
1281
1282 fn from_f64(value: f64) -> Option<Self> {
1283 T::from_f64(value).and_then(|inner| Constrained::try_new(inner).ok())
1284 }
1285}
1286
1287impl<T, C, E> FromStr for Constrained<T, C>
1288where
1289 T: FromStr + Primitive,
1290 C: Constraint<Error = E>,
1291 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1292{
1293 type Err = <T as FromStr>::Err;
1294
1295 fn from_str(string: &str) -> Result<Self, Self::Err> {
1296 T::from_str(string).map(Self::new)
1297 }
1298}
1299
1300impl<T, C> Hash for Constrained<T, C>
1301where
1302 T: Primitive + ToCanonical,
1303{
1304 fn hash<H>(&self, state: &mut H)
1305 where
1306 H: Hasher,
1307 {
1308 self.hash_canonical(state)
1309 }
1310}
1311
1312impl<T, C> InfinityEncoding for Constrained<T, C>
1313where
1314 T: Primitive,
1315 C: Constraint + Member<InfinitySet>,
1316{
1317 const INFINITY: Self = Constrained::unchecked(T::INFINITY);
1318 const NEG_INFINITY: Self = Constrained::unchecked(T::NEG_INFINITY);
1319
1320 fn is_infinite(self) -> bool {
1321 self.into_inner().is_infinite()
1322 }
1323
1324 fn is_finite(self) -> bool {
1325 self.into_inner().is_finite()
1326 }
1327}
1328
1329impl<T, C> EmptyOrd for Constrained<T, C>
1330where
1331 T: Primitive,
1332 C: Constraint,
1333{
1334 type Empty = C::Empty<T>;
1335
1336 #[inline(always)]
1337 fn from_empty(empty: Self::Empty) -> Self {
1338 C::from_empty(empty)
1339 }
1340
1341 #[inline(always)]
1342 fn is_empty(&self) -> bool {
1343 C::is_empty(self.as_ref())
1344 }
1345
1346 fn cmp_empty(&self, other: &Self) -> Result<Ordering, Self::Empty> {
1347 match self.as_ref().cmp_empty(other.as_ref()) {
1348 Ok(ordering) => Ok(ordering),
1349 Err(_) => Err(C::empty()),
1350 }
1351 }
1352}
1353
1354impl<T> EmptyInhabitant for Total<T>
1355where
1356 T: Primitive,
1357{
1358 fn empty() -> Self {
1359 Total::NAN
1360 }
1361}
1362
1363impl<T, C> LowerExp for Constrained<T, C>
1364where
1365 T: LowerExp + Primitive,
1366{
1367 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1368 self.as_ref().fmt(f)
1369 }
1370}
1371
1372impl<T, C> Mul for Constrained<T, C>
1373where
1374 T: Primitive,
1375 C: Constraint,
1376{
1377 type Output = OutputFor<Self>;
1378
1379 fn mul(self, other: Self) -> Self::Output {
1380 self.zip_map(other, Mul::mul)
1381 }
1382}
1383
1384impl<T, C> Mul<T> for Constrained<T, C>
1385where
1386 T: Primitive,
1387 C: Constraint,
1388{
1389 type Output = OutputFor<Self>;
1390
1391 fn mul(self, other: T) -> Self::Output {
1392 self.map(|a| a * other)
1393 }
1394}
1395
1396impl<T, C, E> MulAssign for Constrained<T, C>
1397where
1398 T: Primitive,
1399 C: Constraint<Error = E>,
1400 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1401{
1402 fn mul_assign(&mut self, other: Self) {
1403 *self = *self * other;
1404 }
1405}
1406
1407impl<T, C, E> MulAssign<T> for Constrained<T, C>
1408where
1409 T: Primitive,
1410 C: Constraint<Error = E>,
1411 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1412{
1413 fn mul_assign(&mut self, other: T) {
1414 *self = *self * other;
1415 }
1416}
1417
1418impl<T, C> NanEncoding for Constrained<T, C>
1419where
1420 T: Primitive,
1421 C: Constraint + Member<NanSet>,
1422{
1423 type Nan = Self;
1424
1425 const NAN: Self::Nan = Constrained::unchecked(T::NAN.into_inner());
1426
1427 fn is_nan(self) -> bool {
1428 self.into_inner().is_nan()
1429 }
1430}
1431
1432impl<T, C> Neg for Constrained<T, C>
1433where
1434 T: Primitive,
1435{
1436 type Output = Self;
1437
1438 fn neg(self) -> Self::Output {
1439 Constrained::unchecked(-self.into_inner())
1441 }
1442}
1443
1444impl<T, C, E> Num for Constrained<T, C>
1445where
1446 T: Num + Primitive,
1447 C: Constraint<Error = E>,
1448 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1449{
1450 type FromStrRadixErr = ();
1452
1453 fn from_str_radix(source: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1454 T::from_str_radix(source, radix)
1455 .map_err(|_| ())
1456 .and_then(|inner| Constrained::try_new(inner).map_err(|_| ()))
1457 }
1458}
1459
1460impl<T, C> NumCast for Constrained<T, C>
1461where
1462 T: NumCast + Primitive + ToPrimitive,
1463 C: Constraint,
1464{
1465 fn from<U>(value: U) -> Option<Self>
1466 where
1467 U: ToPrimitive,
1468 {
1469 T::from(value).and_then(|inner| Constrained::try_new(inner).ok())
1470 }
1471}
1472
1473impl<T, C, E> One for Constrained<T, C>
1474where
1475 T: Primitive,
1476 C: Constraint<Error = E>,
1477 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1478{
1479 fn one() -> Self {
1480 UnaryRealFunction::ONE
1481 }
1482}
1483
1484impl<T, C> Ord for Constrained<T, C>
1485where
1486 T: Primitive,
1487{
1488 fn cmp(&self, other: &Self) -> Ordering {
1489 CanonicalOrd::cmp_canonical(self.as_ref(), other.as_ref())
1490 }
1491}
1492
1493impl<T, C> PartialEq for Constrained<T, C>
1494where
1495 T: Primitive,
1496{
1497 fn eq(&self, other: &Self) -> bool {
1498 self.eq_canonical(other)
1499 }
1500}
1501
1502impl<T, C> PartialEq<T> for Constrained<T, C>
1503where
1504 T: Primitive,
1505 C: Constraint,
1506{
1507 fn eq(&self, other: &T) -> bool {
1508 if let Ok(other) = Self::try_new(*other) {
1509 Self::eq(self, &other)
1510 }
1511 else {
1512 false
1513 }
1514 }
1515}
1516
1517impl<T, C> PartialOrd for Constrained<T, C>
1518where
1519 T: Primitive,
1520{
1521 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1522 Some(self.cmp(other))
1523 }
1524}
1525
1526impl<T, C> PartialOrd<T> for Constrained<T, C>
1527where
1528 T: Primitive,
1529 C: Constraint,
1530{
1531 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
1532 Self::try_new(*other)
1533 .ok()
1534 .and_then(|other| Self::partial_cmp(self, &other))
1535 }
1536}
1537
1538impl<T, C, E> Product for Constrained<T, C>
1539where
1540 T: Primitive,
1541 C: Constraint<Error = E>,
1542 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1543{
1544 fn product<I>(input: I) -> Self
1545 where
1546 I: Iterator<Item = Self>,
1547 {
1548 input.fold(UnaryRealFunction::ONE, |a, b| a * b)
1549 }
1550}
1551
1552impl<T, C> Proxy for Constrained<T, C>
1553where
1554 T: Primitive,
1555{
1556 type Primitive = T;
1557}
1558
1559#[cfg(feature = "approx")]
1560impl<T, C> RelativeEq for Constrained<T, C>
1561where
1562 T: Primitive + RelativeEq<Epsilon = T>,
1563 C: Constraint,
1564{
1565 fn default_max_relative() -> Self::Epsilon {
1566 Self::assert(T::default_max_relative())
1567 }
1568
1569 fn relative_eq(
1570 &self,
1571 other: &Self,
1572 epsilon: Self::Epsilon,
1573 max_relative: Self::Epsilon,
1574 ) -> bool {
1575 self.into_inner().relative_eq(
1576 &other.into_inner(),
1577 epsilon.into_inner(),
1578 max_relative.into_inner(),
1579 )
1580 }
1581}
1582
1583impl<T, C> Rem for Constrained<T, C>
1584where
1585 T: Primitive,
1586 C: Constraint,
1587{
1588 type Output = OutputFor<Self>;
1589
1590 fn rem(self, other: Self) -> Self::Output {
1591 self.zip_map(other, Rem::rem)
1592 }
1593}
1594
1595impl<T, C> Rem<T> for Constrained<T, C>
1596where
1597 T: Primitive,
1598 C: Constraint,
1599{
1600 type Output = OutputFor<Self>;
1601
1602 fn rem(self, other: T) -> Self::Output {
1603 self.map(|inner| inner % other)
1604 }
1605}
1606
1607impl<T, C, E> RemAssign for Constrained<T, C>
1608where
1609 T: Primitive,
1610 C: Constraint<Error = E>,
1611 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1612{
1613 fn rem_assign(&mut self, other: Self) {
1614 *self = *self % other;
1615 }
1616}
1617
1618impl<T, C, E> RemAssign<T> for Constrained<T, C>
1619where
1620 T: Primitive,
1621 C: Constraint<Error = E>,
1622 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1623{
1624 fn rem_assign(&mut self, other: T) {
1625 *self = self.map(|inner| inner % other);
1626 }
1627}
1628
1629impl<T, C, E> Signed for Constrained<T, C>
1630where
1631 T: Primitive + Signed,
1632 C: Constraint<Error = E>,
1633 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1634{
1635 fn abs(&self) -> Self {
1636 self.map_unchecked(|inner| Signed::abs(&inner))
1637 }
1638
1639 fn abs_sub(&self, other: &Self) -> Self {
1640 self.zip_map(*other, |a, b| Signed::abs_sub(&a, &b))
1641 }
1642
1643 fn signum(&self) -> Self {
1644 self.map_unchecked(|inner| Signed::signum(&inner))
1645 }
1646
1647 fn is_positive(&self) -> bool {
1648 Signed::is_positive(self.as_ref())
1649 }
1650
1651 fn is_negative(&self) -> bool {
1652 Signed::is_negative(self.as_ref())
1653 }
1654}
1655
1656impl<T, C> Sub for Constrained<T, C>
1657where
1658 T: Primitive,
1659 C: Constraint,
1660{
1661 type Output = OutputFor<Self>;
1662
1663 fn sub(self, other: Self) -> Self::Output {
1664 self.zip_map(other, Sub::sub)
1665 }
1666}
1667
1668impl<T, C> Sub<T> for Constrained<T, C>
1669where
1670 T: Primitive,
1671 C: Constraint,
1672{
1673 type Output = OutputFor<Self>;
1674
1675 fn sub(self, other: T) -> Self::Output {
1676 self.map(|inner| inner - other)
1677 }
1678}
1679
1680impl<T, C, E> SubAssign for Constrained<T, C>
1681where
1682 T: Primitive,
1683 C: Constraint<Error = E>,
1684 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1685{
1686 fn sub_assign(&mut self, other: Self) {
1687 *self = *self - other
1688 }
1689}
1690
1691impl<T, C, E> SubAssign<T> for Constrained<T, C>
1692where
1693 T: Primitive,
1694 C: Constraint<Error = E>,
1695 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1696{
1697 fn sub_assign(&mut self, other: T) {
1698 *self = self.map(|inner| inner - other)
1699 }
1700}
1701
1702impl<T, C, E> Sum for Constrained<T, C>
1703where
1704 T: Primitive,
1705 C: Constraint<Error = E>,
1706 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
1707{
1708 fn sum<I>(input: I) -> Self
1709 where
1710 I: Iterator<Item = Self>,
1711 {
1712 input.fold(UnaryRealFunction::ZERO, |a, b| a + b)
1713 }
1714}
1715
1716impl<T, C> ToCanonical for Constrained<T, C>
1717where
1718 T: Primitive,
1719{
1720 type Canonical = <T as ToCanonical>::Canonical;
1721
1722 fn to_canonical(self) -> Self::Canonical {
1723 self.inner.to_canonical()
1724 }
1725}
1726
1727impl<T, C> ToPrimitive for Constrained<T, C>
1728where
1729 T: Primitive + ToPrimitive,
1730{
1731 fn to_i8(&self) -> Option<i8> {
1732 self.as_ref().to_i8()
1733 }
1734
1735 fn to_u8(&self) -> Option<u8> {
1736 self.as_ref().to_u8()
1737 }
1738
1739 fn to_i16(&self) -> Option<i16> {
1740 self.as_ref().to_i16()
1741 }
1742
1743 fn to_u16(&self) -> Option<u16> {
1744 self.as_ref().to_u16()
1745 }
1746
1747 fn to_i32(&self) -> Option<i32> {
1748 self.as_ref().to_i32()
1749 }
1750
1751 fn to_u32(&self) -> Option<u32> {
1752 self.as_ref().to_u32()
1753 }
1754
1755 fn to_i64(&self) -> Option<i64> {
1756 self.as_ref().to_i64()
1757 }
1758
1759 fn to_u64(&self) -> Option<u64> {
1760 self.as_ref().to_u64()
1761 }
1762
1763 fn to_isize(&self) -> Option<isize> {
1764 self.as_ref().to_isize()
1765 }
1766
1767 fn to_usize(&self) -> Option<usize> {
1768 self.as_ref().to_usize()
1769 }
1770
1771 fn to_f32(&self) -> Option<f32> {
1772 self.as_ref().to_f32()
1773 }
1774
1775 fn to_f64(&self) -> Option<f64> {
1776 self.as_ref().to_f64()
1777 }
1778}
1779
1780#[cfg(feature = "serde")]
1781impl<T, C> TryFrom<Serde<T>> for Constrained<T, C>
1782where
1783 T: Primitive,
1784 C: Constraint,
1785{
1786 type Error = C::Error;
1787
1788 fn try_from(container: Serde<T>) -> Result<Self, Self::Error> {
1789 Self::try_new(container.inner)
1790 }
1791}
1792
1793#[cfg(feature = "approx")]
1794impl<T, C> UlpsEq for Constrained<T, C>
1795where
1796 T: Primitive + UlpsEq<Epsilon = T>,
1797 C: Constraint,
1798{
1799 fn default_max_ulps() -> u32 {
1800 T::default_max_ulps()
1801 }
1802
1803 fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
1804 self.into_inner()
1805 .ulps_eq(&other.into_inner(), epsilon.into_inner(), max_ulps)
1806 }
1807}
1808
1809impl<T, C> UnaryRealFunction for Constrained<T, C>
1810where
1811 T: Primitive,
1812 C: Constraint,
1813{
1814 const ZERO: Self = Constrained::unchecked(UnaryRealFunction::ZERO);
1815 const ONE: Self = Constrained::unchecked(UnaryRealFunction::ONE);
1816 const E: Self = Constrained::unchecked(UnaryRealFunction::E);
1817 const PI: Self = Constrained::unchecked(UnaryRealFunction::PI);
1818 const FRAC_1_PI: Self = Constrained::unchecked(UnaryRealFunction::FRAC_1_PI);
1819 const FRAC_2_PI: Self = Constrained::unchecked(UnaryRealFunction::FRAC_2_PI);
1820 const FRAC_2_SQRT_PI: Self = Constrained::unchecked(UnaryRealFunction::FRAC_2_SQRT_PI);
1821 const FRAC_PI_2: Self = Constrained::unchecked(UnaryRealFunction::FRAC_PI_2);
1822 const FRAC_PI_3: Self = Constrained::unchecked(UnaryRealFunction::FRAC_PI_3);
1823 const FRAC_PI_4: Self = Constrained::unchecked(UnaryRealFunction::FRAC_PI_4);
1824 const FRAC_PI_6: Self = Constrained::unchecked(UnaryRealFunction::FRAC_PI_6);
1825 const FRAC_PI_8: Self = Constrained::unchecked(UnaryRealFunction::FRAC_PI_8);
1826 const SQRT_2: Self = Constrained::unchecked(UnaryRealFunction::SQRT_2);
1827 const FRAC_1_SQRT_2: Self = Constrained::unchecked(UnaryRealFunction::FRAC_1_SQRT_2);
1828 const LN_2: Self = Constrained::unchecked(UnaryRealFunction::LN_2);
1829 const LN_10: Self = Constrained::unchecked(UnaryRealFunction::LN_10);
1830 const LOG2_E: Self = Constrained::unchecked(UnaryRealFunction::LOG2_E);
1831 const LOG10_E: Self = Constrained::unchecked(UnaryRealFunction::LOG10_E);
1832
1833 fn is_zero(self) -> bool {
1834 self.into_inner().is_zero()
1835 }
1836
1837 fn is_one(self) -> bool {
1838 self.into_inner().is_zero()
1839 }
1840
1841 fn sign(self) -> Sign {
1842 self.with_inner(|inner| inner.sign())
1843 }
1844
1845 #[cfg(feature = "std")]
1846 fn abs(self) -> Self {
1847 self.map_unchecked(UnaryRealFunction::abs)
1848 }
1849
1850 #[cfg(feature = "std")]
1851 fn floor(self) -> Self {
1852 self.map_unchecked(UnaryRealFunction::floor)
1853 }
1854
1855 #[cfg(feature = "std")]
1856 fn ceil(self) -> Self {
1857 self.map_unchecked(UnaryRealFunction::ceil)
1858 }
1859
1860 #[cfg(feature = "std")]
1861 fn round(self) -> Self {
1862 self.map_unchecked(UnaryRealFunction::round)
1863 }
1864
1865 #[cfg(feature = "std")]
1866 fn trunc(self) -> Self {
1867 self.map_unchecked(UnaryRealFunction::trunc)
1868 }
1869
1870 #[cfg(feature = "std")]
1871 fn fract(self) -> Self {
1872 self.map_unchecked(UnaryRealFunction::fract)
1873 }
1874
1875 fn recip(self) -> Self::Codomain {
1876 self.map(UnaryRealFunction::recip)
1877 }
1878
1879 #[cfg(feature = "std")]
1880 fn powi(self, n: i32) -> Self::Codomain {
1881 self.map(|inner| UnaryRealFunction::powi(inner, n))
1882 }
1883
1884 #[cfg(feature = "std")]
1885 fn sqrt(self) -> Self::Codomain {
1886 self.map(UnaryRealFunction::sqrt)
1887 }
1888
1889 #[cfg(feature = "std")]
1890 fn cbrt(self) -> Self {
1891 self.map_unchecked(UnaryRealFunction::cbrt)
1892 }
1893
1894 #[cfg(feature = "std")]
1895 fn exp(self) -> Self::Codomain {
1896 self.map(UnaryRealFunction::exp)
1897 }
1898
1899 #[cfg(feature = "std")]
1900 fn exp2(self) -> Self::Codomain {
1901 self.map(UnaryRealFunction::exp2)
1902 }
1903
1904 #[cfg(feature = "std")]
1905 fn exp_m1(self) -> Self::Codomain {
1906 self.map(UnaryRealFunction::exp_m1)
1907 }
1908
1909 #[cfg(feature = "std")]
1910 fn ln(self) -> Self::Codomain {
1911 self.map(UnaryRealFunction::ln)
1912 }
1913
1914 #[cfg(feature = "std")]
1915 fn log2(self) -> Self::Codomain {
1916 self.map(UnaryRealFunction::log2)
1917 }
1918
1919 #[cfg(feature = "std")]
1920 fn log10(self) -> Self::Codomain {
1921 self.map(UnaryRealFunction::log10)
1922 }
1923
1924 #[cfg(feature = "std")]
1925 fn ln_1p(self) -> Self::Codomain {
1926 self.map(UnaryRealFunction::ln_1p)
1927 }
1928
1929 #[cfg(feature = "std")]
1930 fn to_degrees(self) -> Self::Codomain {
1931 self.map(UnaryRealFunction::to_degrees)
1932 }
1933
1934 #[cfg(feature = "std")]
1935 fn to_radians(self) -> Self {
1936 self.map_unchecked(UnaryRealFunction::to_radians)
1937 }
1938
1939 #[cfg(feature = "std")]
1940 fn sin(self) -> Self {
1941 self.map_unchecked(UnaryRealFunction::sin)
1942 }
1943
1944 #[cfg(feature = "std")]
1945 fn cos(self) -> Self {
1946 self.map_unchecked(UnaryRealFunction::cos)
1947 }
1948
1949 #[cfg(feature = "std")]
1950 fn tan(self) -> Self::Codomain {
1951 self.map(UnaryRealFunction::tan)
1952 }
1953
1954 #[cfg(feature = "std")]
1955 fn asin(self) -> Self::Codomain {
1956 self.map(UnaryRealFunction::asin)
1957 }
1958
1959 #[cfg(feature = "std")]
1960 fn acos(self) -> Self::Codomain {
1961 self.map(UnaryRealFunction::acos)
1962 }
1963
1964 #[cfg(feature = "std")]
1965 fn atan(self) -> Self {
1966 self.map_unchecked(UnaryRealFunction::atan)
1967 }
1968
1969 #[cfg(feature = "std")]
1970 fn sin_cos(self) -> (Self, Self) {
1971 let (sin, cos) = self.into_inner().sin_cos();
1972 (Constrained::unchecked(sin), Constrained::unchecked(cos))
1973 }
1974
1975 #[cfg(feature = "std")]
1976 fn sinh(self) -> Self {
1977 self.map_unchecked(UnaryRealFunction::sinh)
1978 }
1979
1980 #[cfg(feature = "std")]
1981 fn cosh(self) -> Self {
1982 self.map_unchecked(UnaryRealFunction::cosh)
1983 }
1984
1985 #[cfg(feature = "std")]
1986 fn tanh(self) -> Self {
1987 self.map_unchecked(UnaryRealFunction::tanh)
1988 }
1989
1990 #[cfg(feature = "std")]
1991 fn asinh(self) -> Self::Codomain {
1992 self.map(UnaryRealFunction::asinh)
1993 }
1994
1995 #[cfg(feature = "std")]
1996 fn acosh(self) -> Self::Codomain {
1997 self.map(UnaryRealFunction::acosh)
1998 }
1999
2000 #[cfg(feature = "std")]
2001 fn atanh(self) -> Self::Codomain {
2002 self.map(UnaryRealFunction::atanh)
2003 }
2004}
2005
2006impl<T, C> UpperExp for Constrained<T, C>
2007where
2008 T: UpperExp,
2009{
2010 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
2011 self.as_ref().fmt(f)
2012 }
2013}
2014
2015impl<T, C, E> Zero for Constrained<T, C>
2016where
2017 T: Primitive,
2018 C: Constraint<Error = E>,
2019 divergence::ContinueFor<C::Divergence>: NonResidual<Self, E>,
2020{
2021 fn zero() -> Self {
2022 UnaryRealFunction::ZERO
2023 }
2024
2025 fn is_zero(&self) -> bool {
2026 self.as_ref().is_zero()
2027 }
2028}
2029
2030macro_rules! impl_binary_operation_for_proxy {
2031 () => {
2032 with_binary_operations!(impl_binary_operation_for_proxy);
2033 };
2034 (operation => $trait:ident :: $method:ident) => {
2035 impl_binary_operation_for_proxy!(operation => $trait :: $method, |left, right| {
2036 right.map(|inner| $trait::$method(left, inner))
2037 });
2038 };
2039 (operation => $trait:ident :: $method:ident, |$left:ident, $right:ident| $f:block) => {
2040 macro_rules! impl_primitive_binary_operation_for_proxy {
2041 (primitive => $t:ty) => {
2042 impl<C> $trait<Constrained<$t, C>> for $t
2043 where
2044 C: Constraint,
2045 {
2046 type Output = OutputFor<Constrained<$t, C>>;
2047
2048 fn $method(self, other: Constrained<$t, C>) -> Self::Output {
2049 let $left = self;
2050 let $right = other;
2051 $f
2052 }
2053 }
2054 };
2055 }
2056 with_primitives!(impl_primitive_binary_operation_for_proxy);
2057 };
2058}
2059impl_binary_operation_for_proxy!();
2060
2061macro_rules! impl_num_traits_real_for_proxy {
2070 () => {
2071 with_primitives!(impl_num_traits_real_for_proxy);
2072 };
2073 (primitive => $t:ty) => {
2074 impl_num_traits_real_for_proxy!(proxy => Real, primitive => $t);
2075 impl_num_traits_real_for_proxy!(proxy => ExtendedReal, primitive => $t);
2076 };
2077 (proxy => $p:ident, primitive => $t:ty) => {
2078 #[cfg(feature = "std")]
2079 impl<D> num_traits::real::Real for $p<$t, D>
2080 where
2081 D: Divergence,
2082 divergence::ContinueFor<D>: NonResidual<Self, ErrorFor<Self>>,
2083 {
2084 fn max_value() -> Self {
2085 BaseEncoding::MAX_FINITE
2086 }
2087
2088 fn min_value() -> Self {
2089 BaseEncoding::MIN_FINITE
2090 }
2091
2092 fn min_positive_value() -> Self {
2093 BaseEncoding::MIN_POSITIVE_NORMAL
2094 }
2095
2096 fn epsilon() -> Self {
2097 BaseEncoding::EPSILON
2098 }
2099
2100 fn min(self, other: Self) -> Self {
2101 self.zip_map(other, num_traits::real::Real::min)
2102 }
2103
2104 fn max(self, other: Self) -> Self {
2105 self.zip_map(other, num_traits::real::Real::max)
2106 }
2107
2108 fn is_sign_positive(self) -> bool {
2109 self.with_inner(num_traits::real::Real::is_sign_positive)
2110 }
2111
2112 fn is_sign_negative(self) -> bool {
2113 self.with_inner(num_traits::real::Real::is_sign_negative)
2114 }
2115
2116 fn signum(self) -> Self {
2117 self.map(num_traits::real::Real::signum)
2118 }
2119
2120 fn abs(self) -> Self {
2121 self.map(num_traits::real::Real::abs)
2122 }
2123
2124 fn floor(self) -> Self {
2125 self.map(num_traits::real::Real::floor)
2126 }
2127
2128 fn ceil(self) -> Self {
2129 self.map(num_traits::real::Real::ceil)
2130 }
2131
2132 fn round(self) -> Self {
2133 self.map(num_traits::real::Real::round)
2134 }
2135
2136 fn trunc(self) -> Self {
2137 self.map(num_traits::real::Real::trunc)
2138 }
2139
2140 fn fract(self) -> Self {
2141 self.map(num_traits::real::Real::fract)
2142 }
2143
2144 fn recip(self) -> Self {
2145 self.map(num_traits::real::Real::recip)
2146 }
2147
2148 fn mul_add(self, a: Self, b: Self) -> Self {
2149 let a = a.into_inner();
2150 let b = b.into_inner();
2151 self.map(|inner| inner.mul_add(a, b))
2152 }
2153
2154 fn abs_sub(self, other: Self) -> Self {
2155 self.zip_map(other, num_traits::real::Real::abs_sub)
2156 }
2157
2158 fn powi(self, n: i32) -> Self {
2159 self.map(|inner| num_traits::real::Real::powi(inner, n))
2160 }
2161
2162 fn powf(self, n: Self) -> Self {
2163 self.zip_map(n, num_traits::real::Real::powf)
2164 }
2165
2166 fn sqrt(self) -> Self {
2167 self.map(num_traits::real::Real::sqrt)
2168 }
2169
2170 fn cbrt(self) -> Self {
2171 self.map(num_traits::real::Real::cbrt)
2172 }
2173
2174 fn exp(self) -> Self {
2175 self.map(num_traits::real::Real::exp)
2176 }
2177
2178 fn exp2(self) -> Self {
2179 self.map(num_traits::real::Real::exp2)
2180 }
2181
2182 fn exp_m1(self) -> Self {
2183 self.map(num_traits::real::Real::exp_m1)
2184 }
2185
2186 fn log(self, base: Self) -> Self {
2187 self.zip_map(base, num_traits::real::Real::log)
2188 }
2189
2190 fn ln(self) -> Self {
2191 self.map(num_traits::real::Real::ln)
2192 }
2193
2194 fn log2(self) -> Self {
2195 self.map(num_traits::real::Real::log2)
2196 }
2197
2198 fn log10(self) -> Self {
2199 self.map(num_traits::real::Real::log10)
2200 }
2201
2202 fn to_degrees(self) -> Self {
2203 self.map(num_traits::real::Real::to_degrees)
2204 }
2205
2206 fn to_radians(self) -> Self {
2207 self.map(num_traits::real::Real::to_radians)
2208 }
2209
2210 fn ln_1p(self) -> Self {
2211 self.map(num_traits::real::Real::ln_1p)
2212 }
2213
2214 fn hypot(self, other: Self) -> Self {
2215 self.zip_map(other, num_traits::real::Real::hypot)
2216 }
2217
2218 fn sin(self) -> Self {
2219 self.map(num_traits::real::Real::sin)
2220 }
2221
2222 fn cos(self) -> Self {
2223 self.map(num_traits::real::Real::cos)
2224 }
2225
2226 fn tan(self) -> Self {
2227 self.map(num_traits::real::Real::tan)
2228 }
2229
2230 fn asin(self) -> Self {
2231 self.map(num_traits::real::Real::asin)
2232 }
2233
2234 fn acos(self) -> Self {
2235 self.map(num_traits::real::Real::acos)
2236 }
2237
2238 fn atan(self) -> Self {
2239 self.map(num_traits::real::Real::atan)
2240 }
2241
2242 fn atan2(self, other: Self) -> Self {
2243 self.zip_map(other, num_traits::real::Real::atan2)
2244 }
2245
2246 fn sin_cos(self) -> (Self, Self) {
2247 let (sin, cos) = self.with_inner(num_traits::real::Real::sin_cos);
2248 ($p::<_, D>::new(sin), $p::<_, D>::new(cos))
2249 }
2250
2251 fn sinh(self) -> Self {
2252 self.map(num_traits::real::Real::sinh)
2253 }
2254
2255 fn cosh(self) -> Self {
2256 self.map(num_traits::real::Real::cosh)
2257 }
2258
2259 fn tanh(self) -> Self {
2260 self.map(num_traits::real::Real::tanh)
2261 }
2262
2263 fn asinh(self) -> Self {
2264 self.map(num_traits::real::Real::asinh)
2265 }
2266
2267 fn acosh(self) -> Self {
2268 self.map(num_traits::real::Real::acosh)
2269 }
2270
2271 fn atanh(self) -> Self {
2272 self.map(num_traits::real::Real::atanh)
2273 }
2274 }
2275 };
2276}
2277impl_num_traits_real_for_proxy!();
2278
2279macro_rules! impl_try_from_for_proxy {
2282 () => {
2283 with_primitives!(impl_try_from_for_proxy);
2284 };
2285 (primitive => $t:ty) => {
2286 impl_try_from_for_proxy!(proxy => Real, primitive => $t);
2287 impl_try_from_for_proxy!(proxy => ExtendedReal, primitive => $t);
2288 };
2289 (proxy => $p:ident, primitive => $t:ty) => {
2290 impl<D> TryFrom<$t> for $p<$t, D>
2291 where
2292 D: Divergence,
2293 {
2294 type Error = ErrorFor<Self>;
2295
2296 fn try_from(inner: $t) -> Result<Self, Self::Error> {
2297 Self::try_new(inner)
2298 }
2299 }
2300
2301 impl<'a, D> TryFrom<&'a $t> for &'a $p<$t, D>
2302 where
2303 D: Divergence,
2304 {
2305 type Error = ErrorFor<$p<$t, D>>;
2306
2307 fn try_from(inner: &'a $t) -> Result<Self, Self::Error> {
2308 ConstraintFor::<$p<$t, D>>::check(*inner).map(|_| {
2309 unsafe { mem::transmute::<&'a $t, Self>(inner) }
2313 })
2314 }
2315 }
2316
2317 impl<'a, D> TryFrom<&'a mut $t> for &'a mut $p<$t, D>
2318 where
2319 D: Divergence,
2320 {
2321 type Error = ErrorFor<$p<$t, D>>;
2322
2323 fn try_from(inner: &'a mut $t) -> Result<Self, Self::Error> {
2324 ConstraintFor::<$p<$t, D>>::check(*inner).map(move |_| {
2325 unsafe { mem::transmute::<&'a mut $t, Self>(inner) }
2329 })
2330 }
2331 }
2332 };
2333}
2334impl_try_from_for_proxy!();
2335
2336#[cfg(test)]
2337mod tests {
2338 use crate::real::RealFunction;
2339 use crate::{ExtendedReal, InfinityEncoding, NanEncoding, Real, Total, E32, R32};
2340
2341 #[test]
2342 fn total_no_panic_on_inf() {
2343 let x: Total<f32> = 1.0.into();
2344 let y = x / 0.0;
2345 assert!(InfinityEncoding::is_infinite(y));
2346 }
2347
2348 #[test]
2349 fn total_no_panic_on_nan() {
2350 let x: Total<f32> = 0.0.into();
2351 let y = x / 0.0;
2352 assert!(NanEncoding::is_nan(y));
2353 }
2354
2355 #[test]
2359 #[allow(clippy::eq_op)]
2360 #[allow(clippy::float_cmp)]
2361 #[allow(clippy::zero_divided_by_zero)]
2362 fn total_no_panic_from_ref_slice() {
2363 let x = 0.0f64 / 0.0;
2364 let y: &Total<_> = (&x).into();
2365 assert!(y.is_nan());
2366
2367 let mut x = 0.0f64;
2368 let y: &mut Total<_> = (&mut x).into();
2369 *y = (0.0f64 / 0.0).into();
2370 assert!(y.is_nan());
2371
2372 let xs = [0.0f64, 1.0];
2373 let ys = Total::from_slice(&xs);
2374 assert_eq!(ys, &[0.0f64, 1.0]);
2375
2376 let xs = [0.0f64, 1.0];
2377 let ys = Total::from_slice(&xs);
2378 assert_eq!(ys, &[0.0f64, 1.0]);
2379 }
2380
2381 #[test]
2382 fn notnan_no_panic_on_inf() {
2383 let x: E32 = 1.0.try_into().unwrap();
2384 let y = x / 0.0;
2385 assert!(InfinityEncoding::is_infinite(y));
2386 }
2387
2388 #[test]
2389 #[should_panic]
2390 fn notnan_panic_on_nan() {
2391 let x: E32 = 0.0.try_into().unwrap();
2392 let _ = x / 0.0;
2393 }
2394
2395 #[test]
2396 #[allow(clippy::eq_op)]
2397 #[allow(clippy::float_cmp)]
2398 fn notnan_no_panic_from_inf_ref_slice() {
2399 let x = 1.0f64 / 0.0;
2400 let y: &ExtendedReal<_> = (&x).try_into().unwrap();
2401 assert!(y.is_infinite());
2402
2403 let xs = [0.0f64, 1.0 / 0.0];
2404 let ys = ExtendedReal::<f64>::try_from_slice(&xs).unwrap();
2405 assert_eq!(ys, &[0.0f64, InfinityEncoding::INFINITY]);
2406 }
2407
2408 #[test]
2409 #[should_panic]
2410 #[allow(clippy::zero_divided_by_zero)]
2411 fn notnan_panic_from_nan_ref() {
2412 let x = 0.0f64 / 0.0;
2413 let _: &ExtendedReal<_> = (&x).try_into().unwrap();
2414 }
2415
2416 #[test]
2417 #[should_panic]
2418 #[allow(clippy::zero_divided_by_zero)]
2419 fn notnan_panic_from_nan_slice() {
2420 let xs = [1.0f64, 0.0f64 / 0.0];
2421 let _ = ExtendedReal::<f64>::try_from_slice(&xs).unwrap();
2422 }
2423
2424 #[test]
2425 #[should_panic]
2426 fn finite_panic_on_nan() {
2427 let x: R32 = 0.0.try_into().unwrap();
2428 let _ = x / 0.0;
2429 }
2430
2431 #[test]
2432 #[should_panic]
2433 fn finite_panic_on_inf() {
2434 let x: R32 = 1.0.try_into().unwrap();
2435 let _ = x / 0.0;
2436 }
2437
2438 #[test]
2439 #[should_panic]
2440 fn finite_panic_on_neg_inf() {
2441 let x: R32 = (-1.0).try_into().unwrap();
2442 let _ = x / 0.0;
2443 }
2444
2445 #[test]
2446 #[should_panic]
2447 fn finite_panic_from_inf_ref() {
2448 let x = 1.0f64 / 0.0;
2449 let _: &Real<_> = (&x).try_into().unwrap();
2450 }
2451
2452 #[test]
2453 #[should_panic]
2454 fn finite_panic_from_inf_slice() {
2455 let xs = [1.0f64, 1.0f64 / 0.0];
2456 let _ = Real::<f64>::try_from_slice(&xs).unwrap();
2457 }
2458
2459 #[test]
2460 #[allow(clippy::eq_op)]
2461 #[allow(clippy::float_cmp)]
2462 #[allow(clippy::zero_divided_by_zero)]
2463 fn total_nan_eq() {
2464 let x: Total<f32> = (0.0 / 0.0).into();
2465 let y: Total<f32> = (0.0 / 0.0).into();
2466 assert_eq!(x, y);
2467
2468 let z: Total<f32> =
2469 (<f32 as InfinityEncoding>::INFINITY + <f32 as InfinityEncoding>::NEG_INFINITY).into();
2470 assert_eq!(x, z);
2471
2472 #[cfg(feature = "std")]
2473 {
2474 use crate::real::UnaryRealFunction;
2475
2476 let w: Total<f32> = (UnaryRealFunction::sqrt(-1.0f32)).into();
2477 assert_eq!(x, w);
2478 }
2479 }
2480
2481 #[test]
2482 #[allow(clippy::eq_op)]
2483 #[allow(clippy::float_cmp)]
2484 #[allow(clippy::zero_divided_by_zero)]
2485 #[allow(invalid_nan_comparisons)]
2486 fn cmp_proxy_primitive() {
2487 let x: Total<f32> = (0.0 / 0.0).into();
2489 assert_eq!(x, f32::sqrt(-1.0));
2490
2491 let y: Total<f32> = (1.0 / 0.0).into();
2493 assert!(y < (0.0 / 0.0));
2494
2495 let z: R32 = 0.0.try_into().unwrap();
2497 assert_eq!(z.partial_cmp(&(1.0 / 0.0)), None);
2498 }
2499
2500 #[test]
2501 fn sum() {
2502 let xs = [
2503 1.0.try_into().unwrap(),
2504 2.0.try_into().unwrap(),
2505 3.0.try_into().unwrap(),
2506 ];
2507 assert_eq!(xs.iter().cloned().sum::<R32>(), R32::assert(6.0));
2508 }
2509
2510 #[test]
2511 fn product() {
2512 let xs = [
2513 1.0.try_into().unwrap(),
2514 2.0.try_into().unwrap(),
2515 3.0.try_into().unwrap(),
2516 ];
2517 assert_eq!(xs.iter().cloned().product::<R32>(), R32::assert(6.0),);
2518 }
2519
2520 #[test]
2522 fn impl_traits() {
2523 fn as_infinite<T>(_: T)
2524 where
2525 T: InfinityEncoding,
2526 {
2527 }
2528
2529 fn as_nan<T>(_: T)
2530 where
2531 T: NanEncoding,
2532 {
2533 }
2534
2535 fn as_real<T>(_: T)
2536 where
2537 T: RealFunction,
2538 {
2539 }
2540
2541 let finite = Real::<f32>::default();
2542 as_real(finite);
2543
2544 let notnan = ExtendedReal::<f32>::default();
2545 as_infinite(notnan);
2546 as_real(notnan);
2547
2548 let ordered = Total::<f32>::default();
2549 as_infinite(ordered);
2550 as_nan(ordered);
2551 }
2552
2553 #[test]
2554 fn fmt() {
2555 let x: Total<f32> = 1.0.into();
2556 format_args!("{0} {0:e} {0:E} {0:?} {0:#?}", x);
2557 let y: ExtendedReal<f32> = 1.0.try_into().unwrap();
2558 format_args!("{0} {0:e} {0:E} {0:?} {0:#?}", y);
2559 let z: Real<f32> = 1.0.try_into().unwrap();
2560 format_args!("{0} {0:e} {0:E} {0:?} {0:#?}", z);
2561 }
2562
2563 #[cfg(feature = "serde")]
2564 #[test]
2565 fn deserialize() {
2566 assert_eq!(
2567 R32::assert(1.0),
2568 serde_json::from_str::<R32>("1.0").unwrap()
2569 );
2570 }
2571
2572 #[cfg(feature = "serde")]
2573 #[test]
2574 #[should_panic]
2575 fn deserialize_panic_on_violation() {
2576 let _: E32 = serde_json::from_str("null").unwrap();
2579 }
2580
2581 #[cfg(feature = "serde")]
2582 #[test]
2583 fn serialize() {
2584 use crate::divergence::OrPanic;
2585
2586 assert_eq!(
2587 "1.0",
2588 serde_json::to_string(&E32::<OrPanic>::assert(1.0)).unwrap()
2589 );
2590 assert_eq!(
2592 "null",
2593 serde_json::to_string(&E32::<OrPanic>::INFINITY).unwrap()
2594 );
2595 }
2596}