%!TEX root = ../Main.tex

\clearpage{}
\section{Type indexed API}
\label{s:TypeIndexing}

The type indexed API extends our work in \cite{Lippmeier:guiding} to present a uniform interface to bulk array operations as well as the new flow operators. The main point is that we want to preserve information about whether an array is random access indexable. This implies its length is known up-front so we can preallocate the result buffer and avoid a coping join to combine the results from the independent threads.

\TODO{We can take the length of a balanced flow, even though it's not random access indexable. Maybe make another class @Balanced@? Which holds the length method.}

% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
data family Array r sh e

type Vector r e = Array r DIM1 e

\end{code}
\end{small}

\caption{Type indexed API}
\label{f:TypeIndexedAPI}
\end{figure}


% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
 class Bulk r a where
  index       :: Shape sh => Array r sh a -> sh  -> a
  linearIndex :: Shape sh => Array r sh a -> Int -> a
  extent      :: Array r sh a -> sh

 length :: Bulk r a => Vector r a -> Int
 length = size . extent

 data D
 data instance Array D sh a    = ADelayed !sh (sh -> a) 
 instance Bulk D a where
  index (ADelayed _ f) ix      = f ix
  ...

 data U
 data instance Array U sh a    = AUnboxed !sh !(UVector a)
 instance Bulk U a where
  linearIndex (AUnboxed _ vec) = unsafeIndex vec ix
  ...
\end{code}
\end{small}
\caption{Bulk Delayed and Manifest Arrays}
\label{f:BulkDelayedArrays}
\end{figure}


% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
  data O mode dist
  data instance Array (O mode dist) sh a
    = AFlow (DistShape dist sh) (ParFlow mode dist a)
  
  data family DistShape dist sh
  data instance DistShape BB sh   = DistBB sh
  data instance DistShape BN sh   = DistBN
\end{code}
\end{small}
\caption{Parallel Flows}
\label{f:ParallelFlows}
\end{figure}


% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
class Compute r1 sh a where
 computeIO{P,S} :: Target r2 a 
                => Array r1 sh a -> IO (Array r2 sh a)

class Shape sh => Load r1 sh e where
 load{P,S}      :: Target r2 e 
                => Array r1 sh e -> MVec r2 e -> IO ()

class Target r a where
 data MVec r a
 newMVec          :: Int -> IO (MVec r a)
 unsafeWriteMVec  :: MVec r a -> Int -> a -> IO ()
 unsafeFreezeMVec :: sh  -> MVec r a -> IO (Array r sh a)
\end{code}
\end{small}
\caption{The Compute, Load and Target Classes}
\label{f:ComputeLoadTarget}
\end{figure}


% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
class Map r a where
 type TM r
 map    :: => (a -> b) -> Array r sh a -> Array (TM r) sh b

instance Map U a where      instance Map D a where
 type TM U = D               type TM D = D
 map f arr = ...             map f arr = ...

instance Map (O mode dist) a where
 type TM (O mode dist) = (O mode dist)
 map f  (AFlow sh ff)  = AFlow sh (mapPF f ff)

\end{code}
\end{small}
\caption{Map preserves indexability of the source}
\label{f:ApiMap}
\end{figure}

% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
class Zip r1 r2 a b where
 type TZ r1 r2
 zip    => Array r1 sh a -> Array r2 sh b
        -> Array (TZ r1 r2) sh (a, b)

instance Zip ...
 type TZ U U                     = D
 type TZ D D                     = D
 type TZ U D                     = D
 type TZ (O mode BB) (O mode BB) = O mode BB
 type TZ (O mode BB) U           = O mode BB
 type TZ (O mode BB) D           = O mode BB

zip3   :: ( Zip r1 (TZ r2 r3) a (b, c)
          , Zip r2 r3         b c
          , Map (TZ r1 (TZ r2 r3)) (a, (b, c)))
       => Vector r1 a -> Vector r2 b -> Vector r3 c
       -> Vector (TM (TZ r1 (TZ r2 r3))) (a, b, c)
zip3 !vec1 !vec2 !vec3
 = map merge \$ zip vec1 (zip vec2 vec3)
 where  merge (x, (y, z)) = (x, y, z)
\end{code}
\end{small}
\caption{Zip preserves generality of source}
\label{f:ApiMap}
\end{figure}


% -----------------------------------------------------------------------------
\begin{figure}
\begin{small}
\begin{code}
-- Packing / Filtering ---------------
class Pack r a where
 pack   :: Vector r (Bool, a) -> Vector (O FD BN) a

-- Parallel Fold ---------------------
class Fold r a where
 fold   :: (a -> a -> a) -> a -> Array r sh a -> a

instance Bulk r a => Fold r a where
 fold f z arr = ...

-- Segmented Fold --------------------
class Folds r a where
 type TF r
 folds  :: (a -> a -> a) -> a  -> Segd
        -> Vector r a    -> Vector (TF r) a

instance Folds ...
 type TF D           = O FD BN
 type TF U           = O FD BN
 type TF (O mode BB) = O mode BN
\end{code}
\end{small}
\caption{Other Vector functions}
\label{f:ApiOther}
\end{figure}

