module Control.Parallel.ScanVectorMachine.SerialScanVectorMachine(SSVM) where
import Data.Array.IArray
import Control.Parallel.ScanVectorMachine.ScanVectorMachine as SVM
newtype SSVM e = SSVM { unSSVM :: Array e e }
azip :: Ix idx => Array idx e1 -> Array idx e2 -> Array idx (e1,e2)
azip x y = array (start, end) $ map (\i -> (i,((x!i),(y!i)))) (range (start,end))
where
(xmin,xmax) = bounds x
(ymin,ymax) = bounds y
start = max xmin ymin
end = min xmax ymax
op2func :: (Ix e, Ord e, Num e) => SVM.Op -> (e -> e -> e)
op2func And x y = if x/=0 && y/=0 then 1 else 0
op2func Or x y = if x/=0 || y/=0 then 1 else 0
op2func Min x y = if x < y then x else y
op2func Max x y = if x > y then x else y
op2func Plus x y = x+y
op2func Times x y = x*y
instance (Ix e, Show e) => Show (SSVM e) where
show (SSVM a) = show $ elems a
instance (Enum e, Ix e, Ord e, Num e) => SVM.ScanVectorMachine SSVM e where
neg (SSVM a) = SSVM $ amap (\x -> if x==0 then 1 else 0) a
leq (SSVM a) (SSVM b) = SSVM $ amap (\(x,y) -> if x <= y then 1 else 0) $ azip a b
op op (SSVM a) (SSVM b) = SSVM $ amap (uncurry $ op2func op) $ azip a b
select (SSVM b) (SSVM x) (SSVM y) = SSVM $ amap (\(b,(x,y)) -> if b/=0 then x else y) $ azip b (azip x y)
permute (SSVM a) (SSVM i) = SSVM $ array (bounds a) $ zip (elems i) (elems a)
insert (SSVM a) pos v = SSVM $ a // [(pos,v)]
extract (SSVM a) pos = a ! pos
distribute v len = SSVM $ array (0,(len1)) [ (i,v) | i <- [0..(len1)] ]
length (SSVM a) = max 0 (endstart+fromInteger 1) where (start,end) = bounds a
scan op (SSVM a) = SSVM $ array (bounds a) $ (0,0):(drop 1 result)
where
result = fst $ foldl mapfunc ([],0) (assocs a)
mapfunc (ret,acc) (i,e) = let acc' = op2func op e acc in (((i+1,acc'):ret),acc')