Strided1DBuffer (Jython API documentation)
Date: 2015-04-29

org.python.core.buffer

## Class Strided1DBuffer

- java.lang.Object
- - org.python.core.buffer.BaseBuffer
  - - org.python.core.buffer.Strided1DBuffer

- All Implemented Interfaces:
    AutoCloseable, BufferProtocol, PyBUF, PyBuffer
  Direct Known Subclasses:
    Strided1DWritableBuffer

      public class Strided1DBuffer
      extends BaseBuffer

  Read-only buffer API over a one-dimensional array of one-byte items, that are evenly-spaced in a storage array. The buffer has `storage`, `index0` and `length` properties in the usual way, designating a slice (or all) of a byte array, but also a `stride` property (equal to `getStrides()[0]`).

  Let the underlying buffer be the byte array u(i) for i=0..N-1, let x be the `Strided1DBuffer`, and let the stride be p. The storage works as follows. Designate by x(j), for j=0..L-1, the byte at index j, that is, the byte retrieved by `x.byteAt(j)`. Thus, we store x(j) at u(a+pj), that is, x(0) = u(a). When we construct such a buffer, we have to supply a = `index0`, L = `length`, and p = `stride` as the constructor arguments. The last item in the slice x(L-1) is stored at u(a+p(L-1)). For the simple case of positive stride, constructor argument `index0` is the low index of the range occupied by the data. When the stride is negative, that is to say p<0, and L>1, this will be to the left of u(a), and the constructor argument `index0` is not then the low index of the range occupied by the data. Clearly both these indexes must be in the range 0 to N-1 inclusive, a rule enforced by the constructors (unless L=0, when it is assumed no array access will take place).

  The class may be used by exporters to create a strided slice (e.g. to export the diagonal of a matrix) and in particular by other buffers to create strided slices of themselves, such as to create the `memoryview` that is returned as an extended slice of a `memoryview`.

- - ### Nested Class Summary

    - ### Nested classes/interfaces inherited from interface org.python.core.PyBuffer

      `PyBuffer.Pointer`

  - ### Field Summary

    - ### Fields inherited from interface org.python.core.PyBUF

      `ANY_CONTIGUOUS, AS_ARRAY, C_CONTIGUOUS, CONTIG, CONTIG_RO, CONTIGUITY, F_CONTIGUOUS, FORMAT, FULL, FULL_RO, INDIRECT, IS_C_CONTIGUOUS, IS_F_CONTIGUOUS, MAX_NDIM, NAVIGATION, ND, RECORDS, RECORDS_RO, SIMPLE, STRIDED, STRIDED_RO, STRIDES, WRITABLE`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Strided1DBuffer(byte[] storage, int index0, int length, int stride)` Provide an instance of `Strided1DBuffer` with navigation variables initialised, for sub-class use.
    `Strided1DBuffer(int flags, byte[] storage, int index0, int length, int stride)` Provide an instance of `Strided1DBuffer` on a particular array of bytes specifying a starting index, the number of items in the result, and a byte-indexing stride.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `byte` | `byteAt(int index)` Return the byte indexed from a one-dimensional buffer with item size one.
    `void` | `copyTo(int srcIndex, byte[] dest, int destPos, int length)` Copy a simple slice of the buffer to the destination byte array, defined by a starting index and length in the source buffer.
    `PyBuffer` | `getBufferSlice(int flags, int start, int length, int stride)` Get a `PyBuffer` that represents a slice of the current one described in terms of a start index, number of items to include in the slice, and the stride in the current buffer.
    `PyBuffer.Pointer` | `getPointer(int... indices)` Return a structure describing the position in a byte array of a single item from the data being exported to the consumer, in the case that array may be multi-dimensional.
    `PyBuffer.Pointer` | `getPointer(int index)` Return a structure describing the position in a byte array of a single item from the data being exported to the consumer.
    `int[]` | `getStrides()` The `strides` array gives the distance in the storage array between adjacent items (in each dimension).
    `boolean` | `isReadonly()` Determine whether the consumer is entitled to write to the exported storage.

    - ### Methods inherited from class org.python.core.buffer.BaseBuffer

      `byteAt, close, copyFrom, copyFrom, copyTo, getBuf, getBuffer, getBufferAgain, getBufferSlice, getFormat, getItemsize, getLen, getNdim, getNIOByteBuffer, getShape, getSuboffsets, hasArray, intAt, intAt, isContiguous, isReleased, release, storeAt, storeAt, toString`

    - ### Methods inherited from class java.lang.Object

      `equals, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Constructor Detail

    - #### Strided1DBuffer

          public Strided1DBuffer(byte[] storage,
                         int index0,
                         int length,
                         int stride)
                          throws ArrayIndexOutOfBoundsException,
                                 NullPointerException

      Provide an instance of `Strided1DBuffer` with navigation variables initialised, for sub-class use. The buffer (`BaseBuffer.storage`, `BaseBuffer.index0`), and the navigation ( `BaseBuffer.shape` array and `stride`) will be initialised from the arguments (which are checked for range).

      The sub-class constructor should check that the intended access is compatible with this object by calling `BaseBuffer.checkRequestFlags(int)`. (See the source of `Strided1DWritableBuffer.Strided1DWritableBuffer(int, byte[], int, int, int)` for an example of this use.)

      Parameters:
        `storage` - raw byte array containing exported data
        `index0` - index into storage of item[0]
        `length` - number of items in the slice
        `stride` - in between successive elements of the new PyBuffer
      Throws:
        `NullPointerException` - if `storage` is null
        `ArrayIndexOutOfBoundsException` - if `index0`, `length` and `stride` are inconsistent with `storage.length`

    - #### Strided1DBuffer

          public Strided1DBuffer(int flags,
                         byte[] storage,
                         int index0,
                         int length,
                         int stride)
                          throws ArrayIndexOutOfBoundsException,
                                 NullPointerException,
                                 PyException

      Provide an instance of `Strided1DBuffer` on a particular array of bytes specifying a starting index, the number of items in the result, and a byte-indexing stride. The result of `byteAt(i)` will be equal to `storage[index0+stride*i]` (whatever the sign of `stride`), valid for `0<=i<length`. The constructor checks that all these indices lie within the `storage` array (unless `length=0`).

      The constructed `PyBuffer` meets the consumer's expectations as expressed in the `flags` argument, or an exception will be thrown if these are incompatible with the type (e.g. the consumer does not specify that it understands the strides array). Note that the actual range in the `storage` array, the lowest and highest index, is not explicitly passed, but is implicit in `index0`, `length` and `stride`. The constructor checks that these indices lie within the `storage` array (unless `length=0`).

      Parameters:
        `flags` - consumer requirements
        `storage` - raw byte array containing exported data
        `index0` - index into storage of item[0]
        `length` - number of items in the slice
        `stride` - in between successive elements of the new PyBuffer
      Throws:
        `NullPointerException` - if `storage` is null
        `ArrayIndexOutOfBoundsException` - if `index0`, `length` and `stride` are inconsistent with `storage.length`
        `PyException` - (BufferError) when expectations do not correspond with the type

  - ### Method Detail

    - #### isReadonly

          public boolean isReadonly()

      Description copied from interface: `PyBUF`
      Determine whether the consumer is entitled to write to the exported storage.
      Specified by:
        `isReadonly` in interface `PyBUF`
      Overrides:
        `isReadonly` in class `BaseBuffer`
      Returns:
        true if writing is not allowed, false if it is.

    - #### byteAt

          public byte byteAt(int index)
                      throws IndexOutOfBoundsException

      Description copied from interface: `PyBuffer`
      Return the byte indexed from a one-dimensional buffer with item size one. This is part of the fully-encapsulated API: the buffer implementation exported takes care of navigating the structure of the buffer. Results are undefined where the number of dimensions is not one or if `itemsize>1`.
      Specified by:
        `byteAt` in interface `PyBuffer`
      Overrides:
        `byteAt` in class `BaseBuffer`
      Parameters:
        `index` - to retrieve from
      Returns:
        the item at index, which is a byte
      Throws:
        `IndexOutOfBoundsException`

    - #### copyTo

          public void copyTo(int srcIndex,
                    byte[] dest,
                    int destPos,
                    int length)
                      throws IndexOutOfBoundsException

      Copy a simple slice of the buffer to the destination byte array, defined by a starting index and length in the source buffer. This may validly be done only for a one-dimensional buffer, as the meaning of the starting index is otherwise not defined. The length (like the source index) is in source buffer items: `length*itemsize` bytes will be occupied in the destination.

      The default implementation in `BaseBuffer` deals with the general one-dimensional case of arbitrary item size and stride. `Strided1DBuffer` provides a version optimised for strided bytes in one dimension.

      Specified by:
        `copyTo` in interface `PyBuffer`
      Overrides:
        `copyTo` in class `BaseBuffer`
      Parameters:
        `srcIndex` - starting index in the source buffer
        `dest` - destination byte array
        `destPos` - index in the destination array of the item [0,...]
        `length` - number of items to copy
      Throws:
        `IndexOutOfBoundsException` - if access out of bounds in source or destination

    - #### getBufferSlice

          public PyBuffer getBufferSlice(int flags,
                                int start,
                                int length,
                                int stride)

      Get a `PyBuffer` that represents a slice of the current one described in terms of a start index, number of items to include in the slice, and the stride in the current buffer. A consumer that obtains a `PyBuffer` with `getBufferSlice` must release it with `PyBuffer.release()` just as if it had been obtained with `PyBuffer.getBuffer(int)`

      Suppose that x(i) denotes the ith element of the current buffer, that is, the byte retrieved by `this.byteAt(i)` or the unit indicated by `this.getPointer(i)`. A request for a slice where `start` = s, `length` = N and `stride` = m, results in a buffer y such that y(k) = x(s+km) where k=0..(N-1). In Python terms, this is the slice x[s : s+(N-1)m+1 : m] (if m>0) or the slice x[s : s+(N-1)m-1 : m] (if m<0). Implementations should check that this range is entirely within the current buffer.

      In a simple buffer backed by a contiguous byte array, the result is a strided PyBuffer on the same storage but where the offset is adjusted by s and the stride is as supplied. If the current buffer is already strided and/or has an item size larger than single bytes, the new `start` index, `length` and `stride` will be translated from the arguments given, through this buffer's stride and item size. The caller always expresses `start` and `strides` in terms of the abstract view of this buffer.

      `Strided1DBuffer` provides an implementation for slicing already-strided bytes in one dimension. In that case, x(i) = u(r+ip) for i = 0..L-1 where u is the underlying buffer, and r, p and L are the start, stride and length with which x was created from u. Thus y(k) = u(r+sp+kmp), that is, the composite `index0` is r+sp and the composite `stride` is mp.

      Parameters:
        `flags` - specifying features demanded and the navigational capabilities of the consumer
        `start` - index in the current buffer
        `length` - number of items in the required slice
        `stride` - index-distance in the current buffer between consecutive items in the slice
      Returns:
        a buffer representing the slice

    - #### getPointer

          public PyBuffer.Pointer getPointer(int index)

      Description copied from interface: `PyBuffer`
      Return a structure describing the position in a byte array of a single item from the data being exported to the consumer. For a one-dimensional contiguous buffer, assuming the following client code where `obj` has type `BufferProtocol`:

           int k = ... ;
           PyBuffer a = obj.getBuffer(PyBUF.FULL);
           int itemsize = a.getItemsize();
           PyBuffer.Pointer b = a.getPointer(k);

      the item with index `k` is in the array `b.storage` at index `[b.offset]` to `[b.offset + itemsize - 1]` inclusive. And if `itemsize==1`, the item is simply the byte `b.storage[b.offset]`

      Essentially this is a method for computing the offset of a particular index. The client is free to navigate the underlying buffer `b.storage` without respecting these boundaries.

      Specified by:
        `getPointer` in interface `PyBuffer`
      Overrides:
        `getPointer` in class `BaseBuffer`
      Parameters:
        `index` - in the buffer to position the pointer
      Returns:
        structure defining the byte[] slice that is the shared data

    - #### getPointer

          public PyBuffer.Pointer getPointer(int... indices)

      Description copied from interface: `PyBuffer`
      Return a structure describing the position in a byte array of a single item from the data being exported to the consumer, in the case that array may be multi-dimensional. For a 3-dimensional contiguous buffer, assuming the following client code where `obj` has type `BufferProtocol`:

           int i, j, k;
           // ... calculation that assigns i, j, k
           PyBuffer a = obj.getBuffer(PyBUF.FULL);
           int itemsize = a.getItemsize();
           PyBuffer.Pointer b = a.getPointer(i,j,k);

      the item with index `[i,j,k]` is in the array `b.storage` at index `[b.offset]` to `[b.offset + itemsize - 1]` inclusive. And if `itemsize==1`, the item is simply the byte `b.storage[b.offset]`

      Essentially this is a method for computing the offset of a particular index. The client is free to navigate the underlying buffer `b.storage` without respecting these boundaries. If the buffer is non-contiguous, the above description is still valid (since a multi-byte item must itself be contiguously stored), but in any additional navigation of `b.storage[]` to other units, the client must use the shape, strides and sub-offsets provided by the API. Normally one starts `b = a.getBuf()` in order to establish the offset of index [0,...,0].

      Specified by:
        `getPointer` in interface `PyBuffer`
      Overrides:
        `getPointer` in class `BaseBuffer`
      Parameters:
        `indices` - multidimensional index at which to position the pointer
      Returns:
        structure defining the byte[] slice that is the shared data

    - #### getStrides

          public int[] getStrides()

      Description copied from interface: `PyBUF`
      The `strides` array gives the distance in the storage array between adjacent items (in each dimension). In the rawest parts of the buffer API, the consumer of the buffer is able to navigate the exported storage. The "strides" array is part of the support for interpreting the buffer as an n-dimensional array of items. It provides the coefficients of the "addressing polynomial". (More on this in the CPython documentation.) The consumer must not modify this array. A valid `strides` array is always returned (difference from CPython).
      Specified by:
        `getStrides` in interface `PyBUF`
      Overrides:
        `getStrides` in class `BaseBuffer`
      Returns:
        the distance in the storage array between adjacent items (in each dimension)

Jython homepage