public class Strided1DBuffer extends BaseBuffer
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
.
PyBuffer.Pointer
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 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. |
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.
|
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
public Strided1DBuffer(byte[] storage, int index0, int length, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException
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.)
storage
- raw byte array containing exported dataindex0
- index into storage of item[0]length
- number of items in the slicestride
- in between successive elements of the new PyBufferNullPointerException
- if storage
is nullArrayIndexOutOfBoundsException
- if index0
, length
and
stride
are inconsistent with storage.length
public Strided1DBuffer(int flags, byte[] storage, int index0, int length, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException, PyException
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
).
flags
- consumer requirementsstorage
- raw byte array containing exported dataindex0
- index into storage of item[0]length
- number of items in the slicestride
- in between successive elements of the new PyBufferNullPointerException
- if storage
is nullArrayIndexOutOfBoundsException
- if index0
, length
and
stride
are inconsistent with storage.length
PyException
- (BufferError) when expectations do not correspond with the typepublic boolean isReadonly()
PyBUF
isReadonly
in interface PyBUF
isReadonly
in class BaseBuffer
public byte byteAt(int index) throws IndexOutOfBoundsException
PyBuffer
itemsize>1
.byteAt
in interface PyBuffer
byteAt
in class BaseBuffer
index
- to retrieve fromIndexOutOfBoundsException
public void copyTo(int srcIndex, byte[] dest, int destPos, int length) throws IndexOutOfBoundsException
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.
copyTo
in interface PyBuffer
copyTo
in class BaseBuffer
srcIndex
- starting index in the source bufferdest
- destination byte arraydestPos
- index in the destination array of the item [0,...]length
- number of items to copyIndexOutOfBoundsException
- if access out of bounds in source or destinationpublic PyBuffer getBufferSlice(int flags, int start, int length, int stride)
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.
flags
- specifying features demanded and the navigational capabilities of the consumerstart
- index in the current bufferlength
- number of items in the required slicestride
- index-distance in the current buffer between consecutive items in the slicepublic PyBuffer.Pointer getPointer(int index)
PyBuffer
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.
getPointer
in interface PyBuffer
getPointer
in class BaseBuffer
index
- in the buffer to position the pointerpublic PyBuffer.Pointer getPointer(int... indices)
PyBuffer
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].
getPointer
in interface PyBuffer
getPointer
in class BaseBuffer
indices
- multidimensional index at which to position the pointerpublic int[] getStrides()
PyBUF
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).getStrides
in interface PyBUF
getStrides
in class BaseBuffer