{-# LANGUAGE TypeFamilies, FlexibleInstances, MultiParamTypeClasses #-}

-- | An instance of @SegmentedScanVectorMachine@ provides a scalar
--   type @s@, a vector type @v@, and a segmented vector
--   (vector-of-vectors) type @v'@ such that @v@ implements the SVM
--   operations over @s@ /and/ @v'@ implements the SVM operations over
--   @v s@.
--
--   This file contains a default instance for @ScanVectorMachine V' (V S)@,
--   given an instance @ScanVectorMachine V S@.  In other words, given an
--   implementation of vectors-of-scalars, this will produce an
--   implementation of vectors-of-vectors-of-scalars.
--
--   This new type @V'@ provides SVM operations over
--   vectors-of-vectors-of-scalars; from the perspective of @V'@, the
--   vectors-of-scalars are called /segments/.  Notice that @V'@ uses
--   vectors-of-scalars wherever ordinary scalars were previously
--   used.  For example, when the /length/ operation is applied to a
--   vector-of-vectors the result is not a scalar, but rather a
--   vector-of-scalars giving the lengths of each of the segments.
--   This phenomenon is crucial to the replication theorem and
--   flattening transformation.
--
--   It turns out that @V'@ is basically @(,)@ -- but this is not
--   exposed to the user.  Blelloch outlines three encodings (figure
--   4.2): head-flags, length, and head-pointer.  The implementation
--   below uses the /length/ style since it can represent zero-length
--   vectors efficiently.
--
--   It is sometimes advantageous for hardware/platform providers to
--   implement vectors-of-vectors-of-scalars directly (see
--   @NestedVectors.hs@ for the reasoning).  To do this, implement the
--   class @SegmentedScanVectorMachine@ below.

module Control.Parallel.ScanVectorMachine.SegmentedScanVectorMachine(SegmentedScanVectorMachine) where
import Control.Parallel.ScanVectorMachine.ScanVectorMachine as SVM

-- sanity check that the two vectors have identical segment descriptors; if not, raise an error
check_eq a b = a  -- FIXME: implement; for now we just trust the user

class (SVM.ScanVectorMachine v s,
       SVM.ScanVectorMachine v' (v' (v s))) =>
       SegmentedScanVectorMachine v' v s

-- private; isomorphic to (,)
data SegVec v = SegVec v v

-- | Default implementation of segments using an auxiliary segment-length vector
instance SVM.ScanVectorMachine v s => SVM.ScanVectorMachine SegVec (v s) where
  neg         (SegVec a alens)                                   = SegVec (neg a)    alens
  leq         (SegVec a alens) (SegVec b blens)                  = SegVec (leq a b)  (check_eq alens blens)
  op       o  (SegVec a alens) (SegVec b blens)                  = SegVec (op o a b) (check_eq alens blens)
  select      (SegVec b blens) (SegVec x xlens) (SegVec y ylens) = SegVec (select b x y) (check_eq blens (check_eq xlens ylens))
  permute     (SegVec a alens) (SegVec i ilens)                  = undefined
  insert      (SegVec a alens) pos v                             = undefined
  extract     (SegVec a alens) pos                               = undefined
  distribute  v len                                              = undefined
  length      (SegVec a alens)                                   = undefined
  scan     o  (SegVec a alens)                                   = undefined