summaryrefslogtreecommitdiff
path: root/packages/base/src/Internal
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2015-06-05 16:38:09 +0200
committerAlberto Ruiz <aruiz@um.es>2015-06-05 16:38:09 +0200
commit8b093ecca2b4e200ff191b84cb0b56a12312867b (patch)
tree222527525810a76b7b67eba5b309ae2c633e90aa /packages/base/src/Internal
parent2dae75e9d2b08a23945e936dcd5244b7f0c46107 (diff)
move convolution
Diffstat (limited to 'packages/base/src/Internal')
-rw-r--r--packages/base/src/Internal/Convolution.hs155
1 files changed, 155 insertions, 0 deletions
diff --git a/packages/base/src/Internal/Convolution.hs b/packages/base/src/Internal/Convolution.hs
new file mode 100644
index 0000000..1a70011
--- /dev/null
+++ b/packages/base/src/Internal/Convolution.hs
@@ -0,0 +1,155 @@
1{-# LANGUAGE FlexibleContexts #-}
2-----------------------------------------------------------------------------
3{- |
4Module : Internal.Convolution
5Copyright : (c) Alberto Ruiz 2012
6License : BSD3
7Maintainer : Alberto Ruiz
8Stability : provisional
9
10-}
11-----------------------------------------------------------------------------
12{-# OPTIONS_HADDOCK hide #-}
13
14module Internal.Convolution(
15 corr, conv, corrMin,
16 corr2, conv2, separable
17) where
18
19import qualified Data.Vector.Storable as SV
20import Internal.Vector
21import Internal.Matrix hiding (mat)
22import Internal.Numeric
23import Internal.Element
24import Internal.Conversion
25import Internal.Container
26
27
28vectSS :: Element t => Int -> Vector t -> Matrix t
29vectSS n v = fromRows [ subVector k n v | k <- [0 .. dim v - n] ]
30
31
32corr
33 :: (Container Vector t, Product t)
34 => Vector t -- ^ kernel
35 -> Vector t -- ^ source
36 -> Vector t
37{- ^ correlation
38
39>>> corr (fromList[1,2,3]) (fromList [1..10])
40fromList [14.0,20.0,26.0,32.0,38.0,44.0,50.0,56.0]
41
42-}
43corr ker v
44 | dim ker == 0 = konst 0 (dim v)
45 | dim ker <= dim v = vectSS (dim ker) v <> ker
46 | otherwise = error $ "corr: dim kernel ("++show (dim ker)++") > dim vector ("++show (dim v)++")"
47
48
49conv :: (Container Vector t, Product t, Num t) => Vector t -> Vector t -> Vector t
50{- ^ convolution ('corr' with reversed kernel and padded input, equivalent to polynomial product)
51
52>>> conv (fromList[1,1]) (fromList [-1,1])
53fromList [-1.0,0.0,1.0]
54
55-}
56conv ker v
57 | dim ker == 0 = konst 0 (dim v)
58 | otherwise = corr ker' v'
59 where
60 ker' = SV.reverse ker
61 v' = vjoin [z,v,z]
62 z = konst 0 (dim ker -1)
63
64corrMin :: (Container Vector t, RealElement t, Product t)
65 => Vector t
66 -> Vector t
67 -> Vector t
68-- ^ similar to 'corr', using 'min' instead of (*)
69corrMin ker v
70 | dim ker == 0 = error "corrMin: empty kernel"
71 | otherwise = minEvery ss (asRow ker) <> ones
72 where
73 minEvery a b = cond a b a a b
74 ss = vectSS (dim ker) v
75 ones = konst 1 (dim ker)
76
77
78
79matSS :: Element t => Int -> Matrix t -> [Matrix t]
80matSS dr m = map (reshape c) [ subVector (k*c) n v | k <- [0 .. r - dr] ]
81 where
82 v = flatten m
83 c = cols m
84 r = rows m
85 n = dr*c
86
87
88{- | 2D correlation (without padding)
89
90>>> disp 5 $ corr2 (konst 1 (3,3)) (ident 10 :: Matrix Double)
918x8
923 2 1 0 0 0 0 0
932 3 2 1 0 0 0 0
941 2 3 2 1 0 0 0
950 1 2 3 2 1 0 0
960 0 1 2 3 2 1 0
970 0 0 1 2 3 2 1
980 0 0 0 1 2 3 2
990 0 0 0 0 1 2 3
100
101-}
102corr2 :: Product a => Matrix a -> Matrix a -> Matrix a
103corr2 ker mat = dims
104 . concatMap (map (udot ker' . flatten) . matSS c . trans)
105 . matSS r $ mat
106 where
107 r = rows ker
108 c = cols ker
109 ker' = flatten (trans ker)
110 rr = rows mat - r + 1
111 rc = cols mat - c + 1
112 dims | rr > 0 && rc > 0 = (rr >< rc)
113 | otherwise = error $ "corr2: dim kernel ("++sz ker++") > dim matrix ("++sz mat++")"
114 sz m = show (rows m)++"x"++show (cols m)
115-- TODO check empty kernel
116
117{- | 2D convolution
118
119>>> disp 5 $ conv2 (konst 1 (3,3)) (ident 10 :: Matrix Double)
12012x12
1211 1 1 0 0 0 0 0 0 0 0 0
1221 2 2 1 0 0 0 0 0 0 0 0
1231 2 3 2 1 0 0 0 0 0 0 0
1240 1 2 3 2 1 0 0 0 0 0 0
1250 0 1 2 3 2 1 0 0 0 0 0
1260 0 0 1 2 3 2 1 0 0 0 0
1270 0 0 0 1 2 3 2 1 0 0 0
1280 0 0 0 0 1 2 3 2 1 0 0
1290 0 0 0 0 0 1 2 3 2 1 0
1300 0 0 0 0 0 0 1 2 3 2 1
1310 0 0 0 0 0 0 0 1 2 2 1
1320 0 0 0 0 0 0 0 0 1 1 1
133
134-}
135conv2
136 :: (Num (Matrix a), Product a, Container Vector a)
137 => Matrix a -- ^ kernel
138 -> Matrix a -> Matrix a
139conv2 k m
140 | empty = konst 0 (rows m + r -1, cols m + c -1)
141 | otherwise = corr2 (fliprl . flipud $ k) padded
142 where
143 padded = fromBlocks [[z,0,0]
144 ,[0,m,0]
145 ,[0,0,z]]
146 r = rows k
147 c = cols k
148 z = konst 0 (r-1,c-1)
149 empty = r == 0 || c == 0
150
151
152separable :: Element t => (Vector t -> Vector t) -> Matrix t -> Matrix t
153-- ^ matrix computation implemented as separated vector operations by rows and columns.
154separable f = fromColumns . map f . toColumns . fromRows . map f . toRows
155