packages feed

easytensor-2.1.0.0: test/Numeric/DataFrame/SubSpaceTest.hs

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE PolyKinds           #-}
{-# LANGUAGE QuasiQuotes         #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}
-- overwise GHC dies trying to optimize 100 equal funs in each test
{-# OPTIONS_GHC -O0       #-}

module Numeric.DataFrame.SubSpaceTest (runTests) where

import Data.Typeable       (typeOf)
import Numeric.Arbitraries
import Numeric.DataFrame
import Numeric.Dimensions
import Test.QuickCheck

prop_IndexFrame0 :: Property
prop_IndexFrame0 = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeQ
    (_, ds) <- someLenAsBsQ 0
    [e| do
      df <- arbitrary @(DataFrame $t $ds)
      return $ conjoin
            [ index U df === df
            , indexOffset 0 df === df ]
      |]
  )

prop_IndexFrame1 :: Property
prop_IndexFrame1 = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeQ
    (as, bs) <- someLenAsBsQ 1
    [e| do
      i@(Idx ii :* U) <- arbitrary @(Idxs $as)
      df <- arbitrary @(DataFrame $t $(concatDimsQ as bs))
      return $ index i df === df ! ii
      |]
  )

prop_IndexFrame2 :: Property
prop_IndexFrame2 = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeQ
    (as, bs) <- someLenAsBsQ 2
    [e| do
      i@((Idx ii1) :* (Idx ii2) :* U) <- arbitrary @(Idxs $as)
      df <- arbitrary @(DataFrame $t $(concatDimsQ as bs))
      return $ index i df === df ! ii1 ! ii2
      |]
  )

prop_IndexOffset :: Property
prop_IndexOffset = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeQ
    (as, bs) <- someAsBsNQ
    [e| do
      i <- arbitrary @(Idxs $as)
      df <- arbitrary @(DataFrame $t $(concatDimsQ as bs))
      let asw = listDims (dims @($as))
          bsN = totalDim (dims @($bs))
          isw = listIdxs i
          off = fromIntegral . snd
              . foldr (\(dn, di) (tn, to) -> (tn*dn, to + tn*di) ) (bsN, 0)
              $ zip asw isw
      return $ index i df === indexOffset off df
      |]
  )

prop_Foldlr :: Property
prop_Foldlr = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeFQ
    (as, bs) <- someAsBsQ
    let asbs = concatDimsQ as bs
    [e| do
      df <- arbitrary @(DataFrame $t $asbs)
      let lim = ewfoldr' @($t) @($asbs) (max.abs) 1 df
              * ewfoldr' @($t) @($as) @($bs) (const (+1)) 0 df
          l = ewfoldl' (+) 10 df
          r = ewfoldr' (+) 0 df + 10 :: DataFrame $t $bs
      return $ approxEq lim l r
      |]
  )

prop_LazyFoldlr :: Property
prop_LazyFoldlr = property $ oneof $( aFewPropVariants $ do
    t <- someElemTypeQ
    (as, bs) <- someAsBsQ
    let asbs = concatDimsQ as bs
    [e| do
      n <- fromIntegral <$> choose (0, maxTotalDim `quot` 2)
      df <- arbitrary @(DataFrame $t $asbs)
      let S td = ewfoldr' @($t) @($as) @($bs) (const (+1)) 0 df
          l  = ewfoldl  @($t) @($as) @($bs) (limitedList) (const []) df n
          l' = ewfoldl' @($t) @($as) @($bs) (flip (:)) [] df
          r  = ewfoldr  @($t) @($as) @($bs) (flip limitedList) (const []) df n
          r' = ewfoldr' @($t) @($as) @($bs) (:) [] df

      return $
        counterexample
        ( unlines
         [ "Failed with dims:"
         , "  n:   " ++ show n
         , "  td:  " ++ show td
         , "  @as: " ++ show (typeOf $ minimalDims @($as))
         , "  @bs: " ++ show (typeOf $ minimalDims @($bs))
         ]
        ) $ conjoin
          [ if n >= td
            then l === reverse r
            else shouldErr (l === l') .&&. shouldErr (r === r')
          , take n l === take n l'
          , take n r === take n r'
          ]
      |]
  ) where
      shouldErr :: Property -> Property
      shouldErr p = ioProperty $ checkErr
        <$> quickCheckWithResult stdArgs { chatty = False }  p
      checkErr :: Result -> Property
      checkErr Failure { theException = Just _}
        = property True
      checkErr _
        = counterexample "Should have failed with undefined." False
      limitedList :: (Int -> [a]) -> a -> Int -> [a]
      limitedList f a k | k <= 0    = undefined
                        | otherwise = a : f (k - 1)


return []
runTests :: Int -> IO Bool
runTests n = $forAllProperties
  $ quickCheckWithResult stdArgs { maxSuccess = n }