{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}

{- |
    Module      :  Test.SDP.Gen
    Copyright   :  (c) Andrey Mulik 2019
    License     :  BSD-style
    Maintainer  :  work.a.mulik@gmail.com
    Portability :  non-portable (requires non-portable modules)
    
    @Test.SDP.Gen@ provides newtypes for QuickCheck.
-}
module Test.SDP.Gen
(
  -- * Common newtypes for QuickCheck
  Short (..), Medium (..), Long (..),
  
  -- ** Related functions
  linearLargeA, linearA, orderA
)
where

import Prelude ()
import SDP.SafePrelude
import SDP.Linear

import Test.QuickCheck

import Data.Coerce

default ()

--------------------------------------------------------------------------------

{- |
  Short is newtype of short data structures [0, 100) in QuickCheck properties.
  
  Short is the equivalent of the standard Arbitrary definition:
  @arbitrary = fromList \<$\> arbitrary@.
-}
newtype Short a = Short a deriving ( Short a -> Short a -> Bool
(Short a -> Short a -> Bool)
-> (Short a -> Short a -> Bool) -> Eq (Short a)
forall a. Eq a => Short a -> Short a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Short a -> Short a -> Bool
$c/= :: forall a. Eq a => Short a -> Short a -> Bool
== :: Short a -> Short a -> Bool
$c== :: forall a. Eq a => Short a -> Short a -> Bool
Eq, Eq (Short a)
Eq (Short a)
-> (Short a -> Short a -> Ordering)
-> (Short a -> Short a -> Bool)
-> (Short a -> Short a -> Bool)
-> (Short a -> Short a -> Bool)
-> (Short a -> Short a -> Bool)
-> (Short a -> Short a -> Short a)
-> (Short a -> Short a -> Short a)
-> Ord (Short a)
Short a -> Short a -> Bool
Short a -> Short a -> Ordering
Short a -> Short a -> Short a
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
forall a. Ord a => Eq (Short a)
forall a. Ord a => Short a -> Short a -> Bool
forall a. Ord a => Short a -> Short a -> Ordering
forall a. Ord a => Short a -> Short a -> Short a
min :: Short a -> Short a -> Short a
$cmin :: forall a. Ord a => Short a -> Short a -> Short a
max :: Short a -> Short a -> Short a
$cmax :: forall a. Ord a => Short a -> Short a -> Short a
>= :: Short a -> Short a -> Bool
$c>= :: forall a. Ord a => Short a -> Short a -> Bool
> :: Short a -> Short a -> Bool
$c> :: forall a. Ord a => Short a -> Short a -> Bool
<= :: Short a -> Short a -> Bool
$c<= :: forall a. Ord a => Short a -> Short a -> Bool
< :: Short a -> Short a -> Bool
$c< :: forall a. Ord a => Short a -> Short a -> Bool
compare :: Short a -> Short a -> Ordering
$ccompare :: forall a. Ord a => Short a -> Short a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Short a)
Ord, ReadPrec [Short a]
ReadPrec (Short a)
Int -> ReadS (Short a)
ReadS [Short a]
(Int -> ReadS (Short a))
-> ReadS [Short a]
-> ReadPrec (Short a)
-> ReadPrec [Short a]
-> Read (Short a)
forall a. Read a => ReadPrec [Short a]
forall a. Read a => ReadPrec (Short a)
forall a. Read a => Int -> ReadS (Short a)
forall a. Read a => ReadS [Short a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Short a]
$creadListPrec :: forall a. Read a => ReadPrec [Short a]
readPrec :: ReadPrec (Short a)
$creadPrec :: forall a. Read a => ReadPrec (Short a)
readList :: ReadS [Short a]
$creadList :: forall a. Read a => ReadS [Short a]
readsPrec :: Int -> ReadS (Short a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Short a)
Read, Int -> Short a -> ShowS
[Short a] -> ShowS
Short a -> String
(Int -> Short a -> ShowS)
-> (Short a -> String) -> ([Short a] -> ShowS) -> Show (Short a)
forall a. Show a => Int -> Short a -> ShowS
forall a. Show a => [Short a] -> ShowS
forall a. Show a => Short a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Short a] -> ShowS
$cshowList :: forall a. Show a => [Short a] -> ShowS
show :: Short a -> String
$cshow :: forall a. Show a => Short a -> String
showsPrec :: Int -> Short a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Short a -> ShowS
Show )

{- |
  Medium is newtype of medium data structures in QuickCheck properties. The
  Arbitrary Medium instance must create a random-sized structure from the range
  [100, 1024).
  
  Medium is useful in testing as a compromise between speed and reliability:
  structures are too short for stress tests, but still human readable and enough
  fast for auto-testing.
-}
newtype Medium a = Medium a deriving ( Medium a -> Medium a -> Bool
(Medium a -> Medium a -> Bool)
-> (Medium a -> Medium a -> Bool) -> Eq (Medium a)
forall a. Eq a => Medium a -> Medium a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Medium a -> Medium a -> Bool
$c/= :: forall a. Eq a => Medium a -> Medium a -> Bool
== :: Medium a -> Medium a -> Bool
$c== :: forall a. Eq a => Medium a -> Medium a -> Bool
Eq, Eq (Medium a)
Eq (Medium a)
-> (Medium a -> Medium a -> Ordering)
-> (Medium a -> Medium a -> Bool)
-> (Medium a -> Medium a -> Bool)
-> (Medium a -> Medium a -> Bool)
-> (Medium a -> Medium a -> Bool)
-> (Medium a -> Medium a -> Medium a)
-> (Medium a -> Medium a -> Medium a)
-> Ord (Medium a)
Medium a -> Medium a -> Bool
Medium a -> Medium a -> Ordering
Medium a -> Medium a -> Medium a
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
forall a. Ord a => Eq (Medium a)
forall a. Ord a => Medium a -> Medium a -> Bool
forall a. Ord a => Medium a -> Medium a -> Ordering
forall a. Ord a => Medium a -> Medium a -> Medium a
min :: Medium a -> Medium a -> Medium a
$cmin :: forall a. Ord a => Medium a -> Medium a -> Medium a
max :: Medium a -> Medium a -> Medium a
$cmax :: forall a. Ord a => Medium a -> Medium a -> Medium a
>= :: Medium a -> Medium a -> Bool
$c>= :: forall a. Ord a => Medium a -> Medium a -> Bool
> :: Medium a -> Medium a -> Bool
$c> :: forall a. Ord a => Medium a -> Medium a -> Bool
<= :: Medium a -> Medium a -> Bool
$c<= :: forall a. Ord a => Medium a -> Medium a -> Bool
< :: Medium a -> Medium a -> Bool
$c< :: forall a. Ord a => Medium a -> Medium a -> Bool
compare :: Medium a -> Medium a -> Ordering
$ccompare :: forall a. Ord a => Medium a -> Medium a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Medium a)
Ord, ReadPrec [Medium a]
ReadPrec (Medium a)
Int -> ReadS (Medium a)
ReadS [Medium a]
(Int -> ReadS (Medium a))
-> ReadS [Medium a]
-> ReadPrec (Medium a)
-> ReadPrec [Medium a]
-> Read (Medium a)
forall a. Read a => ReadPrec [Medium a]
forall a. Read a => ReadPrec (Medium a)
forall a. Read a => Int -> ReadS (Medium a)
forall a. Read a => ReadS [Medium a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Medium a]
$creadListPrec :: forall a. Read a => ReadPrec [Medium a]
readPrec :: ReadPrec (Medium a)
$creadPrec :: forall a. Read a => ReadPrec (Medium a)
readList :: ReadS [Medium a]
$creadList :: forall a. Read a => ReadS [Medium a]
readsPrec :: Int -> ReadS (Medium a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Medium a)
Read, Int -> Medium a -> ShowS
[Medium a] -> ShowS
Medium a -> String
(Int -> Medium a -> ShowS)
-> (Medium a -> String) -> ([Medium a] -> ShowS) -> Show (Medium a)
forall a. Show a => Int -> Medium a -> ShowS
forall a. Show a => [Medium a] -> ShowS
forall a. Show a => Medium a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Medium a] -> ShowS
$cshowList :: forall a. Show a => [Medium a] -> ShowS
show :: Medium a -> String
$cshow :: forall a. Show a => Medium a -> String
showsPrec :: Int -> Medium a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Medium a -> ShowS
Show )

{- |
  Long is newtype of large data structures (>= 1024) in QuickCheck properties.
  Since Large can generate really huge numbers, the maximum length is limited by
  16384 - [1024, 16384).
  
  Long is primarily intended for benchmarks, although a large range of lengths
  makes them not very convenient for a pure comparison of several algorithms
  (but for this can be used vector[Of] and generate). Long works well with
  Unrolled and ByteList, since only the shortest of the allowed structures may
  fit in one standard chunk (1024 elements).
-}
newtype Long a = Long a deriving ( Long a -> Long a -> Bool
(Long a -> Long a -> Bool)
-> (Long a -> Long a -> Bool) -> Eq (Long a)
forall a. Eq a => Long a -> Long a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Long a -> Long a -> Bool
$c/= :: forall a. Eq a => Long a -> Long a -> Bool
== :: Long a -> Long a -> Bool
$c== :: forall a. Eq a => Long a -> Long a -> Bool
Eq, Eq (Long a)
Eq (Long a)
-> (Long a -> Long a -> Ordering)
-> (Long a -> Long a -> Bool)
-> (Long a -> Long a -> Bool)
-> (Long a -> Long a -> Bool)
-> (Long a -> Long a -> Bool)
-> (Long a -> Long a -> Long a)
-> (Long a -> Long a -> Long a)
-> Ord (Long a)
Long a -> Long a -> Bool
Long a -> Long a -> Ordering
Long a -> Long a -> Long a
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
forall a. Ord a => Eq (Long a)
forall a. Ord a => Long a -> Long a -> Bool
forall a. Ord a => Long a -> Long a -> Ordering
forall a. Ord a => Long a -> Long a -> Long a
min :: Long a -> Long a -> Long a
$cmin :: forall a. Ord a => Long a -> Long a -> Long a
max :: Long a -> Long a -> Long a
$cmax :: forall a. Ord a => Long a -> Long a -> Long a
>= :: Long a -> Long a -> Bool
$c>= :: forall a. Ord a => Long a -> Long a -> Bool
> :: Long a -> Long a -> Bool
$c> :: forall a. Ord a => Long a -> Long a -> Bool
<= :: Long a -> Long a -> Bool
$c<= :: forall a. Ord a => Long a -> Long a -> Bool
< :: Long a -> Long a -> Bool
$c< :: forall a. Ord a => Long a -> Long a -> Bool
compare :: Long a -> Long a -> Ordering
$ccompare :: forall a. Ord a => Long a -> Long a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Long a)
Ord, ReadPrec [Long a]
ReadPrec (Long a)
Int -> ReadS (Long a)
ReadS [Long a]
(Int -> ReadS (Long a))
-> ReadS [Long a]
-> ReadPrec (Long a)
-> ReadPrec [Long a]
-> Read (Long a)
forall a. Read a => ReadPrec [Long a]
forall a. Read a => ReadPrec (Long a)
forall a. Read a => Int -> ReadS (Long a)
forall a. Read a => ReadS [Long a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Long a]
$creadListPrec :: forall a. Read a => ReadPrec [Long a]
readPrec :: ReadPrec (Long a)
$creadPrec :: forall a. Read a => ReadPrec (Long a)
readList :: ReadS [Long a]
$creadList :: forall a. Read a => ReadS [Long a]
readsPrec :: Int -> ReadS (Long a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Long a)
Read, Int -> Long a -> ShowS
[Long a] -> ShowS
Long a -> String
(Int -> Long a -> ShowS)
-> (Long a -> String) -> ([Long a] -> ShowS) -> Show (Long a)
forall a. Show a => Int -> Long a -> ShowS
forall a. Show a => [Long a] -> ShowS
forall a. Show a => Long a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Long a] -> ShowS
$cshowList :: forall a. Show a => [Long a] -> ShowS
show :: Long a -> String
$cshow :: forall a. Show a => Long a -> String
showsPrec :: Int -> Long a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Long a -> ShowS
Show )

--------------------------------------------------------------------------------

instance (Linear l e, Arbitrary e) => Arbitrary (Short l)
  where
    arbitrary :: Gen (Short l)
arbitrary = Gen Int
forall a. Arbitrary a => Gen a
arbitrary Gen Int -> (Int -> Gen (Short l)) -> Gen (Short l)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ Int
n -> (l -> Short l
forall a. a -> Short a
Short (l -> Short l) -> ([e] -> l) -> [e] -> Short l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [e] -> l
forall l e. Linear l e => [e] -> l
fromList) ([e] -> Short l) -> Gen [e] -> Gen (Short l)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen [e]
forall a. Arbitrary a => Int -> Gen [a]
vector Int
n

instance (Linear l e, Arbitrary e) => Arbitrary (Medium l)
  where
    arbitrary :: Gen (Medium l)
arbitrary = Gen (Large Int)
forall a. Arbitrary a => Gen a
arbitrary Gen (Large Int) -> (Large Int -> Gen (Medium l)) -> Gen (Medium l)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ (Large Int
n) -> (l -> Medium l
forall a. a -> Medium a
Medium (l -> Medium l) -> ([e] -> l) -> [e] -> Medium l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [e] -> l
forall l e. Linear l e => [e] -> l
fromList) ([e] -> Medium l) -> Gen [e] -> Gen (Medium l)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen [e]
forall a. Arbitrary a => Int -> Gen [a]
vector (Int
100 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
914)

instance (Linear l e, Arbitrary e) => Arbitrary (Long l)
  where
    arbitrary :: Gen (Long l)
arbitrary = Gen (Large Int)
forall a. Arbitrary a => Gen a
arbitrary Gen (Large Int) -> (Large Int -> Gen (Long l)) -> Gen (Long l)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ (Large Int
n) -> (l -> Long l
forall a. a -> Long a
Long (l -> Long l) -> ([e] -> l) -> [e] -> Long l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [e] -> l
forall l e. Linear l e => [e] -> l
fromList) ([e] -> Long l) -> Gen [e] -> Gen (Long l)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen [e]
forall a. Arbitrary a => Int -> Gen [a]
vector (Int
1024 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
15360)

--------------------------------------------------------------------------------

-- | 'linearA' is overloaded 'vector'.
linearA :: (Linear l e, Arbitrary e) => Int -> Gen l
linearA :: Int -> Gen l
linearA =  ([e] -> l) -> Gen [e] -> Gen l
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [e] -> l
forall l e. Linear l e => [e] -> l
fromList (Gen [e] -> Gen l) -> (Int -> Gen [e]) -> Int -> Gen l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Gen [e]
forall a. Arbitrary a => Int -> Gen [a]
vector

-- | 'linearLargeA' is version of 'linearA', which generates 'Large' 'Int's.
linearLargeA :: (Linear l Int) => Int -> Gen l
linearLargeA :: Int -> Gen l
linearLargeA =
  let fromLarge :: [Large Int] -> [Int]
fromLarge = [Large Int] -> [Int]
coerce :: [Large Int] -> [Int]
  in  ([Large Int] -> l) -> Gen [Large Int] -> Gen l
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Int] -> l
forall l e. Linear l e => [e] -> l
fromList ([Int] -> l) -> ([Large Int] -> [Int]) -> [Large Int] -> l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Large Int] -> [Int]
fromLarge) (Gen [Large Int] -> Gen l)
-> (Int -> Gen [Large Int]) -> Int -> Gen l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Gen [Large Int]
forall a. Arbitrary a => Int -> Gen [a]
vector

{- |
  'orderA' returns a simple comparator that can be used to test the behavior of
  higher-order functions (for example, when comparing the results of @takeWhile@
  for different structures).
-}
orderA :: (Ord e) => Gen (e -> e -> Bool)
orderA :: Gen (e -> e -> Bool)
orderA =  [e -> e -> Bool] -> Gen (e -> e -> Bool)
forall a. [a] -> Gen a
elements [e -> e -> Bool
forall a. Ord a => a -> a -> Bool
(>), e -> e -> Bool
forall a. Ord a => a -> a -> Bool
(<), e -> e -> Bool
forall a. Ord a => a -> a -> Bool
(>=), e -> e -> Bool
forall a. Ord a => a -> a -> Bool
(<=), e -> e -> Bool
forall a. Eq a => a -> a -> Bool
(==), e -> e -> Bool
forall a. Eq a => a -> a -> Bool
(/=)]