9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have
23 * questions.
24 */
25 package jdk.incubator.vector;
26
27 import jdk.internal.misc.Unsafe;
28 import jdk.internal.vm.annotation.ForceInline;
29
30 import java.nio.ByteBuffer;
31 import java.nio.ByteOrder;
32 import java.util.function.IntUnaryOperator;
33 import jdk.incubator.vector.*;
34
35 /**
36 * A {@code Vector} is designed for use in computations that can be transformed
37 * by a runtime compiler, on supported hardware, to Single Instruction Multiple
38 * Data (SIMD) computations leveraging vector hardware registers and vector
39 * hardware instructions. Such SIMD computations exploit data parallelism to
40 * perform the same operation on multiple data points simultaneously in a
41 * faster time it would ordinarily take to perform the same operation
42 * sequentially on each data point.
43 * <p>
44 * A Vector represents an ordered immutable sequence of values of the same
45 * element type {@code e} that is one of the following primitive types
46 * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or
47 * {@code double}). The type variable {@code E} corresponds to the boxed
48 * element type, specifically the class that wraps a value of {@code e} in an
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
938 *
939 * @param s the species describing the element type
992 *
993 * @return the box type
994 */
995 abstract Class<?> boxType();
996
997 /**
998 * Returns the vector mask type for this species
999 *
1000 * @return the box type
1001 */
1002 abstract Class<?> maskType();
1003
1004 /**
1005 * Returns the element size, in bits, of vectors produced by this
1006 * species.
1007 *
1008 * @return the element size, in bits
1009 */
1010 public abstract int elementSize();
1011
1012 abstract Class<?> vectorType();
1013
1014 /**
1015 * Returns the shape of masks, shuffles, and vectors produced by this
1016 * species.
1017 *
1018 * @return the primitive element type
1019 */
1020 public abstract Shape shape();
1021
1022 /**
1023 * Returns the mask, shuffe, or vector lanes produced by this species.
1024 *
1025 * @return the the number of lanes
1026 */
1027 public int length() { return shape().length(this); }
1028
1029 /**
1030 * Returns the total vector size, in bits, of vectors produced by this
1031 * species.
1032 *
1033 * @return the total vector size, in bits
1034 */
1035 public int bitSize() { return shape().bitSize(); }
1036
1037 // Factory
1038
1039 /**
1040 * Finds a species for an element type and shape.
1041 *
1042 * @param c the element type
1068 }
1069 else {
1070 throw new IllegalArgumentException("Bad vector element type: " + c.getName());
1071 }
1072 }
1073
1074 /**
1075 * Finds a preferred species for an element type.
1076 * <p>
1077 * A preferred species is a species chosen by the platform that has a
1078 * shape of maximal bit size. A preferred species for different element
1079 * types will have the same shape, and therefore vectors created from
1080 * such species will be shape compatible.
1081 *
1082 * @param c the element type
1083 * @param <E> the boxed element type
1084 * @return a preferred species for an element type
1085 * @throws IllegalArgumentException if no such species exists for the
1086 * element type
1087 */
1088 @SuppressWarnings("unchecked")
1089 public static <E> Vector.Species<E> ofPreferred(Class<E> c) {
1090 Unsafe u = Unsafe.getUnsafe();
1091
1092 int vectorLength = u.getMaxVectorSize(c);
1093 int vectorBitSize = bitSizeForVectorLength(c, vectorLength);
1094 Shape s = Shape.forBitSize(vectorBitSize);
1095 return Species.of(c, s);
1096 }
1097
1098 /**
1099 * Returns a vector where all lane elements are set to the default
1100 * primitive value.
1101 *
1102 * @return a zero vector
1103 */
1104 public abstract Vector<E> zero();
1105
1106 /**
1107 * Converts a given mask of shape {@code T} and element type
1108 * {@code F} to a mask of this species shape {@code S} and element
1109 * type {@code E}.
1110 * <p>
1111 * For each mask lane, where {@code N} is the mask lane index, if the
1112 * mask lane at index {@code N} is set, then the mask lane at index
1113 * {@code N} of the resulting mask is set, otherwise that mask lane is
1114 * not set.
1115 *
1116 * @param m the mask
1117 * @param <F> the boxed element type of the mask
1118 * @return a mask, converted by shape and element type, from a given
1119 * mask.
1120 * @throws IllegalArgumentException if the mask length and this species
1121 * length differ
1122 */
1123 public abstract <F> Mask<E> cast(Mask<F> m);
1124
1125 /**
1126 * Converts a given shuffle of shape {@code T} and element type
1127 * {@code F} to a shuffle of this species shape {@code S} and element
1128 * type {@code E}.
1129 * <p>
1130 * For each shuffle lane, where {@code N} is the mask lane index, the
1131 * shuffle element at index {@code N} is placed, unmodified, into the
1132 * resulting shuffle at index {@code N}.
1133 *
1134 * @param s the shuffle
1135 * @param <F> the boxed element type of the mask
1136 * @return a shuffle, converted by shape and element type, from a given
1137 * shuffle.
1138 * @throws IllegalArgumentException if the shuffle length and this
1139 * species length differ
1140 */
1141 public abstract <F> Shuffle<E> cast(Shuffle<F> s);
1142 }
1143
1144 /**
1145 * A {@code Mask} represents an ordered immutable sequence of {@code boolean}
1146 * values. A Mask can be used with a mask accepting vector operation to
1147 * control the selection and operation of lane elements of input vectors.
1148 * <p>
1149 * The number of values in the sequence is referred to as the Mask
1150 * {@link #length() length}. The length also corresponds to the number of
1151 * Mask lanes. The lane element at lane index {@code N} (from {@code 0},
1152 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th
1153 * value in the sequence.
1154 * A Mask and Vector of the same element type and shape have the same number
1155 * of lanes.
1156 * <p>
1157 * A lane is said to be <em>set</em> if the lane element is {@code true},
1158 * otherwise a lane is said to be <em>unset</em> if the lane element is
1159 * {@code false}.
1160 * <p>
1161 * Mask declares a limited set of unary, binary and reductive 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.
1249 *
1250 * @return the lane elements of this mask packed into a {@code long}
1251 * value.
1252 */
1253 public abstract long toLong();
1254
1255 /**
1256 * Returns an {@code boolean} array containing the lane elements of this
1257 * mask.
1406 /**
1407 * Returns the number of shuffle lanes (the length).
1408 *
1409 * @return the number of shuffle lanes
1410 */
1411 public int length() { return species().length(); }
1412
1413 /**
1414 * Converts this shuffle to a shuffle of the given species of element type {@code F}.
1415 * <p>
1416 * For each shuffle lane, where {@code N} is the lane index, the
1417 * shuffle element at index {@code N} is placed, unmodified, into the
1418 * resulting shuffle at index {@code N}.
1419 *
1420 * @param species species of desired shuffle
1421 * @param <F> the boxed element type of the species
1422 * @return a shuffle converted by shape and element type
1423 * @throws IllegalArgumentException if this shuffle length and the
1424 * species length differ
1425 */
1426 @ForceInline
1427 public <F> Shuffle<F> cast(Species<F> species) {
1428 return species.cast(this);
1429 }
1430
1431 /**
1432 * Returns an {@code int} array containing the lane elements of this
1433 * shuffle.
1434 * <p>
1435 * This method behaves as if it {@link #intoArray(int[], int)} stores}
1436 * this shuffle into an allocated array and returns that array as
1437 * follows:
1438 * <pre>{@code
1439 * int[] a = new int[this.length()];
1440 * this.intoArray(a, 0);
1441 * return a;
1442 * }</pre>
1443 *
1444 * @return an array containing the the lane elements of this vector
1445 */
1446 public abstract int[] toArray();
1447
1448 /**
1449 * Stores this shuffle into an {@code int} array starting at offset.
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have
23 * questions.
24 */
25 package jdk.incubator.vector;
26
27 import jdk.internal.misc.Unsafe;
28 import jdk.internal.vm.annotation.ForceInline;
29 import jdk.internal.vm.annotation.Stable;
30
31 import java.nio.ByteBuffer;
32 import java.nio.ByteOrder;
33 import java.util.function.IntUnaryOperator;
34 import jdk.incubator.vector.*;
35
36 /**
37 * A {@code Vector} is designed for use in computations that can be transformed
38 * by a runtime compiler, on supported hardware, to Single Instruction Multiple
39 * Data (SIMD) computations leveraging vector hardware registers and vector
40 * hardware instructions. Such SIMD computations exploit data parallelism to
41 * perform the same operation on multiple data points simultaneously in a
42 * faster time it would ordinarily take to perform the same operation
43 * sequentially on each data point.
44 * <p>
45 * A Vector represents an ordered immutable sequence of values of the same
46 * element type {@code e} that is one of the following primitive types
47 * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or
48 * {@code double}). The type variable {@code E} corresponds to the boxed
49 * element type, specifically the class that wraps a value of {@code e} in an
901 public abstract void intoByteBuffer(ByteBuffer b, int i, Mask<E> m);
902
903
904 /**
905 * A {@code Shape} governs the total size, in bits, of a
906 * {@link Vector}, {@link Mask}, or {@link Shuffle}. The shape in
907 * combination with the element type together govern the number of lanes.
908 */
909 public enum Shape {
910 /** Shape of length 64 bits */
911 S_64_BIT(64),
912 /** Shape of length 128 bits */
913 S_128_BIT(128),
914 /** Shape of length 256 bits */
915 S_256_BIT(256),
916 /** Shape of length 512 bits */
917 S_512_BIT(512),
918 /** Shape of maximum length supported on the platform */
919 S_Max_BIT(Unsafe.getUnsafe().getMaxVectorSize(byte.class) * 8);
920
921 @Stable
922 final int bitSize;
923
924 Shape(int bitSize) {
925 this.bitSize = bitSize;
926 }
927
928 /**
929 * Returns the size, in bits, of this shape.
930 *
931 * @return the size, in bits, of this shape.
932 */
933 public int bitSize() {
934 return bitSize;
935 }
936
937 /**
938 * Return the number of lanes of a vector of this shape and whose element
939 * type is of the provided species
940 *
941 * @param s the species describing the element type
994 *
995 * @return the box type
996 */
997 abstract Class<?> boxType();
998
999 /**
1000 * Returns the vector mask type for this species
1001 *
1002 * @return the box type
1003 */
1004 abstract Class<?> maskType();
1005
1006 /**
1007 * Returns the element size, in bits, of vectors produced by this
1008 * species.
1009 *
1010 * @return the element size, in bits
1011 */
1012 public abstract int elementSize();
1013
1014 /**
1015 * Returns the shape of masks, shuffles, and vectors produced by this
1016 * species.
1017 *
1018 * @return the primitive element type
1019 */
1020 public abstract Shape shape();
1021
1022 /**
1023 * Returns the shape of the corresponding index species
1024 * @return the shape
1025 */
1026 @ForceInline
1027 public abstract Shape indexShape();
1028
1029 /**
1030 * Returns the mask, shuffe, or vector lanes produced by this species.
1031 *
1032 * @return the the number of lanes
1033 */
1034 public int length() { return shape().length(this); }
1035
1036 /**
1037 * Returns the total vector size, in bits, of vectors produced by this
1038 * species.
1039 *
1040 * @return the total vector size, in bits
1041 */
1042 public int bitSize() { return shape().bitSize(); }
1043
1044 // Factory
1045
1046 /**
1047 * Finds a species for an element type and shape.
1048 *
1049 * @param c the element type
1075 }
1076 else {
1077 throw new IllegalArgumentException("Bad vector element type: " + c.getName());
1078 }
1079 }
1080
1081 /**
1082 * Finds a preferred species for an element type.
1083 * <p>
1084 * A preferred species is a species chosen by the platform that has a
1085 * shape of maximal bit size. A preferred species for different element
1086 * types will have the same shape, and therefore vectors created from
1087 * such species will be shape compatible.
1088 *
1089 * @param c the element type
1090 * @param <E> the boxed element type
1091 * @return a preferred species for an element type
1092 * @throws IllegalArgumentException if no such species exists for the
1093 * element type
1094 */
1095 public static <E> Vector.Species<E> ofPreferred(Class<E> c) {
1096 Unsafe u = Unsafe.getUnsafe();
1097
1098 int vectorLength = u.getMaxVectorSize(c);
1099 int vectorBitSize = bitSizeForVectorLength(c, vectorLength);
1100 Shape s = Shape.forBitSize(vectorBitSize);
1101 return Species.of(c, s);
1102 }
1103 }
1104
1105 abstract static class AbstractSpecies<E> extends Vector.Species<E> {
1106 @Stable
1107 protected final Vector.Shape shape;
1108 @Stable
1109 protected final Class<E> elementType;
1110 @Stable
1111 protected final int elementSize;
1112 @Stable
1113 protected final Class<?> boxType;
1114 @Stable
1115 protected final Class<?> maskType;
1116 @Stable
1117 protected final Shape indexShape;
1118
1119 AbstractSpecies(Vector.Shape shape, Class<E> elementType, int elementSize, Class<?> boxType, Class<?> maskType) {
1120 this.shape = shape;
1121 this.elementType = elementType;
1122 this.elementSize = elementSize;
1123 this.boxType = boxType;
1124 this.maskType = maskType;
1125
1126 if (boxType == Long64Vector.class || boxType == Double64Vector.class) {
1127 indexShape = Vector.Shape.S_64_BIT;
1128 }
1129 else {
1130 int bitSize = Vector.bitSizeForVectorLength(int.class, shape.bitSize() / elementSize);
1131 indexShape = Vector.Shape.forBitSize(bitSize);
1132 }
1133 }
1134
1135 @Override
1136 @ForceInline
1137 public int bitSize() {
1138 return shape.bitSize();
1139 }
1140
1141 @Override
1142 @ForceInline
1143 public int length() {
1144 return shape.bitSize() / elementSize;
1145 }
1146
1147 @Override
1148 @ForceInline
1149 public Class<E> elementType() {
1150 return elementType;
1151 }
1152
1153 @Override
1154 @ForceInline
1155 public Class<?> boxType() {
1156 return boxType;
1157 }
1158
1159 @Override
1160 @ForceInline
1161 public Class<?> maskType() {
1162 return maskType;
1163 }
1164
1165 @Override
1166 @ForceInline
1167 public int elementSize() {
1168 return elementSize;
1169 }
1170
1171 @Override
1172 @ForceInline
1173 public Vector.Shape shape() {
1174 return shape;
1175 }
1176
1177 @Override
1178 @ForceInline
1179 public Vector.Shape indexShape() { return indexShape; }
1180
1181 @Override
1182 public String toString() {
1183 return new StringBuilder("Shape[")
1184 .append(bitSize()).append(" bits, ")
1185 .append(length()).append(" ").append(elementType.getSimpleName()).append("s x ")
1186 .append(elementSize()).append(" bits")
1187 .append("]")
1188 .toString();
1189 }
1190 }
1191
1192 /**
1193 * A {@code Mask} represents an ordered immutable sequence of {@code boolean}
1194 * values. A Mask can be used with a mask accepting vector operation to
1195 * control the selection and operation of lane elements of input vectors.
1196 * <p>
1197 * The number of values in the sequence is referred to as the Mask
1198 * {@link #length() length}. The length also corresponds to the number of
1199 * Mask lanes. The lane element at lane index {@code N} (from {@code 0},
1200 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th
1201 * value in the sequence.
1202 * A Mask and Vector of the same element type and shape have the same number
1203 * of lanes.
1204 * <p>
1205 * A lane is said to be <em>set</em> if the lane element is {@code true},
1206 * otherwise a lane is said to be <em>unset</em> if the lane element is
1207 * {@code false}.
1208 * <p>
1209 * Mask declares a limited set of unary, binary and reductive mask
1256 *
1257 * @return the species of this mask
1258 */
1259 public abstract Species<E> species();
1260
1261 /**
1262 * Returns the number of mask lanes (the length).
1263 *
1264 * @return the number of mask lanes
1265 */
1266 public int length() { return species().length(); }
1267
1268 /**
1269 * Converts this mask to a mask of the given species shape of element type {@code F}.
1270 * <p>
1271 * For each mask lane, where {@code N} is the lane index, if the
1272 * mask lane at index {@code N} is set, then the mask lane at index
1273 * {@code N} of the resulting mask is set, otherwise that mask lane is
1274 * not set.
1275 *
1276 * @param s the species of the desired mask
1277 * @param <F> the boxed element type of the species
1278 * @return a mask converted by shape and element type
1279 * @throws IllegalArgumentException if this mask length and the species
1280 * length differ
1281 */
1282 public abstract <F> Mask<F> cast(Species<F> s);
1283
1284 /**
1285 * Returns the lane elements of this mask packed into a {@code long}
1286 * value for at most the first 64 lane elements.
1287 * <p>
1288 * The lane elements are packed in the order of least significant bit
1289 * to most significant bit.
1290 * For each mask lane where {@code N} is the mask lane index, if the
1291 * mask lane is set then the {@code N}'th bit is set to one in the
1292 * resulting {@code long} value, otherwise the {@code N}'th bit is set
1293 * to zero.
1294 *
1295 * @return the lane elements of this mask packed into a {@code long}
1296 * value.
1297 */
1298 public abstract long toLong();
1299
1300 /**
1301 * Returns an {@code boolean} array containing the lane elements of this
1302 * mask.
1451 /**
1452 * Returns the number of shuffle lanes (the length).
1453 *
1454 * @return the number of shuffle lanes
1455 */
1456 public int length() { return species().length(); }
1457
1458 /**
1459 * Converts this shuffle to a shuffle of the given species of element type {@code F}.
1460 * <p>
1461 * For each shuffle lane, where {@code N} is the lane index, the
1462 * shuffle element at index {@code N} is placed, unmodified, into the
1463 * resulting shuffle at index {@code N}.
1464 *
1465 * @param species species of desired shuffle
1466 * @param <F> the boxed element type of the species
1467 * @return a shuffle converted by shape and element type
1468 * @throws IllegalArgumentException if this shuffle length and the
1469 * species length differ
1470 */
1471 public abstract <F> Shuffle<F> cast(Species<F> species);
1472
1473 /**
1474 * Returns an {@code int} array containing the lane elements of this
1475 * shuffle.
1476 * <p>
1477 * This method behaves as if it {@link #intoArray(int[], int)} stores}
1478 * this shuffle into an allocated array and returns that array as
1479 * follows:
1480 * <pre>{@code
1481 * int[] a = new int[this.length()];
1482 * this.intoArray(a, 0);
1483 * return a;
1484 * }</pre>
1485 *
1486 * @return an array containing the the lane elements of this vector
1487 */
1488 public abstract int[] toArray();
1489
1490 /**
1491 * Stores this shuffle into an {@code int} array starting at offset.
|