content: {-# LANGUAGE TypeApplications #-}
  module ArrayFire.LAPACKSpec where
  
  import qualified ArrayFire       as A
  import           Prelude
  import           Test.Hspec
  import Test.Hspec.ApproxExpect
  
  spec :: Spec
  spec =
    describe "LAPACK spec" $ do
      it "Should have LAPACK available" $ do
        A.isLAPACKAvailable `shouldBe` True
      it "Should perform svd" $ do
        let (s,v,d) = A.svd $ A.matrix @Double (4,2) [ [1,2,3,4], [5,6,7,8] ]
        A.getDims s `shouldBe` (4,4,1,1)
        A.getDims v `shouldBe` (2,1,1,1)
        A.getDims d `shouldBe` (2,2,1,1)
      it "Should perform svd in place" $ do
        let (s,v,d) = A.svdInPlace $ A.matrix @Double (4,2) [ [1,2,3,4], [5,6,7,8] ]
        A.getDims s `shouldBe` (4,4,1,1)
        A.getDims v `shouldBe` (2,1,1,1)
        A.getDims d `shouldBe` (2,2,1,1)
      it "Should perform lu" $ do
        let (s,v,d) = A.lu $ A.matrix @Double (2,2) [[3,1],[4,2]]
        A.getDims s `shouldBe` (2,2,1,1)
        A.getDims v `shouldBe` (2,2,1,1)
        A.getDims d `shouldBe` (2,1,1,1)
      it "Should perform qr" $ do
        let (s,v,d) = A.lu $ A.matrix @Double (3,3) [[12,6,4],[-51,167,24],[4,-68,-41]]
        A.getDims s `shouldBe` (3,3,1,1)
        A.getDims v `shouldBe` (3,3,1,1)
        A.getDims d `shouldBe` (3,1,1,1)
      it "Should get determinant of Double" $ do
        let eles = [[3 A.:+ 1, 8 A.:+ 1], [4 A.:+ 1, 6 A.:+ 1]]
            (x,y) = A.det (A.matrix @(A.Complex Double) (2,2) eles)
        x `shouldBeApprox` (-14)
        let (x,y) = A.det $ A.matrix @Double (2,2) [[3,8],[4,6]]
        x `shouldBeApprox` (-14)
  --    it "Should calculate inverse" $ do
  --      let x = flip A.inverse A.None $ A.matrix @Double (2,2) [[4.0,7.0],[2.0,6.0]]
  --      x `shouldBe` A.matrix (2,2) [[0.6,-0.7],[-0.2,0.4]]
  --    it "Should calculate psuedo inverse" $ do
  --      let x = A.pinverse (A.matrix @Double (2,2) [[4,7],[2,6]]) 1.0 A.None
  --      x `shouldBe` A.matrix @Double (2,2) [[0.6,-0.2],[-0.7,0.4]]
  