summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Data/Packed/Internal/Common.hs8
-rw-r--r--lib/Data/Packed/Internal/Matrix.hs11
-rw-r--r--lib/Data/Packed/Matrix.hs59
3 files changed, 60 insertions, 18 deletions
diff --git a/lib/Data/Packed/Internal/Common.hs b/lib/Data/Packed/Internal/Common.hs
index 629016d..972cd7d 100644
--- a/lib/Data/Packed/Internal/Common.hs
+++ b/lib/Data/Packed/Internal/Common.hs
@@ -18,7 +18,7 @@ module Data.Packed.Internal.Common(
18 Adapt, 18 Adapt,
19 app1, app2, app3, app4, 19 app1, app2, app3, app4,
20 (//), check, 20 (//), check,
21 partit, common, 21 partit, common, compatdim,
22 fi 22 fi
23) where 23) where
24 24
@@ -41,6 +41,12 @@ common f = commonval . map f where
41 commonval [a] = Just a 41 commonval [a] = Just a
42 commonval (a:b:xs) = if a==b then commonval (b:xs) else Nothing 42 commonval (a:b:xs) = if a==b then commonval (b:xs) else Nothing
43 43
44-- | common value with \"adaptable\" 1
45compatdim :: [Int] -> Maybe Int
46compatdim [] = Nothing
47compatdim [a] = Just a
48compatdim (a:b:xs) = if a==b || a==1 || b==1 then compatdim (max a b:xs) else Nothing
49
44-- | postfix function application (@flip ($)@) 50-- | postfix function application (@flip ($)@)
45(//) :: x -> (x -> y) -> y 51(//) :: x -> (x -> y) -> y
46infixl 0 // 52infixl 0 //
diff --git a/lib/Data/Packed/Internal/Matrix.hs b/lib/Data/Packed/Internal/Matrix.hs
index a220f1a..33c9324 100644
--- a/lib/Data/Packed/Internal/Matrix.hs
+++ b/lib/Data/Packed/Internal/Matrix.hs
@@ -135,11 +135,16 @@ type Mt t s = Int -> Int -> Ptr t -> s
135toLists :: (Element t) => Matrix t -> [[t]] 135toLists :: (Element t) => Matrix t -> [[t]]
136toLists m = partit (cols m) . toList . flatten $ m 136toLists m = partit (cols m) . toList . flatten $ m
137 137
138-- | creates a Matrix from a list of vectors 138-- | Create a matrix from a list of vectors.
139-- All vectors must have the same dimension,
140-- or dimension 1, which is are automatically expanded.
139fromRows :: Element t => [Vector t] -> Matrix t 141fromRows :: Element t => [Vector t] -> Matrix t
140fromRows vs = case common dim vs of 142fromRows vs = case compatdim (map dim vs) of
141 Nothing -> error "fromRows applied to [] or to vectors with different sizes" 143 Nothing -> error "fromRows applied to [] or to vectors with different sizes"
142 Just c -> reshape c (join vs) 144 Just c -> reshape c . join . map (adapt c) $ vs
145 where
146 adapt c v | dim v == c = v
147 | otherwise = constantD (v@>0) c
143 148
144-- | extracts the rows of a matrix as a list of vectors 149-- | extracts the rows of a matrix as a list of vectors
145toRows :: Element t => Matrix t -> [Vector t] 150toRows :: Element t => Matrix t -> [Vector t]
diff --git a/lib/Data/Packed/Matrix.hs b/lib/Data/Packed/Matrix.hs
index bd7cb69..912e1c6 100644
--- a/lib/Data/Packed/Matrix.hs
+++ b/lib/Data/Packed/Matrix.hs
@@ -44,28 +44,59 @@ import Text.Printf(printf)
44-- | creates a matrix from a vertical list of matrices 44-- | creates a matrix from a vertical list of matrices
45joinVert :: Element t => [Matrix t] -> Matrix t 45joinVert :: Element t => [Matrix t] -> Matrix t
46joinVert ms = case common cols ms of 46joinVert ms = case common cols ms of
47 Nothing -> error "joinVert on matrices with different number of columns" 47 Nothing -> error "(impossible) joinVert on matrices with different number of columns"
48 Just c -> reshape c $ join (map flatten ms) 48 Just c -> reshape c $ join (map flatten ms)
49 49
50-- | creates a matrix from a horizontal list of matrices 50-- | creates a matrix from a horizontal list of matrices
51joinHoriz :: Element t => [Matrix t] -> Matrix t 51joinHoriz :: Element t => [Matrix t] -> Matrix t
52joinHoriz ms = trans. joinVert . map trans $ ms 52joinHoriz ms = trans. joinVert . map trans $ ms
53 53
54{- | Creates a matrix from blocks given as a list of lists of matrices: 54{- | Creates a matrix from blocks given as a list of lists of matrices.
55 55
56@\> let a = 'diag' $ 'fromList' [5,7,2] 56Single row/column components are automatically expanded to match the
57\> let b = 'reshape' 4 $ 'constant' (-1) 12 57corresponding common row and column:
58\> fromBlocks [[a,b],[b,a]] 58
59(6><7) 59@\> let disp = putStr . dispf 2
60 [ 5.0, 0.0, 0.0, -1.0, -1.0, -1.0, -1.0 60\> let vector xs = fromList xs :: Vector Double
61 , 0.0, 7.0, 0.0, -1.0, -1.0, -1.0, -1.0 61\> let diagl = diag . vector
62 , 0.0, 0.0, 2.0, -1.0, -1.0, -1.0, -1.0 62\> let rowm = asRow . vector
63 , -1.0, -1.0, -1.0, -1.0, 5.0, 0.0, 0.0 63\> disp $ fromBlocks [[ident 5, 7, rowm[10,20]], [3, diagl[1,2,3], 0]]
64 , -1.0, -1.0, -1.0, -1.0, 0.0, 7.0, 0.0 648x10
65 , -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 2.0 ]@ 651 0 0 0 0 7 7 7 10 20
660 1 0 0 0 7 7 7 10 20
670 0 1 0 0 7 7 7 10 20
680 0 0 1 0 7 7 7 10 20
690 0 0 0 1 7 7 7 10 20
703 3 3 3 3 1 0 0 0 0
713 3 3 3 3 0 2 0 0 0
723 3 3 3 3 0 0 3 0 0@
66-} 73-}
67fromBlocks :: Element t => [[Matrix t]] -> Matrix t 74fromBlocks :: Element t => [[Matrix t]] -> Matrix t
68fromBlocks = joinVert . map joinHoriz 75fromBlocks = fromBlocksRaw . adaptBlocks
76
77fromBlocksRaw mms = joinVert . map joinHoriz $ mms
78
79adaptBlocks ms = ms' where
80 bc = case common length ms of
81 Just c -> c
82 Nothing -> error "fromBlocks requires rectangular [[Matrix]]"
83 rs = map (compatdim . map rows) ms
84 cs = map (compatdim . map cols) (transpose ms)
85 szs = sequence [rs,cs]
86 ms' = partit bc $ zipWith g szs (concat ms)
87
88 g [Just nr,Just nc] m
89 | nr == r && nc == c = m
90 | r == 1 && c == 1 = reshape nc (constant x (nr*nc))
91 | r == 1 = fromRows (replicate nr (flatten m))
92 | otherwise = fromColumns (replicate nc (flatten m))
93 where
94 r = rows m
95 c = cols m
96 x = m@@>(0,0)
97 g _ _ = error "inconsistent dimensions in fromBlocks"
98
99-----------------------------------------------------------
69 100
70-- | Reverse rows 101-- | Reverse rows
71flipud :: Element t => Matrix t -> Matrix t 102flipud :: Element t => Matrix t -> Matrix t