1
+ {-# LANGUAGE PatternGuards #-}
1
2
-- |
2
3
-- Module : Statistics.Matrix
3
4
-- Copyright : 2011 Aleksey Khudyakov, 2014 Bryan O'Sullivan
9
10
-- we implement the necessary minimum here.
10
11
11
12
module Statistics.Matrix
12
- (
13
+ ( -- * Data types
13
14
Matrix (.. )
14
15
, Vector
15
- , fromList
16
+ -- * Conversion from/to lists/vectors
16
17
, fromVector
18
+ , fromList
19
+ , fromRowLists
20
+ , fromRows
21
+ , fromColumns
17
22
, toVector
18
23
, toList
24
+ , toRows
25
+ , toColumns
26
+ , toRowLists
27
+ -- * Other
28
+ , generate
29
+ , generateSym
30
+ , ident
31
+ , diag
19
32
, dimension
20
33
, center
21
34
, multiply
@@ -34,10 +47,21 @@ module Statistics.Matrix
34
47
) where
35
48
36
49
import Prelude hiding (exponent , map , sum )
50
+ import Control.Applicative ((<$>) )
51
+ import Control.Monad.ST
52
+ import qualified Data.Vector.Unboxed as U
53
+ import Data.Vector.Unboxed ((!) )
54
+ import qualified Data.Vector.Unboxed.Mutable as UM
55
+
37
56
import Statistics.Function (for , square )
38
57
import Statistics.Matrix.Types
58
+ import Statistics.Matrix.Mutable (unsafeNew ,unsafeWrite ,unsafeFreeze )
39
59
import Statistics.Sample.Internal (sum )
40
- import qualified Data.Vector.Unboxed as U
60
+
61
+
62
+ ----------------------------------------------------------------
63
+ -- Conversion to/from vectors/lists
64
+ ----------------------------------------------------------------
41
65
42
66
-- | Convert from a row-major list.
43
67
fromList :: Int -- ^ Number of rows.
@@ -46,6 +70,10 @@ fromList :: Int -- ^ Number of rows.
46
70
-> Matrix
47
71
fromList r c = fromVector r c . U. fromList
48
72
73
+ -- | create a matrix from a list of lists, as rows
74
+ fromRowLists :: [[Double ]] -> Matrix
75
+ fromRowLists = fromRows . fmap U. fromList
76
+
49
77
-- | Convert from a row-major vector.
50
78
fromVector :: Int -- ^ Number of rows.
51
79
-> Int -- ^ Number of columns.
@@ -56,6 +84,22 @@ fromVector r c v
56
84
| otherwise = Matrix r c 0 v
57
85
where len = U. length v
58
86
87
+ -- | create a matrix from a list of vectors, as rows
88
+ fromRows :: [Vector ] -> Matrix
89
+ fromRows xs
90
+ | [] <- xs = error " Statistics.Matrix.fromRows: empty list of rows!"
91
+ | any (/= nCol) ns = error " Statistics.Matrix.fromRows: row sizes do not match"
92
+ | nCol == 0 = error " Statistics.Matrix.fromRows: zero columns in matrix"
93
+ | otherwise = fromVector nRow nCol (U. concat xs)
94
+ where
95
+ nCol: ns = U. length <$> xs
96
+ nRow = length xs
97
+
98
+
99
+ -- | create a matrix from a list of vectors, as columns
100
+ fromColumns :: [Vector ] -> Matrix
101
+ fromColumns = transpose . fromRows
102
+
59
103
-- | Convert to a row-major flat vector.
60
104
toVector :: Matrix -> U. Vector Double
61
105
toVector (Matrix _ _ _ v) = v
@@ -64,6 +108,78 @@ toVector (Matrix _ _ _ v) = v
64
108
toList :: Matrix -> [Double ]
65
109
toList = U. toList . toVector
66
110
111
+ -- | Convert to a list of lists, as rows
112
+ toRowLists :: Matrix -> [[Double ]]
113
+ toRowLists (Matrix _ nCol _ v)
114
+ = chunks $ U. toList v
115
+ where
116
+ chunks [] = []
117
+ chunks xs = case splitAt nCol xs of
118
+ (rowE,rest) -> rowE : chunks rest
119
+
120
+
121
+ -- | Convert to a list of vectors, as rows
122
+ toRows :: Matrix -> [Vector ]
123
+ toRows (Matrix _ nCol _ v) = chunks v
124
+ where
125
+ chunks xs
126
+ | U. null xs = []
127
+ | otherwise = case U. splitAt nCol xs of
128
+ (rowE,rest) -> rowE : chunks rest
129
+
130
+ -- | Convert to a list of vectors, as columns
131
+ toColumns :: Matrix -> [Vector ]
132
+ toColumns = toRows . transpose
133
+
134
+
135
+
136
+ ----------------------------------------------------------------
137
+ -- Other
138
+ ----------------------------------------------------------------
139
+
140
+ -- | Generate matrix using function
141
+ generate :: Int -- ^ Number of rows
142
+ -> Int -- ^ Number of columns
143
+ -> (Int -> Int -> Double )
144
+ -- ^ Function which takes /row/ and /column/ as argument.
145
+ -> Matrix
146
+ generate nRow nCol f
147
+ = Matrix nRow nCol 0 $ U. generate (nRow* nCol) $ \ i ->
148
+ let (r,c) = i `quotRem` nCol in f r c
149
+
150
+ -- | Generate symmetric square matrix using function
151
+ generateSym
152
+ :: Int -- ^ Number of rows and columns
153
+ -> (Int -> Int -> Double )
154
+ -- ^ Function which takes /row/ and /column/ as argument. It must
155
+ -- be symmetric in arguments: @f i j == f j i@
156
+ -> Matrix
157
+ generateSym n f = runST $ do
158
+ m <- unsafeNew n n
159
+ for 0 n $ \ r -> do
160
+ unsafeWrite m r r (f r r)
161
+ for (r+ 1 ) n $ \ c -> do
162
+ let x = f r c
163
+ unsafeWrite m r c x
164
+ unsafeWrite m c r x
165
+ unsafeFreeze m
166
+
167
+
168
+ -- | Create the square identity matrix with given dimensions.
169
+ ident :: Int -> Matrix
170
+ ident n = diag $ U. replicate n 1.0
171
+
172
+ -- | Create a square matrix with given diagonal, other entries default to 0
173
+ diag :: Vector -> Matrix
174
+ diag v
175
+ = Matrix n n 0 $ U. create $ do
176
+ arr <- UM. replicate (n* n) 0
177
+ for 0 n $ \ i ->
178
+ UM. unsafeWrite arr (i* n + i) (v ! i)
179
+ return arr
180
+ where
181
+ n = U. length v
182
+
67
183
-- | Return the dimensions of this matrix, as a (row,column) pair.
68
184
dimension :: Matrix -> (Int , Int )
69
185
dimension (Matrix r c _ _) = (r, c)
@@ -125,6 +241,7 @@ unsafeIndex :: Matrix
125
241
-> Double
126
242
unsafeIndex = unsafeBounds U. unsafeIndex
127
243
244
+ -- | Apply function to every element of matrix
128
245
map :: (Double -> Double ) -> Matrix -> Matrix
129
246
map f (Matrix r c e v) = Matrix r c e (U. map f v)
130
247
0 commit comments