{-| 
    @enforceRange (Just l, Just u) a@ where @l < u@ returns an arbitrary value @b@ with @u < b < l@.
    Moreover, the returned values are distributed roughly evenly if the input values @a@ are distributed 
    roughly evenly in a large neighbourhood of the interval @[l,r]@.
    In most cases, when @l<a<u@, then @b=a@.
-}
enforceRange ::
    (CanEnforceRange t b) => (Maybe b, Maybe b) -> t -> t
enforceRange (Just l_, Just u_) (a::t) 
    | not (l !<! u) = error "enforceRange: inconsistent range"
    | l !<! a && a !<! u = a
    | l !<! b && b !<! u = b
    | otherwise = (u+l)/2
    where
    l = convertExactly l_ :: t
    u = convertExactly u_ :: t
    b = l + ((abs a) `mod` (u-l))
enforceRange ::
    (CanEnforceRange t b) => (Maybe b, Maybe b) -> t -> t
enforceRange (Just l_, Just u_) (a::t) 
    | not (l !<! u) = error "enforceRange: inconsistent range"
    | l !<! a && a !<! u = a
    | l !<! b && b !<! u = b
    | otherwise = (u+l)/2
    where
    l = convertExactly l_ :: t
    u = convertExactly u_ :: t
    b = l + ((abs a) `mod` (u-l))
enforceRange (Just l_, Just u_) (a::t) 
    | not (l !<! u) = error "enforceRange: inconsistent range"
    | l !<! a && a !<! u = a
    | l !<! b && b !<! u = b
    | otherwise = (u+l)/2
    where
    l = convertExactly l_ :: t
    u = convertExactly u_ :: t
    b = l + ((abs a) `mod` (u-l))