< prev index next > src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java
Print this page
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.incubator.vector;
- import java.nio.ByteBuffer;
+ import jdk.incubator.foreign.MemorySegment;
+
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* A
*
* In such cases memory order corresponds exactly to lane order. The
* first vector lane value occupies the first position in memory, and so on,
* up to the length of the vector. Further, the memory order of stored
* vector lanes corresponds to increasing index values in a Java array or
- * in a {@link java.nio.ByteBuffer}.
+ * in a {@link jdk.incubator.foreign.MemorySegment}.
*
* <p> Byte order for lane storage is chosen such that the stored
* vector values can be read or written as single primitive values,
- * within the array or buffer that holds the vector, producing the
+ * within the array or segment that holds the vector, producing the
* same values as the lane-wise values within the vector.
* This fact is independent of the convenient fiction that lane values
* inside of vectors are stored in little-endian order.
*
* <p> For example,
* {@code VectorShuffle} object, which acts as an routing table
* mapping source lanes to destination lanes. A {@code VectorShuffle}
* can encode a mathematical permutation as well as many other
* patterns of data movement.
*
+ * <li>The {@link #compress(VectorMask)} and {@link #expand(VectorMask)}
+ * methods, which select up to {@code VLENGTH} lanes from an
+ * input vector, and assemble them in lane order. The selection of lanes
+ * is controlled by a {@code VectorMask}, with set lane elements mapping, by
+ * compression or expansion in lane order, source lanes to destination lanes.
+ *
* </ul>
* <p> Some vector operations are not lane-wise, but rather move data
* across lane boundaries. Such operations are typically rare in SIMD
* code, though they are sometimes necessary for specific algorithms
* that manipulate data formats at a low level, and/or require SIMD
* @see VectorShuffle#laneIsValid()
* @see #slice(int,Vector)
*/
public abstract Vector<E> rearrange(VectorShuffle<E> s, Vector<E> v);
+ /**
+ * Compresses the lane elements of this vector selecting lanes
+ * under the control of a specific mask.
+ *
+ * This is a cross-lane operation that compresses the lane
+ * elements of this vector as selected by the specified mask.
+ *
+ * For each lane {@code N} of the mask, if the mask at
+ * lane {@code N} is set, the element at lane {@code N}
+ * of input vector is selected and stored into the output
+ * vector contiguously starting from the lane {@code 0}.
+ * All the upper remaining lanes, if any, of the output
+ * vector are set to zero.
+ *
+ * @param m the mask controlling the compression
+ * @return the compressed lane elements of this vector
+ * @since 19
+ */
+ public abstract Vector<E> compress(VectorMask<E> m);
+
+ /**
+ * Expands the lane elements of this vector
+ * under the control of a specific mask.
+ *
+ * This is a cross-lane operation that expands the contiguous lane
+ * elements of this vector into lanes of an output vector
+ * as selected by the specified mask.
+ *
+ * For each lane {@code N} of the mask, if the mask at
+ * lane {@code N} is set, the next contiguous element of input vector
+ * starting from lane {@code 0} is selected and stored into the output
+ * vector at lane {@code N}.
+ * All the remaining lanes, if any, of the output vector are set to zero.
+ *
+ * @param m the mask controlling the compression
+ * @return the expanded lane elements of this vector
+ * @since 19
+ */
+ public abstract Vector<E> expand(VectorMask<E> m);
+
/**
* Using index values stored in the lanes of this vector,
* assemble values stored in second vector {@code v}.
* The second vector thus serves as a table, whose
* elements are selected by indexes in the current vector.
* <p> If the old and new species have different shape, this is a
* <em>shape-changing</em> operation, and may have special
* implementation costs.
*
* <p> The method behaves as if this vector is stored into a byte
- * buffer or array using little-endian byte ordering and then the
- * desired vector is loaded from the same byte buffer or array
- * using the same ordering.
+ * array using little-endian byte ordering and then the desired vector is loaded from the same byte
+ * array using the same ordering.
*
* <p> The following pseudocode illustrates the behavior:
* <pre>{@code
* int domSize = this.byteSize();
* int ranSize = species.vectorByteSize();
* int M = (domSize > ranSize ? domSize / ranSize : ranSize / domSize);
* assert Math.abs(part) < M;
* assert (part == 0) || (part > 0) == (domSize > ranSize);
- * byte[] ra = new byte[Math.max(domSize, ranSize)];
+ * MemorySegment ms = MemorySegment.ofArray(new byte[Math.max(domSize, ranSize)]);
* if (domSize > ranSize) { // expansion
- * this.intoByteArray(ra, 0, ByteOrder.native());
+ * this.intoMemorySegment(ms, 0, ByteOrder.native());
* int origin = part * ranSize;
- * return species.fromByteArray(ra, origin, ByteOrder.native());
+ * return species.fromMemorySegment(ms, origin, ByteOrder.native());
* } else { // contraction or size-invariant
* int origin = (-part) * domSize;
- * this.intoByteArray(ra, origin, ByteOrder.native());
- * return species.fromByteArray(ra, 0, ByteOrder.native());
+ * this.intoMemorySegment(ms, origin, ByteOrder.native());
+ * return species.fromMemorySegment(ms, 0, ByteOrder.native());
* }
* }</pre>
*
* @apiNote Although this method is defined as if the vectors in
* question were loaded or stored into memory, memory semantics
* within the same vector, such as
* {@link Vector#reinterpretAsInts()}.
*
* @return a {@code ByteVector} with the same shape and information content
* @see Vector#reinterpretShape(VectorSpecies,int)
- * @see IntVector#intoByteArray(byte[], int, ByteOrder)
- * @see FloatVector#intoByteArray(byte[], int, ByteOrder)
+ * @see IntVector#intoMemorySegment(jdk.incubator.foreign.MemorySegment, long, java.nio.ByteOrder)
+ * @see FloatVector#intoMemorySegment(jdk.incubator.foreign.MemorySegment, long, java.nio.ByteOrder)
* @see VectorSpecies#withLanes(Class)
*/
public abstract ByteVector reinterpretAsBytes();
/**
public abstract <F> Vector<F> check(VectorSpecies<F> species);
//Array stores
/**
- * Stores this vector into a byte array starting at an offset
- * using explicit byte order.
+ * Stores this vector into a {@linkplain MemorySegment memory segment}
+ * starting at an offset using explicit byte order.
* <p>
* Bytes are extracted from primitive lane elements according
* to the specified byte ordering.
* The lanes are stored according to their
* <a href="Vector.html#lane-order">memory ordering</a>.
* <p>
* This method behaves as if it calls
- * {@link #intoByteBuffer(ByteBuffer,int,ByteOrder,VectorMask)
- * intoByteBuffer()} as follows:
+ * {@link #intoMemorySegment(MemorySegment,long,ByteOrder,VectorMask)
+ * intoMemorySegment()} as follows:
* <pre>{@code
- * var bb = ByteBuffer.wrap(a);
* var m = maskAll(true);
- * intoByteBuffer(bb, offset, bo, m);
+ * intoMemorySegment(ms, offset, bo, m);
* }</pre>
*
- * @param a the byte array
- * @param offset the offset into the array
+ * @param ms the memory segment
+ * @param offset the offset into the memory segment
* @param bo the intended byte order
* @throws IndexOutOfBoundsException
* if {@code offset+N*ESIZE < 0}
- * or {@code offset+(N+1)*ESIZE > a.length}
+ * or {@code offset+(N+1)*ESIZE > ms.byteSize()}
* for any lane {@code N} in the vector
+ * @throws UnsupportedOperationException
+ * if the memory segment is read-only
+ * @throws IllegalArgumentException if the memory segment is a heap segment that is
+ * not backed by a {@code byte[]} array.
+ * @throws IllegalStateException if the memory segment's session is not alive,
+ * or if access occurs from a thread other than the thread owning the session.
+ * @since 19
*/
- public abstract void intoByteArray(byte[] a, int offset,
- ByteOrder bo);
+ public abstract void intoMemorySegment(MemorySegment ms, long offset, ByteOrder bo);
/**
- * Stores this vector into a byte array starting at an offset
- * using explicit byte order and a mask.
- * <p>
- * Bytes are extracted from primitive lane elements according
- * to the specified byte ordering.
- * The lanes are stored according to their
- * <a href="Vector.html#lane-order">memory ordering</a>.
- * <p>
- * This method behaves as if it calls
- * {@link #intoByteBuffer(ByteBuffer,int,ByteOrder,VectorMask)
- * intoByteBuffer()} as follows:
- * <pre>{@code
- * var bb = ByteBuffer.wrap(a);
- * intoByteBuffer(bb, offset, bo, m);
- * }</pre>
- *
- * @param a the byte array
- * @param offset the offset into the array
- * @param bo the intended byte order
- * @param m the mask controlling lane selection
- * @throws IndexOutOfBoundsException
- * if {@code offset+N*ESIZE < 0}
- * or {@code offset+(N+1)*ESIZE > a.length}
- * for any lane {@code N} in the vector
- * where the mask is set
- */
- public abstract void intoByteArray(byte[] a, int offset,
- ByteOrder bo,
- VectorMask<E> m);
-
- /**
- * Stores this vector into a byte buffer starting at an offset
- * using explicit byte order.
- * <p>
- * Bytes are extracted from primitive lane elements according
- * to the specified byte ordering.
- * The lanes are stored according to their
- * <a href="Vector.html#lane-order">memory ordering</a>.
- * <p>
- * This method behaves as if it calls
- * {@link #intoByteBuffer(ByteBuffer,int,ByteOrder,VectorMask)
- * intoByteBuffer()} as follows:
- * <pre>{@code
- * var m = maskAll(true);
- * intoByteBuffer(bb, offset, bo, m);
- * }</pre>
- *
- * @param bb the byte buffer
- * @param offset the offset into the array
- * @param bo the intended byte order
- * @throws IndexOutOfBoundsException
- * if {@code offset+N*ESIZE < 0}
- * or {@code offset+(N+1)*ESIZE > bb.limit()}
- * for any lane {@code N} in the vector
- * @throws java.nio.ReadOnlyBufferException
- * if the byte buffer is read-only
- */
- public abstract void intoByteBuffer(ByteBuffer bb, int offset, ByteOrder bo);
-
- /**
- * Stores this vector into a byte buffer starting at an offset
- * using explicit byte order and a mask.
+ * Stores this vector into a {@linkplain MemorySegment memory segment}
+ * starting at an offset using explicit byte order and a mask.
* <p>
* Bytes are extracted from primitive lane elements according
* to the specified byte ordering.
* The lanes are stored according to their
* <a href="Vector.html#lane-order">memory ordering</a>.
* <p>
* The following pseudocode illustrates the behavior, where
- * the primitive element type is not of {@code byte},
- * {@code EBuffer} is the primitive buffer type, {@code ETYPE} is the
+ * {@code JAVA_E} is the layout of the primitive element type, {@code ETYPE} is the
* primitive element type, and {@code EVector} is the primitive
* vector type for this vector:
* <pre>{@code
- * EBuffer eb = bb.duplicate()
- * .position(offset)
- * .order(bo).asEBuffer();
* ETYPE[] a = this.toArray();
+ * var slice = ms.asSlice(offset)
* for (int n = 0; n < a.length; n++) {
* if (m.laneIsSet(n)) {
- * eb.put(n, a[n]);
+ * slice.setAtIndex(ValueLayout.JAVA_E.withBitAlignment(8), n);
* }
* }
* }</pre>
- * When the primitive element type is of {@code byte} the primitive
- * byte buffer is obtained as follows, where operation on the buffer
- * remains the same as in the prior pseudocode:
- * <pre>{@code
- * ByteBuffer eb = bb.duplicate()
- * .position(offset);
- * }</pre>
*
* @implNote
* This operation is likely to be more efficient if
* the specified byte order is the same as
* {@linkplain ByteOrder#nativeOrder()
* the bytes of lane values.
* In the special case where {@code ETYPE} is
* {@code byte}, the byte order argument is
* ignored.
*
- * @param bb the byte buffer
- * @param offset the offset into the array
+ * @param ms the memory segment
+ * @param offset the offset into the memory segment
* @param bo the intended byte order
* @param m the mask controlling lane selection
* @throws IndexOutOfBoundsException
* if {@code offset+N*ESIZE < 0}
- * or {@code offset+(N+1)*ESIZE > bb.limit()}
+ * or {@code offset+(N+1)*ESIZE > ms.byteSize()}
* for any lane {@code N} in the vector
* where the mask is set
- * @throws java.nio.ReadOnlyBufferException
- * if the byte buffer is read-only
- */
- public abstract void intoByteBuffer(ByteBuffer bb, int offset,
- ByteOrder bo, VectorMask<E> m);
+ * @throws UnsupportedOperationException
+ * if the memory segment is read-only
+ * @throws IllegalArgumentException if the memory segment is a heap segment that is
+ * not backed by a {@code byte[]} array.
+ * @throws IllegalStateException if the memory segment's session is not alive,
+ * or if access occurs from a thread other than the thread owning the session.
+ * @since 19
+ */
+ public abstract void intoMemorySegment(MemorySegment ms, long offset,
+ ByteOrder bo, VectorMask<E> m);
/**
* Returns a packed array containing all the lane values.
* The array length is the same as the vector length.
* The element type of the array is the same as the element
< prev index next >