1
+ {-# language AllowAmbiguousTypes #-}
1
2
{-# language FlexibleInstances #-}
2
3
{-# language TypeSynonymInstances #-}
3
4
{-# language TypeFamilies #-}
5
+ {-# language TypeApplications #-}
4
6
{-# language CPP #-}
5
7
{-# options_ghc -fno-warn-orphans #-}
6
8
7
9
module Main where
8
10
9
11
import "base" Control.Exception ( evaluate , displayException )
12
+ import "base" Control.Monad
10
13
import "base" Data.Functor ( ($>) )
11
14
import "base" Data.Int
12
15
import "base" Data.Monoid
@@ -17,6 +20,7 @@ import "base" Data.Foldable ( for_, toList )
17
20
import "base" Foreign.C.Types ( CFloat (.. ), CDouble (.. ) )
18
21
import "base" Foreign.Storable ( Storable )
19
22
import qualified "bytestring" Data.ByteString as B
23
+ import "exceptions" Control.Monad.Catch
20
24
import "lens" Control.Lens.Combinators ( view )
21
25
import "linear" Linear.Matrix ( M23 , M33 , (!*) )
22
26
import qualified "linear" Linear as L ( Metric (.. ) )
@@ -29,6 +33,7 @@ import "opencv" OpenCV.Unsafe
29
33
import "opencv" OpenCV.Internal.Core.Types.Mat ( deallocateMatM )
30
34
import "opencv" OpenCV.Internal.Exception ()
31
35
import "opencv" OpenCV.Internal.Core.Types.Mat.Marshal ( marshalDepth , unmarshalDepth )
36
+ import "random" System.Random (Random )
32
37
import qualified "repa" Data.Array.Repa as Repa
33
38
import "repa" Data.Array.Repa.Index ((:.) ((:.) ))
34
39
import "tasty" Test.Tasty
@@ -111,6 +116,7 @@ main = defaultMain $ testGroup "opencv"
111
116
[ HU. testCase " eye_m33 Word8" $ testWithMatAsVec (eye_m33 :: M33 Word8 )
112
117
, HU. testCase " eye_m33 Double" $ testWithMatAsVec (eye_m33 :: M33 Double )
113
118
, HU. testCase " 1..9 Int16" $ testWithMatAsVec (V3 (V3 1 2 3 ) (V3 4 5 6 ) (V3 7 8 9 ) :: M33 Int16 )
119
+ , QC. testProperty " gives a storable vector with row major order" $ propWithMatAsVecOrder (Proxy @ Int32 )
114
120
]
115
121
]
116
122
]
@@ -477,6 +483,48 @@ relError x y
477
483
isSmall :: CFloat -> Bool
478
484
isSmall = (>) 2e-2 . abs
479
485
486
+ genSplitNonZero :: (QC. Arbitrary a , Random a , Ord a , Num a )
487
+ => a -> QC. Gen (a , a )
488
+ genSplitNonZero n
489
+ | n <= 2 = pure (1 , 1 )
490
+ | otherwise = do
491
+ i <- QC. choose (1 , n - 1 )
492
+ pure (i, n - i)
493
+
494
+ genSplit3NonZero :: (QC. Arbitrary a , Random a , Ord a , Num a )
495
+ => a -> QC. Gen (a , a , a )
496
+ genSplit3NonZero n
497
+ | n <= 3 = pure (1 , 1 , 1 )
498
+ | otherwise = do
499
+ (a, z) <- genSplitNonZero n
500
+ (b, c) <- genSplitNonZero z
501
+ pure (a, b, c)
502
+
503
+ genDimensions :: QC. Gen (Int32 , Int32 , Int32 )
504
+ genDimensions = QC. sized $ \ n -> genSplit3NonZero (fromIntegral n)
505
+
506
+ genArray :: (QC. Arbitrary a , Integral n ) => (n , n , n ) -> QC. Gen [[[a ]]]
507
+ genArray (a, b, c) = rep a $ rep b $ rep c QC. arbitrary
508
+ where
509
+ rep x = replicateM $ fromIntegral x
510
+
511
+ propWithMatAsVecOrder :: forall proxy a .
512
+ (Eq a , Show a , Storable a , QC. Arbitrary a , ToDepth (proxy a ))
513
+ => proxy a -> QC. Property
514
+ propWithMatAsVecOrder proxy =
515
+ -- QC.forAll (QC.resize 10 genDimensions) $ \shape@(xDim, yDim, nOfChan) -> do
516
+ QC. forAll genDimensions $ \ shape@ (xDim, yDim, nOfChan) -> do
517
+ QC. forAll (genArray shape) $ \ xs -> QC. ioProperty $
518
+ case runExcept $ matFromFunc [xDim, yDim] nOfChan proxy $ ixToValue xs of
519
+ Left err -> throwM err
520
+ Right mat -> do
521
+ let vect = VS. fromList . concat $ concat xs :: VS. Vector a
522
+ vect' <- withMatAsVec mat $ \ vs -> VS. freeze =<< VS. unsafeThaw vs
523
+ pure $ vect' QC. === vect
524
+ where
525
+ ixToValue ys [x, y] c = ys !! x !! y !! c
526
+ ixToValue _ _ _ = error " ixToValue was called on a non-2D shape."
527
+
480
528
--------------------------------------------------------------------------------
481
529
482
530
eye23_8u_1c :: Mat (ShapeT [2 , 3 ]) ('S 1 ) ('S Word8 )
0 commit comments