module Data.Eigen.LA (
Decomposition(..),
rank,
kernel,
image,
solve,
relativeError,
linearRegression
) where
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import Foreign.Storable
import Foreign.Marshal.Alloc
import qualified Foreign.Concurrent as FC
import Control.Applicative
import Data.Eigen.Matrix
import qualified Data.Eigen.Internal as I
import qualified Data.Eigen.Matrix.Mutable as M
import qualified Data.Vector.Storable as VS
foreign import ccall "eigen-proxy.h eigen_solve" c_solve :: CInt -> Ptr CDouble -> CInt -> CInt -> Ptr CDouble -> CInt -> CInt -> Ptr CDouble -> CInt -> CInt -> IO CString
foreign import ccall "eigen-proxy.h eigen_relativeError" c_relativeError :: Ptr CDouble -> Ptr CDouble -> CInt -> CInt -> Ptr CDouble -> CInt -> CInt -> Ptr CDouble -> CInt -> CInt -> IO CString
foreign import ccall "eigen-proxy.h eigen_rank" c_rank :: CInt -> Ptr CInt -> Ptr CDouble -> CInt -> CInt -> IO CString
foreign import ccall "eigen-proxy.h eigen_image" c_image :: CInt -> Ptr (Ptr CDouble) -> Ptr CInt -> Ptr CInt -> Ptr CDouble -> CInt -> CInt -> IO CString
foreign import ccall "eigen-proxy.h eigen_kernel" c_kernel :: CInt -> Ptr (Ptr CDouble) -> Ptr CInt -> Ptr CInt -> Ptr CDouble -> CInt -> CInt -> IO CString
foreign import ccall "eigen-proxy.h free" c_free :: Ptr a -> IO ()
data Decomposition
= PartialPivLU
| FullPivLU
| HouseholderQR
| ColPivHouseholderQR
| FullPivHouseholderQR
| LLT
| LDLT
| JacobiSVD deriving (Show, Enum)
rank :: Decomposition -> Matrix -> Int
rank d m = I.performIO $
unsafeWith m $ \vals rows cols ->
alloca $ \pr -> do
I.call $ c_rank (I.cast $ fromEnum d) pr vals rows cols
I.cast <$> peek pr
kernel :: Decomposition -> Matrix -> Matrix
kernel d m1 = I.performIO $
alloca $ \pvals ->
alloca $ \prows ->
alloca $ \pcols ->
unsafeWith m1 $ \vals1 rows1 cols1 -> do
I.call $ c_kernel (I.cast $ fromEnum d)
pvals prows pcols
vals1 rows1 cols1
vals <- peek pvals
rows <- I.cast <$> peek prows
cols <- I.cast <$> peek pcols
fp <- FC.newForeignPtr vals $ c_free vals
return $ Matrix rows cols $ VS.unsafeFromForeignPtr0 fp $ rows * cols
image :: Decomposition -> Matrix -> Matrix
image d m1 = I.performIO $
alloca $ \pvals ->
alloca $ \prows ->
alloca $ \pcols ->
unsafeWith m1 $ \vals1 rows1 cols1 -> do
I.call $ c_image (I.cast $ fromEnum d)
pvals prows pcols
vals1 rows1 cols1
vals <- peek pvals
rows <- I.cast <$> peek prows
cols <- I.cast <$> peek pcols
fp <- FC.newForeignPtr vals $ c_free vals
return $ Matrix rows cols $ VS.unsafeFromForeignPtr0 fp $ rows * cols
solve :: Decomposition -> Matrix -> Matrix -> Matrix
solve d a b = I.performIO $ do
x <- M.new (m_cols a) 1
M.unsafeWith x $ \x_vals x_rows x_cols ->
unsafeWith a $ \a_vals a_rows a_cols ->
unsafeWith b $ \b_vals b_rows b_cols ->
I.call $ c_solve (I.cast $ fromEnum d)
x_vals x_rows x_cols
a_vals a_rows a_cols
b_vals b_rows b_cols
unsafeFreeze x
relativeError :: Matrix -> Matrix -> Matrix -> Double
relativeError x a b = I.performIO $
unsafeWith x $ \x_vals x_rows x_cols ->
unsafeWith a $ \a_vals a_rows a_cols ->
unsafeWith b $ \b_vals b_rows b_cols ->
alloca $ \pe -> do
I.call $ c_relativeError pe
x_vals x_rows x_cols
a_vals a_rows a_cols
b_vals b_rows b_cols
I.cast <$> peek pe
linearRegression :: [[Double]] -> ([Double], Double)
linearRegression points = (coeffs, e) where
a = fromList $ map ((1:).tail) points
b = fromList $ map ((:[]).head) points
x = solve ColPivHouseholderQR a b
e = relativeError x a b
coeffs = map head $ toList x