All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.org.python.core.buffer.Strided1DBuffer Maven / Gradle / Ivy

Go to download

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.

There is a newer version: 2.7.4
Show newest version
package org.python.core.buffer;

import org.python.core.BufferProtocol;
import org.python.core.PyBuffer;
import org.python.core.PyException;

/**
 * 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 count
 * 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 = count, 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. */ public class Strided1DBuffer extends BaseArrayBuffer { /** * Step size in the underlying buffer essential to correct translation of an index (or indices) * into an index into the storage. The value is returned by {@link #getStrides()} is an array * with this as the only element. */ protected int stride; /** * Provide an instance of Strided1DBuffer with navigation variables initialised, * for sub-class use. The buffer ({@link #storage}, {@link #index0}), and the navigation ( * {@link #shape} array and {@link #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 {@link #checkRequestFlags(int)}. (See the source of * {@link Strided1DWritableBuffer} for an example of this use.) * * @param obj exporting object (or null) * @param storage raw byte array containing exported data * @param index0 index into storage of item[0] * @param count number of items in the slice * @param stride in between successive elements of the new PyBuffer * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0, count and * stride are inconsistent with storage.length */ protected Strided1DBuffer(BufferProtocol obj, byte[] storage, int index0, int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException { super(storage, STRIDES, index0, count, stride); this.obj = obj; this.stride = stride; // Between items if (count == 0) { // Nothing to check as we'll make no accesses addFeatureFlags(CONTIGUITY); } else { // Need to check lowest and highest index against array int lo, hi; if (stride == 1) { lo = index0; // First byte of item[0] hi = index0 + count; // Last byte of item[L-1] + 1 addFeatureFlags(CONTIGUITY); } else if (stride > 1) { lo = index0; // First byte of item[0] hi = index0 + (count - 1) * stride + 1; // Last byte of item[L-1] + 1 } else { hi = index0 + 1; // Last byte of item[0] + 1 lo = index0 + (count - 1) * stride; // First byte of item[L-1] } // Check indices using "all non-negative" trick if ((count | lo | (storage.length - lo) | hi | (storage.length - hi)) < 0) { throw new ArrayIndexOutOfBoundsException(); } } } /** * 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<count. The constructor * checks that all these indices lie within the storage array (unless * count=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, count and * stride. The constructor checks that these indices lie within the * storage array (unless count=0). * * @param flags consumer requirements * @param obj exporting object (or null) * @param storage raw byte array containing exported data * @param index0 index into storage of item[0] * @param count number of items in the slice * @param stride byte-index distance from one element to the next in the new PyBuffer * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0, count and * stride are inconsistent with storage.length * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public Strided1DBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException, PyException { this(obj, storage, index0, count, stride); checkRequestFlags(flags); // Check request is compatible with type } @Override public boolean isReadonly() { return true; } @Override public final int byteIndex(int index) throws IndexOutOfBoundsException { if (index < 0 || index >= shape[0]) { throw new IndexOutOfBoundsException(); } return index0 + index * stride; } /** * {@inheritDoc} *

* 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 count 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. */ @Override public PyBuffer getBufferSlice(int flags, int start, int count, int stride) { if (count > 0) { // Translate start relative to underlying buffer int compStride = this.stride * stride; int compIndex0 = index0 + start * this.stride; // Construct a view, taking a lock on the root object (this or this.root) return new SlicedView(getRoot(), flags, storage, compIndex0, count, compStride); } else { // Special case for count==0 where above logic would fail. Efficient too. return new ZeroByteBuffer.View(getRoot(), flags); } } @SuppressWarnings("deprecation") @Override public Pointer getPointer(int index) { return new Pointer(storage, index0 + index * stride); } @SuppressWarnings("deprecation") @Override public Pointer getPointer(int... indices) { // BaseBuffer implementation can be simplified since if indices.length!=1 we error. checkDimension(indices.length); return getPointer(indices[0]); } /** * A Strided1DBuffer.SlicedView represents a non-contiguous subsequence of a simple * buffer. */ static class SlicedView extends Strided1DBuffer { /** The buffer on which this is a slice view */ PyBuffer root; /** * Construct a slice of a one-dimensional byte buffer. * * @param root on which release must be called when this is released * @param flags consumer requirements * @param storage raw byte array containing exported data * @param index0 index into storage of item[0] * @param count number of items in the sliced view * @param stride in between successive elements of the new PyBuffer * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count, int stride) throws PyException { // Create a new on the buffer passed in (part of the root) super(flags, root.getObj(), storage, index0, count, stride); // Get a lease on the root PyBuffer (read-only) this.root = root.getBuffer(FULL_RO); } @Override protected PyBuffer getRoot() { return root; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy