summaryrefslogtreecommitdiff
path: root/lib/Numeric/ContainerBoot.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/ContainerBoot.hs')
-rw-r--r--lib/Numeric/ContainerBoot.hs575
1 files changed, 575 insertions, 0 deletions
diff --git a/lib/Numeric/ContainerBoot.hs b/lib/Numeric/ContainerBoot.hs
new file mode 100644
index 0000000..1284639
--- /dev/null
+++ b/lib/Numeric/ContainerBoot.hs
@@ -0,0 +1,575 @@
1{-# LANGUAGE TypeFamilies #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE FunctionalDependencies #-}
6{-# LANGUAGE UndecidableInstances #-}
7
8-----------------------------------------------------------------------------
9-- |
10-- Module : Numeric.ContainerBoot
11-- Copyright : (c) Alberto Ruiz 2010
12-- License : GPL-style
13--
14-- Maintainer : Alberto Ruiz <aruiz@um.es>
15-- Stability : provisional
16-- Portability : portable
17--
18-- Module to avoid cyclyc dependencies.
19--
20-----------------------------------------------------------------------------
21
22module Numeric.ContainerBoot (
23 -- * Basic functions
24 ident, diag, ctrans,
25 -- * Generic operations
26 Container(..),
27 -- * Matrix product and related functions
28 Product(..),
29 mXm,mXv,vXm,
30 outer, kronecker,
31 -- * Element conversion
32 Convert(..),
33 Complexable(),
34 RealElement(),
35
36 RealOf, ComplexOf, SingleOf, DoubleOf,
37
38 IndexOf,
39 module Data.Complex,
40 -- * Experimental
41 build', konst',
42 -- * Deprecated
43 (.*),(*/),(<|>),(<->),
44 vectorMax,vectorMin,
45 vectorMaxIndex, vectorMinIndex
46) where
47
48import Data.Packed
49import Numeric.Conversion
50import Data.Packed.Internal
51import Numeric.GSL.Vector
52
53import Data.Complex
54import Control.Monad(ap)
55
56import Numeric.LinearAlgebra.LAPACK(multiplyR,multiplyC,multiplyF,multiplyQ)
57
58import System.IO.Unsafe
59
60-------------------------------------------------------------------
61
62type family IndexOf c
63
64type instance IndexOf Vector = Int
65type instance IndexOf Matrix = (Int,Int)
66
67type family ArgOf c a
68
69type instance ArgOf Vector a = a -> a
70type instance ArgOf Matrix a = a -> a -> a
71
72-------------------------------------------------------------------
73
74-- | Basic element-by-element functions for numeric containers
75class (Complexable c, Fractional e, Element e) => Container c e where
76 -- | create a structure with a single element
77 scalar :: e -> c e
78 -- | complex conjugate
79 conj :: c e -> c e
80 scale :: e -> c e -> c e
81 -- | scale the element by element reciprocal of the object:
82 --
83 -- @scaleRecip 2 (fromList [5,i]) == 2 |> [0.4 :+ 0.0,0.0 :+ (-2.0)]@
84 scaleRecip :: e -> c e -> c e
85 addConstant :: e -> c e -> c e
86 add :: c e -> c e -> c e
87 sub :: c e -> c e -> c e
88 -- | element by element multiplication
89 mul :: c e -> c e -> c e
90 -- | element by element division
91 divide :: c e -> c e -> c e
92 equal :: c e -> c e -> Bool
93 --
94 -- | cannot implement instance Functor because of Element class constraint
95 cmap :: (Element a, Element b) => (a -> b) -> c a -> c b
96 -- | constant structure of given size
97 konst :: e -> IndexOf c -> c e
98 -- | create a structure using a function
99 --
100 -- Hilbert matrix of order N:
101 --
102 -- @hilb n = build (n,n) (\\i j -> 1/(i+j+1))@
103 build :: IndexOf c -> (ArgOf c e) -> c e
104 --build :: BoundsOf f -> f -> (ContainerOf f) e
105 --
106 -- | indexing function
107 atIndex :: c e -> IndexOf c -> e
108 -- | index of min element
109 minIndex :: c e -> IndexOf c
110 -- | index of max element
111 maxIndex :: c e -> IndexOf c
112 -- | value of min element
113 minElement :: c e -> e
114 -- | value of max element
115 maxElement :: c e -> e
116 -- the C functions sumX/prodX are twice as fast as using foldVector
117 -- | the sum of elements (faster than using @fold@)
118 sumElements :: c e -> e
119 -- | the product of elements (faster than using @fold@)
120 prodElements :: c e -> e
121
122--------------------------------------------------------------------------
123
124instance Container Vector Float where
125 scale = vectorMapValF Scale
126 scaleRecip = vectorMapValF Recip
127 addConstant = vectorMapValF AddConstant
128 add = vectorZipF Add
129 sub = vectorZipF Sub
130 mul = vectorZipF Mul
131 divide = vectorZipF Div
132 equal u v = dim u == dim v && maxElement (vectorMapF Abs (sub u v)) == 0.0
133 scalar x = fromList [x]
134 konst = constantD
135 build = buildV
136 conj = id
137 cmap = mapVector
138 atIndex = (@>)
139 minIndex = round . toScalarF MinIdx
140 maxIndex = round . toScalarF MaxIdx
141 minElement = toScalarF Min
142 maxElement = toScalarF Max
143 sumElements = sumF
144 prodElements = prodF
145
146instance Container Vector Double where
147 scale = vectorMapValR Scale
148 scaleRecip = vectorMapValR Recip
149 addConstant = vectorMapValR AddConstant
150 add = vectorZipR Add
151 sub = vectorZipR Sub
152 mul = vectorZipR Mul
153 divide = vectorZipR Div
154 equal u v = dim u == dim v && maxElement (vectorMapR Abs (sub u v)) == 0.0
155 scalar x = fromList [x]
156 konst = constantD
157 build = buildV
158 conj = id
159 cmap = mapVector
160 atIndex = (@>)
161 minIndex = round . toScalarR MinIdx
162 maxIndex = round . toScalarR MaxIdx
163 minElement = toScalarR Min
164 maxElement = toScalarR Max
165 sumElements = sumR
166 prodElements = prodR
167
168instance Container Vector (Complex Double) where
169 scale = vectorMapValC Scale
170 scaleRecip = vectorMapValC Recip
171 addConstant = vectorMapValC AddConstant
172 add = vectorZipC Add
173 sub = vectorZipC Sub
174 mul = vectorZipC Mul
175 divide = vectorZipC Div
176 equal u v = dim u == dim v && maxElement (mapVector magnitude (sub u v)) == 0.0
177 scalar x = fromList [x]
178 konst = constantD
179 build = buildV
180 conj = conjugateC
181 cmap = mapVector
182 atIndex = (@>)
183 minIndex = minIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)
184 maxIndex = maxIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)
185 minElement = ap (@>) minIndex
186 maxElement = ap (@>) maxIndex
187 sumElements = sumC
188 prodElements = prodC
189
190instance Container Vector (Complex Float) where
191 scale = vectorMapValQ Scale
192 scaleRecip = vectorMapValQ Recip
193 addConstant = vectorMapValQ AddConstant
194 add = vectorZipQ Add
195 sub = vectorZipQ Sub
196 mul = vectorZipQ Mul
197 divide = vectorZipQ Div
198 equal u v = dim u == dim v && maxElement (mapVector magnitude (sub u v)) == 0.0
199 scalar x = fromList [x]
200 konst = constantD
201 build = buildV
202 conj = conjugateQ
203 cmap = mapVector
204 atIndex = (@>)
205 minIndex = minIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)
206 maxIndex = maxIndex . fst . fromComplex . (zipVectorWith (*) `ap` mapVector conjugate)
207 minElement = ap (@>) minIndex
208 maxElement = ap (@>) maxIndex
209 sumElements = sumQ
210 prodElements = prodQ
211
212---------------------------------------------------------------
213
214instance (Container Vector a) => Container Matrix a where
215 scale x = liftMatrix (scale x)
216 scaleRecip x = liftMatrix (scaleRecip x)
217 addConstant x = liftMatrix (addConstant x)
218 add = liftMatrix2 add
219 sub = liftMatrix2 sub
220 mul = liftMatrix2 mul
221 divide = liftMatrix2 divide
222 equal a b = cols a == cols b && flatten a `equal` flatten b
223 scalar x = (1><1) [x]
224 konst v (r,c) = reshape c (konst v (r*c))
225 build = buildM
226 conj = liftMatrix conj
227 cmap f = liftMatrix (mapVector f)
228 atIndex = (@@>)
229 minIndex m = let (r,c) = (rows m,cols m)
230 i = (minIndex $ flatten m)
231 in (i `div` c,i `mod` c)
232 maxIndex m = let (r,c) = (rows m,cols m)
233 i = (maxIndex $ flatten m)
234 in (i `div` c,i `mod` c)
235 minElement = ap (@@>) minIndex
236 maxElement = ap (@@>) maxIndex
237 sumElements = sumElements . flatten
238 prodElements = prodElements . flatten
239
240----------------------------------------------------
241
242-- | Matrix product and related functions
243class Element e => Product e where
244 -- | matrix product
245 multiply :: Matrix e -> Matrix e -> Matrix e
246 -- | dot (inner) product
247 dot :: Vector e -> Vector e -> e
248 -- | sum of absolute value of elements (differs in complex case from @norm1@)
249 absSum :: Vector e -> RealOf e
250 -- | sum of absolute value of elements
251 norm1 :: Vector e -> RealOf e
252 -- | euclidean norm
253 norm2 :: Vector e -> RealOf e
254 -- | element of maximum magnitude
255 normInf :: Vector e -> RealOf e
256
257instance Product Float where
258 norm2 = toScalarF Norm2
259 absSum = toScalarF AbsSum
260 dot = dotF
261 norm1 = toScalarF AbsSum
262 normInf = maxElement . vectorMapF Abs
263 multiply = multiplyF
264
265instance Product Double where
266 norm2 = toScalarR Norm2
267 absSum = toScalarR AbsSum
268 dot = dotR
269 norm1 = toScalarR AbsSum
270 normInf = maxElement . vectorMapR Abs
271 multiply = multiplyR
272
273instance Product (Complex Float) where
274 norm2 = toScalarQ Norm2
275 absSum = toScalarQ AbsSum
276 dot = dotQ
277 norm1 = sumElements . fst . fromComplex . vectorMapQ Abs
278 normInf = maxElement . fst . fromComplex . vectorMapQ Abs
279 multiply = multiplyQ
280
281instance Product (Complex Double) where
282 norm2 = toScalarC Norm2
283 absSum = toScalarC AbsSum
284 dot = dotC
285 norm1 = sumElements . fst . fromComplex . vectorMapC Abs
286 normInf = maxElement . fst . fromComplex . vectorMapC Abs
287 multiply = multiplyC
288
289----------------------------------------------------------
290
291-- synonym for matrix product
292mXm :: Product t => Matrix t -> Matrix t -> Matrix t
293mXm = multiply
294
295-- matrix - vector product
296mXv :: Product t => Matrix t -> Vector t -> Vector t
297mXv m v = flatten $ m `mXm` (asColumn v)
298
299-- vector - matrix product
300vXm :: Product t => Vector t -> Matrix t -> Vector t
301vXm v m = flatten $ (asRow v) `mXm` m
302
303{- | Outer product of two vectors.
304
305@\> 'fromList' [1,2,3] \`outer\` 'fromList' [5,2,3]
306(3><3)
307 [ 5.0, 2.0, 3.0
308 , 10.0, 4.0, 6.0
309 , 15.0, 6.0, 9.0 ]@
310-}
311outer :: (Product t) => Vector t -> Vector t -> Matrix t
312outer u v = asColumn u `multiply` asRow v
313
314{- | Kronecker product of two matrices.
315
316@m1=(2><3)
317 [ 1.0, 2.0, 0.0
318 , 0.0, -1.0, 3.0 ]
319m2=(4><3)
320 [ 1.0, 2.0, 3.0
321 , 4.0, 5.0, 6.0
322 , 7.0, 8.0, 9.0
323 , 10.0, 11.0, 12.0 ]@
324
325@\> kronecker m1 m2
326(8><9)
327 [ 1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 0.0, 0.0, 0.0
328 , 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 0.0, 0.0, 0.0
329 , 7.0, 8.0, 9.0, 14.0, 16.0, 18.0, 0.0, 0.0, 0.0
330 , 10.0, 11.0, 12.0, 20.0, 22.0, 24.0, 0.0, 0.0, 0.0
331 , 0.0, 0.0, 0.0, -1.0, -2.0, -3.0, 3.0, 6.0, 9.0
332 , 0.0, 0.0, 0.0, -4.0, -5.0, -6.0, 12.0, 15.0, 18.0
333 , 0.0, 0.0, 0.0, -7.0, -8.0, -9.0, 21.0, 24.0, 27.0
334 , 0.0, 0.0, 0.0, -10.0, -11.0, -12.0, 30.0, 33.0, 36.0 ]@
335-}
336kronecker :: (Product t) => Matrix t -> Matrix t -> Matrix t
337kronecker a b = fromBlocks
338 . splitEvery (cols a)
339 . map (reshape (cols b))
340 . toRows
341 $ flatten a `outer` flatten b
342
343-------------------------------------------------------------------
344
345
346class Convert t where
347 real :: Container c t => c (RealOf t) -> c t
348 complex :: Container c t => c t -> c (ComplexOf t)
349 single :: Container c t => c t -> c (SingleOf t)
350 double :: Container c t => c t -> c (DoubleOf t)
351 toComplex :: (Container c t, RealElement t) => (c t, c t) -> c (Complex t)
352 fromComplex :: (Container c t, RealElement t) => c (Complex t) -> (c t, c t)
353
354
355instance Convert Double where
356 real = id
357 complex = comp'
358 single = single'
359 double = id
360 toComplex = toComplex'
361 fromComplex = fromComplex'
362
363instance Convert Float where
364 real = id
365 complex = comp'
366 single = id
367 double = double'
368 toComplex = toComplex'
369 fromComplex = fromComplex'
370
371instance Convert (Complex Double) where
372 real = comp'
373 complex = id
374 single = single'
375 double = id
376 toComplex = toComplex'
377 fromComplex = fromComplex'
378
379instance Convert (Complex Float) where
380 real = comp'
381 complex = id
382 single = id
383 double = double'
384 toComplex = toComplex'
385 fromComplex = fromComplex'
386
387-------------------------------------------------------------------
388
389type family RealOf x
390
391type instance RealOf Double = Double
392type instance RealOf (Complex Double) = Double
393
394type instance RealOf Float = Float
395type instance RealOf (Complex Float) = Float
396
397type family ComplexOf x
398
399type instance ComplexOf Double = Complex Double
400type instance ComplexOf (Complex Double) = Complex Double
401
402type instance ComplexOf Float = Complex Float
403type instance ComplexOf (Complex Float) = Complex Float
404
405type family SingleOf x
406
407type instance SingleOf Double = Float
408type instance SingleOf Float = Float
409
410type instance SingleOf (Complex a) = Complex (SingleOf a)
411
412type family DoubleOf x
413
414type instance DoubleOf Double = Double
415type instance DoubleOf Float = Double
416
417type instance DoubleOf (Complex a) = Complex (DoubleOf a)
418
419type family ElementOf c
420
421type instance ElementOf (Vector a) = a
422type instance ElementOf (Matrix a) = a
423
424------------------------------------------------------------
425
426conjugateAux fun x = unsafePerformIO $ do
427 v <- createVector (dim x)
428 app2 fun vec x vec v "conjugateAux"
429 return v
430
431conjugateQ :: Vector (Complex Float) -> Vector (Complex Float)
432conjugateQ = conjugateAux c_conjugateQ
433foreign import ccall "conjugateQ" c_conjugateQ :: TQVQV
434
435conjugateC :: Vector (Complex Double) -> Vector (Complex Double)
436conjugateC = conjugateAux c_conjugateC
437foreign import ccall "conjugateC" c_conjugateC :: TCVCV
438
439----------------------------------------------------
440
441{-# DEPRECATED (.*) "use scale a x or scalar a * x" #-}
442
443-- -- | @x .* a = scale x a@
444-- (.*) :: (Linear c a) => a -> c a -> c a
445infixl 7 .*
446a .* x = scale a x
447
448----------------------------------------------------
449
450{-# DEPRECATED (*/) "use scale (recip a) x or x / scalar a" #-}
451
452-- -- | @a *\/ x = scale (recip x) a@
453-- (*/) :: (Linear c a) => c a -> a -> c a
454infixl 7 */
455v */ x = scale (recip x) v
456
457
458------------------------------------------------
459
460{-# DEPRECATED (<|>) "define operator a & b = fromBlocks[[a,b]] and use asRow/asColumn to join vectors" #-}
461{-# DEPRECATED (<->) "define operator a // b = fromBlocks[[a],[b]] and use asRow/asColumn to join vectors" #-}
462
463class Joinable a b where
464 joinH :: Element t => a t -> b t -> Matrix t
465 joinV :: Element t => a t -> b t -> Matrix t
466
467instance Joinable Matrix Matrix where
468 joinH m1 m2 = fromBlocks [[m1,m2]]
469 joinV m1 m2 = fromBlocks [[m1],[m2]]
470
471instance Joinable Matrix Vector where
472 joinH m v = joinH m (asColumn v)
473 joinV m v = joinV m (asRow v)
474
475instance Joinable Vector Matrix where
476 joinH v m = joinH (asColumn v) m
477 joinV v m = joinV (asRow v) m
478
479infixl 4 <|>
480infixl 3 <->
481
482{-- - | Horizontal concatenation of matrices and vectors:
483
484@> (ident 3 \<-\> 3 * ident 3) \<|\> fromList [1..6.0]
485(6><4)
486 [ 1.0, 0.0, 0.0, 1.0
487 , 0.0, 1.0, 0.0, 2.0
488 , 0.0, 0.0, 1.0, 3.0
489 , 3.0, 0.0, 0.0, 4.0
490 , 0.0, 3.0, 0.0, 5.0
491 , 0.0, 0.0, 3.0, 6.0 ]@
492-}
493-- (<|>) :: (Element t, Joinable a b) => a t -> b t -> Matrix t
494a <|> b = joinH a b
495
496-- -- | Vertical concatenation of matrices and vectors.
497-- (<->) :: (Element t, Joinable a b) => a t -> b t -> Matrix t
498a <-> b = joinV a b
499
500-------------------------------------------------------------------
501
502{-# DEPRECATED vectorMin "use minElement" #-}
503vectorMin :: (Container Vector t, Element t) => Vector t -> t
504vectorMin = minElement
505
506{-# DEPRECATED vectorMax "use maxElement" #-}
507vectorMax :: (Container Vector t, Element t) => Vector t -> t
508vectorMax = maxElement
509
510
511{-# DEPRECATED vectorMaxIndex "use minIndex" #-}
512vectorMaxIndex :: Vector Double -> Int
513vectorMaxIndex = round . toScalarR MaxIdx
514
515{-# DEPRECATED vectorMinIndex "use maxIndex" #-}
516vectorMinIndex :: Vector Double -> Int
517vectorMinIndex = round . toScalarR MinIdx
518
519-----------------------------------------------------
520
521class Build f where
522 build' :: BoundsOf f -> f -> ContainerOf f
523
524type family BoundsOf x
525
526type instance BoundsOf (a->a) = Int
527type instance BoundsOf (a->a->a) = (Int,Int)
528
529type family ContainerOf x
530
531type instance ContainerOf (a->a) = Vector a
532type instance ContainerOf (a->a->a) = Matrix a
533
534instance (Element a, Num a) => Build (a->a) where
535 build' = buildV
536
537instance (Element a, Num a) => Build (a->a->a) where
538 build' = buildM
539
540buildM (rc,cc) f = fromLists [ [f r c | c <- cs] | r <- rs ]
541 where rs = map fromIntegral [0 .. (rc-1)]
542 cs = map fromIntegral [0 .. (cc-1)]
543
544buildV n f = fromList [f k | k <- ks]
545 where ks = map fromIntegral [0 .. (n-1)]
546
547----------------------------------------------------
548-- experimental
549
550class Konst s where
551 konst' :: Element e => e -> s -> ContainerOf' s e
552
553type family ContainerOf' x y
554
555type instance ContainerOf' Int a = Vector a
556type instance ContainerOf' (Int,Int) a = Matrix a
557
558instance Konst Int where
559 konst' = constantD
560
561instance Konst (Int,Int) where
562 konst' k (r,c) = reshape c $ konst' k (r*c)
563
564--------------------------------------------------------
565-- | conjugate transpose
566ctrans :: (Container Vector e, Element e) => Matrix e -> Matrix e
567ctrans = liftMatrix conj . trans
568
569-- | Creates a square matrix with a given diagonal.
570diag :: (Num a, Element a) => Vector a -> Matrix a
571diag v = diagRect 0 v n n where n = dim v
572
573-- | creates the identity matrix of given dimension
574ident :: (Num a, Element a) => Int -> Matrix a
575ident n = diag (constantD 1 n)