module Vector ( tests_Vector ) where import Data.AEq import Debug.Trace import Test.Framework import Test.Framework.Providers.QuickCheck2 import Test.QuickCheck hiding ( vector ) import qualified Test.QuickCheck as QC import Numeric.LinearAlgebra.Vector( Vector ) import qualified Numeric.LinearAlgebra.Vector as V import Test.QuickCheck.LinearAlgebra( TestElem(..), Dim(..), Assocs(..), VectorPair(..) ) import qualified Test.QuickCheck.LinearAlgebra as Test import Typed tests_Vector = testGroup "Vector" [ testPropertyI "dim/fromList" prop_dim_fromList , testPropertyI "at/fromList" prop_at_fromList , testPropertyI "zero" prop_zero , testPropertyI "constant" prop_constant , testPropertyI "indices" prop_indices , testPropertyI "elems" prop_elems , testPropertyI "assocs" prop_assocs , testPropertyI "update" prop_update , testPropertyI "accum" prop_accum , testPropertyI "map" prop_map , testPropertyI "zipWith" prop_zipWith , testPropertyI "concat" prop_concat , testPropertyI "slice" prop_slice , testPropertyI "splitAt" prop_splitAt , testPropertyDZ "sumAbs" prop_sumAbs prop_sumAbs , testPropertyDZ "norm2" prop_norm2 prop_norm2 , testPropertyDZ "whichMaxAbs1" prop_whichMaxAbs1 prop_whichMaxAbs1 , testPropertyDZ "whichMaxAbs2" prop_whichMaxAbs1 prop_whichMaxAbs2 , testPropertyDZ "dot" prop_dot prop_dot , testPropertyDZ "kronecker" prop_kronecker prop_kronecker , testPropertyDZ "add" prop_add prop_add , testPropertyDZ "addWithScale" prop_addWithScale prop_addWithScale , testPropertyDZ "sub" prop_sub prop_sub , testPropertyDZ "scale" prop_scale prop_scale , testPropertyDZ "mul" prop_mul prop_mul , testPropertyDZ "negate" prop_negate prop_negate , testPropertyDZ "conjugate" prop_conjugate prop_conjugate , testPropertyDZ "abs" prop_abs prop_abs , testPropertyDZ "signum" prop_signum prop_signum , testPropertyDZ "div" prop_div prop_div , testPropertyDZ "recip" prop_recip prop_recip , testPropertyDZ "sqrt" prop_sqrt prop_sqrt , testPropertyDZ "exp" prop_exp prop_exp , testPropertyDZ "log" prop_log prop_log , testPropertyDZ "pow" prop_pow prop_pow , testPropertyDZ "sin" prop_sin prop_sin , testPropertyDZ "cos" prop_cos prop_cos , testPropertyDZ "tan" prop_tan prop_tan , testPropertyDZ "asin" prop_asin prop_asin , testPropertyDZ "acos" prop_acos prop_acos , testPropertyDZ "atan" prop_atan prop_atan , testPropertyDZ "sinh" prop_sinh prop_sinh , testPropertyDZ "cosh" prop_cosh prop_cosh , testPropertyDZ "tanh" prop_tanh prop_tanh , testPropertyDZ "asinh" prop_asinh prop_asinh , testPropertyDZ "acosh" prop_acosh prop_acosh , testPropertyDZ "atanh" prop_atanh prop_atanh ] {- abs and signum fail for complex doubles (NB, their ST Vector analogues dont!) abs: Double: [OK, passed 100 tests] Complex Double: [Failed] *** Failed! Falsifiable (after 18 tests and 1 shrink): fromList [(-6.7066276741258) :+ 6.89825617623592,(-11.603500174324518) :+ 62.02307490865834] (used seed -7536870184029858963) signum: Double: [OK, passed 100 tests] Complex Double: [Failed] *** Failed! Falsifiable (after 2 tests): fromList [6.727193397617394 :+ 2.38960475296862] (used seed -6373326149733724790) -} ------------------------- Vector Construction ------------------------------ prop_dim_fromList t (Dim n) = forAll (QC.vector n) $ \es -> let x = typed t $ V.fromList n es in V.dim x == n prop_at_fromList t (Dim n) = forAll (QC.vector n) $ \es -> let x = typed t $ V.fromList n es in and [ V.at x i === e | (i,e) <- zip [ 0..n-1 ] es ] prop_zero t (Dim n) = let x = typed t $ V.zero n in x === V.fromList n (replicate n 0) prop_constant t (Dim n) e = V.constant n e === V.fromList n (replicate n e) where _ = typed t [e] -------------------------- Accessing Vectors ------------------------------ prop_indices t x = V.indices x === [ 0..((V.dim x) - 1) ] where _ = immutableVector x _ = typed t x prop_elems t x = V.elems x === [ V.at x i | i <- V.indices x ] where _ = typed t x prop_assocs t x = V.assocs x === zip (V.indices x) (V.elems x) where _ = typed t x ------------------------- Incremental Updates ------------------------------ prop_update t (Assocs n ies) = forAll (typed t `fmap` Test.vector n) $ \x -> let x' = V.update x ies is = V.indices x is1 = (fst . unzip) ies is0 = [ i | i <- is, i `notElem` is1 ] in and $ [ V.at x' i `elem` [ e | (i',e) <- ies, i' == i ] | i <- is1 ] ++ [ V.at x' i === V.at x i | i <- is0 ] prop_accum t (Blind f) (Assocs n ies) = forAll (typed t `fmap` Test.vector n) $ \x -> let x' = V.accum f x ies in x' === V.fromList n [ foldl f e [ e' | (i',e') <- ies, i' == i] | (i,e) <- V.assocs x ] where _ = typed t $ (snd . unzip) ies -------------------------- Derived Vectors ------------------------------ prop_map t (Blind f) x = V.map f x === V.fromList (V.dim x) (map f $ V.elems x) where _ = typed t x _ = typed t $ V.map f x prop_zipWith t (Blind f) (VectorPair x y) = V.zipWith f x y === (V.fromList (V.dim x) $ zipWith f (V.elems x) (V.elems y)) where _ = typed t x _ = typed t y _ = typed t $ V.zipWith f x y prop_concat t xs = V.elems (V.concat xs) === concatMap V.elems xs where _ = typed t $ head xs ------------------------------ Vector Views-- -------------------------------- prop_slice t x = forAll (choose (0,n)) $ \n' -> forAll (choose (0,n-n')) $ \o -> V.slice o n' x === V.fromList n' (take n' $ drop o $ es) where n = V.dim x es = V.elems x _ = typed t x prop_splitAt t x = forAll (choose (0,n)) $ \k -> V.splitAt k x === (V.fromList k $ take k es, V.fromList (n-k) $ drop k es) where n = V.dim x es = V.elems x _ = typed t x -------------------------- Num Vector Operations -------------------------- prop_add t (VectorPair x y) = x `V.add` y === V.zipWith (+) x y where _ = typed t x prop_addWithScale t alpha (VectorPair x y) = V.addWithScale alpha x y ~== V.add (V.scale alpha x) y where _ = typed t x prop_sub t (VectorPair x y) = x `V.sub` y === V.zipWith (-) x y where _ = typed t x prop_scale t k x = V.scale k x ~== V.map (k*) x where _ = typed t x prop_mul t (VectorPair x y) = x `V.mul` y === V.zipWith (*) x y where _ = typed t x prop_negate t x = V.negate x === V.map negate x where _ = typed t x prop_conjugate t x = V.conjugate x === V.map conjugate x where _ = typed t x prop_abs t x = V.abs x === V.map abs x where _ = typed t x prop_signum t x = V.signum x === V.map signum x where _ = typed t x ---------------------- Fractional Vector Operations ------------------------ prop_div t (VectorPair x y) = x `V.div` y ~== V.zipWith (/) x y where _ = typed t x prop_recip t x = V.recip x ~== V.map (1/) x where _ = typed t x ---------------------- Floating Vector Operations ------------------------ prop_exp t x = V.exp x ~== V.map exp x where _ = typed t x prop_sqrt t x = V.sqrt x ~== V.map sqrt x where _ = typed t x prop_log t x = V.log x ~== V.map log x where _ = typed t x prop_pow t (VectorPair x y) = x `V.pow` y ~== V.zipWith (**) x y where _ = typed t x prop_sin t x = V.sin x ~== V.map sin x where _ = typed t x prop_cos t x = V.cos x ~== V.map cos x where _ = typed t x prop_tan t x = V.tan x ~== V.map tan x where _ = typed t x prop_asin t x = -- trace (show (V.asin x) ++ "\n" ++ (show $ V.map asin x)) $ V.asin x ~== V.map asin x where _ = typed t x prop_acos t x = V.acos x ~== V.map acos x where _ = typed t x prop_atan t x = V.atan x ~== V.map atan x where _ = typed t x prop_sinh t x = V.sinh x ~== V.map sinh x where _ = typed t x prop_cosh t x = V.cosh x ~== V.map cosh x where _ = typed t x prop_tanh t x = V.tanh x ~== V.map tanh x where _ = typed t x prop_asinh t x = -- trace (show (V.asinh x) ++ "\n" ++ (show $ V.map asinh x)) $ V.asinh x ~== V.map asinh x where _ = typed t x prop_acosh t x = V.acosh x ~== V.map acosh x where _ = typed t x prop_atanh t x = V.atanh x ~== V.map atanh x where _ = typed t x -------------------------- Vector Properties --------------------------------- prop_sumAbs t x = V.sumAbs x ~== (sum $ map norm1 $ V.elems x) where _ = typed t x prop_norm2 t x = V.norm2 x ~== (sqrt $ sum $ map (^^2) $ map norm $ V.elems x) where _ = typed t x prop_whichMaxAbs1 t x = (V.dim x > 0) && all (not . isNaN) (map norm1 $ V.elems x) ==> V.at x i === e where (i,e) = V.whichMaxAbs x _ = typed t x prop_whichMaxAbs2 t x = (V.dim x > 0) && all (not . isNaN) (map norm1 $ V.elems x) ==> all (<= norm1 e) $ map norm1 (V.elems x) where (_,e) = V.whichMaxAbs x _ = typed t x prop_dot t (VectorPair x y) = V.dot x y ~== sum (V.elems (x * conj y)) where conj = V.conjugate (*) = V.mul _ = typed t x prop_kronecker t x y = x `V.kronecker` y ~== V.fromList (V.dim x * V.dim y) [ e*f | e <- V.elems x, f <- V.elems y ] where _ = typed t x