summaryrefslogtreecommitdiff
path: root/packages/base/src/Internal/Container.hs
diff options
context:
space:
mode:
Diffstat (limited to 'packages/base/src/Internal/Container.hs')
-rw-r--r--packages/base/src/Internal/Container.hs297
1 files changed, 297 insertions, 0 deletions
diff --git a/packages/base/src/Internal/Container.hs b/packages/base/src/Internal/Container.hs
new file mode 100644
index 0000000..b08f892
--- /dev/null
+++ b/packages/base/src/Internal/Container.hs
@@ -0,0 +1,297 @@
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE UndecidableInstances #-}
6
7-----------------------------------------------------------------------------
8-- |
9-- Module : Internal.Container
10-- Copyright : (c) Alberto Ruiz 2010-14
11-- License : BSD3
12-- Maintainer : Alberto Ruiz
13-- Stability : provisional
14--
15-- Basic numeric operations on 'Vector' and 'Matrix', including conversion routines.
16--
17-- The 'Container' class is used to define optimized generic functions which work
18-- on 'Vector' and 'Matrix' with real or complex elements.
19--
20-- Some of these functions are also available in the instances of the standard
21-- numeric Haskell classes provided by "Numeric.LinearAlgebra".
22--
23-----------------------------------------------------------------------------
24
25module Internal.Container where
26
27import Internal.Vector
28import Internal.Matrix
29import Internal.Element
30import Internal.Numeric
31import Internal.Algorithms(Field,linearSolveSVD)
32
33------------------------------------------------------------------
34
35{- | Creates a real vector containing a range of values:
36
37>>> linspace 5 (-3,7::Double)
38fromList [-3.0,-0.5,2.0,4.5,7.0]@
39
40>>> linspace 5 (8,2+i) :: Vector (Complex Double)
41fromList [8.0 :+ 0.0,6.5 :+ 0.25,5.0 :+ 0.5,3.5 :+ 0.75,2.0 :+ 1.0]
42
43Logarithmic spacing can be defined as follows:
44
45@logspace n (a,b) = 10 ** linspace n (a,b)@
46-}
47linspace :: (Fractional e, Container Vector e) => Int -> (e, e) -> Vector e
48linspace 0 _ = fromList[]
49linspace 1 (a,b) = fromList[(a+b)/2]
50linspace n (a,b) = addConstant a $ scale s $ fromList $ map fromIntegral [0 .. n-1]
51 where s = (b-a)/fromIntegral (n-1)
52
53--------------------------------------------------------------------------------
54
55infixr 8 <.>
56{- | An infix synonym for 'dot'
57
58>>> vector [1,2,3,4] <.> vector [-2,0,1,1]
595.0
60
61>>> let 𝑖 = 0:+1 :: C
62>>> fromList [1+𝑖,1] <.> fromList [1,1+𝑖]
632.0 :+ 0.0
64
65-}
66
67(<.>) :: Numeric t => Vector t -> Vector t -> t
68(<.>) = dot
69
70
71
72
73
74{- | dense matrix-vector product
75
76>>> let m = (2><3) [1..]
77>>> m
78(2><3)
79 [ 1.0, 2.0, 3.0
80 , 4.0, 5.0, 6.0 ]
81
82>>> let v = vector [10,20,30]
83
84>>> m #> v
85fromList [140.0,320.0]
86
87-}
88infixr 8 #>
89(#>) :: Numeric t => Matrix t -> Vector t -> Vector t
90(#>) = mXv
91
92-- | dense matrix-vector product
93app :: Numeric t => Matrix t -> Vector t -> Vector t
94app = (#>)
95
96infixl 8 <#
97-- | dense vector-matrix product
98(<#) :: Numeric t => Vector t -> Matrix t -> Vector t
99(<#) = vXm
100
101--------------------------------------------------------------------------------
102
103class Mul a b c | a b -> c where
104 infixl 7 <>
105 -- | Matrix-matrix, matrix-vector, and vector-matrix products.
106 (<>) :: Product t => a t -> b t -> c t
107
108instance Mul Matrix Matrix Matrix where
109 (<>) = mXm
110
111instance Mul Matrix Vector Vector where
112 (<>) m v = flatten $ m <> asColumn v
113
114instance Mul Vector Matrix Vector where
115 (<>) v m = flatten $ asRow v <> m
116
117--------------------------------------------------------------------------------
118
119{- | Least squares solution of a linear system, similar to the \\ operator of Matlab\/Octave (based on linearSolveSVD)
120
121@
122a = (3><2)
123 [ 1.0, 2.0
124 , 2.0, 4.0
125 , 2.0, -1.0 ]
126@
127
128@
129v = vector [13.0,27.0,1.0]
130@
131
132>>> let x = a <\> v
133>>> x
134fromList [3.0799999999999996,5.159999999999999]
135
136>>> a #> x
137fromList [13.399999999999999,26.799999999999997,1.0]
138
139It also admits multiple right-hand sides stored as columns in a matrix.
140
141-}
142infixl 7 <\>
143(<\>) :: (LSDiv c, Field t) => Matrix t -> c t -> c t
144(<\>) = linSolve
145
146class LSDiv c
147 where
148 linSolve :: Field t => Matrix t -> c t -> c t
149
150instance LSDiv Vector
151 where
152 linSolve m v = flatten (linearSolveSVD m (reshape 1 v))
153
154instance LSDiv Matrix
155 where
156 linSolve = linearSolveSVD
157
158--------------------------------------------------------------------------------
159
160
161class Build d f c e | d -> c, c -> d, f -> e, f -> d, f -> c, c e -> f, d e -> f
162 where
163 -- |
164 -- >>> build 5 (**2) :: Vector Double
165 -- fromList [0.0,1.0,4.0,9.0,16.0]
166 --
167 -- Hilbert matrix of order N:
168 --
169 -- >>> let hilb n = build (n,n) (\i j -> 1/(i+j+1)) :: Matrix Double
170 -- >>> putStr . dispf 2 $ hilb 3
171 -- 3x3
172 -- 1.00 0.50 0.33
173 -- 0.50 0.33 0.25
174 -- 0.33 0.25 0.20
175 --
176 build :: d -> f -> c e
177
178instance Container Vector e => Build Int (e -> e) Vector e
179 where
180 build = build'
181
182instance Container Matrix e => Build (Int,Int) (e -> e -> e) Matrix e
183 where
184 build = build'
185
186--------------------------------------------------------------------------------
187
188-- @dot u v = 'udot' ('conj' u) v@
189dot :: (Numeric t) => Vector t -> Vector t -> t
190dot u v = udot (conj u) v
191
192--------------------------------------------------------------------------------
193
194optimiseMult :: Monoid (Matrix t) => [Matrix t] -> Matrix t
195optimiseMult = mconcat
196
197--------------------------------------------------------------------------------
198
199
200{- | Compute mean vector and covariance matrix of the rows of a matrix.
201
202>>> meanCov $ gaussianSample 666 1000 (fromList[4,5]) (diagl[2,3])
203(fromList [4.010341078059521,5.0197204699640405],
204(2><2)
205 [ 1.9862461923890056, -1.0127225830525157e-2
206 , -1.0127225830525157e-2, 3.0373954915729318 ])
207
208-}
209meanCov :: Matrix Double -> (Vector Double, Matrix Double)
210meanCov x = (med,cov) where
211 r = rows x
212 k = 1 / fromIntegral r
213 med = konst k r `vXm` x
214 meds = konst 1 r `outer` med
215 xc = x `sub` meds
216 cov = scale (recip (fromIntegral (r-1))) (trans xc `mXm` xc)
217
218--------------------------------------------------------------------------------
219
220sortVector :: (Ord t, Element t) => Vector t -> Vector t
221sortVector = sortV
222
223{- |
224
225>>> m <- randn 4 10
226>>> disp 2 m
2274x10
228-0.31 0.41 0.43 -0.19 -0.17 -0.23 -0.17 -1.04 -0.07 -1.24
229 0.26 0.19 0.14 0.83 -1.54 -0.09 0.37 -0.63 0.71 -0.50
230-0.11 -0.10 -1.29 -1.40 -1.04 -0.89 -0.68 0.35 -1.46 1.86
231 1.04 -0.29 0.19 -0.75 -2.20 -0.01 1.06 0.11 -2.09 -1.58
232
233>>> disp 2 $ m ?? (All, Pos $ sortIndex (m!1))
2344x10
235-0.17 -1.04 -1.24 -0.23 0.43 0.41 -0.31 -0.17 -0.07 -0.19
236-1.54 -0.63 -0.50 -0.09 0.14 0.19 0.26 0.37 0.71 0.83
237-1.04 0.35 1.86 -0.89 -1.29 -0.10 -0.11 -0.68 -1.46 -1.40
238-2.20 0.11 -1.58 -0.01 0.19 -0.29 1.04 1.06 -2.09 -0.75
239
240-}
241sortIndex :: (Ord t, Element t) => Vector t -> Vector I
242sortIndex = sortI
243
244ccompare :: (Ord t, Container c t) => c t -> c t -> c I
245ccompare = ccompare'
246
247cselect :: (Container c t) => c I -> c t -> c t -> c t -> c t
248cselect = cselect'
249
250{- | Extract elements from positions given in matrices of rows and columns.
251
252>>> r
253(3><3)
254 [ 1, 1, 1
255 , 1, 2, 2
256 , 1, 2, 3 ]
257>>> c
258(3><3)
259 [ 0, 1, 5
260 , 2, 2, 1
261 , 4, 4, 1 ]
262>>> m
263(4><6)
264 [ 0, 1, 2, 3, 4, 5
265 , 6, 7, 8, 9, 10, 11
266 , 12, 13, 14, 15, 16, 17
267 , 18, 19, 20, 21, 22, 23 ]
268
269>>> remap r c m
270(3><3)
271 [ 6, 7, 11
272 , 8, 14, 13
273 , 10, 16, 19 ]
274
275The indexes are autoconformable.
276
277>>> c'
278(3><1)
279 [ 1
280 , 2
281 , 4 ]
282>>> remap r c' m
283(3><3)
284 [ 7, 7, 7
285 , 8, 14, 14
286 , 10, 16, 22 ]
287
288-}
289remap :: Element t => Matrix I -> Matrix I -> Matrix t -> Matrix t
290remap i j m
291 | minElement i >= 0 && maxElement i < fromIntegral (rows m) &&
292 minElement j >= 0 && maxElement j < fromIntegral (cols m) = remapM i' j' m
293 | otherwise = error $ "out of range index in remap"
294 where
295 [i',j'] = conformMs [i,j]
296
297