packages feed

HNumeric (empty) → 0.2.0.0

raw patch · 9 files changed

+760/−0 lines, 9 filesdep +HNumericdep +basedep +normaldistributionsetup-changed

Dependencies added: HNumeric, base, normaldistribution

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for HNumeric++## Unreleased changes
+ HNumeric.cabal view
@@ -0,0 +1,67 @@+-- This file has been generated from package.yaml by hpack version 0.28.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 0a4c04fe65db3e146424c0f3450ab7549b8db8ec8c21cb1d08bc26575227481f++name:           HNumeric+version:        0.2.0.0+synopsis:       Haskell Numeric Library with pure functionality, R & MATLAB Syntax.+description:    Please see the README on GitHub at <https://github.com/Axect/HNumeric#readme>+category:       HNum, library, Numeric, LinearAlgebra, Statistics, bsd3+homepage:       https://github.com/Axect/HNumeric#readme+bug-reports:    https://github.com/Axect/HNumeric/issues+author:         Tae Geun Kim+maintainer:     edeftg@gmail.com+copyright:      2018 Tae Geun Kim+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10+extra-source-files:+    ChangeLog.md+    README.md++source-repository head+  type: git+  location: https://github.com/Axect/HNumeric++library+  exposed-modules:+      HNum.Stats+      HNum.Vector+  other-modules:+      Paths_HNumeric+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+    , normaldistribution+  default-language: Haskell2010++executable HNumeric-exe+  main-is: Main.hs+  other-modules:+      Paths_HNumeric+  hs-source-dirs:+      app+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      HNumeric+    , base >=4.7 && <5+    , normaldistribution+  default-language: Haskell2010++test-suite HNumeric-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_HNumeric+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      HNumeric+    , base >=4.7 && <5+    , normaldistribution+  default-language: Haskell2010
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Tae Geun Kim (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,193 @@+# HNumeric++![Travis](https://travis-ci.org/Axect/HNumeric.svg?branch=master)++## Packages++* HNum.Vector : Contain vector, matrix, linear algebra+* HNum.Stats : Contain statistical functions++## Installation++### 1. Native Use++You can use this package just change `app/Main.hs`+Then, just type next command++```bash+git clone https://github.com/Axect/HNumeric+```++### 2. Cabal Install++First, install prerequisite.++```sh+cabal install normaldistribution+```+  +Second, install tarball & unpack.++```sh+export VERSION=0.2.0.0++wget -O HNumeric-${VERSION}.tar.gz https://github.com/Axect/HNumeric/blob/master/dist/HNumeric-${VERSION}.tar.gz\?raw\=true++tar -xvf HNumeric-${VERSION}.tar.gz+```++Finally, build & install++```sh+cabal build+cabal install+```++Finish!++### 3. Import to Stack project++If you use this package to your own project, then you should change `stack.yaml` and `package.yaml`++#### 1) Change `stack.yaml`++```yaml+# In stack.yaml+extra-deps:+  - git: https://github.com/Axect/HNumeric.git+    commit: [Latest Commit]+  - normaldistribution-1.1.0,3+```++* Replace [Latest Commit] with latest commit in [HNumeric Commit](https://github.com/Axect/HNumeric/commits/master)++#### 2) Change `package.yaml`++```yaml+# In package.yaml+dependecies:+- base+- HNumeric+- normaldistribution+```++Then enjoy!++## Usage++### Import Module++* HNum.Vector+* HNum.Stats++### Basic Vector Usage++```haskell+-- HNumeric-0.2.0.0 Documentation++let a = vector [1,2,3] -- Vector declaration+let b = vector [4,5,6]++-- Print Vector+print a++-- You can (+1) by fmap (Vector is functor)+(+1) <$> a ++-- Or MATLAB-like operator (.+, .-, .*, ./, .^)+a .+ 1++-- You can make list from vector+toList a -- [1, 2, 3]++-- You can make vector from list+fromList [1,2,3] -- Vector [1,2,3]++-- You can add (subtract, multiply, divide) vectors+a + b -- Vector [5,7,9]++-- Also dot product is here.+a .*. b -- 1*4 + 2*5 + 3*6 = 32++-- Declare Matrix (Syntactic Sugar)+let c = matrix [[1,2],[3,4]]++-- or Declare using R Syntax+let d = Matrix {val = Vector [5,6,7,8], row = 2, col = 2, byRow = True}++-- Determinant+det c++-- Inverse+inv c++-- Transpose+transpose c++-- Matrix ops with Constant (+, -, *, /, ^)+c .+ 1 -- Matrix [[2,3],[4,5]]++-- Matrix ops with Matrix (+, -)+c + c -- Matrix [[2,4],[6,8]]++-- Matrix Multiplication+c %*% d++-- Matrix - Inverse Multiplication+c %/% d++-- Vector Concatenate+hcat a b -- Vector [1,2,3,4,5,6]+vcat a b -- Matrix [[1,2,3],[4,5,6]]++-- Matrix Concatenate+hcat c d -- Matrix [[1,2,5,6],[3,4,7,8]]+vcat c d -- Matrix [[1,2],[3,4],[5,6],[7,8]]++-- Insert Vector to Matrix+Vector [1, 2] .: c -- Matrix [[1,2],[1,2],[3,4]]+```++### Basic Stats Usage++```haskell+-- Sample Vector (import Vector)+v = Vector [1..10]+w = Vector [10, 9 .. 1]++-- Mean+mean v++-- Var+var v++-- Std+std v++-- Cov Matrix+cov v w++-- Only Cov+cov' v w++-- Linear Fit+(intercept, slope) = lm v w -- (11.0, -1.0) -- (Intercept, Slope)++-- Linear Fit function+lineFit (intercept, slope) (Vector [1 .. 20])++-- RSS+rss v w++-- RSE+rse v w+```++### TODO++* ~~Effective Matrix Multiplication~~+* Write Vector to CSV+* ~~Haddock~~+* DataFrame using Map+* ~~Fix Matrix Implementation~~+* ~~Numeric Class Define~~
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,12 @@+module Main where++import           HNum.Vector+import           HNum.Stats+import           Data.Random.Normal++main :: IO ()+main = do+  let a = Vector [1, 3, 4]+  print a+  print $ map ($ a) [mean, var, std]+
+ src/HNum/Stats.hs view
@@ -0,0 +1,48 @@+module HNum.Stats where++import           HNum.Vector++type Coeff a = (a, a)++-- | Expectation Value+mean :: Fractional a => Vector a -> a+mean v = sum v / fromIntegral (length v)++-- | Covariance (Single-Valued)+cov' :: Floating a => Vector a -> Vector a -> a+cov' x y+  | length x <= 1 || length y <= 1 = error "Samples are not enough"+  | length x /= length y = error "Length is not same"+  | otherwise = ((x .- mean x) .*. (y .- mean y)) / fromIntegral (length x - 1)++-- | Variance+var :: Floating a => Vector a -> a+var v = cov' v v++-- | Standard Deviation+std :: Floating a => Vector a -> a+std = sqrt . var++-- | Covariance Matrix+cov :: Floating a => Vector a -> Vector a -> Matrix a+cov x y = matrix [[var x, cov' x y], [cov' y x, var y]]++-- | Least Square Method - (Intercept, Slope)+lm :: Floating a => Vector a -> Vector a -> Coeff a+lm x y = (my - b1 * mx, b1)+ where+  mx = mean x+  my = mean y+  b1 = (x .- mx) .*. (y .- my) / ((x .- mx) .*. (x .- mx))++-- | Line Fitting with (Intercept, Slope) & Range of x+lineFit :: Floating a => Coeff a -> Vector a -> Vector a+lineFit (n, m) x = x .* m .+ n++-- | Residual Sum of Squares+rss :: Floating a => Vector a -> Vector a -> a+rss x y = sum ((y - lineFit (lm x y) x) .^ 2)++-- | Relative Standard Error+rse :: Floating a => Vector a -> Vector a -> a+rse x y = sqrt (1 / fromIntegral (length x - 2) * rss x y)
+ src/HNum/Vector.hs view
@@ -0,0 +1,403 @@+{-|+Module      : HNumeric.Vector+Description : Haskell Vector & Matrix & Linear Algebra Library to do machine learning+CopyRight   : (c) Tae Geun Kim, 2018+License     : GPL-3+Maintainer  : edeftg@gmail.com+Stability   : Experimental+-}+module HNum.Vector where++import           Data.Functor                   ( )+import           Control.Applicative            ( )++---------------------------------------------------+-- Vector+--------------------------------------------------+-- Type Section+newtype Vector a = Vector [a] deriving (Show, Eq)++vector :: [a] -> Vector a+vector = Vector++-- Instance Section+instance Functor Vector where+  fmap f (Vector x) = Vector (fmap f x)++instance Applicative Vector where+  pure a                  = Vector []+  Vector fs <*> Vector xs = Vector (zipWith ($) fs xs)++instance (Num a) => Num (Vector a) where+  negate v      = negate <$> v+  (+) v1 v2     = (+) <$> v1 <*> v2+  (*) v1 v2     = (*) <$> v1 <*> v2+  fromInteger n = fromInteger <$> Vector [n]+  signum v      = signum <$> v+  abs v         = abs <$> v++instance (Fractional a) => Fractional (Vector a) where+  recip v        = recip <$> v+  (/) v1 v2      = (*) <$> v1 <*> recip v2+  fromRational n = fromRational <$> Vector [n]++instance (Floating a) => Floating (Vector a) where+  pi = Vector [pi]+  exp v = exp <$> v+  log v = log <$> v+  sqrt v = sqrt <$> v+  sin v = sin <$> v+  cos v = cos <$> v+  tan v = tan <$> v+  asin v = asin <$> v+  acos v = acos <$> v+  atan v = atan <$> v+  sinh v = sinh <$> v+  cosh v = cosh <$> v+  tanh v = tanh <$> v+  asinh v = asinh <$> v+  acosh v = acosh <$> v+  atanh v = atanh <$> v++instance Foldable Vector where+  foldr _ z (Vector []) = z+  foldr f z (Vector xs) = foldr f z xs++  foldl _ z (Vector []) = z+  foldl f z (Vector xs) = foldl f z xs++-- Class for Vector with List+class List m where+  toList :: m a -> [a]+  fromList :: [a] -> m a++instance List Vector where+  toList (Vector xs) = xs+  fromList = Vector++---------------------------------------------------+-- Matrix+---------------------------------------------------++-- |Definition of Matrix+data Matrix a = Matrix {val :: Vector a, row :: Int, col :: Int, byRow :: Bool} deriving (Eq)++-- |matrix is syntactic sugar to create Matrix+matrix :: [[a]] -> Matrix a+matrix = formMat++-- |Matrices is necessary class for Matrix+class Matrices m where+  matForm :: m a -> [[a]]+  formMat :: [[a]] -> m a++instance Matrices Matrix where+  matForm (Matrix (Vector v) r c b)+    | r*c /= length v = error "Matrix Dimension mismatch!"+    | b = ctake c v+    | otherwise = dtake c v+      where ctake :: Int -> [a] -> [[a]]+            ctake _ [] = []+            ctake n m = take n m : ctake n (drop n m)+            dtake :: Int -> [a] -> [[a]]+            dtake _ [] = []+            dtake n m = [ptake n m r | r <- [0..(length m `div` n - 1)]]+            ptake n v r = [v !! x | x <- idx v, x `mod` (length v `div` n) == r]+            idx v = take (length v) [0..]+  formMat [] = Matrix (Vector []) 0 0 True+  formMat xs = Matrix (Vector (concat xs)) (length xs) (length (head xs)) True++instance Show a => Show (Matrix a) where+  show m = "Matrix " ++ show (matForm m)++instance Functor Matrix where+  fmap f mat = mat { val = fmap f (val mat) }++instance Applicative Matrix where+  pure a = matrix []+  mf <*> mx = mx { val = val mf <*> val mx }++instance Num a => Num (Matrix a) where+  negate m = negate <$> m+  (+) m n = (+) <$> m <*> n+  (*) m n = (*) <$> m <*> n+  fromInteger a = fromInteger <$> matrix [[a]]+  signum m = signum <$> m+  abs m = abs <$> m++instance Fractional a => Fractional (Matrix a) where+  recip m = recip <$> m+  (/) m n = (*) <$> m <*> recip n+  fromRational n = fromRational <$> matrix [[n]]++instance (Floating a) => Floating (Matrix a) where+  pi = matrix [[pi]]+  exp v = exp <$> v+  log v = log <$> v+  sqrt v = sqrt <$> v+  sin v = sin <$> v+  cos v = cos <$> v+  tan v = tan <$> v+  asin v = asin <$> v+  acos v = acos <$> v+  atan v = atan <$> v+  sinh v = sinh <$> v+  cosh v = cosh <$> v+  tanh v = tanh <$> v+  asinh v = asinh <$> v+  acosh v = acosh <$> v+  atanh v = atanh <$> v++instance Foldable Matrix where+  foldr _ z (Matrix (Vector []) _ _ _) = z+  foldr f z (Matrix (Vector xs) _ _ _) = foldr f z xs++  foldl _ z (Matrix (Vector []) _ _ _) = z+  foldl f z (Matrix (Vector xs) _ _ _) = foldl f z xs++---------------------------------------------------+-- Operation+---------------------------------------------------+{-|+   (.<ops>) is an operation Vector(or Matrix) with Constant.+   Dot means position of Vector.+   Example: a .* 2  = twice whole elements of a+            a .*. b = Dot product+-}+class Functor f => VecOps f where+  (.+) :: Num a => f a -> a -> f a+  (.-) :: Num a => f a -> a -> f a+  (.*) :: Num a => f a -> a -> f a+  (./) :: Fractional a => f a -> a -> f a+  (.^) :: Floating a => f a -> a -> f a+  (.*.) :: Num a => f a -> f a -> a+  norm :: Floating a => f a -> a++{-+   MatOps is just additional operations for Matrices.+-}+class Functor f => MatOps f where+  (%*%) :: Num a => f a -> f a -> f a+  (%/%) :: Fractional a => f a -> f a -> f a+  det :: Fractional a => f a -> a+  inv :: Fractional a => f a -> f a+  transpose :: f a -> f a++instance VecOps Vector where+  v .+ n = (+ n) <$> v+  v .- n = (+ negate n) <$> v+  v .* n = (* n) <$> v+  v ./ n = (/ n) <$> v+  v .^ n = (** n) <$> v+  v .*. w = sum $ v * w+  norm v = sqrt $ v .*. v++instance VecOps Matrix where+  v .+ n = (+ n) <$> v+  v .- n = (+ negate n) <$> v+  v .* n = (* n) <$> v+  v ./ n = (/ n) <$> v+  v .^ n = (** n) <$> v+  v .*. w = sum $ v * w+  norm v = sqrt $ v .*. v++instance MatOps Matrix where+  m %*% n | col m /= row n = error "Can't Multiply - Dimension mismatch!"+          | otherwise      = matrix $ matForm m %-*-% matForm n+  m %/% n = m %*% inv n+  det m | col m /= row m = error "Can't calculate determinant of non-square matrix"+        | otherwise = detMat (matForm m)+  inv m | col m /= row m = error "Can't calculate inverse of non-square matrix"+        | otherwise = (matrix . invMat . matForm) m+  transpose m = m {row = col m, col = row m, byRow = not (byRow m)}++-- |Block Partitioning+bp :: Int -> Matrix a -> Matrix a+bp n m = matrix $ bpMat n (matForm m)++---------------------------------------------------+-- Concatenate+---------------------------------------------------+class Functor f => Concatable f where+  hcat :: f a -> f a -> f a+  vcat :: f a -> f a -> Matrix a++instance Concatable Vector where+  hcat v w = fromList (toList v ++ toList w)+  vcat v w = matrix (toList v : [toList w])++instance Concatable Matrix where+  hcat m n | row m == row n = matrix (zipWith (++) mf nf)+           | otherwise = error "Can't concatenate matrices horizontally which have different row"+           where mf = matForm m+                 nf = matForm n+  vcat m n | col m == col n = m {val = hcat (val m) (val n), row = row m + row n}+           | otherwise = error "Can't concatenate matrices vertically which have different col"++-- |(.:) inserts vector to head of matrix.+(.:) :: Vector a -> Matrix a -> Matrix a+v .: m | length v == col m = matrix (toList v : matForm m)+       | otherwise         = error "Can't insert length(Vector) /= col(Matrix)"++---------------------------------------------------+-- Backend Functions (Do not Understand)+---------------------------------------------------+-- Transpose+transposeMat :: [[a]] -> [[a]]+transposeMat m = map (\l -> map (!! l) m) [0 .. (length (head m) - 1)]++-- indexMat+indexMat :: [[a]] -> [[(Int, Int)]]+indexMat m@(xs : xss) = do+  i <- [0 .. (length m - 1)]+  [zip (replicate (length xs) i) [0 .. (length xs - 1)]]++-- dropAtMat+dropAtMat :: Int -> Int -> [[a]] -> [[a]]+dropAtMat i j mat = map (dropAt j) $ dropAt i mat++-- postSplitAt+postSplitAt (x, y) = x ++ tail y++-- dropAt+dropAt :: Int -> [a] -> [a]+dropAt i = postSplitAt . splitAt i++-- dropAtMat' : drop nth array+dropAtMat' :: Int -> [[a]] -> [[a]]+dropAtMat' n mat | n /= (length mat - 1) = dropAt n mat+                 | otherwise             = take n mat++-- Block Partitioning+bpMat :: Int -> [[a]] -> [[a]]+bpMat _ [] = []+bpMat n m | n == 1    = (map (take sl) . take sl) m+          | n == 2    = (map (drop sl) . take sl) m+          | n == 3    = (map (take sl) . drop sl) m+          | n == 4    = (map (drop sl) . drop sl) m+          | otherwise = error "Please input 1 ~ 4"+ where+  l  = length m+  sl = (floor . sqrt . fromIntegral) l++-- Matrix + Matrix+(%-+-%) :: Num a => [[a]] -> [[a]] -> [[a]]+m    %-+-% []   = m+[]   %-+-% m    = m+[[]] %-+-% m    = m+m    %-+-% [[]] = m+m    %-+-% n    = zipWith (zipWith (+)) m n++negMap :: Num a => [[a]] -> [[a]]+negMap = map (map negate)++-- Matrix - Matrix+(%---%) :: Num a => [[a]] -> [[a]] -> [[a]]+m    %---% []   = m+[]   %---% m    = map (map negate) m+[[]] %---% m    = map (map negate) m+m    %---% [[]] = m+m    %---% n    = zipWith (zipWith (-)) m n++-- Matrix Multiplication+(%-*-%) :: Num a => [[a]] -> [[a]] -> [[a]]+_     %-*-% []    = []+[]    %-*-% _     = []+_     %-*-% [[]]  = [[]]+[[] ] %-*-% _     = [[]]+[[x]] %-*-% [[y]] = [[x * y]]+m     %-*-% n     = zipWith (++) a11 a12 ++ zipWith (++) a21 a22+ where+  (m11, n11) = (bpMat 1 m, bpMat 1 n)+  (m12, n12) = (bpMat 2 m, bpMat 2 n)+  (m21, n21) = (bpMat 3 m, bpMat 3 n)+  (m22, n22) = (bpMat 4 m, bpMat 4 n)+  a11        = (m11 %-*-% n11) %-+-% (m12 %-*-% n21)+  a12        = (m11 %-*-% n12) %-+-% (m12 %-*-% n22)+  a21        = (m21 %-*-% n11) %-+-% (m22 %-*-% n21)+  a22        = (m21 %-*-% n12) %-+-% (m22 %-*-% n22)++zerosVec :: Int -> [Int]+zerosVec n = take n [0, 0 ..]++eyeMat :: Int -> [[Int]]+eyeMat n = [ basisVec x n | x <- [0 .. (n - 1)] ]++-- Position -> Length +basisVec :: Int -> Int -> [Int]+basisVec n m = zerosVec n ++ [1] ++ zerosVec (m - n - 1)++permMat :: Int -> Int -> [[a]] -> [[Int]]+permMat i j m+  | i < j+  = take i idx+    ++ [idx !! j]+    ++ take (j - i - 1) (drop (i + 1) idx)+    ++ [idx !! i]+    ++ drop (j + 1) idx+  | otherwise+  = permMat j i m+  where idx = eyeMat (length m)++whichMax :: Ord a => [a] -> Int+whichMax v = whichMax' v 0 m+ where+  m = maximum v+  whichMax' :: Ord a => [a] -> Int -> a -> Int+  whichMax' (x : xs) n m' = if x == m' then n else whichMax' xs (n + 1) m'++colMat :: [[a]] -> Int -> [a]+colMat m n = map (!! n) m++colMaxIdx :: Ord a => [[a]] -> Int -> Int+colMaxIdx m n = whichMax $ colMat m n++-- | Another Block Partitioning+bpMat' :: Int -> [[a]] -> [[a]]+bpMat' _ []  = []+bpMat' _ [x] = [x]+bpMat' n m | n == 1 = (map (take l) . take l) m+           | n == 2 = (map (drop 1) . take l) m+           | n == 3 = (map (take l) . drop 1) m+           | n == 4 = (map (drop 1) . drop 1) m+           | n == 0 = (map (drop 1 . take l) . drop 1 . take l) m+  where l = length m - 1++-- | Determinant for Double List - Order ~ 4^n+detMat :: Fractional a => [[a]] -> a+detMat [[x]] = x+detMat m+  | l == 2    = detMat m11 * detMat m22 - detMat m12 * detMat m21+  | otherwise = (detMat m11 * detMat m22 - detMat m12 * detMat m21) / detMat m00+ where+  l   = length m+  m11 = bpMat' 1 m+  m12 = bpMat' 2 m+  m21 = bpMat' 3 m+  m22 = bpMat' 4 m+  m00 = bpMat' 0 m++-- | Inverse for Double List - Order ~ n * 2^n+invMat :: Fractional a => [[a]] -> [[a]]+invMat []    = []+invMat [[] ] = [[]]+invMat [[x]] = [[x]]+invMat m+  | length m == 2+  = map (map (/ detMat m))+    $  zipWith (++) m22          (negMap m12)+    ++ zipWith (++) (negMap m21) m11+  | otherwise+  = zipWith (++) a11 a12 ++ zipWith (++) a21 a22+ where+  m11 = bpMat 1 m+  m12 = bpMat 2 m+  m21 = bpMat 3 m+  m22 = bpMat 4 m+  a00 = invMat m11+  s   = m22 %---% (m21 %-*-% a00 %-*-% m12)+  s00 = invMat s+  a11 = a00 %-+-% (a00 %-*-% m12 %-*-% s00 %-*-% m21 %-*-% a00)+  a12 = negMap a00 %-*-% m12 %-*-% s00+  a21 = negMap s00 %-*-% m21 %-*-% a00+  a22 = s00
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"