813 * @throws IndexOutOfBoundsException if {@code i < 0} or
814 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
815 */
816 public abstract void intoByteArray(byte[] a, int i);
817
818 /**
819 * Stores this vector into a byte array starting at an offset and using a mask.
820 * <p>
821 * Bytes are extracted from primitive lane elements according to the
822 * native byte order of the underlying platform.
823 * <p>
824 * This method behaves as it calls the
825 * byte buffer, offset, and mask accepting
826 * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows:
827 * <pre>{@code
828 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m);
829 * }</pre>
830 *
831 * @param a the byte array
832 * @param i the offset into the array
833 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
834 * or {@code > a.length},
835 * for any vector lane index {@code N} where the mask at lane {@code N}
836 * is set
837 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
838 */
839 public abstract void intoByteArray(byte[] a, int i, Mask<E> m);
840
841 /**
842 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an
843 * offset into the byte buffer.
844 * <p>
845 * Bytes are extracted from primitive lane elements according to the
846 * native byte order of the underlying platform.
847 * <p>
848 * This method behaves as if it calls the byte buffer, offset, and mask
849 * accepting
850 * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows:
851 * <pre>{@code
852 * this.intoByteBuffer(b, i, this.maskAllTrue())
884 * if (m.isSet(n)) {
885 * eb.put(n, es[n]);
886 * }
887 * }
888 * }</pre>
889 *
890 * @param b the byte buffer
891 * @param i the offset into the byte buffer
892 * @param m the mask
893 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
894 * or {@code > b.limit()},
895 * for any vector lane index {@code N} where the mask at lane {@code N}
896 * is set
897 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes
898 */
899 public abstract void intoByteBuffer(ByteBuffer b, int i, Mask<E> m);
900
901
902 /**
903 * A {@code Shape} governs the total size, in bits, of a
904 * {@link Vector}, {@link Mask}, or {@code Shuffle}. The shape in
905 * combination with the element type together govern the number of lanes.
906 */
907 public enum Shape {
908 S_64_BIT(64),
909 S_128_BIT(128),
910 S_256_BIT(256),
911 S_512_BIT(512),
912 S_Max_BIT(Unsafe.getUnsafe().getMaxVectorSize(byte.class) * 8);
913
914 final int bitSize;
915
916 Shape(int bitSize) {
917 this.bitSize = bitSize;
918 }
919
920 /**
921 * Returns the size, in bits, of this shape.
922 *
923 * @return the size, in bits, of this shape.
924 */
925 public int bitSize() {
926 return bitSize;
927 }
928
929 /**
930 * Return the number of lanes of a vector of this shape and whose element
931 * type is of the provided species
949 case 64:
950 return Shape.S_64_BIT;
951 case 128:
952 return Shape.S_128_BIT;
953 case 256:
954 return Shape.S_256_BIT;
955 case 512:
956 return Shape.S_512_BIT;
957 default:
958 if ((bitSize > 0) && (bitSize <= 2048) && (bitSize % 128 == 0)) {
959 return Shape.S_Max_BIT;
960 } else {
961 throw new IllegalArgumentException("Bad vector bit size: " + bitSize);
962 }
963 }
964 }
965 }
966
967
968 /**
969 * A factory for creating {@link Vector}, {@link Mask} and {@link Shuffle}
970 * values of the same element type and shape.
971 *
972 * @param <E> the boxed element type of this species
973 */
974 public static abstract class Species<E> {
975 Species() {}
976
977 /**
978 * Returns the primitive element type of vectors produced by this
979 * species.
980 *
981 * @return the primitive element type
982 */
983 public abstract Class<E> elementType();
984
985 /**
986 * Returns the vector box type for this species
987 *
988 * @return the box type
989 */
990 abstract Class<?> boxType();
1175 *
1176 * <li>
1177 * A mask binary operation (2-ary) operates on two input
1178 * masks to produce a result mask.
1179 * For each lane of the two input masks,
1180 * a and b say, the corresponding lane elements from a and b are operated on
1181 * using the specified scalar binary operation and the boolean result is placed
1182 * into the mask result at the same lane.
1183 * The following pseudocode expresses the behaviour of this operation category:
1184 *
1185 * <pre>{@code
1186 * Mask<E> a = ...;
1187 * Mask<E> b = ...;
1188 * boolean[] ar = new boolean[a.length()];
1189 * for (int i = 0; i < a.length(); i++) {
1190 * ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i));
1191 * }
1192 * Mask<E> r = a.species().maskFromArray(ar, 0);
1193 * }</pre>
1194 *
1195 * @param <E> the boxed element type of this mask
1196 */
1197 public static abstract class Mask<E> {
1198 Mask() {}
1199
1200 /**
1201 * Returns the species of this mask.
1202 *
1203 * @return the species of this mask
1204 */
1205 public abstract Species<E> species();
1206
1207 /**
1208 * Returns the number of mask lanes (the length).
1209 *
1210 * @return the number of mask lanes
1211 */
1212 public int length() { return species().length(); }
1213
1214 /**
1215 * Converts this mask to a mask of the given species shape of element type {@code F}.
1216 * <p>
1217 * For each mask lane, where {@code N} is the lane index, if the
1218 * mask lane at index {@code N} is set, then the mask lane at index
1219 * {@code N} of the resulting mask is set, otherwise that mask lane is
1220 * not set.
1221 *
1222 * @param s the species of the desired mask
1223 * @param <F> the boxed element type of the species
1224 * @return a mask converted by shape and element type
1225 * @throws IllegalArgumentException if this mask length and the species
1226 * length differ
1227 */
1228 @ForceInline
1229 public <F> Mask<F> cast(Species<F> species) {
1230 return species.cast(this);
1231 }
1232
1233 /**
1234 * Returns the lane elements of this mask packed into a {@code long}
1235 * value for at most the first 64 lane elements.
1236 * <p>
1237 * The lane elements are packed in the order of least significant bit
1238 * to most significant bit.
1239 * For each mask lane where {@code N} is the mask lane index, if the
1240 * mask lane is set then the {@code N}'th bit is set to one in the
1241 * resulting {@code long} value, otherwise the {@code N}'th bit is set
1242 * to zero.
|
813 * @throws IndexOutOfBoundsException if {@code i < 0} or
814 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
815 */
816 public abstract void intoByteArray(byte[] a, int i);
817
818 /**
819 * Stores this vector into a byte array starting at an offset and using a mask.
820 * <p>
821 * Bytes are extracted from primitive lane elements according to the
822 * native byte order of the underlying platform.
823 * <p>
824 * This method behaves as it calls the
825 * byte buffer, offset, and mask accepting
826 * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows:
827 * <pre>{@code
828 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m);
829 * }</pre>
830 *
831 * @param a the byte array
832 * @param i the offset into the array
833 * @param m the mask controlling lane selection
834 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
835 * or {@code > a.length},
836 * for any vector lane index {@code N} where the mask at lane {@code N}
837 * is set
838 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
839 */
840 public abstract void intoByteArray(byte[] a, int i, Mask<E> m);
841
842 /**
843 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an
844 * offset into the byte buffer.
845 * <p>
846 * Bytes are extracted from primitive lane elements according to the
847 * native byte order of the underlying platform.
848 * <p>
849 * This method behaves as if it calls the byte buffer, offset, and mask
850 * accepting
851 * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows:
852 * <pre>{@code
853 * this.intoByteBuffer(b, i, this.maskAllTrue())
885 * if (m.isSet(n)) {
886 * eb.put(n, es[n]);
887 * }
888 * }
889 * }</pre>
890 *
891 * @param b the byte buffer
892 * @param i the offset into the byte buffer
893 * @param m the mask
894 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
895 * or {@code > b.limit()},
896 * for any vector lane index {@code N} where the mask at lane {@code N}
897 * is set
898 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes
899 */
900 public abstract void intoByteBuffer(ByteBuffer b, int i, Mask<E> m);
901
902
903 /**
904 * A {@code Shape} governs the total size, in bits, of a
905 * {@link Vector}, {@link Mask}, or {@link Shuffle}. The shape in
906 * combination with the element type together govern the number of lanes.
907 */
908 public enum Shape {
909 /** Shape of length 64 bits */
910 S_64_BIT(64),
911 /** Shape of length 128 bits */
912 S_128_BIT(128),
913 /** Shape of length 256 bits */
914 S_256_BIT(256),
915 /** Shape of length 512 bits */
916 S_512_BIT(512),
917 /** Shape of maximum length supported on the platform */
918 S_Max_BIT(Unsafe.getUnsafe().getMaxVectorSize(byte.class) * 8);
919
920 final int bitSize;
921
922 Shape(int bitSize) {
923 this.bitSize = bitSize;
924 }
925
926 /**
927 * Returns the size, in bits, of this shape.
928 *
929 * @return the size, in bits, of this shape.
930 */
931 public int bitSize() {
932 return bitSize;
933 }
934
935 /**
936 * Return the number of lanes of a vector of this shape and whose element
937 * type is of the provided species
955 case 64:
956 return Shape.S_64_BIT;
957 case 128:
958 return Shape.S_128_BIT;
959 case 256:
960 return Shape.S_256_BIT;
961 case 512:
962 return Shape.S_512_BIT;
963 default:
964 if ((bitSize > 0) && (bitSize <= 2048) && (bitSize % 128 == 0)) {
965 return Shape.S_Max_BIT;
966 } else {
967 throw new IllegalArgumentException("Bad vector bit size: " + bitSize);
968 }
969 }
970 }
971 }
972
973
974 /**
975 * Class representing vectors of same element type, {@code E} and {@link Vector.Shape Shape}.
976 *
977 * @param <E> the boxed element type of this species
978 */
979 public static abstract class Species<E> {
980 Species() {}
981
982 /**
983 * Returns the primitive element type of vectors produced by this
984 * species.
985 *
986 * @return the primitive element type
987 */
988 public abstract Class<E> elementType();
989
990 /**
991 * Returns the vector box type for this species
992 *
993 * @return the box type
994 */
995 abstract Class<?> boxType();
1180 *
1181 * <li>
1182 * A mask binary operation (2-ary) operates on two input
1183 * masks to produce a result mask.
1184 * For each lane of the two input masks,
1185 * a and b say, the corresponding lane elements from a and b are operated on
1186 * using the specified scalar binary operation and the boolean result is placed
1187 * into the mask result at the same lane.
1188 * The following pseudocode expresses the behaviour of this operation category:
1189 *
1190 * <pre>{@code
1191 * Mask<E> a = ...;
1192 * Mask<E> b = ...;
1193 * boolean[] ar = new boolean[a.length()];
1194 * for (int i = 0; i < a.length(); i++) {
1195 * ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i));
1196 * }
1197 * Mask<E> r = a.species().maskFromArray(ar, 0);
1198 * }</pre>
1199 *
1200 * </ul>
1201 * @param <E> the boxed element type of this mask
1202 */
1203 public static abstract class Mask<E> {
1204 Mask() {}
1205
1206 /**
1207 * Returns the species of this mask.
1208 *
1209 * @return the species of this mask
1210 */
1211 public abstract Species<E> species();
1212
1213 /**
1214 * Returns the number of mask lanes (the length).
1215 *
1216 * @return the number of mask lanes
1217 */
1218 public int length() { return species().length(); }
1219
1220 /**
1221 * Converts this mask to a mask of the given species shape of element type {@code F}.
1222 * <p>
1223 * For each mask lane, where {@code N} is the lane index, if the
1224 * mask lane at index {@code N} is set, then the mask lane at index
1225 * {@code N} of the resulting mask is set, otherwise that mask lane is
1226 * not set.
1227 *
1228 * @param species the species of the desired mask
1229 * @param <F> the boxed element type of the species
1230 * @return a mask converted by shape and element type
1231 * @throws IllegalArgumentException if this mask length and the species
1232 * length differ
1233 */
1234 @ForceInline
1235 public <F> Mask<F> cast(Species<F> species) {
1236 return species.cast(this);
1237 }
1238
1239 /**
1240 * Returns the lane elements of this mask packed into a {@code long}
1241 * value for at most the first 64 lane elements.
1242 * <p>
1243 * The lane elements are packed in the order of least significant bit
1244 * to most significant bit.
1245 * For each mask lane where {@code N} is the mask lane index, if the
1246 * mask lane is set then the {@code N}'th bit is set to one in the
1247 * resulting {@code long} value, otherwise the {@code N}'th bit is set
1248 * to zero.
|