packages feed

tensors-0.1.3: test/Spec.hs

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE PolyKinds           #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies        #-}

module Main where

import           Data.Proxy
import           Data.Reflection
import           Data.Tensor
import           Data.Tensor.Type
import           GHC.Exts         (fromList)
import           GHC.TypeLits
import           Test.Hspec
import           Test.QuickCheck
import           Unsafe.Coerce

main = hspec spec

spec :: Spec
spec = do
  describe "Data.Tensor" specTensor

newtype MagicNats r = MagicNats (forall (n :: [Nat]). HasShape n => Proxy n -> r)
reifyNats :: forall r. [Int] -> (forall (n :: [Nat]). HasShape n => Proxy n -> r) -> r
reifyNats n k = unsafeCoerce (MagicNats k :: MagicNats r) n Proxy

instance HasShape a => Reifies (a::[Nat]) [Int] where
  reflect _ = unShape (toShape :: SShape a)

normalize :: [Int] -> [Int]
normalize = take 5 . fmap (`mod` 10)

specTensor = do
  context "viToti" $ do
    it "quickCheck" $ property $
      \s0 -> let s = normalize s0
                 n = [0..product s - 1]
            in fmap (tiTovi s . viToti s) n == n
    it "index" $ property $
      \i -> let i' = mod i 1000 + 1 :: Int
                go :: forall (s :: Nat). KnownNat s => Int -> Proxy s -> Bool
                go x _ = trace (identity :: Tensor '[s,s] Int) == x
            in reifyNat (toInteger i') (go i')
    it "det" $ property $
      \s0 -> let s = (if null s0 then [1..16] else take 16 $ cycle s0) :: [Int]
                 a = fromList s :: Tensor '[4,4] Int
              in det a == det' a
    it "identity" $ property $
      \i s0 -> let n = mod i 20 + 1 :: Int
                   m = n * n
                   s = if null s0 then [1..m] else take m $ cycle s0
                   go :: forall (n :: Nat). KnownNat n => [Int] -> Proxy n -> Bool
                   go v _ =
                     let a = fromList v :: Tensor '[n,n] Int
                         idt = identity :: Tensor '[n,n] Int
                     in a `dot` idt == idt `dot` a
               in reifyNat (toInteger n) (go s)