anchor.diff:  
               do device.OnDispose.Add (fun _ -> release())
   
  -            member x.Invoke(input : Buffer<'a>, output : Buffer<'a>) =
  -                let rec build (input : BufferVector<'a>) (output : BufferVector<'a>) =
  +            member x.Invoke(input : IBufferVector<'a>, output : IBufferVector<'a>) =
  +                let rec build (input : IBufferVector<'a>) (output : IBufferVector<'a>) =
                       command {
  -                        if input.Size > 0L then
  -                            let cnt = int input.Size
  -                            let args0 = ComputeShader.newInputBinding scan pool
  -                            let blocks = cnt / scanSize
  -
  -                            try
  -                                args0.["inputOffset"] <- input.Offset |> int
  -                                args0.["inputDelta"] <- input.Delta |> int
  -                                args0.["inputSize"] <- input.Size |> int
  -                                args0.["inputData"] <- input.Buffer
  -                                args0.["outputOffset"] <- output.Offset |> int
  -                                args0.["outputDelta"] <- output.Delta |> int
  -                                args0.["outputData"] <- output.Buffer
  -                                args0.Flush()
  -
  -                                do! Command.Bind scan
  -                                do! Command.SetInputs args0
  -                                do! Command.Dispatch(ceilDiv (int input.Size) scanSize)
  -                                do! Command.SyncWrite(output.Buffer)
  -
  -                                if blocks > 0 then
  -                                    let o = output.Skip(int64 scanSize - 1L).Strided(int64 scanSize)
  +                        let cnt = int input.Size
  +                        let args0 = ComputeShader.newInputBinding scan pool
  +
  +                        try
  +                            args0.["inputOffset"] <- input.Offset |> int
  +                            args0.["inputDelta"] <- input.Delta |> int
  +                            args0.["inputSize"] <- input.Size |> int
  +                            args0.["inputData"] <- input.Buffer
  +                            args0.["outputOffset"] <- output.Offset |> int
  +                            args0.["outputDelta"] <- output.Delta |> int
  +                            args0.["outputData"] <- output.Buffer
  +                            args0.Flush()
  +
  +                            do! Command.Bind scan
  +                            do! Command.SetInputs args0
  +                            do! Command.Dispatch(ceilDiv (int input.Size) scanSize)
  +                            do! Command.SyncWrite(output.Buffer)
  +
  +                            let oSums = output.[int64 scanSize - 1L .. ].Strided(scanSize)
  +                            if oSums.Size > 1L then
                               
  -                                    do! build o o
  -
  -                                    let args1 = ComputeShader.newInputBinding fixup pool
  -                                    try
  -                                        args1.["inputData"] <- o.Buffer
  -                                        args1.["inputOffset"] <- o.Offset |> int
  -                                        args1.["inputDelta"] <- o.Delta |> int
  -                                        args1.["outputData"] <- output.Buffer
  -                                        args1.["outputOffset"] <- output.Offset |> int
  -                                        args1.["outputDelta"] <- output.Delta |> int
  -                                        args1.["count"] <- output.Size |> int
  -                                        args1.["groupSize"] <- scanSize
  -                                        args1.Flush()
  -
  -                                        do! Command.Bind fixup
  -                                        do! Command.SetInputs args1
  -                                        do! Command.Dispatch(ceilDiv (int output.Size - scanSize) halfScanSize)
  -                                        do! Command.SyncWrite(output.Buffer)
  -                                    finally
  -                                        args1.Dispose()
  -
  -
  -                            finally
  -                                args0.Dispose()
  +                                do! build oSums oSums
  +
  +                                let args1 = ComputeShader.newInputBinding fixup pool
  +                                try
  +                                    args1.["inputData"] <- oSums.Buffer
  +                                    args1.["inputOffset"] <- oSums.Offset |> int
  +                                    args1.["inputDelta"] <- oSums.Delta |> int
  +                                    args1.["outputData"] <- output.Buffer
  +                                    args1.["outputOffset"] <- output.Offset |> int
  +                                    args1.["outputDelta"] <- output.Delta |> int
  +                                    args1.["count"] <- output.Size |> int
  +                                    args1.["groupSize"] <- scanSize
  +                                    args1.Flush()
  +
  +                                    do! Command.Bind fixup
  +                                    do! Command.SetInputs args1
  +                                    do! Command.Dispatch(ceilDiv (int output.Size - scanSize) halfScanSize)
  +                                    do! Command.SyncWrite(output.Buffer)
  +                                finally
  +                                    args1.Dispose()
  +
  +
  +                        finally
  +                            args0.Dispose()
                       }
   
  -                build (BufferVector input) (BufferVector output)
  +                if input.Size > 1L then
  +                    build input output
  +                else
  +                    Command.Nop
   
               member x.Compile(input : Buffer<'a>, output : Buffer<'a>) =
                   let cmd = device.GraphicsFamily.DefaultCommandPool.CreateCommandBuffer(CommandBufferLevel.Primary)
  
positive.code: 
          member x.Download(dst : 'a[]) =
              x.Download(0L, dst, 0L, min count dst.LongLength)
  
      [<AbstractClass; Sealed; Extension>]
      type DeviceTypedBufferExtensions private() =
  
negative.code:             }
          
          [<LocalSize(X = halfScanSize)>]
          let mapReduceKernel (map : Expr<'a -> 'b>) (reduce : Expr<'b -> 'b -> 'b>) (inputOffset : int) (inputDelta : int) (inputSize : int) (inputData : 'a[]) (outputOffset : int) (outputDelta : int) (outputData : 'b[]) =
              compute {
                  let mem : 'b[] = allocateShared scanSize
                  let gid = getGlobalId().X
  
                  let gid0 = gid
                  let lid0 =  getLocalId().X
  
                  let lgid = 2 * gid0
                  let rgid = lgid + 1
              
                  let llid = 2 * lid0
                  let rlid = llid + 1
  
                  if lgid < inputSize then mem.[llid] <- (%map) inputData.[inputOffset + lgid * inputDelta]
                  if rlid < inputSize then mem.[rlid] <- (%map) inputData.[inputOffset + rgid * inputDelta]
  
  
                  barrier()
              
                  let mutable s = 1
                  let mutable d = 2
                  while d <= scanSize do
                      if llid % d = 0 && llid >= s then
                          mem.[llid] <- (%reduce) mem.[llid - s] mem.[llid]
  
                      barrier()
                      s <- s <<< 1
                      d <- d <<< 1
  
                  d <- d >>> 1
                  s <- s >>> 1
                  while s >= 1 do
                      if llid % d = 0 && llid + s < scanSize then
                          mem.[llid + s] <- (%reduce) mem.[llid] mem.[llid + s]
                      
                      barrier()
                      s <- s >>> 1
                      d <- d >>> 1
  
                  if lgid < inputSize then
                      outputData.[outputOffset + lgid * outputDelta] <- mem.[llid]
                  if rgid < inputSize then
                      outputData.[outputOffset + rgid * outputDelta] <- mem.[rlid]
  
              }
  
          [<LocalSize(X = halfScanSize)>]
          let fixupKernel (add : Expr<'a -> 'a -> 'a>) (inputData : 'a[]) (inputOffset : int) (inputDelta : int) (outputData : 'a[]) (outputOffset : int) (outputDelta : int) (groupSize : int) (count : int) =
              compute {
                  let id = getGlobalId().X + groupSize
  