> It should be possible to extract the macro logic for it and use it for 
> sequences in theory, but that would be non trivial.

<https://github.com/mratsim/constantine/blob/0944454/research/kzg_poly_commit/strided_views.nim#L23-L46>
    
    
    type
      View*[T] = object
        ## A strided view over an (unowned) data buffer
        len*: int
        stride: int
        offset: int
        data: lent UncheckedArray[T]
    
    func `[]`*[T](v: View[T], idx: int): lent T {.inline.} =
      v.data[v.offset + idx*v.stride]
    
    func `[]`*[T](v: var View[T], idx: int): var T {.inline.} =
      # Experimental views indeed ...
      cast[ptr UncheckedArray[T]](v.data)[v.offset + idx*v.stride]
    
    func `[]=`*[T](v: var View[T], idx: int, val: T) {.inline.} =
      # Experimental views indeed ...
      cast[ptr UncheckedArray[T]](v.data)[v.offset + idx*v.stride] = val
    
    func toView*[T](oa: openArray[T]): View[T] {.inline.} =
      result.len = oa.len
      result.stride = 1
      result.offset = 0
      result.data = cast[lent UncheckedArray[T]](oa[0].unsafeAddr)
    
    iterator items*[T](v: View[T]): lent T =
      var cur = v.offset
      for _ in 0 ..< v.len:
        yield v.data[cur]
        cur += v.stride
    
    func slice*(v: View, start, stop, step: int): View {.inline.} =
      ## Slice a view
      ## stop is inclusive
      # General tensor slicing algorithm is
      # 
https://github.com/mratsim/Arraymancer/blob/71cf616/src/arraymancer/tensor/private/p_accessors_macros_read.nim#L26-L56
      #
      # for i, slice in slices:
      #   # Check if we start from the end
      #   let a = if slice.a_from_end: result.shape[i] - slice.a
      #           else: slice.a
      #
      #   let b = if slice.b_from_end: result.shape[i] - slice.b
      #           else: slice.b
      #
      #   # Compute offset:
      #   result.offset += a * result.strides[i]
      #   # Now change shape and strides
      #   result.strides[i] *= slice.step
      #   result.shape[i] = abs((b-a) div slice.step) + 1
      #
      # with slices being of size 1, as we have a monodimensional Tensor
      # and the slice being a..<b with the reverse case: len-1 -> 0
      #
      # result is preinitialized with a copy of v (shape, stride, offset, data)
      result.offset = v.offset + start * v.stride
      result.stride = v.stride * step
      result.len = abs((stop-start) div step) + 1
      result.data = v.data
    
    
    Run

Reply via email to