-- | Internal 'Range' API
module Test.Falsify.Internal.Range (
    -- * Definition
    Range(..)
  , ProperFraction(ProperFraction)
  , Precision(..)
  ) where

import Data.Word
import GHC.Show
import GHC.Stack

{-------------------------------------------------------------------------------
  Proper frations
-------------------------------------------------------------------------------}

-- | Value @x@ such that @0 <= x < 1@
newtype ProperFraction = UnsafeProperFraction { ProperFraction -> Double
getProperFraction :: Double }
  deriving stock (ProperFraction -> ProperFraction -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ProperFraction -> ProperFraction -> Bool
$c/= :: ProperFraction -> ProperFraction -> Bool
== :: ProperFraction -> ProperFraction -> Bool
$c== :: ProperFraction -> ProperFraction -> Bool
Eq, Eq ProperFraction
ProperFraction -> ProperFraction -> Bool
ProperFraction -> ProperFraction -> Ordering
ProperFraction -> ProperFraction -> ProperFraction
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ProperFraction -> ProperFraction -> ProperFraction
$cmin :: ProperFraction -> ProperFraction -> ProperFraction
max :: ProperFraction -> ProperFraction -> ProperFraction
$cmax :: ProperFraction -> ProperFraction -> ProperFraction
>= :: ProperFraction -> ProperFraction -> Bool
$c>= :: ProperFraction -> ProperFraction -> Bool
> :: ProperFraction -> ProperFraction -> Bool
$c> :: ProperFraction -> ProperFraction -> Bool
<= :: ProperFraction -> ProperFraction -> Bool
$c<= :: ProperFraction -> ProperFraction -> Bool
< :: ProperFraction -> ProperFraction -> Bool
$c< :: ProperFraction -> ProperFraction -> Bool
compare :: ProperFraction -> ProperFraction -> Ordering
$ccompare :: ProperFraction -> ProperFraction -> Ordering
Ord)
  deriving newtype (Integer -> ProperFraction
ProperFraction -> ProperFraction
ProperFraction -> ProperFraction -> ProperFraction
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> ProperFraction
$cfromInteger :: Integer -> ProperFraction
signum :: ProperFraction -> ProperFraction
$csignum :: ProperFraction -> ProperFraction
abs :: ProperFraction -> ProperFraction
$cabs :: ProperFraction -> ProperFraction
negate :: ProperFraction -> ProperFraction
$cnegate :: ProperFraction -> ProperFraction
* :: ProperFraction -> ProperFraction -> ProperFraction
$c* :: ProperFraction -> ProperFraction -> ProperFraction
- :: ProperFraction -> ProperFraction -> ProperFraction
$c- :: ProperFraction -> ProperFraction -> ProperFraction
+ :: ProperFraction -> ProperFraction -> ProperFraction
$c+ :: ProperFraction -> ProperFraction -> ProperFraction
Num, Num ProperFraction
Rational -> ProperFraction
ProperFraction -> ProperFraction
ProperFraction -> ProperFraction -> ProperFraction
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> ProperFraction
$cfromRational :: Rational -> ProperFraction
recip :: ProperFraction -> ProperFraction
$crecip :: ProperFraction -> ProperFraction
/ :: ProperFraction -> ProperFraction -> ProperFraction
$c/ :: ProperFraction -> ProperFraction -> ProperFraction
Fractional)

-- | Show instance relies on the 'ProperFraction' pattern synonym
instance Show ProperFraction where
  showsPrec :: Int -> ProperFraction -> ShowS
showsPrec Int
p (UnsafeProperFraction Double
f) = Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
>= Int
appPrec1) forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"ProperFraction "
      forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> ShowS
showsPrec Int
appPrec1 Double
f

mkProperFraction :: HasCallStack => Double -> ProperFraction
mkProperFraction :: HasCallStack => Double -> ProperFraction
mkProperFraction Double
f
  | Double
0 forall a. Ord a => a -> a -> Bool
<= Double
f Bool -> Bool -> Bool
&& Double
f forall a. Ord a => a -> a -> Bool
< Double
1 = Double -> ProperFraction
UnsafeProperFraction Double
f
  | Bool
otherwise = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"mkProperFraction: not a proper fraction: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Double
f

pattern ProperFraction :: Double -> ProperFraction
pattern $bProperFraction :: Double -> ProperFraction
$mProperFraction :: forall {r}. ProperFraction -> (Double -> r) -> ((# #) -> r) -> r
ProperFraction f <- (getProperFraction -> f)
  where
    ProperFraction = HasCallStack => Double -> ProperFraction
mkProperFraction

{-# COMPLETE ProperFraction #-}

{-------------------------------------------------------------------------------
  Precision
-------------------------------------------------------------------------------}

-- | Precision (in bits)
newtype Precision = Precision Word8
  deriving stock (Int -> Precision -> ShowS
[Precision] -> ShowS
Precision -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Precision] -> ShowS
$cshowList :: [Precision] -> ShowS
show :: Precision -> String
$cshow :: Precision -> String
showsPrec :: Int -> Precision -> ShowS
$cshowsPrec :: Int -> Precision -> ShowS
Show, Precision -> Precision -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Precision -> Precision -> Bool
$c/= :: Precision -> Precision -> Bool
== :: Precision -> Precision -> Bool
$c== :: Precision -> Precision -> Bool
Eq, Eq Precision
Precision -> Precision -> Bool
Precision -> Precision -> Ordering
Precision -> Precision -> Precision
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Precision -> Precision -> Precision
$cmin :: Precision -> Precision -> Precision
max :: Precision -> Precision -> Precision
$cmax :: Precision -> Precision -> Precision
>= :: Precision -> Precision -> Bool
$c>= :: Precision -> Precision -> Bool
> :: Precision -> Precision -> Bool
$c> :: Precision -> Precision -> Bool
<= :: Precision -> Precision -> Bool
$c<= :: Precision -> Precision -> Bool
< :: Precision -> Precision -> Bool
$c< :: Precision -> Precision -> Bool
compare :: Precision -> Precision -> Ordering
$ccompare :: Precision -> Precision -> Ordering
Ord)
  deriving newtype (Integer -> Precision
Precision -> Precision
Precision -> Precision -> Precision
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Precision
$cfromInteger :: Integer -> Precision
signum :: Precision -> Precision
$csignum :: Precision -> Precision
abs :: Precision -> Precision
$cabs :: Precision -> Precision
negate :: Precision -> Precision
$cnegate :: Precision -> Precision
* :: Precision -> Precision -> Precision
$c* :: Precision -> Precision -> Precision
- :: Precision -> Precision -> Precision
$c- :: Precision -> Precision -> Precision
+ :: Precision -> Precision -> Precision
$c+ :: Precision -> Precision -> Precision
Num, Int -> Precision
Precision -> Int
Precision -> [Precision]
Precision -> Precision
Precision -> Precision -> [Precision]
Precision -> Precision -> Precision -> [Precision]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Precision -> Precision -> Precision -> [Precision]
$cenumFromThenTo :: Precision -> Precision -> Precision -> [Precision]
enumFromTo :: Precision -> Precision -> [Precision]
$cenumFromTo :: Precision -> Precision -> [Precision]
enumFromThen :: Precision -> Precision -> [Precision]
$cenumFromThen :: Precision -> Precision -> [Precision]
enumFrom :: Precision -> [Precision]
$cenumFrom :: Precision -> [Precision]
fromEnum :: Precision -> Int
$cfromEnum :: Precision -> Int
toEnum :: Int -> Precision
$ctoEnum :: Int -> Precision
pred :: Precision -> Precision
$cpred :: Precision -> Precision
succ :: Precision -> Precision
$csucc :: Precision -> Precision
Enum)

{-------------------------------------------------------------------------------
  Range
-------------------------------------------------------------------------------}

-- | Range of values
data Range a =
    Constant a
  | FromProperFraction Precision (ProperFraction -> a)
  | Towards a [Range a]
  deriving stock (forall a b. a -> Range b -> Range a
forall a b. (a -> b) -> Range a -> Range b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Range b -> Range a
$c<$ :: forall a b. a -> Range b -> Range a
fmap :: forall a b. (a -> b) -> Range a -> Range b
$cfmap :: forall a b. (a -> b) -> Range a -> Range b
Functor)