module Utils.Test.EnforceRange
(enforceRange, CanEnforceRange)
where
import Numeric.MixedTypes.PreludeHiding
import Numeric.MixedTypes.Literals
import Numeric.MixedTypes.Bool
import Numeric.MixedTypes.Ord
import Numeric.MixedTypes.MinMaxAbs
import Numeric.MixedTypes.AddSub
import Numeric.MixedTypes.Mul
import Numeric.MixedTypes.Field
import Numeric.MixedTypes.Round
type CanEnforceRange t b =
(CanAddSubMulDivBy t Integer
, CanAddSameType t, CanSubSameType t, CanAbsSameType t
, CanDivIModIntegerSameType t
, ConvertibleExactly b t
, HasOrderCertainly t t)
enforceRange ::
(CanEnforceRange t b) => (Maybe b, Maybe b) -> t -> t
enforceRange :: (Maybe b, Maybe b) -> t -> t
enforceRange (Just b
l_, Just b
u_) (t
a::t)
| Bool -> NegType Bool
forall t. CanNeg t => t -> NegType t
not (t
l t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
u) = [Char] -> t
forall a. HasCallStack => [Char] -> a
error [Char]
"enforceRange: inconsistent range"
| t
l t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
a Bool -> Bool -> AndOrType Bool Bool
forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& t
a t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
u = t
a
| t
l t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
AddType t t
b Bool -> Bool -> AndOrType Bool Bool
forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& t
AddType t t
b t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
u = t
AddType t t
b
| Bool
otherwise = (t
ut -> t -> AddType t t
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+t
l)t -> Integer -> DivType t Integer
forall t1 t2. CanDiv t1 t2 => t1 -> t2 -> DivType t1 t2
/Integer
2
where
l :: t
l = b -> t
forall t1 t2. ConvertibleExactly t1 t2 => t1 -> t2
convertExactly b
l_ :: t
u :: t
u = b -> t
forall t1 t2. ConvertibleExactly t1 t2 => t1 -> t2
convertExactly b
u_ :: t
b :: AddType t t
b = t
l t -> t -> AddType t t
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ ((t -> AbsType t
forall t. CanAbs t => t -> AbsType t
abs t
a) t -> t -> ModType t t
forall t1 t2. CanDivIMod t1 t2 => t1 -> t2 -> ModType t1 t2
`mod` (t
ut -> t -> SubType t t
forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
-t
l))
enforceRange (Just b
l_, Maybe b
_) (t
a::t)
| t
l t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
a = t
a
| Bool
otherwise = (Integer
2Integer -> t -> MulType Integer t
forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*t
lt -> t -> SubType t t
forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
-t
at -> Integer -> AddType t Integer
forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+Integer
1)
where
l :: t
l = b -> t
forall t1 t2. ConvertibleExactly t1 t2 => t1 -> t2
convertExactly b
l_ :: t
enforceRange (Maybe b
_, Just b
u_) (t
a::t)
| t
a t -> t -> Bool
forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<! t
u = t
a
| Bool
otherwise = (Integer
2Integer -> t -> MulType Integer t
forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*t
ut -> t -> SubType t t
forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
-t
at -> Integer -> SubType t Integer
forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
-Integer
1)
where
u :: t
u = b -> t
forall t1 t2. ConvertibleExactly t1 t2 => t1 -> t2
convertExactly b
u_ :: t
enforceRange (Maybe b, Maybe b)
_ t
a = t
a