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 #if[!byte]
29 import java.nio.$Type$Buffer;
30 #end[!byte]
31 import java.nio.ByteOrder;
32 import java.util.Objects;
33 import java.util.function.IntUnaryOperator;
34 import java.util.concurrent.ThreadLocalRandom;
35
36 import jdk.internal.misc.Unsafe;
37 import jdk.internal.vm.annotation.ForceInline;
38 import static jdk.incubator.vector.VectorIntrinsics.*;
39
40
41 /**
42 * A specialized {@link Vector} representing an ordered immutable sequence of
43 * {@code $type$} values.
44 */
45 @SuppressWarnings("cast")
46 public abstract class $abstractvectortype$ extends Vector<$Boxtype$> {
47
48 $abstractvectortype$() {}
49
50 private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_$TYPE$_INDEX_SCALE);
51
52 // Unary operator
53
95
96 interface FUnCon {
97 void apply(int i, $type$ a);
98 }
99
100 abstract void forEach(FUnCon f);
101
102 abstract void forEach(Mask<$Boxtype$> m, FUnCon f);
103
104 // Static factories
105
106 /**
107 * Returns a vector where all lane elements are set to the default
108 * primitive value.
109 *
110 * @param species species of desired vector
111 * @return a zero vector of given species
112 */
113 @ForceInline
114 @SuppressWarnings("unchecked")
115 public static $abstractvectortype$ zero($Type$Species species) {
116 return species.zero();
117 }
118
119 /**
120 * Loads a vector from a byte array starting at an offset.
121 * <p>
122 * Bytes are composed into primitive lane elements according to the
123 * native byte order of the underlying platform
124 * <p>
125 * This method behaves as if it returns the result of calling the
126 * byte buffer, offset, and mask accepting
127 * {@link #fromByteBuffer($Type$Species, ByteBuffer, int, Mask) method} as follows:
128 * <pre>{@code
129 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
130 * }</pre>
131 *
132 * @param species species of desired vector
133 * @param a the byte array
134 * @param ix the offset into the array
135 * @return a vector loaded from a byte array
136 * @throws IndexOutOfBoundsException if {@code i < 0} or
137 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
138 */
139 @ForceInline
140 @SuppressWarnings("unchecked")
141 public static $abstractvectortype$ fromByteArray($Type$Species species, byte[] a, int ix) {
142 Objects.requireNonNull(a);
143 ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
144 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
145 a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
146 a, ix, species,
147 (c, idx, s) -> {
148 ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
149 $Type$Buffer tb = bbc{#if[byte]?;:.as$Type$Buffer();}
150 return (($Type$Species)s).op(i -> tb.get());
151 });
152 }
153
154 /**
155 * Loads a vector from a byte array starting at an offset and using a
156 * mask.
157 * <p>
158 * Bytes are composed into primitive lane elements according to the
159 * native byte order of the underlying platform.
160 * <p>
161 * This method behaves as if it returns the result of calling the
162 * byte buffer, offset, and mask accepting
163 * {@link #fromByteBuffer($Type$Species, ByteBuffer, int, Mask) method} as follows:
164 * <pre>{@code
165 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
166 * }</pre>
167 *
168 * @param species species of desired vector
169 * @param a the byte array
170 * @param ix the offset into the array
171 * @param m the mask
172 * @return a vector loaded from a byte array
173 * @throws IndexOutOfBoundsException if {@code i < 0} or
174 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
175 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
176 * or {@code > a.length},
177 * for any vector lane index {@code N} where the mask at lane {@code N}
178 * is set
179 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
180 */
181 @ForceInline
182 public static $abstractvectortype$ fromByteArray($Type$Species species, byte[] a, int ix, Mask<$Boxtype$> m) {
183 return zero(species).blend(fromByteArray(species, a, ix), m);
184 }
185
186 /**
187 * Loads a vector from an array starting at offset.
188 * <p>
189 * For each vector lane, where {@code N} is the vector lane index, the
190 * array element at index {@code i + N} is placed into the
191 * resulting vector at lane index {@code N}.
192 *
193 * @param species species of desired vector
194 * @param a the array
195 * @param i the offset into the array
196 * @return the vector loaded from an array
197 * @throws IndexOutOfBoundsException if {@code i < 0}, or
198 * {@code i > a.length - this.length()}
199 */
200 @ForceInline
201 @SuppressWarnings("unchecked")
202 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i){
203 Objects.requireNonNull(a);
204 i = VectorIntrinsics.checkIndex(i, a.length, species.length());
205 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
206 a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_$TYPE$_BASE_OFFSET,
207 a, i, species,
208 (c, idx, s) -> (($Type$Species)s).op(n -> c[idx + n]));
209 }
210
211
212 /**
213 * Loads a vector from an array starting at offset and using a mask.
214 * <p>
215 * For each vector lane, where {@code N} is the vector lane index,
216 * if the mask lane at index {@code N} is set then the array element at
217 * index {@code i + N} is placed into the resulting vector at lane index
218 * {@code N}, otherwise the default element value is placed into the
219 * resulting vector at lane index {@code N}.
220 *
221 * @param species species of desired vector
222 * @param a the array
223 * @param i the offset into the array
224 * @param m the mask
225 * @return the vector loaded from an array
226 * @throws IndexOutOfBoundsException if {@code i < 0}, or
227 * for any vector lane index {@code N} where the mask at lane {@code N}
228 * is set {@code i > a.length - N}
229 */
230 @ForceInline
231 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i, Mask<$Boxtype$> m) {
232 return zero(species).blend(fromArray(species, a, i), m);
233 }
234
235 /**
236 * Loads a vector from an array using indexes obtained from an index
237 * map.
238 * <p>
239 * For each vector lane, where {@code N} is the vector lane index, the
240 * array element at index {@code i + indexMap[j + N]} is placed into the
241 * resulting vector at lane index {@code N}.
242 *
243 * @param species species of desired vector
244 * @param a the array
245 * @param i the offset into the array, may be negative if relative
246 * indexes in the index map compensate to produce a value within the
247 * array bounds
248 * @param indexMap the index map
249 * @param j the offset into the index map
250 * @return the vector loaded from an array
251 * @throws IndexOutOfBoundsException if {@code j < 0}, or
252 * {@code j > indexMap.length - this.length()},
253 * or for any vector lane index {@code N} the result of
254 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
255 */
256 #if[byteOrShort]
257 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i, int[] indexMap, int j) {
258 return species.op(n -> a[i + indexMap[j + n]]);
259 }
260 #else[byteOrShort]
261 @ForceInline
262 @SuppressWarnings("unchecked")
263 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i, int[] indexMap, int j) {
264 Objects.requireNonNull(a);
265 Objects.requireNonNull(indexMap);
266
267 #if[longOrDouble]
268 if (species.length() == 1) {
269 return $abstractvectortype$.fromArray(species, a, i + indexMap[j]);
270 }
271 #end[longOrDouble]
272
273 // Index vector: vix[0:n] = k -> i + indexMap[j + i]
274 IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
275
276 vix = VectorIntrinsics.checkIndex(vix, a.length);
277
278 return VectorIntrinsics.loadWithMap((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
279 species.indexSpecies().vectorType(), a, Unsafe.ARRAY_$TYPE$_BASE_OFFSET, vix,
280 a, i, indexMap, j, species,
281 (c, idx, iMap, idy, s) -> (($Type$Species)s).op(n -> c[idx + iMap[idy+n]]));
282 }
283
284 #end[byteOrShort]
285 /**
286 * Loads a vector from an array using indexes obtained from an index
287 * map and using a mask.
288 * <p>
289 * For each vector lane, where {@code N} is the vector lane index,
290 * if the mask lane at index {@code N} is set then the array element at
291 * index {@code i + indexMap[j + N]} is placed into the resulting vector
292 * at lane index {@code N}.
293 *
294 * @param species species of desired vector
295 * @param a the array
296 * @param i the offset into the array, may be negative if relative
297 * indexes in the index map compensate to produce a value within the
298 * array bounds
299 * @param m the mask
300 * @param indexMap the index map
301 * @param j the offset into the index map
302 * @return the vector loaded from an array
303 * @throws IndexOutOfBoundsException if {@code j < 0}, or
304 * {@code j > indexMap.length - this.length()},
305 * or for any vector lane index {@code N} where the mask at lane
306 * {@code N} is set the result of {@code i + indexMap[j + N]} is
307 * {@code < 0} or {@code >= a.length}
308 */
309 #if[byteOrShort]
310 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
311 return species.op(m, n -> a[i + indexMap[j + n]]);
312 }
313 #else[byteOrShort]
314 @ForceInline
315 @SuppressWarnings("unchecked")
316 public static $abstractvectortype$ fromArray($Type$Species species, $type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
317 // @@@ This can result in out of bounds errors for unset mask lanes
318 return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
319 }
320
321 #end[byteOrShort]
322
323 /**
324 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
325 * offset into the byte buffer.
326 * <p>
327 * Bytes are composed into primitive lane elements according to the
328 * native byte order of the underlying platform.
329 * <p>
330 * This method behaves as if it returns the result of calling the
331 * byte buffer, offset, and mask accepting
332 * {@link #fromByteBuffer($Type$Species, ByteBuffer, int, Mask)} method} as follows:
333 * <pre>{@code
334 * return this.fromByteBuffer(b, i, this.maskAllTrue())
335 * }</pre>
336 *
337 * @param species species of desired vector
338 * @param bb the byte buffer
339 * @param ix the offset into the byte buffer
340 * @return a vector loaded from a byte buffer
341 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
342 * or {@code > b.limit()},
343 * or if there are fewer than
344 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
345 * remaining in the byte buffer from the given offset
346 */
347 @ForceInline
348 @SuppressWarnings("unchecked")
349 public static $abstractvectortype$ fromByteBuffer($Type$Species species, ByteBuffer bb, int ix) {
350 if (bb.order() != ByteOrder.nativeOrder()) {
351 throw new IllegalArgumentException();
352 }
353 ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
354 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
355 U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
356 bb, ix, species,
357 (c, idx, s) -> {
358 ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
359 $Type$Buffer tb = bbc{#if[byte]?;:.as$Type$Buffer();}
360 return (($Type$Species)s).op(i -> tb.get());
361 });
362 }
363
364 /**
365 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
366 * offset into the byte buffer and using a mask.
367 * <p>
368 * This method behaves as if the byte buffer is viewed as a primitive
369 * {@link java.nio.Buffer buffer} for the primitive element type,
381 * e[] es = new e[this.length()];
382 * for (int n = 0; n < t.length; n++) {
383 * if (m.isSet(n))
384 * es[n] = eb.get(n);
385 * }
386 * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
387 * }</pre>
388 *
389 * @param species species of desired vector
390 * @param bb the byte buffer
391 * @param ix the offset into the byte buffer
392 * @param m the mask
393 * @return a vector loaded from a byte buffer
394 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
395 * or {@code > b.limit()},
396 * for any vector lane index {@code N} where the mask at lane {@code N}
397 * is set
398 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
399 */
400 @ForceInline
401 public static $abstractvectortype$ fromByteBuffer($Type$Species species, ByteBuffer bb, int ix, Mask<$Boxtype$> m) {
402 return zero(species).blend(fromByteBuffer(species, bb, ix), m);
403 }
404
405 /**
406 * Returns a mask where each lane is set or unset according to given
407 * {@code boolean} values
408 * <p>
409 * For each mask lane, where {@code N} is the mask lane index,
410 * if the given {@code boolean} value at index {@code N} is {@code true}
411 * then the mask lane at index {@code N} is set, otherwise it is unset.
412 *
413 * @param species mask species
414 * @param bits the given {@code boolean} values
415 * @return a mask where each lane is set or unset according to the given {@code boolean} value
416 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
417 */
418 @ForceInline
419 public static Mask<$Boxtype$> maskFromValues($Type$Species species, boolean... bits) {
420 if (species.boxType() == $Type$MaxVector.class)
421 return new $Type$MaxVector.$Type$MaxMask(bits);
422 switch (species.bitSize()) {
423 case 64: return new $Type$64Vector.$Type$64Mask(bits);
424 case 128: return new $Type$128Vector.$Type$128Mask(bits);
425 case 256: return new $Type$256Vector.$Type$256Mask(bits);
426 case 512: return new $Type$512Vector.$Type$512Mask(bits);
427 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
428 }
429 }
430
431 // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
432 static Mask<$Boxtype$> trueMask($Type$Species species) {
433 if (species.boxType() == $Type$MaxVector.class)
434 return $Type$MaxVector.$Type$MaxMask.TRUE_MASK;
435 switch (species.bitSize()) {
436 case 64: return $Type$64Vector.$Type$64Mask.TRUE_MASK;
437 case 128: return $Type$128Vector.$Type$128Mask.TRUE_MASK;
438 case 256: return $Type$256Vector.$Type$256Mask.TRUE_MASK;
439 case 512: return $Type$512Vector.$Type$512Mask.TRUE_MASK;
440 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
441 }
442 }
443
444 static Mask<$Boxtype$> falseMask($Type$Species species) {
445 if (species.boxType() == $Type$MaxVector.class)
446 return $Type$MaxVector.$Type$MaxMask.FALSE_MASK;
447 switch (species.bitSize()) {
448 case 64: return $Type$64Vector.$Type$64Mask.FALSE_MASK;
449 case 128: return $Type$128Vector.$Type$128Mask.FALSE_MASK;
450 case 256: return $Type$256Vector.$Type$256Mask.FALSE_MASK;
451 case 512: return $Type$512Vector.$Type$512Mask.FALSE_MASK;
452 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
453 }
454 }
455
456 /**
457 * Loads a mask from a {@code boolean} array starting at an offset.
458 * <p>
459 * For each mask lane, where {@code N} is the mask lane index,
460 * if the array element at index {@code ix + N} is {@code true} then the
461 * mask lane at index {@code N} is set, otherwise it is unset.
462 *
463 * @param species mask species
464 * @param bits the {@code boolean} array
465 * @param ix the offset into the array
466 * @return the mask loaded from a {@code boolean} array
467 * @throws IndexOutOfBoundsException if {@code ix < 0}, or
468 * {@code ix > bits.length - species.length()}
469 */
470 @ForceInline
471 @SuppressWarnings("unchecked")
472 public static Mask<$Boxtype$> maskFromArray($Type$Species species, boolean[] bits, int ix) {
473 Objects.requireNonNull(bits);
474 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
475 return VectorIntrinsics.load((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
476 bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
477 bits, ix, species,
478 (c, idx, s) -> (Mask<$Boxtype$>) (($Type$Species)s).opm(n -> c[idx + n]));
479 }
480
481 /**
482 * Returns a mask where all lanes are set.
483 *
484 * @param species mask species
485 * @return a mask where all lanes are set
486 */
487 @ForceInline
488 @SuppressWarnings("unchecked")
489 public static Mask<$Boxtype$> maskAllTrue($Type$Species species) {
490 return VectorIntrinsics.broadcastCoerced((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
491 ($bitstype$)-1, species,
492 ((z, s) -> trueMask(($Type$Species)s)));
493 }
494
495 /**
496 * Returns a mask where all lanes are unset.
497 *
498 * @param species mask species
499 * @return a mask where all lanes are unset
500 */
501 @ForceInline
502 @SuppressWarnings("unchecked")
503 public static Mask<$Boxtype$> maskAllFalse($Type$Species species) {
504 return VectorIntrinsics.broadcastCoerced((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
505 0, species,
506 ((z, s) -> falseMask(($Type$Species)s)));
507 }
508
509 /**
510 * Returns a shuffle of mapped indexes where each lane element is
511 * the result of applying a mapping function to the corresponding lane
512 * index.
513 * <p>
514 * Care should be taken to ensure Shuffle values produced from this
515 * method are consumed as constants to ensure optimal generation of
516 * code. For example, values held in static final fields or values
517 * held in loop constant local variables.
518 * <p>
519 * This method behaves as if a shuffle is created from an array of
520 * mapped indexes as follows:
521 * <pre>{@code
522 * int[] a = new int[species.length()];
523 * for (int i = 0; i < a.length; i++) {
524 * a[i] = f.applyAsInt(i);
525 * }
526 * return this.shuffleFromValues(a);
527 * }</pre>
528 *
529 * @param species shuffle species
530 * @param f the lane index mapping function
531 * @return a shuffle of mapped indexes
532 */
533 @ForceInline
534 public static Shuffle<$Boxtype$> shuffle($Type$Species species, IntUnaryOperator f) {
535 if (species.boxType() == $Type$MaxVector.class)
536 return new $Type$MaxVector.$Type$MaxShuffle(f);
537 switch (species.bitSize()) {
538 case 64: return new $Type$64Vector.$Type$64Shuffle(f);
539 case 128: return new $Type$128Vector.$Type$128Shuffle(f);
540 case 256: return new $Type$256Vector.$Type$256Shuffle(f);
541 case 512: return new $Type$512Vector.$Type$512Shuffle(f);
542 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
543 }
544 }
545
546 /**
547 * Returns a shuffle where each lane element is the value of its
548 * corresponding lane index.
549 * <p>
550 * This method behaves as if a shuffle is created from an identity
551 * index mapping function as follows:
552 * <pre>{@code
553 * return this.shuffle(i -> i);
554 * }</pre>
555 *
556 * @param species shuffle species
557 * @return a shuffle of lane indexes
558 */
559 @ForceInline
560 public static Shuffle<$Boxtype$> shuffleIota($Type$Species species) {
561 if (species.boxType() == $Type$MaxVector.class)
562 return new $Type$MaxVector.$Type$MaxShuffle(AbstractShuffle.IDENTITY);
563 switch (species.bitSize()) {
564 case 64: return new $Type$64Vector.$Type$64Shuffle(AbstractShuffle.IDENTITY);
565 case 128: return new $Type$128Vector.$Type$128Shuffle(AbstractShuffle.IDENTITY);
566 case 256: return new $Type$256Vector.$Type$256Shuffle(AbstractShuffle.IDENTITY);
567 case 512: return new $Type$512Vector.$Type$512Shuffle(AbstractShuffle.IDENTITY);
568 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
569 }
570 }
571
572 /**
573 * Returns a shuffle where each lane element is set to a given
574 * {@code int} value logically AND'ed by the species length minus one.
575 * <p>
576 * For each shuffle lane, where {@code N} is the shuffle lane index, the
577 * the {@code int} value at index {@code N} logically AND'ed by
578 * {@code species.length() - 1} is placed into the resulting shuffle at
579 * lane index {@code N}.
580 *
581 * @param species shuffle species
582 * @param ixs the given {@code int} values
583 * @return a shuffle where each lane element is set to a given
584 * {@code int} value
585 * @throws IndexOutOfBoundsException if the number of int values is
586 * {@code < species.length()}
587 */
588 @ForceInline
589 public static Shuffle<$Boxtype$> shuffleFromValues($Type$Species species, int... ixs) {
590 if (species.boxType() == $Type$MaxVector.class)
591 return new $Type$MaxVector.$Type$MaxShuffle(ixs);
592 switch (species.bitSize()) {
593 case 64: return new $Type$64Vector.$Type$64Shuffle(ixs);
594 case 128: return new $Type$128Vector.$Type$128Shuffle(ixs);
595 case 256: return new $Type$256Vector.$Type$256Shuffle(ixs);
596 case 512: return new $Type$512Vector.$Type$512Shuffle(ixs);
597 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
598 }
599 }
600
601 /**
602 * Loads a shuffle from an {@code int} array starting at an offset.
603 * <p>
604 * For each shuffle lane, where {@code N} is the shuffle lane index, the
605 * array element at index {@code i + N} logically AND'ed by
606 * {@code species.length() - 1} is placed into the resulting shuffle at lane
607 * index {@code N}.
608 *
609 * @param species shuffle species
610 * @param ixs the {@code int} array
611 * @param i the offset into the array
612 * @return a shuffle loaded from the {@code int} array
613 * @throws IndexOutOfBoundsException if {@code i < 0}, or
614 * {@code i > a.length - species.length()}
615 */
616 @ForceInline
617 public static Shuffle<$Boxtype$> shuffleFromArray($Type$Species species, int[] ixs, int i) {
618 if (species.boxType() == $Type$MaxVector.class)
619 return new $Type$MaxVector.$Type$MaxShuffle(ixs, i);
620 switch (species.bitSize()) {
621 case 64: return new $Type$64Vector.$Type$64Shuffle(ixs, i);
622 case 128: return new $Type$128Vector.$Type$128Shuffle(ixs, i);
623 case 256: return new $Type$256Vector.$Type$256Shuffle(ixs, i);
624 case 512: return new $Type$512Vector.$Type$512Shuffle(ixs, i);
625 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
626 }
627 }
628
629
630 // Ops
631
632 @Override
633 public abstract $abstractvectortype$ add(Vector<$Boxtype$> v);
634
635 /**
636 * Adds this vector to the broadcast of an input scalar.
637 * <p>
638 * This is a vector binary operation where the primitive addition operation
639 * ({@code +}) is applied to lane elements.
640 *
641 * @param s the input scalar
642 * @return the result of adding this vector to the broadcast of an input
643 * scalar
644 */
645 public abstract $abstractvectortype$ add($type$ s);
646
647 @Override
648 public abstract $abstractvectortype$ add(Vector<$Boxtype$> v, Mask<$Boxtype$> m);
649
2797 * array bounds
2798 * @param m the mask
2799 * @param indexMap the index map
2800 * @param j the offset into the index map
2801 * @throws IndexOutOfBoundsException if {@code j < 0}, or
2802 * {@code j > indexMap.length - this.length()},
2803 * or for any vector lane index {@code N} where the mask at lane
2804 * {@code N} is set the result of {@code i + indexMap[j + N]} is
2805 * {@code < 0} or {@code >= a.length}
2806 */
2807 #if[byteOrShort]
2808 public void intoArray($type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
2809 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
2810 }
2811 #else[byteOrShort]
2812 public abstract void intoArray($type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j);
2813 #end[byteOrShort]
2814 // Species
2815
2816 @Override
2817 public abstract $Type$Species species();
2818
2819 /**
2820 * Class representing {@link $abstractvectortype$}'s of the same {@link Vector.Shape Shape}.
2821 */
2822 public static abstract class $Type$Species extends Vector.Species<$Boxtype$> {
2823 interface FOp {
2824 $type$ apply(int i);
2825 }
2826
2827 abstract $abstractvectortype$ op(FOp f);
2828
2829 abstract $abstractvectortype$ op(Mask<$Boxtype$> m, FOp f);
2830
2831 interface FOpm {
2832 boolean apply(int i);
2833 }
2834
2835 abstract Mask<$Boxtype$> opm(FOpm f);
2836
2837 #if[!byteOrShort]
2838 abstract IntVector.IntSpecies indexSpecies();
2839 #end[!byteOrShort]
2840
2841
2842 // Factories
2843
2844 @Override
2845 public abstract $abstractvectortype$ zero();
2846
2847 /**
2848 * Returns a vector where all lane elements are set to the primitive
2849 * value {@code e}.
2850 *
2851 * @param e the value
2852 * @return a vector of vector where all lane elements are set to
2853 * the primitive value {@code e}
2854 */
2855 public abstract $abstractvectortype$ broadcast($type$ e);
2856
2857 /**
2858 * Returns a vector where the first lane element is set to the primtive
2859 * value {@code e}, all other lane elements are set to the default
2860 * value.
2861 *
2862 * @param e the value
2863 * @return a vector where the first lane element is set to the primitive
2864 * value {@code e}
2865 */
2866 @ForceInline
2867 public final $abstractvectortype$ single($type$ e) {
2868 return zero().with(0, e);
2869 }
2870
2871 /**
2872 * Returns a vector where each lane element is set to a randomly
2873 * generated primitive value.
2874 *
2875 * The semantics are equivalent to calling
2876 #if[FP]
2877 * {@code ThreadLocalRandom#next$Type$}.
2878 #else[FP]
2879 * {@code ($type$)ThreadLocalRandom#nextInt()}.
2880 #end[FP]
2881 *
2882 * @return a vector where each lane elements is set to a randomly
2883 * generated primitive value
2884 */
2885 #if[intOrLong]
2886 public $abstractvectortype$ random() {
2887 ThreadLocalRandom r = ThreadLocalRandom.current();
2888 return op(i -> r.next$Type$());
2889 }
2890 #else[intOrLong]
2891 #if[FP]
2892 public $abstractvectortype$ random() {
2893 ThreadLocalRandom r = ThreadLocalRandom.current();
2894 return op(i -> r.next$Type$());
2895 }
2896 #else[FP]
2897 public $abstractvectortype$ random() {
2898 ThreadLocalRandom r = ThreadLocalRandom.current();
2899 return op(i -> ($type$) r.nextInt());
2900 }
2901 #end[FP]
2902 #end[intOrLong]
2903
2904 /**
2905 * Returns a vector where each lane element is set to a given
2906 * primitive value.
2907 * <p>
2908 * For each vector lane, where {@code N} is the vector lane index, the
2909 * the primitive value at index {@code N} is placed into the resulting
2910 * vector at lane index {@code N}.
2911 *
2912 * @param es the given primitive values
2913 * @return a vector where each lane element is set to a given primitive
2914 * value
2915 * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
2916 */
2917 public abstract $abstractvectortype$ scalars($type$... es);
2918 }
2919
2920 /**
2921 * Finds the preferred species for an element type of {@code $type$}.
2922 * <p>
2923 * A preferred species is a species chosen by the platform that has a
2924 * shape of maximal bit size. A preferred species for different element
2925 * types will have the same shape, and therefore vectors, masks, and
2926 * shuffles created from such species will be shape compatible.
2927 *
2928 * @return the preferred species for an element type of {@code $type$}
2929 */
2930 @SuppressWarnings("unchecked")
2931 public static $Type$Species preferredSpecies() {
2932 return ($Type$Species) Species.ofPreferred($type$.class);
2933 }
2934
2935 /**
2936 * Finds a species for an element type of {@code $type$} and shape.
2937 *
2938 * @param s the shape
2939 * @return a species for an element type of {@code $type$} and shape
2940 * @throws IllegalArgumentException if no such species exists for the shape
2941 */
2942 @SuppressWarnings("unchecked")
2943 public static $Type$Species species(Vector.Shape s) {
2944 Objects.requireNonNull(s);
2945 switch (s) {
2946 case S_64_BIT: return $Type$64Vector.SPECIES;
2947 case S_128_BIT: return $Type$128Vector.SPECIES;
2948 case S_256_BIT: return $Type$256Vector.SPECIES;
2949 case S_512_BIT: return $Type$512Vector.SPECIES;
2950 case S_Max_BIT: return $Type$MaxVector.SPECIES;
2951 default: throw new IllegalArgumentException("Bad shape: " + s);
2952 }
2953 }
2954 }
|
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 #if[!byte]
29 import java.nio.$Type$Buffer;
30 #end[!byte]
31 import java.nio.ByteOrder;
32 import java.util.Objects;
33 import java.util.function.IntUnaryOperator;
34 import java.util.function.Function;
35 import java.util.concurrent.ThreadLocalRandom;
36
37 import jdk.internal.misc.Unsafe;
38 import jdk.internal.vm.annotation.ForceInline;
39 import static jdk.incubator.vector.VectorIntrinsics.*;
40
41
42 /**
43 * A specialized {@link Vector} representing an ordered immutable sequence of
44 * {@code $type$} values.
45 */
46 @SuppressWarnings("cast")
47 public abstract class $abstractvectortype$ extends Vector<$Boxtype$> {
48
49 $abstractvectortype$() {}
50
51 private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_$TYPE$_INDEX_SCALE);
52
53 // Unary operator
54
96
97 interface FUnCon {
98 void apply(int i, $type$ a);
99 }
100
101 abstract void forEach(FUnCon f);
102
103 abstract void forEach(Mask<$Boxtype$> m, FUnCon f);
104
105 // Static factories
106
107 /**
108 * Returns a vector where all lane elements are set to the default
109 * primitive value.
110 *
111 * @param species species of desired vector
112 * @return a zero vector of given species
113 */
114 @ForceInline
115 @SuppressWarnings("unchecked")
116 public static $abstractvectortype$ zero(Species<$Boxtype$> species) {
117 #if[FP]
118 return VectorIntrinsics.broadcastCoerced((Class<$Type$Vector>) species.boxType(), $type$.class, species.length(),
119 $Type$.$type$To$Bitstype$Bits(0.0f), species,
120 ((bits, s) -> (($Type$Species)s).op(i -> $Type$.$bitstype$BitsTo$Type$(($bitstype$)bits))));
121 #else[FP]
122 return VectorIntrinsics.broadcastCoerced((Class<$Type$Vector>) species.boxType(), $type$.class, species.length(),
123 0, species,
124 ((bits, s) -> (($Type$Species)s).op(i -> ($type$)bits)));
125 #end[FP]
126 }
127
128 /**
129 * Loads a vector from a byte array starting at an offset.
130 * <p>
131 * Bytes are composed into primitive lane elements according to the
132 * native byte order of the underlying platform
133 * <p>
134 * This method behaves as if it returns the result of calling the
135 * byte buffer, offset, and mask accepting
136 * {@link #fromByteBuffer(Species<$Boxtype$>, ByteBuffer, int, Mask) method} as follows:
137 * <pre>{@code
138 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
139 * }</pre>
140 *
141 * @param species species of desired vector
142 * @param a the byte array
143 * @param ix the offset into the array
144 * @return a vector loaded from a byte array
145 * @throws IndexOutOfBoundsException if {@code i < 0} or
146 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
147 */
148 @ForceInline
149 @SuppressWarnings("unchecked")
150 public static $abstractvectortype$ fromByteArray(Species<$Boxtype$> species, byte[] a, int ix) {
151 Objects.requireNonNull(a);
152 ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
153 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
154 a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
155 a, ix, species,
156 (c, idx, s) -> {
157 ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
158 $Type$Buffer tb = bbc{#if[byte]?;:.as$Type$Buffer();}
159 return (($Type$Species)s).op(i -> tb.get());
160 });
161 }
162
163 /**
164 * Loads a vector from a byte array starting at an offset and using a
165 * mask.
166 * <p>
167 * Bytes are composed into primitive lane elements according to the
168 * native byte order of the underlying platform.
169 * <p>
170 * This method behaves as if it returns the result of calling the
171 * byte buffer, offset, and mask accepting
172 * {@link #fromByteBuffer(Species<$Boxtype$>, ByteBuffer, int, Mask) method} as follows:
173 * <pre>{@code
174 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
175 * }</pre>
176 *
177 * @param species species of desired vector
178 * @param a the byte array
179 * @param ix the offset into the array
180 * @param m the mask
181 * @return a vector loaded from a byte array
182 * @throws IndexOutOfBoundsException if {@code i < 0} or
183 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
184 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
185 * or {@code > a.length},
186 * for any vector lane index {@code N} where the mask at lane {@code N}
187 * is set
188 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
189 */
190 @ForceInline
191 public static $abstractvectortype$ fromByteArray(Species<$Boxtype$> species, byte[] a, int ix, Mask<$Boxtype$> m) {
192 return zero(species).blend(fromByteArray(species, a, ix), m);
193 }
194
195 /**
196 * Loads a vector from an array starting at offset.
197 * <p>
198 * For each vector lane, where {@code N} is the vector lane index, the
199 * array element at index {@code i + N} is placed into the
200 * resulting vector at lane index {@code N}.
201 *
202 * @param species species of desired vector
203 * @param a the array
204 * @param i the offset into the array
205 * @return the vector loaded from an array
206 * @throws IndexOutOfBoundsException if {@code i < 0}, or
207 * {@code i > a.length - this.length()}
208 */
209 @ForceInline
210 @SuppressWarnings("unchecked")
211 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i){
212 Objects.requireNonNull(a);
213 i = VectorIntrinsics.checkIndex(i, a.length, species.length());
214 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
215 a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_$TYPE$_BASE_OFFSET,
216 a, i, species,
217 (c, idx, s) -> (($Type$Species)s).op(n -> c[idx + n]));
218 }
219
220
221 /**
222 * Loads a vector from an array starting at offset and using a mask.
223 * <p>
224 * For each vector lane, where {@code N} is the vector lane index,
225 * if the mask lane at index {@code N} is set then the array element at
226 * index {@code i + N} is placed into the resulting vector at lane index
227 * {@code N}, otherwise the default element value is placed into the
228 * resulting vector at lane index {@code N}.
229 *
230 * @param species species of desired vector
231 * @param a the array
232 * @param i the offset into the array
233 * @param m the mask
234 * @return the vector loaded from an array
235 * @throws IndexOutOfBoundsException if {@code i < 0}, or
236 * for any vector lane index {@code N} where the mask at lane {@code N}
237 * is set {@code i > a.length - N}
238 */
239 @ForceInline
240 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i, Mask<$Boxtype$> m) {
241 return zero(species).blend(fromArray(species, a, i), m);
242 }
243
244 /**
245 * Loads a vector from an array using indexes obtained from an index
246 * map.
247 * <p>
248 * For each vector lane, where {@code N} is the vector lane index, the
249 * array element at index {@code i + indexMap[j + N]} is placed into the
250 * resulting vector at lane index {@code N}.
251 *
252 * @param species species of desired vector
253 * @param a the array
254 * @param i the offset into the array, may be negative if relative
255 * indexes in the index map compensate to produce a value within the
256 * array bounds
257 * @param indexMap the index map
258 * @param j the offset into the index map
259 * @return the vector loaded from an array
260 * @throws IndexOutOfBoundsException if {@code j < 0}, or
261 * {@code j > indexMap.length - this.length()},
262 * or for any vector lane index {@code N} the result of
263 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
264 */
265 #if[byteOrShort]
266 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i, int[] indexMap, int j) {
267 return (($Type$Species)species).op(n -> a[i + indexMap[j + n]]);
268 }
269 #else[byteOrShort]
270 @ForceInline
271 @SuppressWarnings("unchecked")
272 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i, int[] indexMap, int j) {
273 Objects.requireNonNull(a);
274 Objects.requireNonNull(indexMap);
275
276 #if[longOrDouble]
277 if (species.length() == 1) {
278 return $abstractvectortype$.fromArray(species, a, i + indexMap[j]);
279 }
280 #end[longOrDouble]
281
282 // Index vector: vix[0:n] = k -> i + indexMap[j + k]
283 IntVector vix = IntVector.fromArray(IntVector.species(species.indexShape()), indexMap, j).add(i);
284
285 vix = VectorIntrinsics.checkIndex(vix, a.length);
286
287 return VectorIntrinsics.loadWithMap((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
288 IntVector.species(species.indexShape()).boxType(), a, Unsafe.ARRAY_$TYPE$_BASE_OFFSET, vix,
289 a, i, indexMap, j, species,
290 ($type$[] c, int idx, int[] iMap, int idy, Species<$Boxtype$> s) ->
291 (($Type$Species)s).op(n -> c[idx + iMap[idy+n]]));
292 }
293
294 #end[byteOrShort]
295 /**
296 * Loads a vector from an array using indexes obtained from an index
297 * map and using a mask.
298 * <p>
299 * For each vector lane, where {@code N} is the vector lane index,
300 * if the mask lane at index {@code N} is set then the array element at
301 * index {@code i + indexMap[j + N]} is placed into the resulting vector
302 * at lane index {@code N}.
303 *
304 * @param species species of desired vector
305 * @param a the array
306 * @param i the offset into the array, may be negative if relative
307 * indexes in the index map compensate to produce a value within the
308 * array bounds
309 * @param m the mask
310 * @param indexMap the index map
311 * @param j the offset into the index map
312 * @return the vector loaded from an array
313 * @throws IndexOutOfBoundsException if {@code j < 0}, or
314 * {@code j > indexMap.length - this.length()},
315 * or for any vector lane index {@code N} where the mask at lane
316 * {@code N} is set the result of {@code i + indexMap[j + N]} is
317 * {@code < 0} or {@code >= a.length}
318 */
319 #if[byteOrShort]
320 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
321 return (($Type$Species)species).op(m, n -> a[i + indexMap[j + n]]);
322 }
323 #else[byteOrShort]
324 @ForceInline
325 @SuppressWarnings("unchecked")
326 public static $abstractvectortype$ fromArray(Species<$Boxtype$> species, $type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
327 // @@@ This can result in out of bounds errors for unset mask lanes
328 return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
329 }
330
331 #end[byteOrShort]
332
333 /**
334 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
335 * offset into the byte buffer.
336 * <p>
337 * Bytes are composed into primitive lane elements according to the
338 * native byte order of the underlying platform.
339 * <p>
340 * This method behaves as if it returns the result of calling the
341 * byte buffer, offset, and mask accepting
342 * {@link #fromByteBuffer(Species<$Boxtype$>, ByteBuffer, int, Mask)} method} as follows:
343 * <pre>{@code
344 * return this.fromByteBuffer(b, i, this.maskAllTrue())
345 * }</pre>
346 *
347 * @param species species of desired vector
348 * @param bb the byte buffer
349 * @param ix the offset into the byte buffer
350 * @return a vector loaded from a byte buffer
351 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
352 * or {@code > b.limit()},
353 * or if there are fewer than
354 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
355 * remaining in the byte buffer from the given offset
356 */
357 @ForceInline
358 @SuppressWarnings("unchecked")
359 public static $abstractvectortype$ fromByteBuffer(Species<$Boxtype$> species, ByteBuffer bb, int ix) {
360 if (bb.order() != ByteOrder.nativeOrder()) {
361 throw new IllegalArgumentException();
362 }
363 ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
364 return VectorIntrinsics.load((Class<$abstractvectortype$>) species.boxType(), $type$.class, species.length(),
365 U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
366 bb, ix, species,
367 (c, idx, s) -> {
368 ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
369 $Type$Buffer tb = bbc{#if[byte]?;:.as$Type$Buffer();}
370 return (($Type$Species)s).op(i -> tb.get());
371 });
372 }
373
374 /**
375 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
376 * offset into the byte buffer and using a mask.
377 * <p>
378 * This method behaves as if the byte buffer is viewed as a primitive
379 * {@link java.nio.Buffer buffer} for the primitive element type,
391 * e[] es = new e[this.length()];
392 * for (int n = 0; n < t.length; n++) {
393 * if (m.isSet(n))
394 * es[n] = eb.get(n);
395 * }
396 * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
397 * }</pre>
398 *
399 * @param species species of desired vector
400 * @param bb the byte buffer
401 * @param ix the offset into the byte buffer
402 * @param m the mask
403 * @return a vector loaded from a byte buffer
404 * @throws IndexOutOfBoundsException if the offset is {@code < 0},
405 * or {@code > b.limit()},
406 * for any vector lane index {@code N} where the mask at lane {@code N}
407 * is set
408 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
409 */
410 @ForceInline
411 public static $abstractvectortype$ fromByteBuffer(Species<$Boxtype$> species, ByteBuffer bb, int ix, Mask<$Boxtype$> m) {
412 return zero(species).blend(fromByteBuffer(species, bb, ix), m);
413 }
414
415 /**
416 * Returns a vector where all lane elements are set to the primitive
417 * value {@code e}.
418 *
419 * @param s species of the desired vector
420 * @param e the value
421 * @return a vector of vector where all lane elements are set to
422 * the primitive value {@code e}
423 */
424 #if[FP]
425 @ForceInline
426 @SuppressWarnings("unchecked")
427 public static $abstractvectortype$ broadcast(Species<$Boxtype$> s, $type$ e) {
428 return VectorIntrinsics.broadcastCoerced(
429 (Class<$abstractvectortype$>) s.boxType(), $type$.class, s.length(),
430 $Type$.$type$To$Bitstype$Bits(e), s,
431 ((bits, sp) -> (($Type$Species)sp).op(i -> $Type$.$bitstype$BitsTo$Type$(($bitstype$)bits))));
432 }
433 #else[FP]
434 @ForceInline
435 @SuppressWarnings("unchecked")
436 public static $abstractvectortype$ broadcast(Species<$Boxtype$> s, $type$ e) {
437 return VectorIntrinsics.broadcastCoerced(
438 (Class<$abstractvectortype$>) s.boxType(), $type$.class, s.length(),
439 e, s,
440 ((bits, sp) -> (($Type$Species)sp).op(i -> ($type$)bits)));
441 }
442 #end[FP]
443
444 /**
445 * Returns a vector where each lane element is set to a given
446 * primitive value.
447 * <p>
448 * For each vector lane, where {@code N} is the vector lane index, the
449 * the primitive value at index {@code N} is placed into the resulting
450 * vector at lane index {@code N}.
451 *
452 * @param s species of the desired vector
453 * @param es the given primitive values
454 * @return a vector where each lane element is set to a given primitive
455 * value
456 * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
457 */
458 @ForceInline
459 @SuppressWarnings("unchecked")
460 public static $abstractvectortype$ scalars(Species<$Boxtype$> s, $type$... es) {
461 Objects.requireNonNull(es);
462 int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
463 return VectorIntrinsics.load((Class<$abstractvectortype$>) s.boxType(), $type$.class, s.length(),
464 es, Unsafe.ARRAY_$TYPE$_BASE_OFFSET,
465 es, ix, s,
466 (c, idx, sp) -> (($Type$Species)sp).op(n -> c[idx + n]));
467 }
468
469 /**
470 * Returns a vector where the first lane element is set to the primtive
471 * value {@code e}, all other lane elements are set to the default
472 * value.
473 *
474 * @param s species of the desired vector
475 * @param e the value
476 * @return a vector where the first lane element is set to the primitive
477 * value {@code e}
478 */
479 @ForceInline
480 public static final $abstractvectortype$ single(Species<$Boxtype$> s, $type$ e) {
481 return zero(s).with(0, e);
482 }
483
484 /**
485 * Returns a vector where each lane element is set to a randomly
486 * generated primitive value.
487 *
488 * The semantics are equivalent to calling
489 #if[byteOrShort]
490 * ($type$){@link ThreadLocalRandom#nextInt()}
491 #else[byteOrShort]
492 * {@link ThreadLocalRandom#next$Type$()}
493 #end[byteOrShort]
494 *
495 * @param s species of the desired vector
496 * @return a vector where each lane elements is set to a randomly
497 * generated primitive value
498 */
499 #if[intOrLong]
500 public static $abstractvectortype$ random(Species<$Boxtype$> s) {
501 ThreadLocalRandom r = ThreadLocalRandom.current();
502 return (($Type$Species)s).op(i -> r.next$Type$());
503 }
504 #else[intOrLong]
505 #if[FP]
506 public static $abstractvectortype$ random(Species<$Boxtype$> s) {
507 ThreadLocalRandom r = ThreadLocalRandom.current();
508 return (($Type$Species)s).op(i -> r.next$Type$());
509 }
510 #else[FP]
511 public static $abstractvectortype$ random(Species<$Boxtype$> s) {
512 ThreadLocalRandom r = ThreadLocalRandom.current();
513 return (($Type$Species)s).op(i -> ($type$) r.nextInt());
514 }
515 #end[FP]
516 #end[intOrLong]
517
518 /**
519 * Returns a mask where each lane is set or unset according to given
520 * {@code boolean} values
521 * <p>
522 * For each mask lane, where {@code N} is the mask lane index,
523 * if the given {@code boolean} value at index {@code N} is {@code true}
524 * then the mask lane at index {@code N} is set, otherwise it is unset.
525 *
526 * @param species mask species
527 * @param bits the given {@code boolean} values
528 * @return a mask where each lane is set or unset according to the given {@code boolean} value
529 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
530 */
531 @ForceInline
532 public static Mask<$Boxtype$> maskFromValues(Species<$Boxtype$> species, boolean... bits) {
533 if (species.boxType() == $Type$MaxVector.class)
534 return new $Type$MaxVector.$Type$MaxMask(bits);
535 switch (species.bitSize()) {
536 case 64: return new $Type$64Vector.$Type$64Mask(bits);
537 case 128: return new $Type$128Vector.$Type$128Mask(bits);
538 case 256: return new $Type$256Vector.$Type$256Mask(bits);
539 case 512: return new $Type$512Vector.$Type$512Mask(bits);
540 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
541 }
542 }
543
544 // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
545 static Mask<$Boxtype$> trueMask(Species<$Boxtype$> species) {
546 if (species.boxType() == $Type$MaxVector.class)
547 return $Type$MaxVector.$Type$MaxMask.TRUE_MASK;
548 switch (species.bitSize()) {
549 case 64: return $Type$64Vector.$Type$64Mask.TRUE_MASK;
550 case 128: return $Type$128Vector.$Type$128Mask.TRUE_MASK;
551 case 256: return $Type$256Vector.$Type$256Mask.TRUE_MASK;
552 case 512: return $Type$512Vector.$Type$512Mask.TRUE_MASK;
553 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
554 }
555 }
556
557 static Mask<$Boxtype$> falseMask(Species<$Boxtype$> species) {
558 if (species.boxType() == $Type$MaxVector.class)
559 return $Type$MaxVector.$Type$MaxMask.FALSE_MASK;
560 switch (species.bitSize()) {
561 case 64: return $Type$64Vector.$Type$64Mask.FALSE_MASK;
562 case 128: return $Type$128Vector.$Type$128Mask.FALSE_MASK;
563 case 256: return $Type$256Vector.$Type$256Mask.FALSE_MASK;
564 case 512: return $Type$512Vector.$Type$512Mask.FALSE_MASK;
565 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
566 }
567 }
568
569 /**
570 * Loads a mask from a {@code boolean} array starting at an offset.
571 * <p>
572 * For each mask lane, where {@code N} is the mask lane index,
573 * if the array element at index {@code ix + N} is {@code true} then the
574 * mask lane at index {@code N} is set, otherwise it is unset.
575 *
576 * @param species mask species
577 * @param bits the {@code boolean} array
578 * @param ix the offset into the array
579 * @return the mask loaded from a {@code boolean} array
580 * @throws IndexOutOfBoundsException if {@code ix < 0}, or
581 * {@code ix > bits.length - species.length()}
582 */
583 @ForceInline
584 @SuppressWarnings("unchecked")
585 public static Mask<$Boxtype$> maskFromArray(Species<$Boxtype$> species, boolean[] bits, int ix) {
586 Objects.requireNonNull(bits);
587 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
588 return VectorIntrinsics.load((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
589 bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
590 bits, ix, species,
591 (c, idx, s) -> (Mask<$Boxtype$>) (($Type$Species)s).opm(n -> c[idx + n]));
592 }
593
594 /**
595 * Returns a mask where all lanes are set.
596 *
597 * @param species mask species
598 * @return a mask where all lanes are set
599 */
600 @ForceInline
601 @SuppressWarnings("unchecked")
602 public static Mask<$Boxtype$> maskAllTrue(Species<$Boxtype$> species) {
603 return VectorIntrinsics.broadcastCoerced((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
604 ($bitstype$)-1, species,
605 ((z, s) -> trueMask(s)));
606 }
607
608 /**
609 * Returns a mask where all lanes are unset.
610 *
611 * @param species mask species
612 * @return a mask where all lanes are unset
613 */
614 @ForceInline
615 @SuppressWarnings("unchecked")
616 public static Mask<$Boxtype$> maskAllFalse(Species<$Boxtype$> species) {
617 return VectorIntrinsics.broadcastCoerced((Class<Mask<$Boxtype$>>) species.maskType(), $bitstype$.class, species.length(),
618 0, species,
619 ((z, s) -> falseMask(s)));
620 }
621
622 /**
623 * Returns a shuffle of mapped indexes where each lane element is
624 * the result of applying a mapping function to the corresponding lane
625 * index.
626 * <p>
627 * Care should be taken to ensure Shuffle values produced from this
628 * method are consumed as constants to ensure optimal generation of
629 * code. For example, values held in static final fields or values
630 * held in loop constant local variables.
631 * <p>
632 * This method behaves as if a shuffle is created from an array of
633 * mapped indexes as follows:
634 * <pre>{@code
635 * int[] a = new int[species.length()];
636 * for (int i = 0; i < a.length; i++) {
637 * a[i] = f.applyAsInt(i);
638 * }
639 * return this.shuffleFromValues(a);
640 * }</pre>
641 *
642 * @param species shuffle species
643 * @param f the lane index mapping function
644 * @return a shuffle of mapped indexes
645 */
646 @ForceInline
647 public static Shuffle<$Boxtype$> shuffle(Species<$Boxtype$> species, IntUnaryOperator f) {
648 if (species.boxType() == $Type$MaxVector.class)
649 return new $Type$MaxVector.$Type$MaxShuffle(f);
650 switch (species.bitSize()) {
651 case 64: return new $Type$64Vector.$Type$64Shuffle(f);
652 case 128: return new $Type$128Vector.$Type$128Shuffle(f);
653 case 256: return new $Type$256Vector.$Type$256Shuffle(f);
654 case 512: return new $Type$512Vector.$Type$512Shuffle(f);
655 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
656 }
657 }
658
659 /**
660 * Returns a shuffle where each lane element is the value of its
661 * corresponding lane index.
662 * <p>
663 * This method behaves as if a shuffle is created from an identity
664 * index mapping function as follows:
665 * <pre>{@code
666 * return this.shuffle(i -> i);
667 * }</pre>
668 *
669 * @param species shuffle species
670 * @return a shuffle of lane indexes
671 */
672 @ForceInline
673 public static Shuffle<$Boxtype$> shuffleIota(Species<$Boxtype$> species) {
674 if (species.boxType() == $Type$MaxVector.class)
675 return new $Type$MaxVector.$Type$MaxShuffle(AbstractShuffle.IDENTITY);
676 switch (species.bitSize()) {
677 case 64: return new $Type$64Vector.$Type$64Shuffle(AbstractShuffle.IDENTITY);
678 case 128: return new $Type$128Vector.$Type$128Shuffle(AbstractShuffle.IDENTITY);
679 case 256: return new $Type$256Vector.$Type$256Shuffle(AbstractShuffle.IDENTITY);
680 case 512: return new $Type$512Vector.$Type$512Shuffle(AbstractShuffle.IDENTITY);
681 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
682 }
683 }
684
685 /**
686 * Returns a shuffle where each lane element is set to a given
687 * {@code int} value logically AND'ed by the species length minus one.
688 * <p>
689 * For each shuffle lane, where {@code N} is the shuffle lane index, the
690 * the {@code int} value at index {@code N} logically AND'ed by
691 * {@code species.length() - 1} is placed into the resulting shuffle at
692 * lane index {@code N}.
693 *
694 * @param species shuffle species
695 * @param ixs the given {@code int} values
696 * @return a shuffle where each lane element is set to a given
697 * {@code int} value
698 * @throws IndexOutOfBoundsException if the number of int values is
699 * {@code < species.length()}
700 */
701 @ForceInline
702 public static Shuffle<$Boxtype$> shuffleFromValues(Species<$Boxtype$> species, int... ixs) {
703 if (species.boxType() == $Type$MaxVector.class)
704 return new $Type$MaxVector.$Type$MaxShuffle(ixs);
705 switch (species.bitSize()) {
706 case 64: return new $Type$64Vector.$Type$64Shuffle(ixs);
707 case 128: return new $Type$128Vector.$Type$128Shuffle(ixs);
708 case 256: return new $Type$256Vector.$Type$256Shuffle(ixs);
709 case 512: return new $Type$512Vector.$Type$512Shuffle(ixs);
710 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
711 }
712 }
713
714 /**
715 * Loads a shuffle from an {@code int} array starting at an offset.
716 * <p>
717 * For each shuffle lane, where {@code N} is the shuffle lane index, the
718 * array element at index {@code i + N} logically AND'ed by
719 * {@code species.length() - 1} is placed into the resulting shuffle at lane
720 * index {@code N}.
721 *
722 * @param species shuffle species
723 * @param ixs the {@code int} array
724 * @param i the offset into the array
725 * @return a shuffle loaded from the {@code int} array
726 * @throws IndexOutOfBoundsException if {@code i < 0}, or
727 * {@code i > a.length - species.length()}
728 */
729 @ForceInline
730 public static Shuffle<$Boxtype$> shuffleFromArray(Species<$Boxtype$> species, int[] ixs, int i) {
731 if (species.boxType() == $Type$MaxVector.class)
732 return new $Type$MaxVector.$Type$MaxShuffle(ixs, i);
733 switch (species.bitSize()) {
734 case 64: return new $Type$64Vector.$Type$64Shuffle(ixs, i);
735 case 128: return new $Type$128Vector.$Type$128Shuffle(ixs, i);
736 case 256: return new $Type$256Vector.$Type$256Shuffle(ixs, i);
737 case 512: return new $Type$512Vector.$Type$512Shuffle(ixs, i);
738 default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
739 }
740 }
741
742 // Ops
743
744 @Override
745 public abstract $abstractvectortype$ add(Vector<$Boxtype$> v);
746
747 /**
748 * Adds this vector to the broadcast of an input scalar.
749 * <p>
750 * This is a vector binary operation where the primitive addition operation
751 * ({@code +}) is applied to lane elements.
752 *
753 * @param s the input scalar
754 * @return the result of adding this vector to the broadcast of an input
755 * scalar
756 */
757 public abstract $abstractvectortype$ add($type$ s);
758
759 @Override
760 public abstract $abstractvectortype$ add(Vector<$Boxtype$> v, Mask<$Boxtype$> m);
761
2909 * array bounds
2910 * @param m the mask
2911 * @param indexMap the index map
2912 * @param j the offset into the index map
2913 * @throws IndexOutOfBoundsException if {@code j < 0}, or
2914 * {@code j > indexMap.length - this.length()},
2915 * or for any vector lane index {@code N} where the mask at lane
2916 * {@code N} is set the result of {@code i + indexMap[j + N]} is
2917 * {@code < 0} or {@code >= a.length}
2918 */
2919 #if[byteOrShort]
2920 public void intoArray($type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j) {
2921 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
2922 }
2923 #else[byteOrShort]
2924 public abstract void intoArray($type$[] a, int i, Mask<$Boxtype$> m, int[] indexMap, int j);
2925 #end[byteOrShort]
2926 // Species
2927
2928 @Override
2929 public abstract Species<$Boxtype$> species();
2930
2931 /**
2932 * Class representing {@link $abstractvectortype$}'s of the same {@link Vector.Shape Shape}.
2933 */
2934 static final class $Type$Species extends Vector.AbstractSpecies<$Boxtype$> {
2935 final Function<$type$[], $Type$Vector> vectorFactory;
2936 final Function<boolean[], Vector.Mask<$Boxtype$>> maskFactory;
2937
2938 private $Type$Species(Vector.Shape shape,
2939 Class<?> boxType,
2940 Class<?> maskType,
2941 Function<$type$[], $Type$Vector> vectorFactory,
2942 Function<boolean[], Vector.Mask<$Boxtype$>> maskFactory) {
2943 super(shape, $type$.class, $Boxtype$.SIZE, boxType, maskType);
2944 this.vectorFactory = vectorFactory;
2945 this.maskFactory = maskFactory;
2946 }
2947
2948 interface FOp {
2949 $type$ apply(int i);
2950 }
2951
2952 interface FOpm {
2953 boolean apply(int i);
2954 }
2955
2956 $Type$Vector op(FOp f) {
2957 $type$[] res = new $type$[length()];
2958 for (int i = 0; i < length(); i++) {
2959 res[i] = f.apply(i);
2960 }
2961 return vectorFactory.apply(res);
2962 }
2963
2964 $Type$Vector op(Vector.Mask<$Boxtype$> o, FOp f) {
2965 $type$[] res = new $type$[length()];
2966 boolean[] mbits = ((AbstractMask<$Boxtype$>)o).getBits();
2967 for (int i = 0; i < length(); i++) {
2968 if (mbits[i]) {
2969 res[i] = f.apply(i);
2970 }
2971 }
2972 return vectorFactory.apply(res);
2973 }
2974
2975 Vector.Mask<$Boxtype$> opm(IntVector.IntSpecies.FOpm f) {
2976 boolean[] res = new boolean[length()];
2977 for (int i = 0; i < length(); i++) {
2978 res[i] = (boolean)f.apply(i);
2979 }
2980 return maskFactory.apply(res);
2981 }
2982 }
2983
2984 /**
2985 * Finds the preferred species for an element type of {@code $type$}.
2986 * <p>
2987 * A preferred species is a species chosen by the platform that has a
2988 * shape of maximal bit size. A preferred species for different element
2989 * types will have the same shape, and therefore vectors, masks, and
2990 * shuffles created from such species will be shape compatible.
2991 *
2992 * @return the preferred species for an element type of {@code $type$}
2993 */
2994 private static $Type$Species preferredSpecies() {
2995 return ($Type$Species) Species.ofPreferred($type$.class);
2996 }
2997
2998 /**
2999 * Finds a species for an element type of {@code $type$} and shape.
3000 *
3001 * @param s the shape
3002 * @return a species for an element type of {@code $type$} and shape
3003 * @throws IllegalArgumentException if no such species exists for the shape
3004 */
3005 static $Type$Species species(Vector.Shape s) {
3006 Objects.requireNonNull(s);
3007 switch (s) {
3008 case S_64_BIT: return ($Type$Species) SPECIES_64;
3009 case S_128_BIT: return ($Type$Species) SPECIES_128;
3010 case S_256_BIT: return ($Type$Species) SPECIES_256;
3011 case S_512_BIT: return ($Type$Species) SPECIES_512;
3012 case S_Max_BIT: return ($Type$Species) SPECIES_MAX;
3013 default: throw new IllegalArgumentException("Bad shape: " + s);
3014 }
3015 }
3016
3017 /** Species representing {@link $Type$Vector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
3018 public static final Species<$Boxtype$> SPECIES_64 = new $Type$Species(Shape.S_64_BIT, $Type$64Vector.class, $Type$64Vector.$Type$64Mask.class,
3019 $Type$64Vector::new, $Type$64Vector.$Type$64Mask::new);
3020
3021 /** Species representing {@link $Type$Vector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
3022 public static final Species<$Boxtype$> SPECIES_128 = new $Type$Species(Shape.S_128_BIT, $Type$128Vector.class, $Type$128Vector.$Type$128Mask.class,
3023 $Type$128Vector::new, $Type$128Vector.$Type$128Mask::new);
3024
3025 /** Species representing {@link $Type$Vector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
3026 public static final Species<$Boxtype$> SPECIES_256 = new $Type$Species(Shape.S_256_BIT, $Type$256Vector.class, $Type$256Vector.$Type$256Mask.class,
3027 $Type$256Vector::new, $Type$256Vector.$Type$256Mask::new);
3028
3029 /** Species representing {@link $Type$Vector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
3030 public static final Species<$Boxtype$> SPECIES_512 = new $Type$Species(Shape.S_512_BIT, $Type$512Vector.class, $Type$512Vector.$Type$512Mask.class,
3031 $Type$512Vector::new, $Type$512Vector.$Type$512Mask::new);
3032
3033 /** Species representing {@link $Type$Vector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
3034 public static final Species<$Boxtype$> SPECIES_MAX = new $Type$Species(Shape.S_Max_BIT, $Type$MaxVector.class, $Type$MaxVector.$Type$MaxMask.class,
3035 $Type$MaxVector::new, $Type$MaxVector.$Type$MaxMask::new);
3036
3037 /**
3038 * Preferred species for {@link $Type$Vector}s.
3039 * A preferred species is a species of maximal bit size for the platform.
3040 */
3041 public static final Species<$Boxtype$> SPECIES_PREFERRED = (Species<$Boxtype$>) preferredSpecies();
3042 }
|