packages feed

Obsidian-0.0.0.5: Obsidian/LibraryG.hs

{-# LANGUAGE ScopedTypeVariables #-}
module Obsidian.LibraryG where

import Obsidian.Array
import Obsidian.Program
import Obsidian.Exp
import Obsidian.Memory

import Data.Word


---------------------------------------------------------------------------
-- 
--------------------------------------------------------------------------- 
mapG :: ASize l => (SPull a -> BProgram (SPull b))
        -> Pull l (SPull a)
        -> Push Grid l b
mapG kern as =
  Push (blocks * fromIntegral rn) $
  \wf ->
    do
      forAllBlocks (sizeConv blocks) $ \bix -> do
        res <- kern (as ! bix)
        let (Push _ p) = push Block res
            wf' a ix = wf a (bix * sizeConv rn + ix)
        p wf'
  where
    blocks = len as
    -- TODO: ensure this is not insane (runPrg functionality) 
    rn = len $ fst $ runPrg 0 (kern (as ! 0))
    n = len (as ! 0)


mapT :: (SPull a -> TProgram (SPull b))
        -> SPull (SPull a)
        -> SPush Block b
mapT threadf as =
  Push (n * m) $
  \wf ->
    do
      forAll (sizeConv n) $ \tix -> do
        res <- threadf (as ! tix)
        let (Push _ p) = push Thread res
            wf' a ix = wf a (tix * sizeConv m + ix)
        p wf'      

  where
    n = len as
    m = len (as ! 0) 
---------------------------------------------------------------------------
-- 
--------------------------------------------------------------------------- 
zipWithG :: ASize l => (SPull a -> SPull b -> BProgram (SPull c))
           -> Pull l (SPull a)
           -> Pull l (SPull b)
           -> Push Grid l c
zipWithG kern as bs =
  Push (blocks * fromIntegral rn) $
  \wf ->
    do
      forAllBlocks (sizeConv blocks) $ \bix -> do
        res <- kern (as ! bix) (bs ! bix)
        let (Push _ p) = push Block res
            wf' a ix = wf a (bix * sizeConv rn + ix)
        p wf'
  where
    -- Is this ok?! (does it break?) 
    rn = len $ fst $ runPrg 0 (kern (as ! 0) (bs ! 0))
    n = min m k
    -- assume uniformity
    m = len (as ! 0)
    k = len (bs ! 0)
    blocks = min (len as) (len bs) 
     

zipWithT :: (SPull a -> SPull b -> TProgram (SPull c))
        -> SPull (SPull a)
        -> SPull (SPull b) 
        -> SPush Block c
zipWithT threadf as bs =
  Push (threads * rn) $
  \wf ->
    do
      forAll (sizeConv threads) $ \tix -> do
        res <- threadf (as ! tix) (bs ! tix) 
        let (Push _ p) = push Thread res
            wf' a ix = wf a (tix * sizeConv n + ix)
        p wf'      

  where

    -- Is this ok?! (does it break?) 
    rn = len $ fst $ runPrg 0 (threadf (as ! 0) (bs ! 0))
    n = min m k 

    m  = len (as ! 0)
    k  = len (bs ! 0)
    threads = min (len as) (len bs) 

---------------------------------------------------------------------------
-- Experimental
---------------------------------------------------------------------------
zipWithG' :: forall a b c l. (ASize l, MemoryOps c)
             => (SPull a -> SPull b -> BProgram (SPull c))
             -> Pull l (SPull a)
             -> Pull l (SPull b)
             -> GProgram (Push Grid l c)
zipWithG' kern as bs =
  do
    snames <- forAllBlocks (sizeConv n) $ \bix ->
      do
        res <- kern (as ! bix) (bs ! bix)
        let (Push _ p) = push Block res
        p (assignArrayN n)
    let pully = Pull blocks $ \bix -> (pullFromS snames n :: Pull Word32 c)
        
    return $ Push (blocks * fromIntegral n) $
      \wf ->
      do
        forAllBlocks (sizeConv blocks) $ \bix ->
          forAll (sizeConv n) $ \tix ->
            do
              wf ((pully ! bix) ! tix) (bix * (sizeConv n) + tix)
      
  where
    n = min m k 
    -- Assume uniformity
    m = len (as ! 0)
    k = len (bs ! 0)
    blocks = (min (len as) (len bs))