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 java.nio.ByteBuffer;
28 import java.nio.ShortBuffer;
29 import java.nio.ByteOrder;
30 import java.util.Objects;
31 import java.util.function.IntUnaryOperator;
32 import java.util.concurrent.ThreadLocalRandom;
33
34 import jdk.internal.misc.Unsafe;
35 import jdk.internal.vm.annotation.ForceInline;
36 import static jdk.incubator.vector.VectorIntrinsics.*;
37
38
39 /**
40 * A specialized {@link Vector} representing an ordered immutable sequence of
41 * {@code short} values.
42 */
43 @SuppressWarnings("cast")
44 public abstract class ShortVector extends Vector<Short> {
45
46 ShortVector() {}
47
48 private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_SHORT_INDEX_SCALE);
49
50 // Unary operator
51
93
94 interface FUnCon {
95 void apply(int i, short a);
96 }
97
98 abstract void forEach(FUnCon f);
99
100 abstract void forEach(Mask<Short> m, FUnCon f);
101
102 // Static factories
103
104 /**
105 * Returns a vector where all lane elements are set to the default
106 * primitive value.
107 *
108 * @param species species of desired vector
109 * @return a zero vector of given species
110 */
111 @ForceInline
112 @SuppressWarnings("unchecked")
113 public static ShortVector zero(ShortSpecies species) {
114 return species.zero();
115 }
116
117 /**
118 * Loads a vector from a byte array starting at an offset.
119 * <p>
120 * Bytes are composed into primitive lane elements according to the
121 * native byte order of the underlying platform
122 * <p>
123 * This method behaves as if it returns the result of calling the
124 * byte buffer, offset, and mask accepting
125 * {@link #fromByteBuffer(ShortSpecies, ByteBuffer, int, Mask) method} as follows:
126 * <pre>{@code
127 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
128 * }</pre>
129 *
130 * @param species species of desired vector
131 * @param a the byte array
132 * @param ix the offset into the array
133 * @return a vector loaded from a byte array
134 * @throws IndexOutOfBoundsException if {@code i < 0} or
135 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
136 */
137 @ForceInline
138 @SuppressWarnings("unchecked")
139 public static ShortVector fromByteArray(ShortSpecies species, byte[] a, int ix) {
140 Objects.requireNonNull(a);
141 ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
142 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
143 a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
144 a, ix, species,
145 (c, idx, s) -> {
146 ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
147 ShortBuffer tb = bbc.asShortBuffer();
148 return ((ShortSpecies)s).op(i -> tb.get());
149 });
150 }
151
152 /**
153 * Loads a vector from a byte array starting at an offset and using a
154 * mask.
155 * <p>
156 * Bytes are composed into primitive lane elements according to the
157 * native byte order of the underlying platform.
158 * <p>
159 * This method behaves as if it returns the result of calling the
160 * byte buffer, offset, and mask accepting
161 * {@link #fromByteBuffer(ShortSpecies, ByteBuffer, int, Mask) method} as follows:
162 * <pre>{@code
163 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
164 * }</pre>
165 *
166 * @param species species of desired vector
167 * @param a the byte array
168 * @param ix the offset into the array
169 * @param m the mask
170 * @return a vector loaded from a byte array
171 * @throws IndexOutOfBoundsException if {@code i < 0} or
172 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
173 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
174 * or {@code > a.length},
175 * for any vector lane index {@code N} where the mask at lane {@code N}
176 * is set
177 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
178 */
179 @ForceInline
180 public static ShortVector fromByteArray(ShortSpecies species, byte[] a, int ix, Mask<Short> m) {
181 return zero(species).blend(fromByteArray(species, a, ix), m);
182 }
183
184 /**
185 * Loads a vector from an array starting at offset.
186 * <p>
187 * For each vector lane, where {@code N} is the vector lane index, the
188 * array element at index {@code i + N} is placed into the
189 * resulting vector at lane index {@code N}.
190 *
191 * @param species species of desired vector
192 * @param a the array
193 * @param i the offset into the array
194 * @return the vector loaded from an array
195 * @throws IndexOutOfBoundsException if {@code i < 0}, or
196 * {@code i > a.length - this.length()}
197 */
198 @ForceInline
199 @SuppressWarnings("unchecked")
200 public static ShortVector fromArray(ShortSpecies species, short[] a, int i){
201 Objects.requireNonNull(a);
202 i = VectorIntrinsics.checkIndex(i, a.length, species.length());
203 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
204 a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_SHORT_BASE_OFFSET,
205 a, i, species,
206 (c, idx, s) -> ((ShortSpecies)s).op(n -> c[idx + n]));
207 }
208
209
210 /**
211 * Loads a vector from an array starting at offset and using a mask.
212 * <p>
213 * For each vector lane, where {@code N} is the vector lane index,
214 * if the mask lane at index {@code N} is set then the array element at
215 * index {@code i + N} is placed into the resulting vector at lane index
216 * {@code N}, otherwise the default element value is placed into the
217 * resulting vector at lane index {@code N}.
218 *
219 * @param species species of desired vector
220 * @param a the array
221 * @param i the offset into the array
222 * @param m the mask
223 * @return the vector loaded from an array
224 * @throws IndexOutOfBoundsException if {@code i < 0}, or
225 * for any vector lane index {@code N} where the mask at lane {@code N}
226 * is set {@code i > a.length - N}
227 */
228 @ForceInline
229 public static ShortVector fromArray(ShortSpecies species, short[] a, int i, Mask<Short> m) {
230 return zero(species).blend(fromArray(species, a, i), m);
231 }
232
233 /**
234 * Loads a vector from an array using indexes obtained from an index
235 * map.
236 * <p>
237 * For each vector lane, where {@code N} is the vector lane index, the
238 * array element at index {@code i + indexMap[j + N]} is placed into the
239 * resulting vector at lane index {@code N}.
240 *
241 * @param species species of desired vector
242 * @param a the array
243 * @param i the offset into the array, may be negative if relative
244 * indexes in the index map compensate to produce a value within the
245 * array bounds
246 * @param indexMap the index map
247 * @param j the offset into the index map
248 * @return the vector loaded from an array
249 * @throws IndexOutOfBoundsException if {@code j < 0}, or
250 * {@code j > indexMap.length - this.length()},
251 * or for any vector lane index {@code N} the result of
252 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
253 */
254 public static ShortVector fromArray(ShortSpecies species, short[] a, int i, int[] indexMap, int j) {
255 return species.op(n -> a[i + indexMap[j + n]]);
256 }
257 /**
258 * Loads a vector from an array using indexes obtained from an index
259 * map and using a mask.
260 * <p>
261 * For each vector lane, where {@code N} is the vector lane index,
262 * if the mask lane at index {@code N} is set then the array element at
263 * index {@code i + indexMap[j + N]} is placed into the resulting vector
264 * at lane index {@code N}.
265 *
266 * @param species species of desired vector
267 * @param a the array
268 * @param i the offset into the array, may be negative if relative
269 * indexes in the index map compensate to produce a value within the
270 * array bounds
271 * @param m the mask
272 * @param indexMap the index map
273 * @param j the offset into the index map
274 * @return the vector loaded from an array
275 * @throws IndexOutOfBoundsException if {@code j < 0}, or
276 * {@code j > indexMap.length - this.length()},
277 * or for any vector lane index {@code N} where the mask at lane
278 * {@code N} is set the result of {@code i + indexMap[j + N]} is
279 * {@code < 0} or {@code >= a.length}
280 */
281 public static ShortVector fromArray(ShortSpecies species, short[] a, int i, Mask<Short> m, int[] indexMap, int j) {
282 return species.op(m, n -> a[i + indexMap[j + n]]);
283 }
284
285 /**
286 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
287 * offset into the byte buffer.
288 * <p>
289 * Bytes are composed into primitive lane elements according to the
290 * native byte order of the underlying platform.
291 * <p>
292 * This method behaves as if it returns the result of calling the
293 * byte buffer, offset, and mask accepting
294 * {@link #fromByteBuffer(ShortSpecies, ByteBuffer, int, Mask)} method} as follows:
295 * <pre>{@code
296 * return this.fromByteBuffer(b, i, this.maskAllTrue())
297 * }</pre>
298 *
299 * @param species species of desired vector
300 * @param bb the byte buffer
301 * @param ix the offset into the byte buffer
302 * @return a vector loaded from a byte buffer
303 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
304 * or {@code > b.limit()},
305 * or if there are fewer than
306 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
307 * remaining in the byte buffer from the given offset
308 */
309 @ForceInline
310 @SuppressWarnings("unchecked")
311 public static ShortVector fromByteBuffer(ShortSpecies species, ByteBuffer bb, int ix) {
312 if (bb.order() != ByteOrder.nativeOrder()) {
313 throw new IllegalArgumentException();
314 }
315 ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
316 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
317 U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
318 bb, ix, species,
319 (c, idx, s) -> {
320 ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
321 ShortBuffer tb = bbc.asShortBuffer();
322 return ((ShortSpecies)s).op(i -> tb.get());
323 });
324 }
325
326 /**
327 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
328 * offset into the byte buffer and using a mask.
329 * <p>
330 * This method behaves as if the byte buffer is viewed as a primitive
331 * {@link java.nio.Buffer buffer} for the primitive element type,
343 * e[] es = new e[this.length()];
344 * for (int n = 0; n < t.length; n++) {
345 * if (m.isSet(n))
346 * es[n] = eb.get(n);
347 * }
348 * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
349 * }</pre>
350 *
351 * @param species species of desired vector
352 * @param bb the byte buffer
353 * @param ix the offset into the byte buffer
354 * @param m the mask
355 * @return a vector loaded from a byte buffer
356 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
357 * or {@code > b.limit()},
358 * for any vector lane index {@code N} where the mask at lane {@code N}
359 * is set
360 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
361 */
362 @ForceInline
363 public static ShortVector fromByteBuffer(ShortSpecies species, ByteBuffer bb, int ix, Mask<Short> m) {
364 return zero(species).blend(fromByteBuffer(species, bb, ix), m);
365 }
366
367 /**
368 * Returns a mask where each lane is set or unset according to given
369 * {@code boolean} values
370 * <p>
371 * For each mask lane, where {@code N} is the mask lane index,
372 * if the given {@code boolean} value at index {@code N} is {@code true}
373 * then the mask lane at index {@code N} is set, otherwise it is unset.
374 *
375 * @param species mask species
376 * @param bits the given {@code boolean} values
377 * @return a mask where each lane is set or unset according to the given {@code boolean} value
378 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
379 */
380 @ForceInline
381 public static Mask<Short> maskFromValues(ShortSpecies species, boolean... bits) {
382 if (species.boxType() == ShortMaxVector.class)
383 return new ShortMaxVector.ShortMaxMask(bits);
384 switch (species.bitSize()) {
385 case 64: return new Short64Vector.Short64Mask(bits);
386 case 128: return new Short128Vector.Short128Mask(bits);
387 case 256: return new Short256Vector.Short256Mask(bits);
388 case 512: return new Short512Vector.Short512Mask(bits);
389 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
390 }
391 }
392
393 // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
394 static Mask<Short> trueMask(ShortSpecies species) {
395 if (species.boxType() == ShortMaxVector.class)
396 return ShortMaxVector.ShortMaxMask.TRUE_MASK;
397 switch (species.bitSize()) {
398 case 64: return Short64Vector.Short64Mask.TRUE_MASK;
399 case 128: return Short128Vector.Short128Mask.TRUE_MASK;
400 case 256: return Short256Vector.Short256Mask.TRUE_MASK;
401 case 512: return Short512Vector.Short512Mask.TRUE_MASK;
402 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
403 }
404 }
405
406 static Mask<Short> falseMask(ShortSpecies species) {
407 if (species.boxType() == ShortMaxVector.class)
408 return ShortMaxVector.ShortMaxMask.FALSE_MASK;
409 switch (species.bitSize()) {
410 case 64: return Short64Vector.Short64Mask.FALSE_MASK;
411 case 128: return Short128Vector.Short128Mask.FALSE_MASK;
412 case 256: return Short256Vector.Short256Mask.FALSE_MASK;
413 case 512: return Short512Vector.Short512Mask.FALSE_MASK;
414 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
415 }
416 }
417
418 /**
419 * Loads a mask from a {@code boolean} array starting at an offset.
420 * <p>
421 * For each mask lane, where {@code N} is the mask lane index,
422 * if the array element at index {@code ix + N} is {@code true} then the
423 * mask lane at index {@code N} is set, otherwise it is unset.
424 *
425 * @param species mask species
426 * @param bits the {@code boolean} array
427 * @param ix the offset into the array
428 * @return the mask loaded from a {@code boolean} array
429 * @throws IndexOutOfBoundsException if {@code ix < 0}, or
430 * {@code ix > bits.length - species.length()}
431 */
432 @ForceInline
433 @SuppressWarnings("unchecked")
434 public static Mask<Short> maskFromArray(ShortSpecies species, boolean[] bits, int ix) {
435 Objects.requireNonNull(bits);
436 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
437 return VectorIntrinsics.load((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
438 bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
439 bits, ix, species,
440 (c, idx, s) -> (Mask<Short>) ((ShortSpecies)s).opm(n -> c[idx + n]));
441 }
442
443 /**
444 * Returns a mask where all lanes are set.
445 *
446 * @param species mask species
447 * @return a mask where all lanes are set
448 */
449 @ForceInline
450 @SuppressWarnings("unchecked")
451 public static Mask<Short> maskAllTrue(ShortSpecies species) {
452 return VectorIntrinsics.broadcastCoerced((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
453 (short)-1, species,
454 ((z, s) -> trueMask((ShortSpecies)s)));
455 }
456
457 /**
458 * Returns a mask where all lanes are unset.
459 *
460 * @param species mask species
461 * @return a mask where all lanes are unset
462 */
463 @ForceInline
464 @SuppressWarnings("unchecked")
465 public static Mask<Short> maskAllFalse(ShortSpecies species) {
466 return VectorIntrinsics.broadcastCoerced((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
467 0, species,
468 ((z, s) -> falseMask((ShortSpecies)s)));
469 }
470
471 /**
472 * Returns a shuffle of mapped indexes where each lane element is
473 * the result of applying a mapping function to the corresponding lane
474 * index.
475 * <p>
476 * Care should be taken to ensure Shuffle values produced from this
477 * method are consumed as constants to ensure optimal generation of
478 * code. For example, values held in static final fields or values
479 * held in loop constant local variables.
480 * <p>
481 * This method behaves as if a shuffle is created from an array of
482 * mapped indexes as follows:
483 * <pre>{@code
484 * int[] a = new int[species.length()];
485 * for (int i = 0; i < a.length; i++) {
486 * a[i] = f.applyAsInt(i);
487 * }
488 * return this.shuffleFromValues(a);
489 * }</pre>
490 *
491 * @param species shuffle species
492 * @param f the lane index mapping function
493 * @return a shuffle of mapped indexes
494 */
495 @ForceInline
496 public static Shuffle<Short> shuffle(ShortSpecies species, IntUnaryOperator f) {
497 if (species.boxType() == ShortMaxVector.class)
498 return new ShortMaxVector.ShortMaxShuffle(f);
499 switch (species.bitSize()) {
500 case 64: return new Short64Vector.Short64Shuffle(f);
501 case 128: return new Short128Vector.Short128Shuffle(f);
502 case 256: return new Short256Vector.Short256Shuffle(f);
503 case 512: return new Short512Vector.Short512Shuffle(f);
504 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
505 }
506 }
507
508 /**
509 * Returns a shuffle where each lane element is the value of its
510 * corresponding lane index.
511 * <p>
512 * This method behaves as if a shuffle is created from an identity
513 * index mapping function as follows:
514 * <pre>{@code
515 * return this.shuffle(i -> i);
516 * }</pre>
517 *
518 * @param species shuffle species
519 * @return a shuffle of lane indexes
520 */
521 @ForceInline
522 public static Shuffle<Short> shuffleIota(ShortSpecies species) {
523 if (species.boxType() == ShortMaxVector.class)
524 return new ShortMaxVector.ShortMaxShuffle(AbstractShuffle.IDENTITY);
525 switch (species.bitSize()) {
526 case 64: return new Short64Vector.Short64Shuffle(AbstractShuffle.IDENTITY);
527 case 128: return new Short128Vector.Short128Shuffle(AbstractShuffle.IDENTITY);
528 case 256: return new Short256Vector.Short256Shuffle(AbstractShuffle.IDENTITY);
529 case 512: return new Short512Vector.Short512Shuffle(AbstractShuffle.IDENTITY);
530 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
531 }
532 }
533
534 /**
535 * Returns a shuffle where each lane element is set to a given
536 * {@code int} value logically AND'ed by the species length minus one.
537 * <p>
538 * For each shuffle lane, where {@code N} is the shuffle lane index, the
539 * the {@code int} value at index {@code N} logically AND'ed by
540 * {@code species.length() - 1} is placed into the resulting shuffle at
541 * lane index {@code N}.
542 *
543 * @param species shuffle species
544 * @param ixs the given {@code int} values
545 * @return a shuffle where each lane element is set to a given
546 * {@code int} value
547 * @throws IndexOutOfBoundsException if the number of int values is
548 * {@code < species.length()}
549 */
550 @ForceInline
551 public static Shuffle<Short> shuffleFromValues(ShortSpecies species, int... ixs) {
552 if (species.boxType() == ShortMaxVector.class)
553 return new ShortMaxVector.ShortMaxShuffle(ixs);
554 switch (species.bitSize()) {
555 case 64: return new Short64Vector.Short64Shuffle(ixs);
556 case 128: return new Short128Vector.Short128Shuffle(ixs);
557 case 256: return new Short256Vector.Short256Shuffle(ixs);
558 case 512: return new Short512Vector.Short512Shuffle(ixs);
559 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
560 }
561 }
562
563 /**
564 * Loads a shuffle from an {@code int} array starting at an offset.
565 * <p>
566 * For each shuffle lane, where {@code N} is the shuffle lane index, the
567 * array element at index {@code i + N} logically AND'ed by
568 * {@code species.length() - 1} is placed into the resulting shuffle at lane
569 * index {@code N}.
570 *
571 * @param species shuffle species
572 * @param ixs the {@code int} array
573 * @param i the offset into the array
574 * @return a shuffle loaded from the {@code int} array
575 * @throws IndexOutOfBoundsException if {@code i < 0}, or
576 * {@code i > a.length - species.length()}
577 */
578 @ForceInline
579 public static Shuffle<Short> shuffleFromArray(ShortSpecies species, int[] ixs, int i) {
580 if (species.boxType() == ShortMaxVector.class)
581 return new ShortMaxVector.ShortMaxShuffle(ixs, i);
582 switch (species.bitSize()) {
583 case 64: return new Short64Vector.Short64Shuffle(ixs, i);
584 case 128: return new Short128Vector.Short128Shuffle(ixs, i);
585 case 256: return new Short256Vector.Short256Shuffle(ixs, i);
586 case 512: return new Short512Vector.Short512Shuffle(ixs, i);
587 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
588 }
589 }
590
591
592 // Ops
593
594 @Override
595 public abstract ShortVector add(Vector<Short> v);
596
597 /**
598 * Adds this vector to the broadcast of an input scalar.
599 * <p>
600 * This is a vector binary operation where the primitive addition operation
601 * ({@code +}) is applied to lane elements.
602 *
603 * @param s the input scalar
604 * @return the result of adding this vector to the broadcast of an input
605 * scalar
606 */
607 public abstract ShortVector add(short s);
608
609 @Override
610 public abstract ShortVector add(Vector<Short> v, Mask<Short> m);
611
1452 *
1453 * @param a the array
1454 * @param i the offset into the array, may be negative if relative
1455 * indexes in the index map compensate to produce a value within the
1456 * array bounds
1457 * @param m the mask
1458 * @param indexMap the index map
1459 * @param j the offset into the index map
1460 * @throws IndexOutOfBoundsException if {@code j < 0}, or
1461 * {@code j > indexMap.length - this.length()},
1462 * or for any vector lane index {@code N} where the mask at lane
1463 * {@code N} is set the result of {@code i + indexMap[j + N]} is
1464 * {@code < 0} or {@code >= a.length}
1465 */
1466 public void intoArray(short[] a, int i, Mask<Short> m, int[] indexMap, int j) {
1467 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
1468 }
1469 // Species
1470
1471 @Override
1472 public abstract ShortSpecies species();
1473
1474 /**
1475 * Class representing {@link ShortVector}'s of the same {@link Vector.Shape Shape}.
1476 */
1477 public static abstract class ShortSpecies extends Vector.Species<Short> {
1478 interface FOp {
1479 short apply(int i);
1480 }
1481
1482 abstract ShortVector op(FOp f);
1483
1484 abstract ShortVector op(Mask<Short> m, FOp f);
1485
1486 interface FOpm {
1487 boolean apply(int i);
1488 }
1489
1490 abstract Mask<Short> opm(FOpm f);
1491
1492
1493
1494 // Factories
1495
1496 @Override
1497 public abstract ShortVector zero();
1498
1499 /**
1500 * Returns a vector where all lane elements are set to the primitive
1501 * value {@code e}.
1502 *
1503 * @param e the value
1504 * @return a vector of vector where all lane elements are set to
1505 * the primitive value {@code e}
1506 */
1507 public abstract ShortVector broadcast(short e);
1508
1509 /**
1510 * Returns a vector where the first lane element is set to the primtive
1511 * value {@code e}, all other lane elements are set to the default
1512 * value.
1513 *
1514 * @param e the value
1515 * @return a vector where the first lane element is set to the primitive
1516 * value {@code e}
1517 */
1518 @ForceInline
1519 public final ShortVector single(short e) {
1520 return zero().with(0, e);
1521 }
1522
1523 /**
1524 * Returns a vector where each lane element is set to a randomly
1525 * generated primitive value.
1526 *
1527 * The semantics are equivalent to calling
1528 * {@code (short)ThreadLocalRandom#nextInt()}.
1529 *
1530 * @return a vector where each lane elements is set to a randomly
1531 * generated primitive value
1532 */
1533 public ShortVector random() {
1534 ThreadLocalRandom r = ThreadLocalRandom.current();
1535 return op(i -> (short) r.nextInt());
1536 }
1537
1538 /**
1539 * Returns a vector where each lane element is set to a given
1540 * primitive value.
1541 * <p>
1542 * For each vector lane, where {@code N} is the vector lane index, the
1543 * the primitive value at index {@code N} is placed into the resulting
1544 * vector at lane index {@code N}.
1545 *
1546 * @param es the given primitive values
1547 * @return a vector where each lane element is set to a given primitive
1548 * value
1549 * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
1550 */
1551 public abstract ShortVector scalars(short... es);
1552 }
1553
1554 /**
1555 * Finds the preferred species for an element type of {@code short}.
1556 * <p>
1557 * A preferred species is a species chosen by the platform that has a
1558 * shape of maximal bit size. A preferred species for different element
1559 * types will have the same shape, and therefore vectors, masks, and
1560 * shuffles created from such species will be shape compatible.
1561 *
1562 * @return the preferred species for an element type of {@code short}
1563 */
1564 @SuppressWarnings("unchecked")
1565 public static ShortSpecies preferredSpecies() {
1566 return (ShortSpecies) Species.ofPreferred(short.class);
1567 }
1568
1569 /**
1570 * Finds a species for an element type of {@code short} and shape.
1571 *
1572 * @param s the shape
1573 * @return a species for an element type of {@code short} and shape
1574 * @throws IllegalArgumentException if no such species exists for the shape
1575 */
1576 @SuppressWarnings("unchecked")
1577 public static ShortSpecies species(Vector.Shape s) {
1578 Objects.requireNonNull(s);
1579 switch (s) {
1580 case S_64_BIT: return Short64Vector.SPECIES;
1581 case S_128_BIT: return Short128Vector.SPECIES;
1582 case S_256_BIT: return Short256Vector.SPECIES;
1583 case S_512_BIT: return Short512Vector.SPECIES;
1584 case S_Max_BIT: return ShortMaxVector.SPECIES;
1585 default: throw new IllegalArgumentException("Bad shape: " + s);
1586 }
1587 }
1588 }
|
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 java.nio.ByteBuffer;
28 import java.nio.ShortBuffer;
29 import java.nio.ByteOrder;
30 import java.util.Objects;
31 import java.util.function.IntUnaryOperator;
32 import java.util.function.Function;
33 import java.util.concurrent.ThreadLocalRandom;
34
35 import jdk.internal.misc.Unsafe;
36 import jdk.internal.vm.annotation.ForceInline;
37 import static jdk.incubator.vector.VectorIntrinsics.*;
38
39
40 /**
41 * A specialized {@link Vector} representing an ordered immutable sequence of
42 * {@code short} values.
43 */
44 @SuppressWarnings("cast")
45 public abstract class ShortVector extends Vector<Short> {
46
47 ShortVector() {}
48
49 private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_SHORT_INDEX_SCALE);
50
51 // Unary operator
52
94
95 interface FUnCon {
96 void apply(int i, short a);
97 }
98
99 abstract void forEach(FUnCon f);
100
101 abstract void forEach(Mask<Short> m, FUnCon f);
102
103 // Static factories
104
105 /**
106 * Returns a vector where all lane elements are set to the default
107 * primitive value.
108 *
109 * @param species species of desired vector
110 * @return a zero vector of given species
111 */
112 @ForceInline
113 @SuppressWarnings("unchecked")
114 public static ShortVector zero(Species<Short> species) {
115 return VectorIntrinsics.broadcastCoerced((Class<ShortVector>) species.boxType(), short.class, species.length(),
116 0, species,
117 ((bits, s) -> ((ShortSpecies)s).op(i -> (short)bits)));
118 }
119
120 /**
121 * Loads a vector from a byte array starting at an offset.
122 * <p>
123 * Bytes are composed into primitive lane elements according to the
124 * native byte order of the underlying platform
125 * <p>
126 * This method behaves as if it returns the result of calling the
127 * byte buffer, offset, and mask accepting
128 * {@link #fromByteBuffer(Species<Short>, ByteBuffer, int, Mask) method} as follows:
129 * <pre>{@code
130 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
131 * }</pre>
132 *
133 * @param species species of desired vector
134 * @param a the byte array
135 * @param ix the offset into the array
136 * @return a vector loaded from a byte array
137 * @throws IndexOutOfBoundsException if {@code i < 0} or
138 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
139 */
140 @ForceInline
141 @SuppressWarnings("unchecked")
142 public static ShortVector fromByteArray(Species<Short> species, byte[] a, int ix) {
143 Objects.requireNonNull(a);
144 ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
145 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
146 a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
147 a, ix, species,
148 (c, idx, s) -> {
149 ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
150 ShortBuffer tb = bbc.asShortBuffer();
151 return ((ShortSpecies)s).op(i -> tb.get());
152 });
153 }
154
155 /**
156 * Loads a vector from a byte array starting at an offset and using a
157 * mask.
158 * <p>
159 * Bytes are composed into primitive lane elements according to the
160 * native byte order of the underlying platform.
161 * <p>
162 * This method behaves as if it returns the result of calling the
163 * byte buffer, offset, and mask accepting
164 * {@link #fromByteBuffer(Species<Short>, ByteBuffer, int, Mask) method} as follows:
165 * <pre>{@code
166 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
167 * }</pre>
168 *
169 * @param species species of desired vector
170 * @param a the byte array
171 * @param ix the offset into the array
172 * @param m the mask
173 * @return a vector loaded from a byte array
174 * @throws IndexOutOfBoundsException if {@code i < 0} or
175 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
176 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
177 * or {@code > a.length},
178 * for any vector lane index {@code N} where the mask at lane {@code N}
179 * is set
180 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
181 */
182 @ForceInline
183 public static ShortVector fromByteArray(Species<Short> species, byte[] a, int ix, Mask<Short> m) {
184 return zero(species).blend(fromByteArray(species, a, ix), m);
185 }
186
187 /**
188 * Loads a vector from an array starting at offset.
189 * <p>
190 * For each vector lane, where {@code N} is the vector lane index, the
191 * array element at index {@code i + N} is placed into the
192 * resulting vector at lane index {@code N}.
193 *
194 * @param species species of desired vector
195 * @param a the array
196 * @param i the offset into the array
197 * @return the vector loaded from an array
198 * @throws IndexOutOfBoundsException if {@code i < 0}, or
199 * {@code i > a.length - this.length()}
200 */
201 @ForceInline
202 @SuppressWarnings("unchecked")
203 public static ShortVector fromArray(Species<Short> species, short[] a, int i){
204 Objects.requireNonNull(a);
205 i = VectorIntrinsics.checkIndex(i, a.length, species.length());
206 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
207 a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_SHORT_BASE_OFFSET,
208 a, i, species,
209 (c, idx, s) -> ((ShortSpecies)s).op(n -> c[idx + n]));
210 }
211
212
213 /**
214 * Loads a vector from an array starting at offset and using a mask.
215 * <p>
216 * For each vector lane, where {@code N} is the vector lane index,
217 * if the mask lane at index {@code N} is set then the array element at
218 * index {@code i + N} is placed into the resulting vector at lane index
219 * {@code N}, otherwise the default element value is placed into the
220 * resulting vector at lane index {@code N}.
221 *
222 * @param species species of desired vector
223 * @param a the array
224 * @param i the offset into the array
225 * @param m the mask
226 * @return the vector loaded from an array
227 * @throws IndexOutOfBoundsException if {@code i < 0}, or
228 * for any vector lane index {@code N} where the mask at lane {@code N}
229 * is set {@code i > a.length - N}
230 */
231 @ForceInline
232 public static ShortVector fromArray(Species<Short> species, short[] a, int i, Mask<Short> m) {
233 return zero(species).blend(fromArray(species, a, i), m);
234 }
235
236 /**
237 * Loads a vector from an array using indexes obtained from an index
238 * map.
239 * <p>
240 * For each vector lane, where {@code N} is the vector lane index, the
241 * array element at index {@code i + indexMap[j + N]} is placed into the
242 * resulting vector at lane index {@code N}.
243 *
244 * @param species species of desired vector
245 * @param a the array
246 * @param i the offset into the array, may be negative if relative
247 * indexes in the index map compensate to produce a value within the
248 * array bounds
249 * @param indexMap the index map
250 * @param j the offset into the index map
251 * @return the vector loaded from an array
252 * @throws IndexOutOfBoundsException if {@code j < 0}, or
253 * {@code j > indexMap.length - this.length()},
254 * or for any vector lane index {@code N} the result of
255 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
256 */
257 public static ShortVector fromArray(Species<Short> species, short[] a, int i, int[] indexMap, int j) {
258 return ((ShortSpecies)species).op(n -> a[i + indexMap[j + n]]);
259 }
260 /**
261 * Loads a vector from an array using indexes obtained from an index
262 * map and using a mask.
263 * <p>
264 * For each vector lane, where {@code N} is the vector lane index,
265 * if the mask lane at index {@code N} is set then the array element at
266 * index {@code i + indexMap[j + N]} is placed into the resulting vector
267 * at lane index {@code N}.
268 *
269 * @param species species of desired vector
270 * @param a the array
271 * @param i the offset into the array, may be negative if relative
272 * indexes in the index map compensate to produce a value within the
273 * array bounds
274 * @param m the mask
275 * @param indexMap the index map
276 * @param j the offset into the index map
277 * @return the vector loaded from an array
278 * @throws IndexOutOfBoundsException if {@code j < 0}, or
279 * {@code j > indexMap.length - this.length()},
280 * or for any vector lane index {@code N} where the mask at lane
281 * {@code N} is set the result of {@code i + indexMap[j + N]} is
282 * {@code < 0} or {@code >= a.length}
283 */
284 public static ShortVector fromArray(Species<Short> species, short[] a, int i, Mask<Short> m, int[] indexMap, int j) {
285 return ((ShortSpecies)species).op(m, n -> a[i + indexMap[j + n]]);
286 }
287
288 /**
289 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
290 * offset into the byte buffer.
291 * <p>
292 * Bytes are composed into primitive lane elements according to the
293 * native byte order of the underlying platform.
294 * <p>
295 * This method behaves as if it returns the result of calling the
296 * byte buffer, offset, and mask accepting
297 * {@link #fromByteBuffer(Species<Short>, ByteBuffer, int, Mask)} method} as follows:
298 * <pre>{@code
299 * return this.fromByteBuffer(b, i, this.maskAllTrue())
300 * }</pre>
301 *
302 * @param species species of desired vector
303 * @param bb the byte buffer
304 * @param ix the offset into the byte buffer
305 * @return a vector loaded from a byte buffer
306 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
307 * or {@code > b.limit()},
308 * or if there are fewer than
309 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
310 * remaining in the byte buffer from the given offset
311 */
312 @ForceInline
313 @SuppressWarnings("unchecked")
314 public static ShortVector fromByteBuffer(Species<Short> species, ByteBuffer bb, int ix) {
315 if (bb.order() != ByteOrder.nativeOrder()) {
316 throw new IllegalArgumentException();
317 }
318 ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
319 return VectorIntrinsics.load((Class<ShortVector>) species.boxType(), short.class, species.length(),
320 U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
321 bb, ix, species,
322 (c, idx, s) -> {
323 ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
324 ShortBuffer tb = bbc.asShortBuffer();
325 return ((ShortSpecies)s).op(i -> tb.get());
326 });
327 }
328
329 /**
330 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
331 * offset into the byte buffer and using a mask.
332 * <p>
333 * This method behaves as if the byte buffer is viewed as a primitive
334 * {@link java.nio.Buffer buffer} for the primitive element type,
346 * e[] es = new e[this.length()];
347 * for (int n = 0; n < t.length; n++) {
348 * if (m.isSet(n))
349 * es[n] = eb.get(n);
350 * }
351 * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
352 * }</pre>
353 *
354 * @param species species of desired vector
355 * @param bb the byte buffer
356 * @param ix the offset into the byte buffer
357 * @param m the mask
358 * @return a vector loaded from a byte buffer
359 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
360 * or {@code > b.limit()},
361 * for any vector lane index {@code N} where the mask at lane {@code N}
362 * is set
363 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
364 */
365 @ForceInline
366 public static ShortVector fromByteBuffer(Species<Short> species, ByteBuffer bb, int ix, Mask<Short> m) {
367 return zero(species).blend(fromByteBuffer(species, bb, ix), m);
368 }
369
370 /**
371 * Returns a vector where all lane elements are set to the primitive
372 * value {@code e}.
373 *
374 * @param s species of the desired vector
375 * @param e the value
376 * @return a vector of vector where all lane elements are set to
377 * the primitive value {@code e}
378 */
379 @ForceInline
380 @SuppressWarnings("unchecked")
381 public static ShortVector broadcast(Species<Short> s, short e) {
382 return VectorIntrinsics.broadcastCoerced(
383 (Class<ShortVector>) s.boxType(), short.class, s.length(),
384 e, s,
385 ((bits, sp) -> ((ShortSpecies)sp).op(i -> (short)bits)));
386 }
387
388 /**
389 * Returns a vector where each lane element is set to a given
390 * primitive value.
391 * <p>
392 * For each vector lane, where {@code N} is the vector lane index, the
393 * the primitive value at index {@code N} is placed into the resulting
394 * vector at lane index {@code N}.
395 *
396 * @param s species of the desired vector
397 * @param es the given primitive values
398 * @return a vector where each lane element is set to a given primitive
399 * value
400 * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
401 */
402 @ForceInline
403 @SuppressWarnings("unchecked")
404 public static ShortVector scalars(Species<Short> s, short... es) {
405 Objects.requireNonNull(es);
406 int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
407 return VectorIntrinsics.load((Class<ShortVector>) s.boxType(), short.class, s.length(),
408 es, Unsafe.ARRAY_SHORT_BASE_OFFSET,
409 es, ix, s,
410 (c, idx, sp) -> ((ShortSpecies)sp).op(n -> c[idx + n]));
411 }
412
413 /**
414 * Returns a vector where the first lane element is set to the primtive
415 * value {@code e}, all other lane elements are set to the default
416 * value.
417 *
418 * @param s species of the desired vector
419 * @param e the value
420 * @return a vector where the first lane element is set to the primitive
421 * value {@code e}
422 */
423 @ForceInline
424 public static final ShortVector single(Species<Short> s, short e) {
425 return zero(s).with(0, e);
426 }
427
428 /**
429 * Returns a vector where each lane element is set to a randomly
430 * generated primitive value.
431 *
432 * The semantics are equivalent to calling
433 * (short){@link ThreadLocalRandom#nextInt()}
434 *
435 * @param s species of the desired vector
436 * @return a vector where each lane elements is set to a randomly
437 * generated primitive value
438 */
439 public static ShortVector random(Species<Short> s) {
440 ThreadLocalRandom r = ThreadLocalRandom.current();
441 return ((ShortSpecies)s).op(i -> (short) r.nextInt());
442 }
443
444 /**
445 * Returns a mask where each lane is set or unset according to given
446 * {@code boolean} values
447 * <p>
448 * For each mask lane, where {@code N} is the mask lane index,
449 * if the given {@code boolean} value at index {@code N} is {@code true}
450 * then the mask lane at index {@code N} is set, otherwise it is unset.
451 *
452 * @param species mask species
453 * @param bits the given {@code boolean} values
454 * @return a mask where each lane is set or unset according to the given {@code boolean} value
455 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
456 */
457 @ForceInline
458 public static Mask<Short> maskFromValues(Species<Short> species, boolean... bits) {
459 if (species.boxType() == ShortMaxVector.class)
460 return new ShortMaxVector.ShortMaxMask(bits);
461 switch (species.bitSize()) {
462 case 64: return new Short64Vector.Short64Mask(bits);
463 case 128: return new Short128Vector.Short128Mask(bits);
464 case 256: return new Short256Vector.Short256Mask(bits);
465 case 512: return new Short512Vector.Short512Mask(bits);
466 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
467 }
468 }
469
470 // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
471 static Mask<Short> trueMask(Species<Short> species) {
472 if (species.boxType() == ShortMaxVector.class)
473 return ShortMaxVector.ShortMaxMask.TRUE_MASK;
474 switch (species.bitSize()) {
475 case 64: return Short64Vector.Short64Mask.TRUE_MASK;
476 case 128: return Short128Vector.Short128Mask.TRUE_MASK;
477 case 256: return Short256Vector.Short256Mask.TRUE_MASK;
478 case 512: return Short512Vector.Short512Mask.TRUE_MASK;
479 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
480 }
481 }
482
483 static Mask<Short> falseMask(Species<Short> species) {
484 if (species.boxType() == ShortMaxVector.class)
485 return ShortMaxVector.ShortMaxMask.FALSE_MASK;
486 switch (species.bitSize()) {
487 case 64: return Short64Vector.Short64Mask.FALSE_MASK;
488 case 128: return Short128Vector.Short128Mask.FALSE_MASK;
489 case 256: return Short256Vector.Short256Mask.FALSE_MASK;
490 case 512: return Short512Vector.Short512Mask.FALSE_MASK;
491 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
492 }
493 }
494
495 /**
496 * Loads a mask from a {@code boolean} array starting at an offset.
497 * <p>
498 * For each mask lane, where {@code N} is the mask lane index,
499 * if the array element at index {@code ix + N} is {@code true} then the
500 * mask lane at index {@code N} is set, otherwise it is unset.
501 *
502 * @param species mask species
503 * @param bits the {@code boolean} array
504 * @param ix the offset into the array
505 * @return the mask loaded from a {@code boolean} array
506 * @throws IndexOutOfBoundsException if {@code ix < 0}, or
507 * {@code ix > bits.length - species.length()}
508 */
509 @ForceInline
510 @SuppressWarnings("unchecked")
511 public static Mask<Short> maskFromArray(Species<Short> species, boolean[] bits, int ix) {
512 Objects.requireNonNull(bits);
513 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
514 return VectorIntrinsics.load((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
515 bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
516 bits, ix, species,
517 (c, idx, s) -> (Mask<Short>) ((ShortSpecies)s).opm(n -> c[idx + n]));
518 }
519
520 /**
521 * Returns a mask where all lanes are set.
522 *
523 * @param species mask species
524 * @return a mask where all lanes are set
525 */
526 @ForceInline
527 @SuppressWarnings("unchecked")
528 public static Mask<Short> maskAllTrue(Species<Short> species) {
529 return VectorIntrinsics.broadcastCoerced((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
530 (short)-1, species,
531 ((z, s) -> trueMask(s)));
532 }
533
534 /**
535 * Returns a mask where all lanes are unset.
536 *
537 * @param species mask species
538 * @return a mask where all lanes are unset
539 */
540 @ForceInline
541 @SuppressWarnings("unchecked")
542 public static Mask<Short> maskAllFalse(Species<Short> species) {
543 return VectorIntrinsics.broadcastCoerced((Class<Mask<Short>>) species.maskType(), short.class, species.length(),
544 0, species,
545 ((z, s) -> falseMask(s)));
546 }
547
548 /**
549 * Returns a shuffle of mapped indexes where each lane element is
550 * the result of applying a mapping function to the corresponding lane
551 * index.
552 * <p>
553 * Care should be taken to ensure Shuffle values produced from this
554 * method are consumed as constants to ensure optimal generation of
555 * code. For example, values held in static final fields or values
556 * held in loop constant local variables.
557 * <p>
558 * This method behaves as if a shuffle is created from an array of
559 * mapped indexes as follows:
560 * <pre>{@code
561 * int[] a = new int[species.length()];
562 * for (int i = 0; i < a.length; i++) {
563 * a[i] = f.applyAsInt(i);
564 * }
565 * return this.shuffleFromValues(a);
566 * }</pre>
567 *
568 * @param species shuffle species
569 * @param f the lane index mapping function
570 * @return a shuffle of mapped indexes
571 */
572 @ForceInline
573 public static Shuffle<Short> shuffle(Species<Short> species, IntUnaryOperator f) {
574 if (species.boxType() == ShortMaxVector.class)
575 return new ShortMaxVector.ShortMaxShuffle(f);
576 switch (species.bitSize()) {
577 case 64: return new Short64Vector.Short64Shuffle(f);
578 case 128: return new Short128Vector.Short128Shuffle(f);
579 case 256: return new Short256Vector.Short256Shuffle(f);
580 case 512: return new Short512Vector.Short512Shuffle(f);
581 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
582 }
583 }
584
585 /**
586 * Returns a shuffle where each lane element is the value of its
587 * corresponding lane index.
588 * <p>
589 * This method behaves as if a shuffle is created from an identity
590 * index mapping function as follows:
591 * <pre>{@code
592 * return this.shuffle(i -> i);
593 * }</pre>
594 *
595 * @param species shuffle species
596 * @return a shuffle of lane indexes
597 */
598 @ForceInline
599 public static Shuffle<Short> shuffleIota(Species<Short> species) {
600 if (species.boxType() == ShortMaxVector.class)
601 return new ShortMaxVector.ShortMaxShuffle(AbstractShuffle.IDENTITY);
602 switch (species.bitSize()) {
603 case 64: return new Short64Vector.Short64Shuffle(AbstractShuffle.IDENTITY);
604 case 128: return new Short128Vector.Short128Shuffle(AbstractShuffle.IDENTITY);
605 case 256: return new Short256Vector.Short256Shuffle(AbstractShuffle.IDENTITY);
606 case 512: return new Short512Vector.Short512Shuffle(AbstractShuffle.IDENTITY);
607 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
608 }
609 }
610
611 /**
612 * Returns a shuffle where each lane element is set to a given
613 * {@code int} value logically AND'ed by the species length minus one.
614 * <p>
615 * For each shuffle lane, where {@code N} is the shuffle lane index, the
616 * the {@code int} value at index {@code N} logically AND'ed by
617 * {@code species.length() - 1} is placed into the resulting shuffle at
618 * lane index {@code N}.
619 *
620 * @param species shuffle species
621 * @param ixs the given {@code int} values
622 * @return a shuffle where each lane element is set to a given
623 * {@code int} value
624 * @throws IndexOutOfBoundsException if the number of int values is
625 * {@code < species.length()}
626 */
627 @ForceInline
628 public static Shuffle<Short> shuffleFromValues(Species<Short> species, int... ixs) {
629 if (species.boxType() == ShortMaxVector.class)
630 return new ShortMaxVector.ShortMaxShuffle(ixs);
631 switch (species.bitSize()) {
632 case 64: return new Short64Vector.Short64Shuffle(ixs);
633 case 128: return new Short128Vector.Short128Shuffle(ixs);
634 case 256: return new Short256Vector.Short256Shuffle(ixs);
635 case 512: return new Short512Vector.Short512Shuffle(ixs);
636 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
637 }
638 }
639
640 /**
641 * Loads a shuffle from an {@code int} array starting at an offset.
642 * <p>
643 * For each shuffle lane, where {@code N} is the shuffle lane index, the
644 * array element at index {@code i + N} logically AND'ed by
645 * {@code species.length() - 1} is placed into the resulting shuffle at lane
646 * index {@code N}.
647 *
648 * @param species shuffle species
649 * @param ixs the {@code int} array
650 * @param i the offset into the array
651 * @return a shuffle loaded from the {@code int} array
652 * @throws IndexOutOfBoundsException if {@code i < 0}, or
653 * {@code i > a.length - species.length()}
654 */
655 @ForceInline
656 public static Shuffle<Short> shuffleFromArray(Species<Short> species, int[] ixs, int i) {
657 if (species.boxType() == ShortMaxVector.class)
658 return new ShortMaxVector.ShortMaxShuffle(ixs, i);
659 switch (species.bitSize()) {
660 case 64: return new Short64Vector.Short64Shuffle(ixs, i);
661 case 128: return new Short128Vector.Short128Shuffle(ixs, i);
662 case 256: return new Short256Vector.Short256Shuffle(ixs, i);
663 case 512: return new Short512Vector.Short512Shuffle(ixs, i);
664 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
665 }
666 }
667
668 // Ops
669
670 @Override
671 public abstract ShortVector add(Vector<Short> v);
672
673 /**
674 * Adds this vector to the broadcast of an input scalar.
675 * <p>
676 * This is a vector binary operation where the primitive addition operation
677 * ({@code +}) is applied to lane elements.
678 *
679 * @param s the input scalar
680 * @return the result of adding this vector to the broadcast of an input
681 * scalar
682 */
683 public abstract ShortVector add(short s);
684
685 @Override
686 public abstract ShortVector add(Vector<Short> v, Mask<Short> m);
687
1528 *
1529 * @param a the array
1530 * @param i the offset into the array, may be negative if relative
1531 * indexes in the index map compensate to produce a value within the
1532 * array bounds
1533 * @param m the mask
1534 * @param indexMap the index map
1535 * @param j the offset into the index map
1536 * @throws IndexOutOfBoundsException if {@code j < 0}, or
1537 * {@code j > indexMap.length - this.length()},
1538 * or for any vector lane index {@code N} where the mask at lane
1539 * {@code N} is set the result of {@code i + indexMap[j + N]} is
1540 * {@code < 0} or {@code >= a.length}
1541 */
1542 public void intoArray(short[] a, int i, Mask<Short> m, int[] indexMap, int j) {
1543 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
1544 }
1545 // Species
1546
1547 @Override
1548 public abstract Species<Short> species();
1549
1550 /**
1551 * Class representing {@link ShortVector}'s of the same {@link Vector.Shape Shape}.
1552 */
1553 static final class ShortSpecies extends Vector.AbstractSpecies<Short> {
1554 final Function<short[], ShortVector> vectorFactory;
1555 final Function<boolean[], Vector.Mask<Short>> maskFactory;
1556
1557 private ShortSpecies(Vector.Shape shape,
1558 Class<?> boxType,
1559 Class<?> maskType,
1560 Function<short[], ShortVector> vectorFactory,
1561 Function<boolean[], Vector.Mask<Short>> maskFactory) {
1562 super(shape, short.class, Short.SIZE, boxType, maskType);
1563 this.vectorFactory = vectorFactory;
1564 this.maskFactory = maskFactory;
1565 }
1566
1567 interface FOp {
1568 short apply(int i);
1569 }
1570
1571 interface FOpm {
1572 boolean apply(int i);
1573 }
1574
1575 ShortVector op(FOp f) {
1576 short[] res = new short[length()];
1577 for (int i = 0; i < length(); i++) {
1578 res[i] = f.apply(i);
1579 }
1580 return vectorFactory.apply(res);
1581 }
1582
1583 ShortVector op(Vector.Mask<Short> o, FOp f) {
1584 short[] res = new short[length()];
1585 boolean[] mbits = ((AbstractMask<Short>)o).getBits();
1586 for (int i = 0; i < length(); i++) {
1587 if (mbits[i]) {
1588 res[i] = f.apply(i);
1589 }
1590 }
1591 return vectorFactory.apply(res);
1592 }
1593
1594 Vector.Mask<Short> opm(IntVector.IntSpecies.FOpm f) {
1595 boolean[] res = new boolean[length()];
1596 for (int i = 0; i < length(); i++) {
1597 res[i] = (boolean)f.apply(i);
1598 }
1599 return maskFactory.apply(res);
1600 }
1601 }
1602
1603 /**
1604 * Finds the preferred species for an element type of {@code short}.
1605 * <p>
1606 * A preferred species is a species chosen by the platform that has a
1607 * shape of maximal bit size. A preferred species for different element
1608 * types will have the same shape, and therefore vectors, masks, and
1609 * shuffles created from such species will be shape compatible.
1610 *
1611 * @return the preferred species for an element type of {@code short}
1612 */
1613 private static ShortSpecies preferredSpecies() {
1614 return (ShortSpecies) Species.ofPreferred(short.class);
1615 }
1616
1617 /**
1618 * Finds a species for an element type of {@code short} and shape.
1619 *
1620 * @param s the shape
1621 * @return a species for an element type of {@code short} and shape
1622 * @throws IllegalArgumentException if no such species exists for the shape
1623 */
1624 static ShortSpecies species(Vector.Shape s) {
1625 Objects.requireNonNull(s);
1626 switch (s) {
1627 case S_64_BIT: return (ShortSpecies) SPECIES_64;
1628 case S_128_BIT: return (ShortSpecies) SPECIES_128;
1629 case S_256_BIT: return (ShortSpecies) SPECIES_256;
1630 case S_512_BIT: return (ShortSpecies) SPECIES_512;
1631 case S_Max_BIT: return (ShortSpecies) SPECIES_MAX;
1632 default: throw new IllegalArgumentException("Bad shape: " + s);
1633 }
1634 }
1635
1636 /** Species representing {@link ShortVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
1637 public static final Species<Short> SPECIES_64 = new ShortSpecies(Shape.S_64_BIT, Short64Vector.class, Short64Vector.Short64Mask.class,
1638 Short64Vector::new, Short64Vector.Short64Mask::new);
1639
1640 /** Species representing {@link ShortVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
1641 public static final Species<Short> SPECIES_128 = new ShortSpecies(Shape.S_128_BIT, Short128Vector.class, Short128Vector.Short128Mask.class,
1642 Short128Vector::new, Short128Vector.Short128Mask::new);
1643
1644 /** Species representing {@link ShortVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
1645 public static final Species<Short> SPECIES_256 = new ShortSpecies(Shape.S_256_BIT, Short256Vector.class, Short256Vector.Short256Mask.class,
1646 Short256Vector::new, Short256Vector.Short256Mask::new);
1647
1648 /** Species representing {@link ShortVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
1649 public static final Species<Short> SPECIES_512 = new ShortSpecies(Shape.S_512_BIT, Short512Vector.class, Short512Vector.Short512Mask.class,
1650 Short512Vector::new, Short512Vector.Short512Mask::new);
1651
1652 /** Species representing {@link ShortVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
1653 public static final Species<Short> SPECIES_MAX = new ShortSpecies(Shape.S_Max_BIT, ShortMaxVector.class, ShortMaxVector.ShortMaxMask.class,
1654 ShortMaxVector::new, ShortMaxVector.ShortMaxMask::new);
1655
1656 /**
1657 * Preferred species for {@link ShortVector}s.
1658 * A preferred species is a species of maximal bit size for the platform.
1659 */
1660 public static final Species<Short> SPECIES_PREFERRED = (Species<Short>) preferredSpecies();
1661 }
|