packages feed

morfette-0.2: GramLab/Perceptron/Vector.hs

{-# LANGUAGE FlexibleContexts, BangPatterns #-}
module GramLab.Perceptron.Vector 
    ( SparseVector
    , DenseVector
    , DenseVectorST
    , for_
    , plus_
    , scale
    , dot 
    , dot_
    , unsafeDot
    )
where

import Data.Array.ST
import Data.Array.Unboxed (UArray,bounds,(!))
import Control.Monad.ST
import Data.STRef
import GHC.Arr (unsafeIndex)
import Data.Array.Base (unsafeAt)

type SparseVector y i = ([(i,Float)],y)
type DenseVectorST s i = STUArray s i Float
type DenseVector i = UArray i Float


{-# INLINE for_ #-}
for_ xs f = mapM_ f xs


{-# SPECIALIZE plus_ :: DenseVectorST s (Int,Int) 
                     -> SparseVector Int Int -> ST s () #-}
plus_ :: (Show (y,i),Ix (y,i)) => 
         DenseVectorST s (y,i) 
      -> SparseVector y i -> ST s ()
plus_ w (v,y) = do
  for_ v $ \(i,vi) -> do
             wi <- readArray w (y,i) 
             writeArray w (y,i) (wi + vi)

{-# SPECIALIZE scale :: SparseVector Int Int 
                     -> Float 
                     -> SparseVector Int Int #-}
scale :: (Ix i)  => SparseVector y i -> Float -> SparseVector y i
scale (v,y) n = (map (\(i,vi) -> (i,vi*n)) v,y)

{-# INLINE dot #-}
{-# SPECIALIZE dot :: DenseVector (Int,Int) 
                   -> ([(Int,Float)],Int)-> Float #-}
dot :: (Ix (y,i)) => DenseVector (y,i) -> ([(i,Float)],y) -> Float
dot w (x,!y) = go 0 x
    where go !s [] = s
          go !s ((!i,!xi):x) = go (s + (w ! (y,i)) * xi) x

{-# INLINE dot_ #-}
dot_ :: (STRef s Int, DenseVectorST s (Int,Int), DenseVectorST s (Int,Int))  
     -> ([(Int,Float)],Int)
     -> ST s Float
dot_ (c,params,params_a) (x,y) = do
  c' <- fmap fromIntegral (readSTRef c)
  let go !s [] = return s
      go !s ((i,xi):x) = do
        e   <- readArray params   (y,i)
        e_a <- readArray params_a (y,i)
        go (s + (e - (e_a * (1/c'))) * xi) x
  go 0 x

{-# INLINE unsafeDot #-}
{-# SPECIALIZE unsafeDot :: DenseVector (Int,Int) 
                         -> ([(Int,Float)],Int)-> Float #-}
unsafeDot :: (Ix (y,i)) => DenseVector (y,i) -> ([(i,Float)],y) -> Float
unsafeDot w (x,!y) = go 0 x
    where bs = bounds w
          go !s [] = s
          go !s ((!i,!xi):x) = go (s + unsafeAt w (unsafeIndex bs (y,i)) * xi) x