1 /*
2  * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package jdk.incubator.vector;
26 
27 import java.nio.ByteBuffer;
28 import java.nio.ByteOrder;
29 import java.nio.ReadOnlyBufferException;
30 import java.util.Arrays;
31 import java.util.Objects;
32 import java.util.function.BinaryOperator;
33 import java.util.function.Function;
34 import java.util.function.UnaryOperator;
35 
36 import jdk.internal.misc.Unsafe;
37 import jdk.internal.vm.annotation.ForceInline;
38 import jdk.internal.vm.vector.VectorSupport;
39 
40 import static jdk.internal.vm.vector.VectorSupport.*;
41 import static jdk.incubator.vector.VectorIntrinsics.*;
42 
43 import static jdk.incubator.vector.VectorOperators.*;
44 
45 // -- This file was mechanically generated: Do not edit! -- //
46 
47 /**
48  * A specialized {@link Vector} representing an ordered immutable sequence of
49  * {@code int} values.
50  */
51 @SuppressWarnings("cast")  // warning: redundant cast
52 public abstract class IntVector extends AbstractVector<Integer> {
53 
IntVector(int[] vec)54     IntVector(int[] vec) {
55         super(vec);
56     }
57 
58     static final int FORBID_OPCODE_KIND = VO_ONLYFP;
59 
60     @ForceInline
opCode(Operator op)61     static int opCode(Operator op) {
62         return VectorOperators.opCode(op, VO_OPCODE_VALID, FORBID_OPCODE_KIND);
63     }
64     @ForceInline
opCode(Operator op, int requireKind)65     static int opCode(Operator op, int requireKind) {
66         requireKind |= VO_OPCODE_VALID;
67         return VectorOperators.opCode(op, requireKind, FORBID_OPCODE_KIND);
68     }
69     @ForceInline
opKind(Operator op, int bit)70     static boolean opKind(Operator op, int bit) {
71         return VectorOperators.opKind(op, bit);
72     }
73 
74     // Virtualized factories and operators,
75     // coded with portable definitions.
76     // These are all @ForceInline in case
77     // they need to be used performantly.
78     // The various shape-specific subclasses
79     // also specialize them by wrapping
80     // them in a call like this:
81     //    return (Byte128Vector)
82     //       super.bOp((Byte128Vector) o);
83     // The purpose of that is to forcibly inline
84     // the generic definition from this file
85     // into a sharply type- and size-specific
86     // wrapper in the subclass file, so that
87     // the JIT can specialize the code.
88     // The code is only inlined and expanded
89     // if it gets hot.  Think of it as a cheap
90     // and lazy version of C++ templates.
91 
92     // Virtualized getter
93 
94     /*package-private*/
vec()95     abstract int[] vec();
96 
97     // Virtualized constructors
98 
99     /**
100      * Build a vector directly using my own constructor.
101      * It is an error if the array is aliased elsewhere.
102      */
103     /*package-private*/
vectorFactory(int[] vec)104     abstract IntVector vectorFactory(int[] vec);
105 
106     /**
107      * Build a mask directly using my species.
108      * It is an error if the array is aliased elsewhere.
109      */
110     /*package-private*/
111     @ForceInline
112     final
maskFactory(boolean[] bits)113     AbstractMask<Integer> maskFactory(boolean[] bits) {
114         return vspecies().maskFactory(bits);
115     }
116 
117     // Constant loader (takes dummy as vector arg)
118     interface FVOp {
apply(int i)119         int apply(int i);
120     }
121 
122     /*package-private*/
123     @ForceInline
124     final
vOp(FVOp f)125     IntVector vOp(FVOp f) {
126         int[] res = new int[length()];
127         for (int i = 0; i < res.length; i++) {
128             res[i] = f.apply(i);
129         }
130         return vectorFactory(res);
131     }
132 
133     @ForceInline
134     final
vOp(VectorMask<Integer> m, FVOp f)135     IntVector vOp(VectorMask<Integer> m, FVOp f) {
136         int[] res = new int[length()];
137         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
138         for (int i = 0; i < res.length; i++) {
139             if (mbits[i]) {
140                 res[i] = f.apply(i);
141             }
142         }
143         return vectorFactory(res);
144     }
145 
146     // Unary operator
147 
148     /*package-private*/
149     interface FUnOp {
apply(int i, int a)150         int apply(int i, int a);
151     }
152 
153     /*package-private*/
154     abstract
uOp(FUnOp f)155     IntVector uOp(FUnOp f);
156     @ForceInline
157     final
uOpTemplate(FUnOp f)158     IntVector uOpTemplate(FUnOp f) {
159         int[] vec = vec();
160         int[] res = new int[length()];
161         for (int i = 0; i < res.length; i++) {
162             res[i] = f.apply(i, vec[i]);
163         }
164         return vectorFactory(res);
165     }
166 
167     /*package-private*/
168     abstract
uOp(VectorMask<Integer> m, FUnOp f)169     IntVector uOp(VectorMask<Integer> m,
170                              FUnOp f);
171     @ForceInline
172     final
uOpTemplate(VectorMask<Integer> m, FUnOp f)173     IntVector uOpTemplate(VectorMask<Integer> m,
174                                      FUnOp f) {
175         int[] vec = vec();
176         int[] res = new int[length()];
177         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
178         for (int i = 0; i < res.length; i++) {
179             res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i];
180         }
181         return vectorFactory(res);
182     }
183 
184     // Binary operator
185 
186     /*package-private*/
187     interface FBinOp {
apply(int i, int a, int b)188         int apply(int i, int a, int b);
189     }
190 
191     /*package-private*/
192     abstract
bOp(Vector<Integer> o, FBinOp f)193     IntVector bOp(Vector<Integer> o,
194                              FBinOp f);
195     @ForceInline
196     final
bOpTemplate(Vector<Integer> o, FBinOp f)197     IntVector bOpTemplate(Vector<Integer> o,
198                                      FBinOp f) {
199         int[] res = new int[length()];
200         int[] vec1 = this.vec();
201         int[] vec2 = ((IntVector)o).vec();
202         for (int i = 0; i < res.length; i++) {
203             res[i] = f.apply(i, vec1[i], vec2[i]);
204         }
205         return vectorFactory(res);
206     }
207 
208     /*package-private*/
209     abstract
bOp(Vector<Integer> o, VectorMask<Integer> m, FBinOp f)210     IntVector bOp(Vector<Integer> o,
211                              VectorMask<Integer> m,
212                              FBinOp f);
213     @ForceInline
214     final
bOpTemplate(Vector<Integer> o, VectorMask<Integer> m, FBinOp f)215     IntVector bOpTemplate(Vector<Integer> o,
216                                      VectorMask<Integer> m,
217                                      FBinOp f) {
218         int[] res = new int[length()];
219         int[] vec1 = this.vec();
220         int[] vec2 = ((IntVector)o).vec();
221         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
222         for (int i = 0; i < res.length; i++) {
223             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i];
224         }
225         return vectorFactory(res);
226     }
227 
228     // Ternary operator
229 
230     /*package-private*/
231     interface FTriOp {
apply(int i, int a, int b, int c)232         int apply(int i, int a, int b, int c);
233     }
234 
235     /*package-private*/
236     abstract
tOp(Vector<Integer> o1, Vector<Integer> o2, FTriOp f)237     IntVector tOp(Vector<Integer> o1,
238                              Vector<Integer> o2,
239                              FTriOp f);
240     @ForceInline
241     final
tOpTemplate(Vector<Integer> o1, Vector<Integer> o2, FTriOp f)242     IntVector tOpTemplate(Vector<Integer> o1,
243                                      Vector<Integer> o2,
244                                      FTriOp f) {
245         int[] res = new int[length()];
246         int[] vec1 = this.vec();
247         int[] vec2 = ((IntVector)o1).vec();
248         int[] vec3 = ((IntVector)o2).vec();
249         for (int i = 0; i < res.length; i++) {
250             res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]);
251         }
252         return vectorFactory(res);
253     }
254 
255     /*package-private*/
256     abstract
tOp(Vector<Integer> o1, Vector<Integer> o2, VectorMask<Integer> m, FTriOp f)257     IntVector tOp(Vector<Integer> o1,
258                              Vector<Integer> o2,
259                              VectorMask<Integer> m,
260                              FTriOp f);
261     @ForceInline
262     final
tOpTemplate(Vector<Integer> o1, Vector<Integer> o2, VectorMask<Integer> m, FTriOp f)263     IntVector tOpTemplate(Vector<Integer> o1,
264                                      Vector<Integer> o2,
265                                      VectorMask<Integer> m,
266                                      FTriOp f) {
267         int[] res = new int[length()];
268         int[] vec1 = this.vec();
269         int[] vec2 = ((IntVector)o1).vec();
270         int[] vec3 = ((IntVector)o2).vec();
271         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
272         for (int i = 0; i < res.length; i++) {
273             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i];
274         }
275         return vectorFactory(res);
276     }
277 
278     // Reduction operator
279 
280     /*package-private*/
281     abstract
rOp(int v, FBinOp f)282     int rOp(int v, FBinOp f);
283     @ForceInline
284     final
rOpTemplate(int v, FBinOp f)285     int rOpTemplate(int v, FBinOp f) {
286         int[] vec = vec();
287         for (int i = 0; i < vec.length; i++) {
288             v = f.apply(i, v, vec[i]);
289         }
290         return v;
291     }
292 
293     // Memory reference
294 
295     /*package-private*/
296     interface FLdOp<M> {
apply(M memory, int offset, int i)297         int apply(M memory, int offset, int i);
298     }
299 
300     /*package-private*/
301     @ForceInline
302     final
ldOp(M memory, int offset, FLdOp<M> f)303     <M> IntVector ldOp(M memory, int offset,
304                                   FLdOp<M> f) {
305         //dummy; no vec = vec();
306         int[] res = new int[length()];
307         for (int i = 0; i < res.length; i++) {
308             res[i] = f.apply(memory, offset, i);
309         }
310         return vectorFactory(res);
311     }
312 
313     /*package-private*/
314     @ForceInline
315     final
ldOp(M memory, int offset, VectorMask<Integer> m, FLdOp<M> f)316     <M> IntVector ldOp(M memory, int offset,
317                                   VectorMask<Integer> m,
318                                   FLdOp<M> f) {
319         //int[] vec = vec();
320         int[] res = new int[length()];
321         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
322         for (int i = 0; i < res.length; i++) {
323             if (mbits[i]) {
324                 res[i] = f.apply(memory, offset, i);
325             }
326         }
327         return vectorFactory(res);
328     }
329 
330     interface FStOp<M> {
apply(M memory, int offset, int i, int a)331         void apply(M memory, int offset, int i, int a);
332     }
333 
334     /*package-private*/
335     @ForceInline
336     final
stOp(M memory, int offset, FStOp<M> f)337     <M> void stOp(M memory, int offset,
338                   FStOp<M> f) {
339         int[] vec = vec();
340         for (int i = 0; i < vec.length; i++) {
341             f.apply(memory, offset, i, vec[i]);
342         }
343     }
344 
345     /*package-private*/
346     @ForceInline
347     final
stOp(M memory, int offset, VectorMask<Integer> m, FStOp<M> f)348     <M> void stOp(M memory, int offset,
349                   VectorMask<Integer> m,
350                   FStOp<M> f) {
351         int[] vec = vec();
352         boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
353         for (int i = 0; i < vec.length; i++) {
354             if (mbits[i]) {
355                 f.apply(memory, offset, i, vec[i]);
356             }
357         }
358     }
359 
360     // Binary test
361 
362     /*package-private*/
363     interface FBinTest {
apply(int cond, int i, int a, int b)364         boolean apply(int cond, int i, int a, int b);
365     }
366 
367     /*package-private*/
368     @ForceInline
369     final
bTest(int cond, Vector<Integer> o, FBinTest f)370     AbstractMask<Integer> bTest(int cond,
371                                   Vector<Integer> o,
372                                   FBinTest f) {
373         int[] vec1 = vec();
374         int[] vec2 = ((IntVector)o).vec();
375         boolean[] bits = new boolean[length()];
376         for (int i = 0; i < length(); i++){
377             bits[i] = f.apply(cond, i, vec1[i], vec2[i]);
378         }
379         return maskFactory(bits);
380     }
381 
382     /*package-private*/
383     @ForceInline
doBinTest(int cond, int a, int b)384     static boolean doBinTest(int cond, int a, int b) {
385         switch (cond) {
386         case BT_eq:  return a == b;
387         case BT_ne:  return a != b;
388         case BT_lt:  return a < b;
389         case BT_le:  return a <= b;
390         case BT_gt:  return a > b;
391         case BT_ge:  return a >= b;
392         }
393         throw new AssertionError(Integer.toHexString(cond));
394     }
395 
396     /*package-private*/
397     @Override
vspecies()398     abstract IntSpecies vspecies();
399 
400     /*package-private*/
401     @ForceInline
toBits(int e)402     static long toBits(int e) {
403         return  e;
404     }
405 
406     /*package-private*/
407     @ForceInline
fromBits(long bits)408     static int fromBits(long bits) {
409         return ((int)bits);
410     }
411 
412     // Static factories (other than memory operations)
413 
414     // Note: A surprising behavior in javadoc
415     // sometimes makes a lone /** {@inheritDoc} */
416     // comment drop the method altogether,
417     // apparently if the method mentions an
418     // parameter or return type of Vector<Integer>
419     // instead of Vector<E> as originally specified.
420     // Adding an empty HTML fragment appears to
421     // nudge javadoc into providing the desired
422     // inherited documentation.  We use the HTML
423     // comment <!--workaround--> for this.
424 
425     /**
426      * Returns a vector of the given species
427      * where all lane elements are set to
428      * zero, the default primitive value.
429      *
430      * @param species species of the desired zero vector
431      * @return a zero vector
432      */
433     @ForceInline
zero(VectorSpecies<Integer> species)434     public static IntVector zero(VectorSpecies<Integer> species) {
435         IntSpecies vsp = (IntSpecies) species;
436         return VectorSupport.broadcastCoerced(vsp.vectorType(), int.class, species.length(),
437                                 0, vsp,
438                                 ((bits_, s_) -> s_.rvOp(i -> bits_)));
439     }
440 
441     /**
442      * Returns a vector of the same species as this one
443      * where all lane elements are set to
444      * the primitive value {@code e}.
445      *
446      * The contents of the current vector are discarded;
447      * only the species is relevant to this operation.
448      *
449      * <p> This method returns the value of this expression:
450      * {@code IntVector.broadcast(this.species(), e)}.
451      *
452      * @apiNote
453      * Unlike the similar method named {@code broadcast()}
454      * in the supertype {@code Vector}, this method does not
455      * need to validate its argument, and cannot throw
456      * {@code IllegalArgumentException}.  This method is
457      * therefore preferable to the supertype method.
458      *
459      * @param e the value to broadcast
460      * @return a vector where all lane elements are set to
461      *         the primitive value {@code e}
462      * @see #broadcast(VectorSpecies,long)
463      * @see Vector#broadcast(long)
464      * @see VectorSpecies#broadcast(long)
465      */
broadcast(int e)466     public abstract IntVector broadcast(int e);
467 
468     /**
469      * Returns a vector of the given species
470      * where all lane elements are set to
471      * the primitive value {@code e}.
472      *
473      * @param species species of the desired vector
474      * @param e the value to broadcast
475      * @return a vector where all lane elements are set to
476      *         the primitive value {@code e}
477      * @see #broadcast(long)
478      * @see Vector#broadcast(long)
479      * @see VectorSpecies#broadcast(long)
480      */
481     @ForceInline
broadcast(VectorSpecies<Integer> species, int e)482     public static IntVector broadcast(VectorSpecies<Integer> species, int e) {
483         IntSpecies vsp = (IntSpecies) species;
484         return vsp.broadcast(e);
485     }
486 
487     /*package-private*/
488     @ForceInline
broadcastTemplate(int e)489     final IntVector broadcastTemplate(int e) {
490         IntSpecies vsp = vspecies();
491         return vsp.broadcast(e);
492     }
493 
494     /**
495      * {@inheritDoc} <!--workaround-->
496      * @apiNote
497      * When working with vector subtypes like {@code IntVector},
498      * {@linkplain #broadcast(int) the more strongly typed method}
499      * is typically selected.  It can be explicitly selected
500      * using a cast: {@code v.broadcast((int)e)}.
501      * The two expressions will produce numerically identical results.
502      */
503     @Override
broadcast(long e)504     public abstract IntVector broadcast(long e);
505 
506     /**
507      * Returns a vector of the given species
508      * where all lane elements are set to
509      * the primitive value {@code e}.
510      *
511      * The {@code long} value must be accurately representable
512      * by the {@code ETYPE} of the vector species, so that
513      * {@code e==(long)(ETYPE)e}.
514      *
515      * @param species species of the desired vector
516      * @param e the value to broadcast
517      * @return a vector where all lane elements are set to
518      *         the primitive value {@code e}
519      * @throws IllegalArgumentException
520      *         if the given {@code long} value cannot
521      *         be represented by the vector's {@code ETYPE}
522      * @see #broadcast(VectorSpecies,int)
523      * @see VectorSpecies#checkValue(long)
524      */
525     @ForceInline
broadcast(VectorSpecies<Integer> species, long e)526     public static IntVector broadcast(VectorSpecies<Integer> species, long e) {
527         IntSpecies vsp = (IntSpecies) species;
528         return vsp.broadcast(e);
529     }
530 
531     /*package-private*/
532     @ForceInline
broadcastTemplate(long e)533     final IntVector broadcastTemplate(long e) {
534         return vspecies().broadcast(e);
535     }
536 
537     // Unary lanewise support
538 
539     /**
540      * {@inheritDoc} <!--workaround-->
541      */
542     public abstract
lanewise(VectorOperators.Unary op)543     IntVector lanewise(VectorOperators.Unary op);
544 
545     @ForceInline
546     final
lanewiseTemplate(VectorOperators.Unary op)547     IntVector lanewiseTemplate(VectorOperators.Unary op) {
548         if (opKind(op, VO_SPECIAL)) {
549             if (op == ZOMO) {
550                 return blend(broadcast(-1), compare(NE, 0));
551             }
552             if (op == NOT) {
553                 return broadcast(-1).lanewiseTemplate(XOR, this);
554             } else if (op == NEG) {
555                 // FIXME: Support this in the JIT.
556                 return broadcast(0).lanewiseTemplate(SUB, this);
557             }
558         }
559         int opc = opCode(op);
560         return VectorSupport.unaryOp(
561             opc, getClass(), int.class, length(),
562             this,
563             UN_IMPL.find(op, opc, (opc_) -> {
564               switch (opc_) {
565                 case VECTOR_OP_NEG: return v0 ->
566                         v0.uOp((i, a) -> (int) -a);
567                 case VECTOR_OP_ABS: return v0 ->
568                         v0.uOp((i, a) -> (int) Math.abs(a));
569                 default: return null;
570               }}));
571     }
572     private static final
573     ImplCache<Unary,UnaryOperator<IntVector>> UN_IMPL
574         = new ImplCache<>(Unary.class, IntVector.class);
575 
576     /**
577      * {@inheritDoc} <!--workaround-->
578      */
579     @ForceInline
580     public final
581     IntVector lanewise(VectorOperators.Unary op,
582                                   VectorMask<Integer> m) {
583         return blend(lanewise(op), m);
584     }
585 
586     // Binary lanewise support
587 
588     /**
589      * {@inheritDoc} <!--workaround-->
590      * @see #lanewise(VectorOperators.Binary,int)
591      * @see #lanewise(VectorOperators.Binary,int,VectorMask)
592      */
593     @Override
594     public abstract
595     IntVector lanewise(VectorOperators.Binary op,
596                                   Vector<Integer> v);
597     @ForceInline
598     final
599     IntVector lanewiseTemplate(VectorOperators.Binary op,
600                                           Vector<Integer> v) {
601         IntVector that = (IntVector) v;
602         that.check(this);
603         if (opKind(op, VO_SPECIAL  | VO_SHIFT)) {
604             if (op == FIRST_NONZERO) {
605                 // FIXME: Support this in the JIT.
606                 VectorMask<Integer> thisNZ
607                     = this.viewAsIntegralLanes().compare(NE, (int) 0);
608                 that = that.blend((int) 0, thisNZ.cast(vspecies()));
609                 op = OR_UNCHECKED;
610             }
611             if (opKind(op, VO_SHIFT)) {
612                 // As per shift specification for Java, mask the shift count.
613                 // This allows the JIT to ignore some ISA details.
614                 that = that.lanewise(AND, SHIFT_MASK);
615             }
616             if (op == ROR || op == ROL) {  // FIXME: JIT should do this
617                 IntVector neg = that.lanewise(NEG);
618                 IntVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that);
619                 IntVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg);
620                 return hi.lanewise(OR, lo);
621             } else if (op == AND_NOT) {
622                 // FIXME: Support this in the JIT.
623                 that = that.lanewise(NOT);
624                 op = AND;
625             } else if (op == DIV) {
626                 VectorMask<Integer> eqz = that.eq((int)0);
627                 if (eqz.anyTrue()) {
628                     throw that.divZeroException();
629                 }
630             }
631         }
632         int opc = opCode(op);
633         return VectorSupport.binaryOp(
634             opc, getClass(), int.class, length(),
635             this, that,
636             BIN_IMPL.find(op, opc, (opc_) -> {
637               switch (opc_) {
638                 case VECTOR_OP_ADD: return (v0, v1) ->
639                         v0.bOp(v1, (i, a, b) -> (int)(a + b));
640                 case VECTOR_OP_SUB: return (v0, v1) ->
641                         v0.bOp(v1, (i, a, b) -> (int)(a - b));
642                 case VECTOR_OP_MUL: return (v0, v1) ->
643                         v0.bOp(v1, (i, a, b) -> (int)(a * b));
644                 case VECTOR_OP_DIV: return (v0, v1) ->
645                         v0.bOp(v1, (i, a, b) -> (int)(a / b));
646                 case VECTOR_OP_MAX: return (v0, v1) ->
647                         v0.bOp(v1, (i, a, b) -> (int)Math.max(a, b));
648                 case VECTOR_OP_MIN: return (v0, v1) ->
649                         v0.bOp(v1, (i, a, b) -> (int)Math.min(a, b));
650                 case VECTOR_OP_AND: return (v0, v1) ->
651                         v0.bOp(v1, (i, a, b) -> (int)(a & b));
652                 case VECTOR_OP_OR: return (v0, v1) ->
653                         v0.bOp(v1, (i, a, b) -> (int)(a | b));
654                 case VECTOR_OP_XOR: return (v0, v1) ->
655                         v0.bOp(v1, (i, a, b) -> (int)(a ^ b));
656                 case VECTOR_OP_LSHIFT: return (v0, v1) ->
657                         v0.bOp(v1, (i, a, n) -> (int)(a << n));
658                 case VECTOR_OP_RSHIFT: return (v0, v1) ->
659                         v0.bOp(v1, (i, a, n) -> (int)(a >> n));
660                 case VECTOR_OP_URSHIFT: return (v0, v1) ->
661                         v0.bOp(v1, (i, a, n) -> (int)((a & LSHR_SETUP_MASK) >>> n));
662                 default: return null;
663                 }}));
664     }
665     private static final
666     ImplCache<Binary,BinaryOperator<IntVector>> BIN_IMPL
667         = new ImplCache<>(Binary.class, IntVector.class);
668 
669     /**
670      * {@inheritDoc} <!--workaround-->
671      * @see #lanewise(VectorOperators.Binary,int,VectorMask)
672      */
673     @ForceInline
674     public final
675     IntVector lanewise(VectorOperators.Binary op,
676                                   Vector<Integer> v,
677                                   VectorMask<Integer> m) {
678         IntVector that = (IntVector) v;
679         if (op == DIV) {
680             VectorMask<Integer> eqz = that.eq((int)0);
681             if (eqz.and(m).anyTrue()) {
682                 throw that.divZeroException();
683             }
684             // suppress div/0 exceptions in unset lanes
685             that = that.lanewise(NOT, eqz);
686             return blend(lanewise(DIV, that), m);
687         }
688         return blend(lanewise(op, v), m);
689     }
690     // FIXME: Maybe all of the public final methods in this file (the
691     // simple ones that just call lanewise) should be pushed down to
692     // the X-VectorBits template.  They can't optimize properly at
693     // this level, and must rely on inlining.  Does it work?
694     // (If it works, of course keep the code here.)
695 
696     /**
697      * Combines the lane values of this vector
698      * with the value of a broadcast scalar.
699      *
700      * This is a lane-wise binary operation which applies
701      * the selected operation to each lane.
702      * The return value will be equal to this expression:
703      * {@code this.lanewise(op, this.broadcast(e))}.
704      *
705      * @param op the operation used to process lane values
706      * @param e the input scalar
707      * @return the result of applying the operation lane-wise
708      *         to the two input vectors
709      * @throws UnsupportedOperationException if this vector does
710      *         not support the requested operation
711      * @see #lanewise(VectorOperators.Binary,Vector)
712      * @see #lanewise(VectorOperators.Binary,int,VectorMask)
713      */
714     @ForceInline
715     public final
716     IntVector lanewise(VectorOperators.Binary op,
717                                   int e) {
718         if (opKind(op, VO_SHIFT) && (int)(int)e == e) {
719             return lanewiseShift(op, (int) e);
720         }
721         if (op == AND_NOT) {
722             op = AND; e = (int) ~e;
723         }
724         return lanewise(op, broadcast(e));
725     }
726 
727     /**
728      * Combines the lane values of this vector
729      * with the value of a broadcast scalar,
730      * with selection of lane elements controlled by a mask.
731      *
732      * This is a masked lane-wise binary operation which applies
733      * the selected operation to each lane.
734      * The return value will be equal to this expression:
735      * {@code this.lanewise(op, this.broadcast(e), m)}.
736      *
737      * @param op the operation used to process lane values
738      * @param e the input scalar
739      * @param m the mask controlling lane selection
740      * @return the result of applying the operation lane-wise
741      *         to the input vector and the scalar
742      * @throws UnsupportedOperationException if this vector does
743      *         not support the requested operation
744      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
745      * @see #lanewise(VectorOperators.Binary,int)
746      */
747     @ForceInline
748     public final
749     IntVector lanewise(VectorOperators.Binary op,
750                                   int e,
751                                   VectorMask<Integer> m) {
752         return blend(lanewise(op, e), m);
753     }
754 
755     /**
756      * {@inheritDoc} <!--workaround-->
757      * @apiNote
758      * When working with vector subtypes like {@code IntVector},
759      * {@linkplain #lanewise(VectorOperators.Binary,int)
760      * the more strongly typed method}
761      * is typically selected.  It can be explicitly selected
762      * using a cast: {@code v.lanewise(op,(int)e)}.
763      * The two expressions will produce numerically identical results.
764      */
765     @ForceInline
766     public final
767     IntVector lanewise(VectorOperators.Binary op,
768                                   long e) {
769         int e1 = (int) e;
770         if ((long)e1 != e
771             // allow shift ops to clip down their int parameters
772             && !(opKind(op, VO_SHIFT) && (int)e1 == e)
773             ) {
774             vspecies().checkValue(e);  // for exception
775         }
776         return lanewise(op, e1);
777     }
778 
779     /**
780      * {@inheritDoc} <!--workaround-->
781      * @apiNote
782      * When working with vector subtypes like {@code IntVector},
783      * {@linkplain #lanewise(VectorOperators.Binary,int,VectorMask)
784      * the more strongly typed method}
785      * is typically selected.  It can be explicitly selected
786      * using a cast: {@code v.lanewise(op,(int)e,m)}.
787      * The two expressions will produce numerically identical results.
788      */
789     @ForceInline
790     public final
791     IntVector lanewise(VectorOperators.Binary op,
792                                   long e, VectorMask<Integer> m) {
793         return blend(lanewise(op, e), m);
794     }
795 
796     /*package-private*/
797     abstract IntVector
798     lanewiseShift(VectorOperators.Binary op, int e);
799 
800     /*package-private*/
801     @ForceInline
802     final IntVector
803     lanewiseShiftTemplate(VectorOperators.Binary op, int e) {
804         // Special handling for these.  FIXME: Refactor?
805         assert(opKind(op, VO_SHIFT));
806         // As per shift specification for Java, mask the shift count.
807         e &= SHIFT_MASK;
808         if (op == ROR || op == ROL) {  // FIXME: JIT should do this
809             IntVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e);
810             IntVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e);
811             return hi.lanewise(OR, lo);
812         }
813         int opc = opCode(op);
814         return VectorSupport.broadcastInt(
815             opc, getClass(), int.class, length(),
816             this, e,
817             BIN_INT_IMPL.find(op, opc, (opc_) -> {
818               switch (opc_) {
819                 case VECTOR_OP_LSHIFT: return (v, n) ->
820                         v.uOp((i, a) -> (int)(a << n));
821                 case VECTOR_OP_RSHIFT: return (v, n) ->
822                         v.uOp((i, a) -> (int)(a >> n));
823                 case VECTOR_OP_URSHIFT: return (v, n) ->
824                         v.uOp((i, a) -> (int)((a & LSHR_SETUP_MASK) >>> n));
825                 default: return null;
826                 }}));
827     }
828     private static final
829     ImplCache<Binary,VectorBroadcastIntOp<IntVector>> BIN_INT_IMPL
830         = new ImplCache<>(Binary.class, IntVector.class);
831 
832     // As per shift specification for Java, mask the shift count.
833     // We mask 0X3F (long), 0X1F (int), 0x0F (short), 0x7 (byte).
834     // The latter two maskings go beyond the JLS, but seem reasonable
835     // since our lane types are first-class types, not just dressed
836     // up ints.
837     private static final int SHIFT_MASK = (Integer.SIZE - 1);
838     private static final int LSHR_SETUP_MASK = -1;
839 
840     // Ternary lanewise support
841 
842     // Ternary operators come in eight variations:
843     //   lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2])
844     //   lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2], mask)
845 
846     // It is annoying to support all of these variations of masking
847     // and broadcast, but it would be more surprising not to continue
848     // the obvious pattern started by unary and binary.
849 
850    /**
851      * {@inheritDoc} <!--workaround-->
852      * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask)
853      * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask)
854      * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask)
855      * @see #lanewise(VectorOperators.Ternary,int,int)
856      * @see #lanewise(VectorOperators.Ternary,Vector,int)
857      * @see #lanewise(VectorOperators.Ternary,int,Vector)
858      */
859     @Override
860     public abstract
861     IntVector lanewise(VectorOperators.Ternary op,
862                                                   Vector<Integer> v1,
863                                                   Vector<Integer> v2);
864     @ForceInline
865     final
866     IntVector lanewiseTemplate(VectorOperators.Ternary op,
867                                           Vector<Integer> v1,
868                                           Vector<Integer> v2) {
869         IntVector that = (IntVector) v1;
870         IntVector tother = (IntVector) v2;
871         // It's a word: https://www.dictionary.com/browse/tother
872         // See also Chapter 11 of Dickens, Our Mutual Friend:
873         // "Totherest Governor," replied Mr Riderhood...
874         that.check(this);
875         tother.check(this);
876         if (op == BITWISE_BLEND) {
877             // FIXME: Support this in the JIT.
878             that = this.lanewise(XOR, that).lanewise(AND, tother);
879             return this.lanewise(XOR, that);
880         }
881         int opc = opCode(op);
882         return VectorSupport.ternaryOp(
883             opc, getClass(), int.class, length(),
884             this, that, tother,
885             TERN_IMPL.find(op, opc, (opc_) -> {
886               switch (opc_) {
887                 default: return null;
888                 }}));
889     }
890     private static final
891     ImplCache<Ternary,TernaryOperation<IntVector>> TERN_IMPL
892         = new ImplCache<>(Ternary.class, IntVector.class);
893 
894     /**
895      * {@inheritDoc} <!--workaround-->
896      * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask)
897      * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask)
898      * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask)
899      */
900     @ForceInline
901     public final
902     IntVector lanewise(VectorOperators.Ternary op,
903                                   Vector<Integer> v1,
904                                   Vector<Integer> v2,
905                                   VectorMask<Integer> m) {
906         return blend(lanewise(op, v1, v2), m);
907     }
908 
909     /**
910      * Combines the lane values of this vector
911      * with the values of two broadcast scalars.
912      *
913      * This is a lane-wise ternary operation which applies
914      * the selected operation to each lane.
915      * The return value will be equal to this expression:
916      * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2))}.
917      *
918      * @param op the operation used to combine lane values
919      * @param e1 the first input scalar
920      * @param e2 the second input scalar
921      * @return the result of applying the operation lane-wise
922      *         to the input vector and the scalars
923      * @throws UnsupportedOperationException if this vector does
924      *         not support the requested operation
925      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
926      * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask)
927      */
928     @ForceInline
929     public final
930     IntVector lanewise(VectorOperators.Ternary op, //(op,e1,e2)
931                                   int e1,
932                                   int e2) {
933         return lanewise(op, broadcast(e1), broadcast(e2));
934     }
935 
936     /**
937      * Combines the lane values of this vector
938      * with the values of two broadcast scalars,
939      * with selection of lane elements controlled by a mask.
940      *
941      * This is a masked lane-wise ternary operation which applies
942      * the selected operation to each lane.
943      * The return value will be equal to this expression:
944      * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2), m)}.
945      *
946      * @param op the operation used to combine lane values
947      * @param e1 the first input scalar
948      * @param e2 the second input scalar
949      * @param m the mask controlling lane selection
950      * @return the result of applying the operation lane-wise
951      *         to the input vector and the scalars
952      * @throws UnsupportedOperationException if this vector does
953      *         not support the requested operation
954      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
955      * @see #lanewise(VectorOperators.Ternary,int,int)
956      */
957     @ForceInline
958     public final
959     IntVector lanewise(VectorOperators.Ternary op, //(op,e1,e2,m)
960                                   int e1,
961                                   int e2,
962                                   VectorMask<Integer> m) {
963         return blend(lanewise(op, e1, e2), m);
964     }
965 
966     /**
967      * Combines the lane values of this vector
968      * with the values of another vector and a broadcast scalar.
969      *
970      * This is a lane-wise ternary operation which applies
971      * the selected operation to each lane.
972      * The return value will be equal to this expression:
973      * {@code this.lanewise(op, v1, this.broadcast(e2))}.
974      *
975      * @param op the operation used to combine lane values
976      * @param v1 the other input vector
977      * @param e2 the input scalar
978      * @return the result of applying the operation lane-wise
979      *         to the input vectors and the scalar
980      * @throws UnsupportedOperationException if this vector does
981      *         not support the requested operation
982      * @see #lanewise(VectorOperators.Ternary,int,int)
983      * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask)
984      */
985     @ForceInline
986     public final
987     IntVector lanewise(VectorOperators.Ternary op, //(op,v1,e2)
988                                   Vector<Integer> v1,
989                                   int e2) {
990         return lanewise(op, v1, broadcast(e2));
991     }
992 
993     /**
994      * Combines the lane values of this vector
995      * with the values of another vector and a broadcast scalar,
996      * with selection of lane elements controlled by a mask.
997      *
998      * This is a masked lane-wise ternary operation which applies
999      * the selected operation to each lane.
1000      * The return value will be equal to this expression:
1001      * {@code this.lanewise(op, v1, this.broadcast(e2), m)}.
1002      *
1003      * @param op the operation used to combine lane values
1004      * @param v1 the other input vector
1005      * @param e2 the input scalar
1006      * @param m the mask controlling lane selection
1007      * @return the result of applying the operation lane-wise
1008      *         to the input vectors and the scalar
1009      * @throws UnsupportedOperationException if this vector does
1010      *         not support the requested operation
1011      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
1012      * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask)
1013      * @see #lanewise(VectorOperators.Ternary,Vector,int)
1014      */
1015     @ForceInline
1016     public final
1017     IntVector lanewise(VectorOperators.Ternary op, //(op,v1,e2,m)
1018                                   Vector<Integer> v1,
1019                                   int e2,
1020                                   VectorMask<Integer> m) {
1021         return blend(lanewise(op, v1, e2), m);
1022     }
1023 
1024     /**
1025      * Combines the lane values of this vector
1026      * with the values of another vector and a broadcast scalar.
1027      *
1028      * This is a lane-wise ternary operation which applies
1029      * the selected operation to each lane.
1030      * The return value will be equal to this expression:
1031      * {@code this.lanewise(op, this.broadcast(e1), v2)}.
1032      *
1033      * @param op the operation used to combine lane values
1034      * @param e1 the input scalar
1035      * @param v2 the other input vector
1036      * @return the result of applying the operation lane-wise
1037      *         to the input vectors and the scalar
1038      * @throws UnsupportedOperationException if this vector does
1039      *         not support the requested operation
1040      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
1041      * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask)
1042      */
1043     @ForceInline
1044     public final
1045     IntVector lanewise(VectorOperators.Ternary op, //(op,e1,v2)
1046                                   int e1,
1047                                   Vector<Integer> v2) {
1048         return lanewise(op, broadcast(e1), v2);
1049     }
1050 
1051     /**
1052      * Combines the lane values of this vector
1053      * with the values of another vector and a broadcast scalar,
1054      * with selection of lane elements controlled by a mask.
1055      *
1056      * This is a masked lane-wise ternary operation which applies
1057      * the selected operation to each lane.
1058      * The return value will be equal to this expression:
1059      * {@code this.lanewise(op, this.broadcast(e1), v2, m)}.
1060      *
1061      * @param op the operation used to combine lane values
1062      * @param e1 the input scalar
1063      * @param v2 the other input vector
1064      * @param m the mask controlling lane selection
1065      * @return the result of applying the operation lane-wise
1066      *         to the input vectors and the scalar
1067      * @throws UnsupportedOperationException if this vector does
1068      *         not support the requested operation
1069      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
1070      * @see #lanewise(VectorOperators.Ternary,int,Vector)
1071      */
1072     @ForceInline
1073     public final
1074     IntVector lanewise(VectorOperators.Ternary op, //(op,e1,v2,m)
1075                                   int e1,
1076                                   Vector<Integer> v2,
1077                                   VectorMask<Integer> m) {
1078         return blend(lanewise(op, e1, v2), m);
1079     }
1080 
1081     // (Thus endeth the Great and Mighty Ternary Ogdoad.)
1082     // https://en.wikipedia.org/wiki/Ogdoad
1083 
1084     /// FULL-SERVICE BINARY METHODS: ADD, SUB, MUL, DIV
1085     //
1086     // These include masked and non-masked versions.
1087     // This subclass adds broadcast (masked or not).
1088 
1089     /**
1090      * {@inheritDoc} <!--workaround-->
1091      * @see #add(int)
1092      */
1093     @Override
1094     @ForceInline
1095     public final IntVector add(Vector<Integer> v) {
1096         return lanewise(ADD, v);
1097     }
1098 
1099     /**
1100      * Adds this vector to the broadcast of an input scalar.
1101      *
1102      * This is a lane-wise binary operation which applies
1103      * the primitive addition operation ({@code +}) to each lane.
1104      *
1105      * This method is also equivalent to the expression
1106      * {@link #lanewise(VectorOperators.Binary,int)
1107      *    lanewise}{@code (}{@link VectorOperators#ADD
1108      *    ADD}{@code , e)}.
1109      *
1110      * @param e the input scalar
1111      * @return the result of adding each lane of this vector to the scalar
1112      * @see #add(Vector)
1113      * @see #broadcast(int)
1114      * @see #add(int,VectorMask)
1115      * @see VectorOperators#ADD
1116      * @see #lanewise(VectorOperators.Binary,Vector)
1117      * @see #lanewise(VectorOperators.Binary,int)
1118      */
1119     @ForceInline
1120     public final
1121     IntVector add(int e) {
1122         return lanewise(ADD, e);
1123     }
1124 
1125     /**
1126      * {@inheritDoc} <!--workaround-->
1127      * @see #add(int,VectorMask)
1128      */
1129     @Override
1130     @ForceInline
1131     public final IntVector add(Vector<Integer> v,
1132                                           VectorMask<Integer> m) {
1133         return lanewise(ADD, v, m);
1134     }
1135 
1136     /**
1137      * Adds this vector to the broadcast of an input scalar,
1138      * selecting lane elements controlled by a mask.
1139      *
1140      * This is a masked lane-wise binary operation which applies
1141      * the primitive addition operation ({@code +}) to each lane.
1142      *
1143      * This method is also equivalent to the expression
1144      * {@link #lanewise(VectorOperators.Binary,int,VectorMask)
1145      *    lanewise}{@code (}{@link VectorOperators#ADD
1146      *    ADD}{@code , s, m)}.
1147      *
1148      * @param e the input scalar
1149      * @param m the mask controlling lane selection
1150      * @return the result of adding each lane of this vector to the scalar
1151      * @see #add(Vector,VectorMask)
1152      * @see #broadcast(int)
1153      * @see #add(int)
1154      * @see VectorOperators#ADD
1155      * @see #lanewise(VectorOperators.Binary,Vector)
1156      * @see #lanewise(VectorOperators.Binary,int)
1157      */
1158     @ForceInline
1159     public final IntVector add(int e,
1160                                           VectorMask<Integer> m) {
1161         return lanewise(ADD, e, m);
1162     }
1163 
1164     /**
1165      * {@inheritDoc} <!--workaround-->
1166      * @see #sub(int)
1167      */
1168     @Override
1169     @ForceInline
1170     public final IntVector sub(Vector<Integer> v) {
1171         return lanewise(SUB, v);
1172     }
1173 
1174     /**
1175      * Subtracts an input scalar from this vector.
1176      *
1177      * This is a masked lane-wise binary operation which applies
1178      * the primitive subtraction operation ({@code -}) to each lane.
1179      *
1180      * This method is also equivalent to the expression
1181      * {@link #lanewise(VectorOperators.Binary,int)
1182      *    lanewise}{@code (}{@link VectorOperators#SUB
1183      *    SUB}{@code , e)}.
1184      *
1185      * @param e the input scalar
1186      * @return the result of subtracting the scalar from each lane of this vector
1187      * @see #sub(Vector)
1188      * @see #broadcast(int)
1189      * @see #sub(int,VectorMask)
1190      * @see VectorOperators#SUB
1191      * @see #lanewise(VectorOperators.Binary,Vector)
1192      * @see #lanewise(VectorOperators.Binary,int)
1193      */
1194     @ForceInline
1195     public final IntVector sub(int e) {
1196         return lanewise(SUB, e);
1197     }
1198 
1199     /**
1200      * {@inheritDoc} <!--workaround-->
1201      * @see #sub(int,VectorMask)
1202      */
1203     @Override
1204     @ForceInline
1205     public final IntVector sub(Vector<Integer> v,
1206                                           VectorMask<Integer> m) {
1207         return lanewise(SUB, v, m);
1208     }
1209 
1210     /**
1211      * Subtracts an input scalar from this vector
1212      * under the control of a mask.
1213      *
1214      * This is a masked lane-wise binary operation which applies
1215      * the primitive subtraction operation ({@code -}) to each lane.
1216      *
1217      * This method is also equivalent to the expression
1218      * {@link #lanewise(VectorOperators.Binary,int,VectorMask)
1219      *    lanewise}{@code (}{@link VectorOperators#SUB
1220      *    SUB}{@code , s, m)}.
1221      *
1222      * @param e the input scalar
1223      * @param m the mask controlling lane selection
1224      * @return the result of subtracting the scalar from each lane of this vector
1225      * @see #sub(Vector,VectorMask)
1226      * @see #broadcast(int)
1227      * @see #sub(int)
1228      * @see VectorOperators#SUB
1229      * @see #lanewise(VectorOperators.Binary,Vector)
1230      * @see #lanewise(VectorOperators.Binary,int)
1231      */
1232     @ForceInline
1233     public final IntVector sub(int e,
1234                                           VectorMask<Integer> m) {
1235         return lanewise(SUB, e, m);
1236     }
1237 
1238     /**
1239      * {@inheritDoc} <!--workaround-->
1240      * @see #mul(int)
1241      */
1242     @Override
1243     @ForceInline
1244     public final IntVector mul(Vector<Integer> v) {
1245         return lanewise(MUL, v);
1246     }
1247 
1248     /**
1249      * Multiplies this vector by the broadcast of an input scalar.
1250      *
1251      * This is a lane-wise binary operation which applies
1252      * the primitive multiplication operation ({@code *}) to each lane.
1253      *
1254      * This method is also equivalent to the expression
1255      * {@link #lanewise(VectorOperators.Binary,int)
1256      *    lanewise}{@code (}{@link VectorOperators#MUL
1257      *    MUL}{@code , e)}.
1258      *
1259      * @param e the input scalar
1260      * @return the result of multiplying this vector by the given scalar
1261      * @see #mul(Vector)
1262      * @see #broadcast(int)
1263      * @see #mul(int,VectorMask)
1264      * @see VectorOperators#MUL
1265      * @see #lanewise(VectorOperators.Binary,Vector)
1266      * @see #lanewise(VectorOperators.Binary,int)
1267      */
1268     @ForceInline
1269     public final IntVector mul(int e) {
1270         return lanewise(MUL, e);
1271     }
1272 
1273     /**
1274      * {@inheritDoc} <!--workaround-->
1275      * @see #mul(int,VectorMask)
1276      */
1277     @Override
1278     @ForceInline
1279     public final IntVector mul(Vector<Integer> v,
1280                                           VectorMask<Integer> m) {
1281         return lanewise(MUL, v, m);
1282     }
1283 
1284     /**
1285      * Multiplies this vector by the broadcast of an input scalar,
1286      * selecting lane elements controlled by a mask.
1287      *
1288      * This is a masked lane-wise binary operation which applies
1289      * the primitive multiplication operation ({@code *}) to each lane.
1290      *
1291      * This method is also equivalent to the expression
1292      * {@link #lanewise(VectorOperators.Binary,int,VectorMask)
1293      *    lanewise}{@code (}{@link VectorOperators#MUL
1294      *    MUL}{@code , s, m)}.
1295      *
1296      * @param e the input scalar
1297      * @param m the mask controlling lane selection
1298      * @return the result of muling each lane of this vector to the scalar
1299      * @see #mul(Vector,VectorMask)
1300      * @see #broadcast(int)
1301      * @see #mul(int)
1302      * @see VectorOperators#MUL
1303      * @see #lanewise(VectorOperators.Binary,Vector)
1304      * @see #lanewise(VectorOperators.Binary,int)
1305      */
1306     @ForceInline
1307     public final IntVector mul(int e,
1308                                           VectorMask<Integer> m) {
1309         return lanewise(MUL, e, m);
1310     }
1311 
1312     /**
1313      * {@inheritDoc} <!--workaround-->
1314      * @apiNote If there is a zero divisor, {@code
1315      * ArithmeticException} will be thrown.
1316      */
1317     @Override
1318     @ForceInline
1319     public final IntVector div(Vector<Integer> v) {
1320         return lanewise(DIV, v);
1321     }
1322 
1323     /**
1324      * Divides this vector by the broadcast of an input scalar.
1325      *
1326      * This is a lane-wise binary operation which applies
1327      * the primitive division operation ({@code /}) to each lane.
1328      *
1329      * This method is also equivalent to the expression
1330      * {@link #lanewise(VectorOperators.Binary,int)
1331      *    lanewise}{@code (}{@link VectorOperators#DIV
1332      *    DIV}{@code , e)}.
1333      *
1334      * @apiNote If there is a zero divisor, {@code
1335      * ArithmeticException} will be thrown.
1336      *
1337      * @param e the input scalar
1338      * @return the result of dividing each lane of this vector by the scalar
1339      * @see #div(Vector)
1340      * @see #broadcast(int)
1341      * @see #div(int,VectorMask)
1342      * @see VectorOperators#DIV
1343      * @see #lanewise(VectorOperators.Binary,Vector)
1344      * @see #lanewise(VectorOperators.Binary,int)
1345      */
1346     @ForceInline
1347     public final IntVector div(int e) {
1348         return lanewise(DIV, e);
1349     }
1350 
1351     /**
1352      * {@inheritDoc} <!--workaround-->
1353      * @see #div(int,VectorMask)
1354      * @apiNote If there is a zero divisor, {@code
1355      * ArithmeticException} will be thrown.
1356      */
1357     @Override
1358     @ForceInline
1359     public final IntVector div(Vector<Integer> v,
1360                                           VectorMask<Integer> m) {
1361         return lanewise(DIV, v, m);
1362     }
1363 
1364     /**
1365      * Divides this vector by the broadcast of an input scalar,
1366      * selecting lane elements controlled by a mask.
1367      *
1368      * This is a masked lane-wise binary operation which applies
1369      * the primitive division operation ({@code /}) to each lane.
1370      *
1371      * This method is also equivalent to the expression
1372      * {@link #lanewise(VectorOperators.Binary,int,VectorMask)
1373      *    lanewise}{@code (}{@link VectorOperators#DIV
1374      *    DIV}{@code , s, m)}.
1375      *
1376      * @apiNote If there is a zero divisor, {@code
1377      * ArithmeticException} will be thrown.
1378      *
1379      * @param e the input scalar
1380      * @param m the mask controlling lane selection
1381      * @return the result of dividing each lane of this vector by the scalar
1382      * @see #div(Vector,VectorMask)
1383      * @see #broadcast(int)
1384      * @see #div(int)
1385      * @see VectorOperators#DIV
1386      * @see #lanewise(VectorOperators.Binary,Vector)
1387      * @see #lanewise(VectorOperators.Binary,int)
1388      */
1389     @ForceInline
1390     public final IntVector div(int e,
1391                                           VectorMask<Integer> m) {
1392         return lanewise(DIV, e, m);
1393     }
1394 
1395     /// END OF FULL-SERVICE BINARY METHODS
1396 
1397     /// SECOND-TIER BINARY METHODS
1398     //
1399     // There are no masked versions.
1400 
1401     /**
1402      * {@inheritDoc} <!--workaround-->
1403      */
1404     @Override
1405     @ForceInline
1406     public final IntVector min(Vector<Integer> v) {
1407         return lanewise(MIN, v);
1408     }
1409 
1410     // FIXME:  "broadcast of an input scalar" is really wordy.  Reduce?
1411     /**
1412      * Computes the smaller of this vector and the broadcast of an input scalar.
1413      *
1414      * This is a lane-wise binary operation which applies the
1415      * operation {@code Math.min()} to each pair of
1416      * corresponding lane values.
1417      *
1418      * This method is also equivalent to the expression
1419      * {@link #lanewise(VectorOperators.Binary,int)
1420      *    lanewise}{@code (}{@link VectorOperators#MIN
1421      *    MIN}{@code , e)}.
1422      *
1423      * @param e the input scalar
1424      * @return the result of multiplying this vector by the given scalar
1425      * @see #min(Vector)
1426      * @see #broadcast(int)
1427      * @see VectorOperators#MIN
1428      * @see #lanewise(VectorOperators.Binary,int,VectorMask)
1429      */
1430     @ForceInline
1431     public final IntVector min(int e) {
1432         return lanewise(MIN, e);
1433     }
1434 
1435     /**
1436      * {@inheritDoc} <!--workaround-->
1437      */
1438     @Override
1439     @ForceInline
1440     public final IntVector max(Vector<Integer> v) {
1441         return lanewise(MAX, v);
1442     }
1443 
1444     /**
1445      * Computes the larger of this vector and the broadcast of an input scalar.
1446      *
1447      * This is a lane-wise binary operation which applies the
1448      * operation {@code Math.max()} to each pair of
1449      * corresponding lane values.
1450      *
1451      * This method is also equivalent to the expression
1452      * {@link #lanewise(VectorOperators.Binary,int)
1453      *    lanewise}{@code (}{@link VectorOperators#MAX
1454      *    MAX}{@code , e)}.
1455      *
1456      * @param e the input scalar
1457      * @return the result of multiplying this vector by the given scalar
1458      * @see #max(Vector)
1459      * @see #broadcast(int)
1460      * @see VectorOperators#MAX
1461      * @see #lanewise(VectorOperators.Binary,int,VectorMask)
1462      */
1463     @ForceInline
1464     public final IntVector max(int e) {
1465         return lanewise(MAX, e);
1466     }
1467 
1468     // common bitwise operators: and, or, not (with scalar versions)
1469     /**
1470      * Computes the bitwise logical conjunction ({@code &})
1471      * of this vector and a second input vector.
1472      *
1473      * This is a lane-wise binary operation which applies the
1474      * the primitive bitwise "and" operation ({@code &})
1475      * to each pair of corresponding lane values.
1476      *
1477      * This method is also equivalent to the expression
1478      * {@link #lanewise(VectorOperators.Binary,Vector)
1479      *    lanewise}{@code (}{@link VectorOperators#AND
1480      *    AND}{@code , v)}.
1481      *
1482      * <p>
1483      * This is not a full-service named operation like
1484      * {@link #add(Vector) add}.  A masked version of
1485      * this operation is not directly available
1486      * but may be obtained via the masked version of
1487      * {@code lanewise}.
1488      *
1489      * @param v a second input vector
1490      * @return the bitwise {@code &} of this vector and the second input vector
1491      * @see #and(int)
1492      * @see #or(Vector)
1493      * @see #not()
1494      * @see VectorOperators#AND
1495      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
1496      */
1497     @ForceInline
1498     public final IntVector and(Vector<Integer> v) {
1499         return lanewise(AND, v);
1500     }
1501 
1502     /**
1503      * Computes the bitwise logical conjunction ({@code &})
1504      * of this vector and a scalar.
1505      *
1506      * This is a lane-wise binary operation which applies the
1507      * the primitive bitwise "and" operation ({@code &})
1508      * to each pair of corresponding lane values.
1509      *
1510      * This method is also equivalent to the expression
1511      * {@link #lanewise(VectorOperators.Binary,Vector)
1512      *    lanewise}{@code (}{@link VectorOperators#AND
1513      *    AND}{@code , e)}.
1514      *
1515      * @param e an input scalar
1516      * @return the bitwise {@code &} of this vector and scalar
1517      * @see #and(Vector)
1518      * @see VectorOperators#AND
1519      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
1520      */
1521     @ForceInline
1522     public final IntVector and(int e) {
1523         return lanewise(AND, e);
1524     }
1525 
1526     /**
1527      * Computes the bitwise logical disjunction ({@code |})
1528      * of this vector and a second input vector.
1529      *
1530      * This is a lane-wise binary operation which applies the
1531      * the primitive bitwise "or" operation ({@code |})
1532      * to each pair of corresponding lane values.
1533      *
1534      * This method is also equivalent to the expression
1535      * {@link #lanewise(VectorOperators.Binary,Vector)
1536      *    lanewise}{@code (}{@link VectorOperators#OR
1537      *    AND}{@code , v)}.
1538      *
1539      * <p>
1540      * This is not a full-service named operation like
1541      * {@link #add(Vector) add}.  A masked version of
1542      * this operation is not directly available
1543      * but may be obtained via the masked version of
1544      * {@code lanewise}.
1545      *
1546      * @param v a second input vector
1547      * @return the bitwise {@code |} of this vector and the second input vector
1548      * @see #or(int)
1549      * @see #and(Vector)
1550      * @see #not()
1551      * @see VectorOperators#OR
1552      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
1553      */
1554     @ForceInline
1555     public final IntVector or(Vector<Integer> v) {
1556         return lanewise(OR, v);
1557     }
1558 
1559     /**
1560      * Computes the bitwise logical disjunction ({@code |})
1561      * of this vector and a scalar.
1562      *
1563      * This is a lane-wise binary operation which applies the
1564      * the primitive bitwise "or" operation ({@code |})
1565      * to each pair of corresponding lane values.
1566      *
1567      * This method is also equivalent to the expression
1568      * {@link #lanewise(VectorOperators.Binary,Vector)
1569      *    lanewise}{@code (}{@link VectorOperators#OR
1570      *    OR}{@code , e)}.
1571      *
1572      * @param e an input scalar
1573      * @return the bitwise {@code |} of this vector and scalar
1574      * @see #or(Vector)
1575      * @see VectorOperators#OR
1576      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
1577      */
1578     @ForceInline
1579     public final IntVector or(int e) {
1580         return lanewise(OR, e);
1581     }
1582 
1583 
1584 
1585     /// UNARY METHODS
1586 
1587     /**
1588      * {@inheritDoc} <!--workaround-->
1589      */
1590     @Override
1591     @ForceInline
1592     public final
1593     IntVector neg() {
1594         return lanewise(NEG);
1595     }
1596 
1597     /**
1598      * {@inheritDoc} <!--workaround-->
1599      */
1600     @Override
1601     @ForceInline
1602     public final
1603     IntVector abs() {
1604         return lanewise(ABS);
1605     }
1606 
1607     // not (~)
1608     /**
1609      * Computes the bitwise logical complement ({@code ~})
1610      * of this vector.
1611      *
1612      * This is a lane-wise binary operation which applies the
1613      * the primitive bitwise "not" operation ({@code ~})
1614      * to each lane value.
1615      *
1616      * This method is also equivalent to the expression
1617      * {@link #lanewise(VectorOperators.Unary)
1618      *    lanewise}{@code (}{@link VectorOperators#NOT
1619      *    NOT}{@code )}.
1620      *
1621      * <p>
1622      * This is not a full-service named operation like
1623      * {@link #add(Vector) add}.  A masked version of
1624      * this operation is not directly available
1625      * but may be obtained via the masked version of
1626      * {@code lanewise}.
1627      *
1628      * @return the bitwise complement {@code ~} of this vector
1629      * @see #and(Vector)
1630      * @see VectorOperators#NOT
1631      * @see #lanewise(VectorOperators.Unary,VectorMask)
1632      */
1633     @ForceInline
1634     public final IntVector not() {
1635         return lanewise(NOT);
1636     }
1637 
1638 
1639     /// COMPARISONS
1640 
1641     /**
1642      * {@inheritDoc} <!--workaround-->
1643      */
1644     @Override
1645     @ForceInline
1646     public final
1647     VectorMask<Integer> eq(Vector<Integer> v) {
1648         return compare(EQ, v);
1649     }
1650 
1651     /**
1652      * Tests if this vector is equal to an input scalar.
1653      *
1654      * This is a lane-wise binary test operation which applies
1655      * the primitive equals operation ({@code ==}) to each lane.
1656      * The result is the same as {@code compare(VectorOperators.Comparison.EQ, e)}.
1657      *
1658      * @param e the input scalar
1659      * @return the result mask of testing if this vector
1660      *         is equal to {@code e}
1661      * @see #compare(VectorOperators.Comparison,int)
1662      */
1663     @ForceInline
1664     public final
1665     VectorMask<Integer> eq(int e) {
1666         return compare(EQ, e);
1667     }
1668 
1669     /**
1670      * {@inheritDoc} <!--workaround-->
1671      */
1672     @Override
1673     @ForceInline
1674     public final
1675     VectorMask<Integer> lt(Vector<Integer> v) {
1676         return compare(LT, v);
1677     }
1678 
1679     /**
1680      * Tests if this vector is less than an input scalar.
1681      *
1682      * This is a lane-wise binary test operation which applies
1683      * the primitive less than operation ({@code <}) to each lane.
1684      * The result is the same as {@code compare(VectorOperators.LT, e)}.
1685      *
1686      * @param e the input scalar
1687      * @return the mask result of testing if this vector
1688      *         is less than the input scalar
1689      * @see #compare(VectorOperators.Comparison,int)
1690      */
1691     @ForceInline
1692     public final
1693     VectorMask<Integer> lt(int e) {
1694         return compare(LT, e);
1695     }
1696 
1697     /**
1698      * {@inheritDoc} <!--workaround-->
1699      */
1700     @Override
1701     public abstract
1702     VectorMask<Integer> test(VectorOperators.Test op);
1703 
1704     /*package-private*/
1705     @ForceInline
1706     final
1707     <M extends VectorMask<Integer>>
1708     M testTemplate(Class<M> maskType, Test op) {
1709         IntSpecies vsp = vspecies();
1710         if (opKind(op, VO_SPECIAL)) {
1711             IntVector bits = this.viewAsIntegralLanes();
1712             VectorMask<Integer> m;
1713             if (op == IS_DEFAULT) {
1714                 m = bits.compare(EQ, (int) 0);
1715             } else if (op == IS_NEGATIVE) {
1716                 m = bits.compare(LT, (int) 0);
1717             }
1718             else {
1719                 throw new AssertionError(op);
1720             }
1721             return maskType.cast(m);
1722         }
1723         int opc = opCode(op);
1724         throw new AssertionError(op);
1725     }
1726 
1727     /**
1728      * {@inheritDoc} <!--workaround-->
1729      */
1730     @Override
1731     @ForceInline
1732     public final
1733     VectorMask<Integer> test(VectorOperators.Test op,
1734                                   VectorMask<Integer> m) {
1735         return test(op).and(m);
1736     }
1737 
1738     /**
1739      * {@inheritDoc} <!--workaround-->
1740      */
1741     @Override
1742     public abstract
1743     VectorMask<Integer> compare(VectorOperators.Comparison op, Vector<Integer> v);
1744 
1745     /*package-private*/
1746     @ForceInline
1747     final
1748     <M extends VectorMask<Integer>>
1749     M compareTemplate(Class<M> maskType, Comparison op, Vector<Integer> v) {
1750         Objects.requireNonNull(v);
1751         IntSpecies vsp = vspecies();
1752         IntVector that = (IntVector) v;
1753         that.check(this);
1754         int opc = opCode(op);
1755         return VectorSupport.compare(
1756             opc, getClass(), maskType, int.class, length(),
1757             this, that,
1758             (cond, v0, v1) -> {
1759                 AbstractMask<Integer> m
1760                     = v0.bTest(cond, v1, (cond_, i, a, b)
1761                                -> compareWithOp(cond, a, b));
1762                 @SuppressWarnings("unchecked")
1763                 M m2 = (M) m;
1764                 return m2;
1765             });
1766     }
1767 
1768     @ForceInline
1769     private static
1770     boolean compareWithOp(int cond, int a, int b) {
1771         switch (cond) {
1772         case BT_eq:  return a == b;
1773         case BT_ne:  return a != b;
1774         case BT_lt:  return a <  b;
1775         case BT_le:  return a <= b;
1776         case BT_gt:  return a >  b;
1777         case BT_ge:  return a >= b;
1778         }
1779         throw new AssertionError();
1780     }
1781 
1782     /**
1783      * {@inheritDoc} <!--workaround-->
1784      */
1785     @Override
1786     @ForceInline
1787     public final
1788     VectorMask<Integer> compare(VectorOperators.Comparison op,
1789                                   Vector<Integer> v,
1790                                   VectorMask<Integer> m) {
1791         return compare(op, v).and(m);
1792     }
1793 
1794     /**
1795      * Tests this vector by comparing it with an input scalar,
1796      * according to the given comparison operation.
1797      *
1798      * This is a lane-wise binary test operation which applies
1799      * the comparison operation to each lane.
1800      * <p>
1801      * The result is the same as
1802      * {@code compare(op, broadcast(species(), e))}.
1803      * That is, the scalar may be regarded as broadcast to
1804      * a vector of the same species, and then compared
1805      * against the original vector, using the selected
1806      * comparison operation.
1807      *
1808      * @param op the operation used to compare lane values
1809      * @param e the input scalar
1810      * @return the mask result of testing lane-wise if this vector
1811      *         compares to the input, according to the selected
1812      *         comparison operator
1813      * @see IntVector#compare(VectorOperators.Comparison,Vector)
1814      * @see #eq(int)
1815      * @see #lt(int)
1816      */
1817     public abstract
1818     VectorMask<Integer> compare(Comparison op, int e);
1819 
1820     /*package-private*/
1821     @ForceInline
1822     final
1823     <M extends VectorMask<Integer>>
1824     M compareTemplate(Class<M> maskType, Comparison op, int e) {
1825         return compareTemplate(maskType, op, broadcast(e));
1826     }
1827 
1828     /**
1829      * Tests this vector by comparing it with an input scalar,
1830      * according to the given comparison operation,
1831      * in lanes selected by a mask.
1832      *
1833      * This is a masked lane-wise binary test operation which applies
1834      * to each pair of corresponding lane values.
1835      *
1836      * The returned result is equal to the expression
1837      * {@code compare(op,s).and(m)}.
1838      *
1839      * @param op the operation used to compare lane values
1840      * @param e the input scalar
1841      * @param m the mask controlling lane selection
1842      * @return the mask result of testing lane-wise if this vector
1843      *         compares to the input, according to the selected
1844      *         comparison operator,
1845      *         and only in the lanes selected by the mask
1846      * @see IntVector#compare(VectorOperators.Comparison,Vector,VectorMask)
1847      */
1848     @ForceInline
1849     public final VectorMask<Integer> compare(VectorOperators.Comparison op,
1850                                                int e,
1851                                                VectorMask<Integer> m) {
1852         return compare(op, e).and(m);
1853     }
1854 
1855     /**
1856      * {@inheritDoc} <!--workaround-->
1857      */
1858     @Override
1859     public abstract
1860     VectorMask<Integer> compare(Comparison op, long e);
1861 
1862     /*package-private*/
1863     @ForceInline
1864     final
1865     <M extends VectorMask<Integer>>
1866     M compareTemplate(Class<M> maskType, Comparison op, long e) {
1867         return compareTemplate(maskType, op, broadcast(e));
1868     }
1869 
1870     /**
1871      * {@inheritDoc} <!--workaround-->
1872      */
1873     @Override
1874     @ForceInline
1875     public final
1876     VectorMask<Integer> compare(Comparison op, long e, VectorMask<Integer> m) {
1877         return compare(op, broadcast(e), m);
1878     }
1879 
1880 
1881 
1882     /**
1883      * {@inheritDoc} <!--workaround-->
1884      */
1885     @Override public abstract
1886     IntVector blend(Vector<Integer> v, VectorMask<Integer> m);
1887 
1888     /*package-private*/
1889     @ForceInline
1890     final
1891     <M extends VectorMask<Integer>>
1892     IntVector
1893     blendTemplate(Class<M> maskType, IntVector v, M m) {
1894         v.check(this);
1895         return VectorSupport.blend(
1896             getClass(), maskType, int.class, length(),
1897             this, v, m,
1898             (v0, v1, m_) -> v0.bOp(v1, m_, (i, a, b) -> b));
1899     }
1900 
1901     /**
1902      * {@inheritDoc} <!--workaround-->
1903      */
1904     @Override public abstract IntVector addIndex(int scale);
1905 
1906     /*package-private*/
1907     @ForceInline
1908     final IntVector addIndexTemplate(int scale) {
1909         IntSpecies vsp = vspecies();
1910         // make sure VLENGTH*scale doesn't overflow:
1911         vsp.checkScale(scale);
1912         return VectorSupport.indexVector(
1913             getClass(), int.class, length(),
1914             this, scale, vsp,
1915             (v, scale_, s)
1916             -> {
1917                 // If the platform doesn't support an INDEX
1918                 // instruction directly, load IOTA from memory
1919                 // and multiply.
1920                 IntVector iota = s.iota();
1921                 int sc = (int) scale_;
1922                 return v.add(sc == 1 ? iota : iota.mul(sc));
1923             });
1924     }
1925 
1926     /**
1927      * Replaces selected lanes of this vector with
1928      * a scalar value
1929      * under the control of a mask.
1930      *
1931      * This is a masked lane-wise binary operation which
1932      * selects each lane value from one or the other input.
1933      *
1934      * The returned result is equal to the expression
1935      * {@code blend(broadcast(e),m)}.
1936      *
1937      * @param e the input scalar, containing the replacement lane value
1938      * @param m the mask controlling lane selection of the scalar
1939      * @return the result of blending the lane elements of this vector with
1940      *         the scalar value
1941      */
1942     @ForceInline
1943     public final IntVector blend(int e,
1944                                             VectorMask<Integer> m) {
1945         return blend(broadcast(e), m);
1946     }
1947 
1948     /**
1949      * Replaces selected lanes of this vector with
1950      * a scalar value
1951      * under the control of a mask.
1952      *
1953      * This is a masked lane-wise binary operation which
1954      * selects each lane value from one or the other input.
1955      *
1956      * The returned result is equal to the expression
1957      * {@code blend(broadcast(e),m)}.
1958      *
1959      * @param e the input scalar, containing the replacement lane value
1960      * @param m the mask controlling lane selection of the scalar
1961      * @return the result of blending the lane elements of this vector with
1962      *         the scalar value
1963      */
1964     @ForceInline
1965     public final IntVector blend(long e,
1966                                             VectorMask<Integer> m) {
1967         return blend(broadcast(e), m);
1968     }
1969 
1970     /**
1971      * {@inheritDoc} <!--workaround-->
1972      */
1973     @Override
1974     public abstract
1975     IntVector slice(int origin, Vector<Integer> v1);
1976 
1977     /*package-private*/
1978     final
1979     @ForceInline
1980     IntVector sliceTemplate(int origin, Vector<Integer> v1) {
1981         IntVector that = (IntVector) v1;
1982         that.check(this);
1983         int[] a0 = this.vec();
1984         int[] a1 = that.vec();
1985         int[] res = new int[a0.length];
1986         int vlen = res.length;
1987         int firstPart = vlen - origin;
1988         System.arraycopy(a0, origin, res, 0, firstPart);
1989         System.arraycopy(a1, 0, res, firstPart, origin);
1990         return vectorFactory(res);
1991     }
1992 
1993     /**
1994      * {@inheritDoc} <!--workaround-->
1995      */
1996     @Override
1997     @ForceInline
1998     public final
1999     IntVector slice(int origin,
2000                                Vector<Integer> w,
2001                                VectorMask<Integer> m) {
2002         return broadcast(0).blend(slice(origin, w), m);
2003     }
2004 
2005     /**
2006      * {@inheritDoc} <!--workaround-->
2007      */
2008     @Override
2009     public abstract
2010     IntVector slice(int origin);
2011 
2012     /**
2013      * {@inheritDoc} <!--workaround-->
2014      */
2015     @Override
2016     public abstract
2017     IntVector unslice(int origin, Vector<Integer> w, int part);
2018 
2019     /*package-private*/
2020     final
2021     @ForceInline
2022     IntVector
2023     unsliceTemplate(int origin, Vector<Integer> w, int part) {
2024         IntVector that = (IntVector) w;
2025         that.check(this);
2026         int[] slice = this.vec();
2027         int[] res = that.vec().clone();
2028         int vlen = res.length;
2029         int firstPart = vlen - origin;
2030         switch (part) {
2031         case 0:
2032             System.arraycopy(slice, 0, res, origin, firstPart);
2033             break;
2034         case 1:
2035             System.arraycopy(slice, firstPart, res, 0, origin);
2036             break;
2037         default:
2038             throw wrongPartForSlice(part);
2039         }
2040         return vectorFactory(res);
2041     }
2042 
2043     /*package-private*/
2044     final
2045     @ForceInline
2046     <M extends VectorMask<Integer>>
2047     IntVector
2048     unsliceTemplate(Class<M> maskType, int origin, Vector<Integer> w, int part, M m) {
2049         IntVector that = (IntVector) w;
2050         that.check(this);
2051         IntVector slice = that.sliceTemplate(origin, that);
2052         slice = slice.blendTemplate(maskType, this, m);
2053         return slice.unsliceTemplate(origin, w, part);
2054     }
2055 
2056     /**
2057      * {@inheritDoc} <!--workaround-->
2058      */
2059     @Override
2060     public abstract
2061     IntVector unslice(int origin, Vector<Integer> w, int part, VectorMask<Integer> m);
2062 
2063     /**
2064      * {@inheritDoc} <!--workaround-->
2065      */
2066     @Override
2067     public abstract
2068     IntVector unslice(int origin);
2069 
2070     private ArrayIndexOutOfBoundsException
2071     wrongPartForSlice(int part) {
2072         String msg = String.format("bad part number %d for slice operation",
2073                                    part);
2074         return new ArrayIndexOutOfBoundsException(msg);
2075     }
2076 
2077     /**
2078      * {@inheritDoc} <!--workaround-->
2079      */
2080     @Override
2081     public abstract
2082     IntVector rearrange(VectorShuffle<Integer> m);
2083 
2084     /*package-private*/
2085     @ForceInline
2086     final
2087     <S extends VectorShuffle<Integer>>
2088     IntVector rearrangeTemplate(Class<S> shuffletype, S shuffle) {
2089         shuffle.checkIndexes();
2090         return VectorSupport.rearrangeOp(
2091             getClass(), shuffletype, int.class, length(),
2092             this, shuffle,
2093             (v1, s_) -> v1.uOp((i, a) -> {
2094                 int ei = s_.laneSource(i);
2095                 return v1.lane(ei);
2096             }));
2097     }
2098 
2099     /**
2100      * {@inheritDoc} <!--workaround-->
2101      */
2102     @Override
2103     public abstract
2104     IntVector rearrange(VectorShuffle<Integer> s,
2105                                    VectorMask<Integer> m);
2106 
2107     /*package-private*/
2108     @ForceInline
2109     final
2110     <S extends VectorShuffle<Integer>>
2111     IntVector rearrangeTemplate(Class<S> shuffletype,
2112                                            S shuffle,
2113                                            VectorMask<Integer> m) {
2114         IntVector unmasked =
2115             VectorSupport.rearrangeOp(
2116                 getClass(), shuffletype, int.class, length(),
2117                 this, shuffle,
2118                 (v1, s_) -> v1.uOp((i, a) -> {
2119                     int ei = s_.laneSource(i);
2120                     return ei < 0 ? 0 : v1.lane(ei);
2121                 }));
2122         VectorMask<Integer> valid = shuffle.laneIsValid();
2123         if (m.andNot(valid).anyTrue()) {
2124             shuffle.checkIndexes();
2125             throw new AssertionError();
2126         }
2127         return broadcast((int)0).blend(unmasked, m);
2128     }
2129 
2130     /**
2131      * {@inheritDoc} <!--workaround-->
2132      */
2133     @Override
2134     public abstract
2135     IntVector rearrange(VectorShuffle<Integer> s,
2136                                    Vector<Integer> v);
2137 
2138     /*package-private*/
2139     @ForceInline
2140     final
2141     <S extends VectorShuffle<Integer>>
2142     IntVector rearrangeTemplate(Class<S> shuffletype,
2143                                            S shuffle,
2144                                            IntVector v) {
2145         VectorMask<Integer> valid = shuffle.laneIsValid();
2146         S ws = shuffletype.cast(shuffle.wrapIndexes());
2147         IntVector r0 =
2148             VectorSupport.rearrangeOp(
2149                 getClass(), shuffletype, int.class, length(),
2150                 this, ws,
2151                 (v0, s_) -> v0.uOp((i, a) -> {
2152                     int ei = s_.laneSource(i);
2153                     return v0.lane(ei);
2154                 }));
2155         IntVector r1 =
2156             VectorSupport.rearrangeOp(
2157                 getClass(), shuffletype, int.class, length(),
2158                 v, ws,
2159                 (v1, s_) -> v1.uOp((i, a) -> {
2160                     int ei = s_.laneSource(i);
2161                     return v1.lane(ei);
2162                 }));
2163         return r1.blend(r0, valid);
2164     }
2165 
2166     /**
2167      * {@inheritDoc} <!--workaround-->
2168      */
2169     @Override
2170     public abstract
2171     IntVector selectFrom(Vector<Integer> v);
2172 
2173     /*package-private*/
2174     @ForceInline
2175     final IntVector selectFromTemplate(IntVector v) {
2176         return v.rearrange(this.toShuffle());
2177     }
2178 
2179     /**
2180      * {@inheritDoc} <!--workaround-->
2181      */
2182     @Override
2183     public abstract
2184     IntVector selectFrom(Vector<Integer> s, VectorMask<Integer> m);
2185 
2186     /*package-private*/
2187     @ForceInline
2188     final IntVector selectFromTemplate(IntVector v,
2189                                                   AbstractMask<Integer> m) {
2190         return v.rearrange(this.toShuffle(), m);
2191     }
2192 
2193     /// Ternary operations
2194 
2195     /**
2196      * Blends together the bits of two vectors under
2197      * the control of a third, which supplies mask bits.
2198      *
2199      * This is a lane-wise ternary operation which performs
2200      * a bitwise blending operation {@code (a&~c)|(b&c)}
2201      * to each lane.
2202      *
2203      * This method is also equivalent to the expression
2204      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2205      *    lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND
2206      *    BITWISE_BLEND}{@code , bits, mask)}.
2207      *
2208      * @param bits input bits to blend into the current vector
2209      * @param mask a bitwise mask to enable blending of the input bits
2210      * @return the bitwise blend of the given bits into the current vector,
2211      *         under control of the bitwise mask
2212      * @see #bitwiseBlend(int,int)
2213      * @see #bitwiseBlend(int,Vector)
2214      * @see #bitwiseBlend(Vector,int)
2215      * @see VectorOperators#BITWISE_BLEND
2216      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
2217      */
2218     @ForceInline
2219     public final
2220     IntVector bitwiseBlend(Vector<Integer> bits, Vector<Integer> mask) {
2221         return lanewise(BITWISE_BLEND, bits, mask);
2222     }
2223 
2224     /**
2225      * Blends together the bits of a vector and a scalar under
2226      * the control of another scalar, which supplies mask bits.
2227      *
2228      * This is a lane-wise ternary operation which performs
2229      * a bitwise blending operation {@code (a&~c)|(b&c)}
2230      * to each lane.
2231      *
2232      * This method is also equivalent to the expression
2233      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2234      *    lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND
2235      *    BITWISE_BLEND}{@code , bits, mask)}.
2236      *
2237      * @param bits input bits to blend into the current vector
2238      * @param mask a bitwise mask to enable blending of the input bits
2239      * @return the bitwise blend of the given bits into the current vector,
2240      *         under control of the bitwise mask
2241      * @see #bitwiseBlend(Vector,Vector)
2242      * @see VectorOperators#BITWISE_BLEND
2243      * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask)
2244      */
2245     @ForceInline
2246     public final
2247     IntVector bitwiseBlend(int bits, int mask) {
2248         return lanewise(BITWISE_BLEND, bits, mask);
2249     }
2250 
2251     /**
2252      * Blends together the bits of a vector and a scalar under
2253      * the control of another vector, which supplies mask bits.
2254      *
2255      * This is a lane-wise ternary operation which performs
2256      * a bitwise blending operation {@code (a&~c)|(b&c)}
2257      * to each lane.
2258      *
2259      * This method is also equivalent to the expression
2260      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2261      *    lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND
2262      *    BITWISE_BLEND}{@code , bits, mask)}.
2263      *
2264      * @param bits input bits to blend into the current vector
2265      * @param mask a bitwise mask to enable blending of the input bits
2266      * @return the bitwise blend of the given bits into the current vector,
2267      *         under control of the bitwise mask
2268      * @see #bitwiseBlend(Vector,Vector)
2269      * @see VectorOperators#BITWISE_BLEND
2270      * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask)
2271      */
2272     @ForceInline
2273     public final
2274     IntVector bitwiseBlend(int bits, Vector<Integer> mask) {
2275         return lanewise(BITWISE_BLEND, bits, mask);
2276     }
2277 
2278     /**
2279      * Blends together the bits of two vectors under
2280      * the control of a scalar, which supplies mask bits.
2281      *
2282      * This is a lane-wise ternary operation which performs
2283      * a bitwise blending operation {@code (a&~c)|(b&c)}
2284      * to each lane.
2285      *
2286      * This method is also equivalent to the expression
2287      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2288      *    lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND
2289      *    BITWISE_BLEND}{@code , bits, mask)}.
2290      *
2291      * @param bits input bits to blend into the current vector
2292      * @param mask a bitwise mask to enable blending of the input bits
2293      * @return the bitwise blend of the given bits into the current vector,
2294      *         under control of the bitwise mask
2295      * @see #bitwiseBlend(Vector,Vector)
2296      * @see VectorOperators#BITWISE_BLEND
2297      * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask)
2298      */
2299     @ForceInline
2300     public final
2301     IntVector bitwiseBlend(Vector<Integer> bits, int mask) {
2302         return lanewise(BITWISE_BLEND, bits, mask);
2303     }
2304 
2305 
2306     // Type specific horizontal reductions
2307 
2308     /**
2309      * Returns a value accumulated from all the lanes of this vector.
2310      *
2311      * This is an associative cross-lane reduction operation which
2312      * applies the specified operation to all the lane elements.
2313      * <p>
2314      * A few reduction operations do not support arbitrary reordering
2315      * of their operands, yet are included here because of their
2316      * usefulness.
2317      * <ul>
2318      * <li>
2319      * In the case of {@code FIRST_NONZERO}, the reduction returns
2320      * the value from the lowest-numbered non-zero lane.
2321      * <li>
2322      * All other reduction operations are fully commutative and
2323      * associative.  The implementation can choose any order of
2324      * processing, yet it will always produce the same result.
2325      * </ul>
2326      *
2327      * @param op the operation used to combine lane values
2328      * @return the accumulated result
2329      * @throws UnsupportedOperationException if this vector does
2330      *         not support the requested operation
2331      * @see #reduceLanes(VectorOperators.Associative,VectorMask)
2332      * @see #add(Vector)
2333      * @see #mul(Vector)
2334      * @see #min(Vector)
2335      * @see #max(Vector)
2336      * @see #and(Vector)
2337      * @see #or(Vector)
2338      * @see VectorOperators#XOR
2339      * @see VectorOperators#FIRST_NONZERO
2340      */
2341     public abstract int reduceLanes(VectorOperators.Associative op);
2342 
2343     /**
2344      * Returns a value accumulated from selected lanes of this vector,
2345      * controlled by a mask.
2346      *
2347      * This is an associative cross-lane reduction operation which
2348      * applies the specified operation to the selected lane elements.
2349      * <p>
2350      * If no elements are selected, an operation-specific identity
2351      * value is returned.
2352      * <ul>
2353      * <li>
2354      * If the operation is
2355      *  {@code ADD}, {@code XOR}, {@code OR},
2356      * or {@code FIRST_NONZERO},
2357      * then the identity value is zero, the default {@code int} value.
2358      * <li>
2359      * If the operation is {@code MUL},
2360      * then the identity value is one.
2361      * <li>
2362      * If the operation is {@code AND},
2363      * then the identity value is minus one (all bits set).
2364      * <li>
2365      * If the operation is {@code MAX},
2366      * then the identity value is {@code Integer.MIN_VALUE}.
2367      * <li>
2368      * If the operation is {@code MIN},
2369      * then the identity value is {@code Integer.MAX_VALUE}.
2370      * </ul>
2371      * <p>
2372      * A few reduction operations do not support arbitrary reordering
2373      * of their operands, yet are included here because of their
2374      * usefulness.
2375      * <ul>
2376      * <li>
2377      * In the case of {@code FIRST_NONZERO}, the reduction returns
2378      * the value from the lowest-numbered non-zero lane.
2379      * <li>
2380      * All other reduction operations are fully commutative and
2381      * associative.  The implementation can choose any order of
2382      * processing, yet it will always produce the same result.
2383      * </ul>
2384      *
2385      * @param op the operation used to combine lane values
2386      * @param m the mask controlling lane selection
2387      * @return the reduced result accumulated from the selected lane values
2388      * @throws UnsupportedOperationException if this vector does
2389      *         not support the requested operation
2390      * @see #reduceLanes(VectorOperators.Associative)
2391      */
2392     public abstract int reduceLanes(VectorOperators.Associative op,
2393                                        VectorMask<Integer> m);
2394 
2395     /*package-private*/
2396     @ForceInline
2397     final
2398     int reduceLanesTemplate(VectorOperators.Associative op,
2399                                VectorMask<Integer> m) {
2400         IntVector v = reduceIdentityVector(op).blend(this, m);
2401         return v.reduceLanesTemplate(op);
2402     }
2403 
2404     /*package-private*/
2405     @ForceInline
2406     final
2407     int reduceLanesTemplate(VectorOperators.Associative op) {
2408         if (op == FIRST_NONZERO) {
2409             // FIXME:  The JIT should handle this, and other scan ops alos.
2410             VectorMask<Integer> thisNZ
2411                 = this.viewAsIntegralLanes().compare(NE, (int) 0);
2412             return this.lane(thisNZ.firstTrue());
2413         }
2414         int opc = opCode(op);
2415         return fromBits(VectorSupport.reductionCoerced(
2416             opc, getClass(), int.class, length(),
2417             this,
2418             REDUCE_IMPL.find(op, opc, (opc_) -> {
2419               switch (opc_) {
2420               case VECTOR_OP_ADD: return v ->
2421                       toBits(v.rOp((int)0, (i, a, b) -> (int)(a + b)));
2422               case VECTOR_OP_MUL: return v ->
2423                       toBits(v.rOp((int)1, (i, a, b) -> (int)(a * b)));
2424               case VECTOR_OP_MIN: return v ->
2425                       toBits(v.rOp(MAX_OR_INF, (i, a, b) -> (int) Math.min(a, b)));
2426               case VECTOR_OP_MAX: return v ->
2427                       toBits(v.rOp(MIN_OR_INF, (i, a, b) -> (int) Math.max(a, b)));
2428               case VECTOR_OP_AND: return v ->
2429                       toBits(v.rOp((int)-1, (i, a, b) -> (int)(a & b)));
2430               case VECTOR_OP_OR: return v ->
2431                       toBits(v.rOp((int)0, (i, a, b) -> (int)(a | b)));
2432               case VECTOR_OP_XOR: return v ->
2433                       toBits(v.rOp((int)0, (i, a, b) -> (int)(a ^ b)));
2434               default: return null;
2435               }})));
2436     }
2437     private static final
2438     ImplCache<Associative,Function<IntVector,Long>> REDUCE_IMPL
2439         = new ImplCache<>(Associative.class, IntVector.class);
2440 
2441     private
2442     @ForceInline
2443     IntVector reduceIdentityVector(VectorOperators.Associative op) {
2444         int opc = opCode(op);
2445         UnaryOperator<IntVector> fn
2446             = REDUCE_ID_IMPL.find(op, opc, (opc_) -> {
2447                 switch (opc_) {
2448                 case VECTOR_OP_ADD:
2449                 case VECTOR_OP_OR:
2450                 case VECTOR_OP_XOR:
2451                     return v -> v.broadcast(0);
2452                 case VECTOR_OP_MUL:
2453                     return v -> v.broadcast(1);
2454                 case VECTOR_OP_AND:
2455                     return v -> v.broadcast(-1);
2456                 case VECTOR_OP_MIN:
2457                     return v -> v.broadcast(MAX_OR_INF);
2458                 case VECTOR_OP_MAX:
2459                     return v -> v.broadcast(MIN_OR_INF);
2460                 default: return null;
2461                 }
2462             });
2463         return fn.apply(this);
2464     }
2465     private static final
2466     ImplCache<Associative,UnaryOperator<IntVector>> REDUCE_ID_IMPL
2467         = new ImplCache<>(Associative.class, IntVector.class);
2468 
2469     private static final int MIN_OR_INF = Integer.MIN_VALUE;
2470     private static final int MAX_OR_INF = Integer.MAX_VALUE;
2471 
2472     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op);
2473     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op,
2474                                                      VectorMask<Integer> m);
2475 
2476     // Type specific accessors
2477 
2478     /**
2479      * Gets the lane element at lane index {@code i}
2480      *
2481      * @param i the lane index
2482      * @return the lane element at lane index {@code i}
2483      * @throws IllegalArgumentException if the index is is out of range
2484      * ({@code < 0 || >= length()})
2485      */
2486     public abstract int lane(int i);
2487 
2488     /**
2489      * Replaces the lane element of this vector at lane index {@code i} with
2490      * value {@code e}.
2491      *
2492      * This is a cross-lane operation and behaves as if it returns the result
2493      * of blending this vector with an input vector that is the result of
2494      * broadcasting {@code e} and a mask that has only one lane set at lane
2495      * index {@code i}.
2496      *
2497      * @param i the lane index of the lane element to be replaced
2498      * @param e the value to be placed
2499      * @return the result of replacing the lane element of this vector at lane
2500      * index {@code i} with value {@code e}.
2501      * @throws IllegalArgumentException if the index is is out of range
2502      * ({@code < 0 || >= length()})
2503      */
2504     public abstract IntVector withLane(int i, int e);
2505 
2506     // Memory load operations
2507 
2508     /**
2509      * Returns an array of type {@code int[]}
2510      * containing all the lane values.
2511      * The array length is the same as the vector length.
2512      * The array elements are stored in lane order.
2513      * <p>
2514      * This method behaves as if it stores
2515      * this vector into an allocated array
2516      * (using {@link #intoArray(int[], int) intoArray})
2517      * and returns the array as follows:
2518      * <pre>{@code
2519      *   int[] a = new int[this.length()];
2520      *   this.intoArray(a, 0);
2521      *   return a;
2522      * }</pre>
2523      *
2524      * @return an array containing the lane values of this vector
2525      */
2526     @ForceInline
2527     @Override
2528     public final int[] toArray() {
2529         int[] a = new int[vspecies().laneCount()];
2530         intoArray(a, 0);
2531         return a;
2532     }
2533 
2534     /**
2535      * {@inheritDoc} <!--workaround-->
2536      * This is an alias for {@link #toArray()}
2537      * When this method is used on used on vectors
2538      * of type {@code IntVector},
2539      * there will be no loss of range or precision.
2540      */
2541     @ForceInline
2542     @Override
2543     public final int[] toIntArray() {
2544         return toArray();
2545     }
2546 
2547     /** {@inheritDoc} <!--workaround-->
2548      * @implNote
2549      * When this method is used on used on vectors
2550      * of type {@code IntVector},
2551      * there will be no loss of precision or range,
2552      * and so no {@code UnsupportedOperationException} will
2553      * be thrown.
2554      */
2555     @ForceInline
2556     @Override
2557     public final long[] toLongArray() {
2558         int[] a = toArray();
2559         long[] res = new long[a.length];
2560         for (int i = 0; i < a.length; i++) {
2561             int e = a[i];
2562             res[i] = IntSpecies.toIntegralChecked(e, false);
2563         }
2564         return res;
2565     }
2566 
2567     /** {@inheritDoc} <!--workaround-->
2568      * @implNote
2569      * When this method is used on used on vectors
2570      * of type {@code IntVector},
2571      * there will be no loss of precision.
2572      */
2573     @ForceInline
2574     @Override
2575     public final double[] toDoubleArray() {
2576         int[] a = toArray();
2577         double[] res = new double[a.length];
2578         for (int i = 0; i < a.length; i++) {
2579             res[i] = (double) a[i];
2580         }
2581         return res;
2582     }
2583 
2584     /**
2585      * Loads a vector from a byte array starting at an offset.
2586      * Bytes are composed into primitive lane elements according
2587      * to the specified byte order.
2588      * The vector is arranged into lanes according to
2589      * <a href="Vector.html#lane-order">memory ordering</a>.
2590      * <p>
2591      * This method behaves as if it returns the result of calling
2592      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2593      * fromByteBuffer()} as follows:
2594      * <pre>{@code
2595      * var bb = ByteBuffer.wrap(a);
2596      * var m = species.maskAll(true);
2597      * return fromByteBuffer(species, bb, offset, bo, m);
2598      * }</pre>
2599      *
2600      * @param species species of desired vector
2601      * @param a the byte array
2602      * @param offset the offset into the array
2603      * @param bo the intended byte order
2604      * @return a vector loaded from a byte array
2605      * @throws IndexOutOfBoundsException
2606      *         if {@code offset+N*ESIZE < 0}
2607      *         or {@code offset+(N+1)*ESIZE > a.length}
2608      *         for any lane {@code N} in the vector
2609      */
2610     @ForceInline
2611     public static
2612     IntVector fromByteArray(VectorSpecies<Integer> species,
2613                                        byte[] a, int offset,
2614                                        ByteOrder bo) {
2615         offset = checkFromIndexSize(offset, species.vectorByteSize(), a.length);
2616         IntSpecies vsp = (IntSpecies) species;
2617         return vsp.dummyVector().fromByteArray0(a, offset).maybeSwap(bo);
2618     }
2619 
2620     /**
2621      * Loads a vector from a byte array starting at an offset
2622      * and using a mask.
2623      * Lanes where the mask is unset are filled with the default
2624      * value of {@code int} (zero).
2625      * Bytes are composed into primitive lane elements according
2626      * to the specified byte order.
2627      * The vector is arranged into lanes according to
2628      * <a href="Vector.html#lane-order">memory ordering</a>.
2629      * <p>
2630      * This method behaves as if it returns the result of calling
2631      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2632      * fromByteBuffer()} as follows:
2633      * <pre>{@code
2634      * var bb = ByteBuffer.wrap(a);
2635      * return fromByteBuffer(species, bb, offset, bo, m);
2636      * }</pre>
2637      *
2638      * @param species species of desired vector
2639      * @param a the byte array
2640      * @param offset the offset into the array
2641      * @param bo the intended byte order
2642      * @param m the mask controlling lane selection
2643      * @return a vector loaded from a byte array
2644      * @throws IndexOutOfBoundsException
2645      *         if {@code offset+N*ESIZE < 0}
2646      *         or {@code offset+(N+1)*ESIZE > a.length}
2647      *         for any lane {@code N} in the vector
2648      *         where the mask is set
2649      */
2650     @ForceInline
2651     public static
2652     IntVector fromByteArray(VectorSpecies<Integer> species,
2653                                        byte[] a, int offset,
2654                                        ByteOrder bo,
2655                                        VectorMask<Integer> m) {
2656         IntSpecies vsp = (IntSpecies) species;
2657         if (offset >= 0 && offset <= (a.length - species.vectorByteSize())) {
2658             IntVector zero = vsp.zero();
2659             IntVector v = zero.fromByteArray0(a, offset);
2660             return zero.blend(v.maybeSwap(bo), m);
2661         }
2662 
2663         // FIXME: optimize
2664         checkMaskFromIndexSize(offset, vsp, m, 4, a.length);
2665         ByteBuffer wb = wrapper(a, bo);
2666         return vsp.ldOp(wb, offset, (AbstractMask<Integer>)m,
2667                    (wb_, o, i)  -> wb_.getInt(o + i * 4));
2668     }
2669 
2670     /**
2671      * Loads a vector from an array of type {@code int[]}
2672      * starting at an offset.
2673      * For each vector lane, where {@code N} is the vector lane index, the
2674      * array element at index {@code offset + N} is placed into the
2675      * resulting vector at lane index {@code N}.
2676      *
2677      * @param species species of desired vector
2678      * @param a the array
2679      * @param offset the offset into the array
2680      * @return the vector loaded from an array
2681      * @throws IndexOutOfBoundsException
2682      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2683      *         for any lane {@code N} in the vector
2684      */
2685     @ForceInline
2686     public static
2687     IntVector fromArray(VectorSpecies<Integer> species,
2688                                    int[] a, int offset) {
2689         offset = checkFromIndexSize(offset, species.length(), a.length);
2690         IntSpecies vsp = (IntSpecies) species;
2691         return vsp.dummyVector().fromArray0(a, offset);
2692     }
2693 
2694     /**
2695      * Loads a vector from an array of type {@code int[]}
2696      * starting at an offset and using a mask.
2697      * Lanes where the mask is unset are filled with the default
2698      * value of {@code int} (zero).
2699      * For each vector lane, where {@code N} is the vector lane index,
2700      * if the mask lane at index {@code N} is set then the array element at
2701      * index {@code offset + N} is placed into the resulting vector at lane index
2702      * {@code N}, otherwise the default element value is placed into the
2703      * resulting vector at lane index {@code N}.
2704      *
2705      * @param species species of desired vector
2706      * @param a the array
2707      * @param offset the offset into the array
2708      * @param m the mask controlling lane selection
2709      * @return the vector loaded from an array
2710      * @throws IndexOutOfBoundsException
2711      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2712      *         for any lane {@code N} in the vector
2713      *         where the mask is set
2714      */
2715     @ForceInline
2716     public static
2717     IntVector fromArray(VectorSpecies<Integer> species,
2718                                    int[] a, int offset,
2719                                    VectorMask<Integer> m) {
2720         IntSpecies vsp = (IntSpecies) species;
2721         if (offset >= 0 && offset <= (a.length - species.length())) {
2722             IntVector zero = vsp.zero();
2723             return zero.blend(zero.fromArray0(a, offset), m);
2724         }
2725 
2726         // FIXME: optimize
2727         checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
2728         return vsp.vOp(m, i -> a[offset + i]);
2729     }
2730 
2731     /**
2732      * Gathers a new vector composed of elements from an array of type
2733      * {@code int[]},
2734      * using indexes obtained by adding a fixed {@code offset} to a
2735      * series of secondary offsets from an <em>index map</em>.
2736      * The index map is a contiguous sequence of {@code VLENGTH}
2737      * elements in a second array of {@code int}s, starting at a given
2738      * {@code mapOffset}.
2739      * <p>
2740      * For each vector lane, where {@code N} is the vector lane index,
2741      * the lane is loaded from the array
2742      * element {@code a[f(N)]}, where {@code f(N)} is the
2743      * index mapping expression
2744      * {@code offset + indexMap[mapOffset + N]]}.
2745      *
2746      * @param species species of desired vector
2747      * @param a the array
2748      * @param offset the offset into the array, may be negative if relative
2749      * indexes in the index map compensate to produce a value within the
2750      * array bounds
2751      * @param indexMap the index map
2752      * @param mapOffset the offset into the index map
2753      * @return the vector loaded from the indexed elements of the array
2754      * @throws IndexOutOfBoundsException
2755      *         if {@code mapOffset+N < 0}
2756      *         or if {@code mapOffset+N >= indexMap.length},
2757      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2758      *         is an invalid index into {@code a},
2759      *         for any lane {@code N} in the vector
2760      * @see IntVector#toIntArray()
2761      */
2762     @ForceInline
2763     public static
2764     IntVector fromArray(VectorSpecies<Integer> species,
2765                                    int[] a, int offset,
2766                                    int[] indexMap, int mapOffset) {
2767         IntSpecies vsp = (IntSpecies) species;
2768         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
2769         Objects.requireNonNull(a);
2770         Objects.requireNonNull(indexMap);
2771         Class<? extends IntVector> vectorType = vsp.vectorType();
2772 
2773         // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k]
2774         IntVector vix = IntVector
2775             .fromArray(isp, indexMap, mapOffset)
2776             .add(offset);
2777 
2778         vix = VectorIntrinsics.checkIndex(vix, a.length);
2779 
2780         return VectorSupport.loadWithMap(
2781             vectorType, int.class, vsp.laneCount(),
2782             IntVector.species(vsp.indexShape()).vectorType(),
2783             a, ARRAY_BASE, vix,
2784             a, offset, indexMap, mapOffset, vsp,
2785             (int[] c, int idx, int[] iMap, int idy, IntSpecies s) ->
2786             s.vOp(n -> c[idx + iMap[idy+n]]));
2787         }
2788 
2789     /**
2790      * Gathers a new vector composed of elements from an array of type
2791      * {@code int[]},
2792      * under the control of a mask, and
2793      * using indexes obtained by adding a fixed {@code offset} to a
2794      * series of secondary offsets from an <em>index map</em>.
2795      * The index map is a contiguous sequence of {@code VLENGTH}
2796      * elements in a second array of {@code int}s, starting at a given
2797      * {@code mapOffset}.
2798      * <p>
2799      * For each vector lane, where {@code N} is the vector lane index,
2800      * if the lane is set in the mask,
2801      * the lane is loaded from the array
2802      * element {@code a[f(N)]}, where {@code f(N)} is the
2803      * index mapping expression
2804      * {@code offset + indexMap[mapOffset + N]]}.
2805      * Unset lanes in the resulting vector are set to zero.
2806      *
2807      * @param species species of desired vector
2808      * @param a the array
2809      * @param offset the offset into the array, may be negative if relative
2810      * indexes in the index map compensate to produce a value within the
2811      * array bounds
2812      * @param indexMap the index map
2813      * @param mapOffset the offset into the index map
2814      * @param m the mask controlling lane selection
2815      * @return the vector loaded from the indexed elements of the array
2816      * @throws IndexOutOfBoundsException
2817      *         if {@code mapOffset+N < 0}
2818      *         or if {@code mapOffset+N >= indexMap.length},
2819      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2820      *         is an invalid index into {@code a},
2821      *         for any lane {@code N} in the vector
2822      *         where the mask is set
2823      * @see IntVector#toIntArray()
2824      */
2825     @ForceInline
2826     public static
2827     IntVector fromArray(VectorSpecies<Integer> species,
2828                                    int[] a, int offset,
2829                                    int[] indexMap, int mapOffset,
2830                                    VectorMask<Integer> m) {
2831         if (m.allTrue()) {
2832             return fromArray(species, a, offset, indexMap, mapOffset);
2833         }
2834         else {
2835             // FIXME: Cannot vectorize yet, if there's a mask.
2836             IntSpecies vsp = (IntSpecies) species;
2837             return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]);
2838         }
2839     }
2840 
2841     /**
2842      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2843      * starting at an offset into the byte buffer.
2844      * Bytes are composed into primitive lane elements according
2845      * to the specified byte order.
2846      * The vector is arranged into lanes according to
2847      * <a href="Vector.html#lane-order">memory ordering</a>.
2848      * <p>
2849      * This method behaves as if it returns the result of calling
2850      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2851      * fromByteBuffer()} as follows:
2852      * <pre>{@code
2853      * var m = species.maskAll(true);
2854      * return fromByteBuffer(species, bb, offset, bo, m);
2855      * }</pre>
2856      *
2857      * @param species species of desired vector
2858      * @param bb the byte buffer
2859      * @param offset the offset into the byte buffer
2860      * @param bo the intended byte order
2861      * @return a vector loaded from a byte buffer
2862      * @throws IndexOutOfBoundsException
2863      *         if {@code offset+N*4 < 0}
2864      *         or {@code offset+N*4 >= bb.limit()}
2865      *         for any lane {@code N} in the vector
2866      */
2867     @ForceInline
2868     public static
2869     IntVector fromByteBuffer(VectorSpecies<Integer> species,
2870                                         ByteBuffer bb, int offset,
2871                                         ByteOrder bo) {
2872         offset = checkFromIndexSize(offset, species.vectorByteSize(), bb.limit());
2873         IntSpecies vsp = (IntSpecies) species;
2874         return vsp.dummyVector().fromByteBuffer0(bb, offset).maybeSwap(bo);
2875     }
2876 
2877     /**
2878      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2879      * starting at an offset into the byte buffer
2880      * and using a mask.
2881      * Lanes where the mask is unset are filled with the default
2882      * value of {@code int} (zero).
2883      * Bytes are composed into primitive lane elements according
2884      * to the specified byte order.
2885      * The vector is arranged into lanes according to
2886      * <a href="Vector.html#lane-order">memory ordering</a>.
2887      * <p>
2888      * The following pseudocode illustrates the behavior:
2889      * <pre>{@code
2890      * IntBuffer eb = bb.duplicate()
2891      *     .position(offset)
2892      *     .order(bo).asIntBuffer();
2893      * int[] ar = new int[species.length()];
2894      * for (int n = 0; n < ar.length; n++) {
2895      *     if (m.laneIsSet(n)) {
2896      *         ar[n] = eb.get(n);
2897      *     }
2898      * }
2899      * IntVector r = IntVector.fromArray(species, ar, 0);
2900      * }</pre>
2901      * @implNote
2902      * This operation is likely to be more efficient if
2903      * the specified byte order is the same as
2904      * {@linkplain ByteOrder#nativeOrder()
2905      * the platform native order},
2906      * since this method will not need to reorder
2907      * the bytes of lane values.
2908      *
2909      * @param species species of desired vector
2910      * @param bb the byte buffer
2911      * @param offset the offset into the byte buffer
2912      * @param bo the intended byte order
2913      * @param m the mask controlling lane selection
2914      * @return a vector loaded from a byte buffer
2915      * @throws IndexOutOfBoundsException
2916      *         if {@code offset+N*4 < 0}
2917      *         or {@code offset+N*4 >= bb.limit()}
2918      *         for any lane {@code N} in the vector
2919      *         where the mask is set
2920      */
2921     @ForceInline
2922     public static
2923     IntVector fromByteBuffer(VectorSpecies<Integer> species,
2924                                         ByteBuffer bb, int offset,
2925                                         ByteOrder bo,
2926                                         VectorMask<Integer> m) {
2927         IntSpecies vsp = (IntSpecies) species;
2928         if (offset >= 0 && offset <= (bb.limit() - species.vectorByteSize())) {
2929             IntVector zero = vsp.zero();
2930             IntVector v = zero.fromByteBuffer0(bb, offset);
2931             return zero.blend(v.maybeSwap(bo), m);
2932         }
2933 
2934         // FIXME: optimize
2935         checkMaskFromIndexSize(offset, vsp, m, 4, bb.limit());
2936         ByteBuffer wb = wrapper(bb, bo);
2937         return vsp.ldOp(wb, offset, (AbstractMask<Integer>)m,
2938                    (wb_, o, i)  -> wb_.getInt(o + i * 4));
2939     }
2940 
2941     // Memory store operations
2942 
2943     /**
2944      * Stores this vector into an array of type {@code int[]}
2945      * starting at an offset.
2946      * <p>
2947      * For each vector lane, where {@code N} is the vector lane index,
2948      * the lane element at index {@code N} is stored into the array
2949      * element {@code a[offset+N]}.
2950      *
2951      * @param a the array, of type {@code int[]}
2952      * @param offset the offset into the array
2953      * @throws IndexOutOfBoundsException
2954      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2955      *         for any lane {@code N} in the vector
2956      */
2957     @ForceInline
2958     public final
2959     void intoArray(int[] a, int offset) {
2960         offset = checkFromIndexSize(offset, length(), a.length);
2961         IntSpecies vsp = vspecies();
2962         VectorSupport.store(
2963             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
2964             a, arrayAddress(a, offset),
2965             this,
2966             a, offset,
2967             (arr, off, v)
2968             -> v.stOp(arr, off,
2969                       (arr_, off_, i, e) -> arr_[off_ + i] = e));
2970     }
2971 
2972     /**
2973      * Stores this vector into an array of {@code int}
2974      * starting at offset and using a mask.
2975      * <p>
2976      * For each vector lane, where {@code N} is the vector lane index,
2977      * the lane element at index {@code N} is stored into the array
2978      * element {@code a[offset+N]}.
2979      * If the mask lane at {@code N} is unset then the corresponding
2980      * array element {@code a[offset+N]} is left unchanged.
2981      * <p>
2982      * Array range checking is done for lanes where the mask is set.
2983      * Lanes where the mask is unset are not stored and do not need
2984      * to correspond to legitimate elements of {@code a}.
2985      * That is, unset lanes may correspond to array indexes less than
2986      * zero or beyond the end of the array.
2987      *
2988      * @param a the array, of type {@code int[]}
2989      * @param offset the offset into the array
2990      * @param m the mask controlling lane storage
2991      * @throws IndexOutOfBoundsException
2992      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2993      *         for any lane {@code N} in the vector
2994      *         where the mask is set
2995      */
2996     @ForceInline
2997     public final
2998     void intoArray(int[] a, int offset,
2999                    VectorMask<Integer> m) {
3000         if (m.allTrue()) {
3001             intoArray(a, offset);
3002         } else {
3003             // FIXME: optimize
3004             IntSpecies vsp = vspecies();
3005             checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
3006             stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = v);
3007         }
3008     }
3009 
3010     /**
3011      * Scatters this vector into an array of type {@code int[]}
3012      * using indexes obtained by adding a fixed {@code offset} to a
3013      * series of secondary offsets from an <em>index map</em>.
3014      * The index map is a contiguous sequence of {@code VLENGTH}
3015      * elements in a second array of {@code int}s, starting at a given
3016      * {@code mapOffset}.
3017      * <p>
3018      * For each vector lane, where {@code N} is the vector lane index,
3019      * the lane element at index {@code N} is stored into the array
3020      * element {@code a[f(N)]}, where {@code f(N)} is the
3021      * index mapping expression
3022      * {@code offset + indexMap[mapOffset + N]]}.
3023      *
3024      * @param a the array
3025      * @param offset an offset to combine with the index map offsets
3026      * @param indexMap the index map
3027      * @param mapOffset the offset into the index map
3028      * @throws IndexOutOfBoundsException
3029      *         if {@code mapOffset+N < 0}
3030      *         or if {@code mapOffset+N >= indexMap.length},
3031      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
3032      *         is an invalid index into {@code a},
3033      *         for any lane {@code N} in the vector
3034      * @see IntVector#toIntArray()
3035      */
3036     @ForceInline
3037     public final
3038     void intoArray(int[] a, int offset,
3039                    int[] indexMap, int mapOffset) {
3040         IntSpecies vsp = vspecies();
3041         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
3042         // Index vector: vix[0:n] = i -> offset + indexMap[mo + i]
3043         IntVector vix = IntVector
3044             .fromArray(isp, indexMap, mapOffset)
3045             .add(offset);
3046 
3047         vix = VectorIntrinsics.checkIndex(vix, a.length);
3048 
3049         VectorSupport.storeWithMap(
3050             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3051             isp.vectorType(),
3052             a, arrayAddress(a, 0), vix,
3053             this,
3054             a, offset, indexMap, mapOffset,
3055             (arr, off, v, map, mo)
3056             -> v.stOp(arr, off,
3057                       (arr_, off_, i, e) -> {
3058                           int j = map[mo + i];
3059                           arr[off + j] = e;
3060                       }));
3061     }
3062 
3063     /**
3064      * Scatters this vector into an array of type {@code int[]},
3065      * under the control of a mask, and
3066      * using indexes obtained by adding a fixed {@code offset} to a
3067      * series of secondary offsets from an <em>index map</em>.
3068      * The index map is a contiguous sequence of {@code VLENGTH}
3069      * elements in a second array of {@code int}s, starting at a given
3070      * {@code mapOffset}.
3071      * <p>
3072      * For each vector lane, where {@code N} is the vector lane index,
3073      * if the mask lane at index {@code N} is set then
3074      * the lane element at index {@code N} is stored into the array
3075      * element {@code a[f(N)]}, where {@code f(N)} is the
3076      * index mapping expression
3077      * {@code offset + indexMap[mapOffset + N]]}.
3078      *
3079      * @param a the array
3080      * @param offset an offset to combine with the index map offsets
3081      * @param indexMap the index map
3082      * @param mapOffset the offset into the index map
3083      * @param m the mask
3084      * @throws IndexOutOfBoundsException
3085      *         if {@code mapOffset+N < 0}
3086      *         or if {@code mapOffset+N >= indexMap.length},
3087      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
3088      *         is an invalid index into {@code a},
3089      *         for any lane {@code N} in the vector
3090      *         where the mask is set
3091      * @see IntVector#toIntArray()
3092      */
3093     @ForceInline
3094     public final
3095     void intoArray(int[] a, int offset,
3096                    int[] indexMap, int mapOffset,
3097                    VectorMask<Integer> m) {
3098         if (m.allTrue()) {
3099             intoArray(a, offset, indexMap, mapOffset);
3100         }
3101         else {
3102             // FIXME: Cannot vectorize yet, if there's a mask.
3103             stOp(a, offset, m,
3104                  (arr, off, i, e) -> {
3105                      int j = indexMap[mapOffset + i];
3106                      arr[off + j] = e;
3107                  });
3108         }
3109     }
3110 
3111     /**
3112      * {@inheritDoc} <!--workaround-->
3113      */
3114     @Override
3115     @ForceInline
3116     public final
3117     void intoByteArray(byte[] a, int offset,
3118                        ByteOrder bo) {
3119         offset = checkFromIndexSize(offset, byteSize(), a.length);
3120         maybeSwap(bo).intoByteArray0(a, offset);
3121     }
3122 
3123     /**
3124      * {@inheritDoc} <!--workaround-->
3125      */
3126     @Override
3127     @ForceInline
3128     public final
3129     void intoByteArray(byte[] a, int offset,
3130                        ByteOrder bo,
3131                        VectorMask<Integer> m) {
3132         if (m.allTrue()) {
3133             intoByteArray(a, offset, bo);
3134         } else {
3135             // FIXME: optimize
3136             IntSpecies vsp = vspecies();
3137             checkMaskFromIndexSize(offset, vsp, m, 4, a.length);
3138             ByteBuffer wb = wrapper(a, bo);
3139             this.stOp(wb, offset, m,
3140                     (wb_, o, i, e) -> wb_.putInt(o + i * 4, e));
3141         }
3142     }
3143 
3144     /**
3145      * {@inheritDoc} <!--workaround-->
3146      */
3147     @Override
3148     @ForceInline
3149     public final
3150     void intoByteBuffer(ByteBuffer bb, int offset,
3151                         ByteOrder bo) {
3152         if (bb.isReadOnly()) {
3153             throw new ReadOnlyBufferException();
3154         }
3155         offset = checkFromIndexSize(offset, byteSize(), bb.limit());
3156         maybeSwap(bo).intoByteBuffer0(bb, offset);
3157     }
3158 
3159     /**
3160      * {@inheritDoc} <!--workaround-->
3161      */
3162     @Override
3163     @ForceInline
3164     public final
3165     void intoByteBuffer(ByteBuffer bb, int offset,
3166                         ByteOrder bo,
3167                         VectorMask<Integer> m) {
3168         if (m.allTrue()) {
3169             intoByteBuffer(bb, offset, bo);
3170         } else {
3171             // FIXME: optimize
3172             if (bb.isReadOnly()) {
3173                 throw new ReadOnlyBufferException();
3174             }
3175             IntSpecies vsp = vspecies();
3176             checkMaskFromIndexSize(offset, vsp, m, 4, bb.limit());
3177             ByteBuffer wb = wrapper(bb, bo);
3178             this.stOp(wb, offset, m,
3179                     (wb_, o, i, e) -> wb_.putInt(o + i * 4, e));
3180         }
3181     }
3182 
3183     // ================================================
3184 
3185     // Low-level memory operations.
3186     //
3187     // Note that all of these operations *must* inline into a context
3188     // where the exact species of the involved vector is a
3189     // compile-time constant.  Otherwise, the intrinsic generation
3190     // will fail and performance will suffer.
3191     //
3192     // In many cases this is achieved by re-deriving a version of the
3193     // method in each concrete subclass (per species).  The re-derived
3194     // method simply calls one of these generic methods, with exact
3195     // parameters for the controlling metadata, which is either a
3196     // typed vector or constant species instance.
3197 
3198     // Unchecked loading operations in native byte order.
3199     // Caller is responsible for applying index checks, masking, and
3200     // byte swapping.
3201 
3202     /*package-private*/
3203     abstract
3204     IntVector fromArray0(int[] a, int offset);
3205     @ForceInline
3206     final
3207     IntVector fromArray0Template(int[] a, int offset) {
3208         IntSpecies vsp = vspecies();
3209         return VectorSupport.load(
3210             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3211             a, arrayAddress(a, offset),
3212             a, offset, vsp,
3213             (arr, off, s) -> s.ldOp(arr, off,
3214                                     (arr_, off_, i) -> arr_[off_ + i]));
3215     }
3216 
3217     @Override
3218     abstract
3219     IntVector fromByteArray0(byte[] a, int offset);
3220     @ForceInline
3221     final
3222     IntVector fromByteArray0Template(byte[] a, int offset) {
3223         IntSpecies vsp = vspecies();
3224         return VectorSupport.load(
3225             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3226             a, byteArrayAddress(a, offset),
3227             a, offset, vsp,
3228             (arr, off, s) -> {
3229                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3230                 return s.ldOp(wb, off,
3231                         (wb_, o, i) -> wb_.getInt(o + i * 4));
3232             });
3233     }
3234 
3235     abstract
3236     IntVector fromByteBuffer0(ByteBuffer bb, int offset);
3237     @ForceInline
3238     final
3239     IntVector fromByteBuffer0Template(ByteBuffer bb, int offset) {
3240         IntSpecies vsp = vspecies();
3241         return VectorSupport.load(
3242             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3243             bufferBase(bb), bufferAddress(bb, offset),
3244             bb, offset, vsp,
3245             (buf, off, s) -> {
3246                 ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3247                 return s.ldOp(wb, off,
3248                         (wb_, o, i) -> wb_.getInt(o + i * 4));
3249            });
3250     }
3251 
3252     // Unchecked storing operations in native byte order.
3253     // Caller is responsible for applying index checks, masking, and
3254     // byte swapping.
3255 
3256     abstract
3257     void intoArray0(int[] a, int offset);
3258     @ForceInline
3259     final
3260     void intoArray0Template(int[] a, int offset) {
3261         IntSpecies vsp = vspecies();
3262         VectorSupport.store(
3263             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3264             a, arrayAddress(a, offset),
3265             this, a, offset,
3266             (arr, off, v)
3267             -> v.stOp(arr, off,
3268                       (arr_, off_, i, e) -> arr_[off_+i] = e));
3269     }
3270 
3271     abstract
3272     void intoByteArray0(byte[] a, int offset);
3273     @ForceInline
3274     final
3275     void intoByteArray0Template(byte[] a, int offset) {
3276         IntSpecies vsp = vspecies();
3277         VectorSupport.store(
3278             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3279             a, byteArrayAddress(a, offset),
3280             this, a, offset,
3281             (arr, off, v) -> {
3282                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3283                 v.stOp(wb, off,
3284                         (tb_, o, i, e) -> tb_.putInt(o + i * 4, e));
3285             });
3286     }
3287 
3288     @ForceInline
3289     final
3290     void intoByteBuffer0(ByteBuffer bb, int offset) {
3291         IntSpecies vsp = vspecies();
3292         VectorSupport.store(
3293             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3294             bufferBase(bb), bufferAddress(bb, offset),
3295             this, bb, offset,
3296             (buf, off, v) -> {
3297                 ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3298                 v.stOp(wb, off,
3299                         (wb_, o, i, e) -> wb_.putInt(o + i * 4, e));
3300             });
3301     }
3302 
3303     // End of low-level memory operations.
3304 
3305     private static
3306     void checkMaskFromIndexSize(int offset,
3307                                 IntSpecies vsp,
3308                                 VectorMask<Integer> m,
3309                                 int scale,
3310                                 int limit) {
3311         ((AbstractMask<Integer>)m)
3312             .checkIndexByLane(offset, limit, vsp.iota(), scale);
3313     }
3314 
3315     @ForceInline
3316     private void conditionalStoreNYI(int offset,
3317                                      IntSpecies vsp,
3318                                      VectorMask<Integer> m,
3319                                      int scale,
3320                                      int limit) {
3321         if (offset < 0 || offset + vsp.laneCount() * scale > limit) {
3322             String msg =
3323                 String.format("unimplemented: store @%d in [0..%d), %s in %s",
3324                               offset, limit, m, vsp);
3325             throw new AssertionError(msg);
3326         }
3327     }
3328 
3329     /*package-private*/
3330     @Override
3331     @ForceInline
3332     final
3333     IntVector maybeSwap(ByteOrder bo) {
3334         if (bo != NATIVE_ENDIAN) {
3335             return this.reinterpretAsBytes()
3336                 .rearrange(swapBytesShuffle())
3337                 .reinterpretAsInts();
3338         }
3339         return this;
3340     }
3341 
3342     static final int ARRAY_SHIFT =
3343         31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_INT_INDEX_SCALE);
3344     static final long ARRAY_BASE =
3345         Unsafe.ARRAY_INT_BASE_OFFSET;
3346 
3347     @ForceInline
3348     static long arrayAddress(int[] a, int index) {
3349         return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
3350     }
3351 
3352     @ForceInline
3353     static long byteArrayAddress(byte[] a, int index) {
3354         return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
3355     }
3356 
3357     // ================================================
3358 
3359     /// Reinterpreting view methods:
3360     //   lanewise reinterpret: viewAsXVector()
3361     //   keep shape, redraw lanes: reinterpretAsEs()
3362 
3363     /**
3364      * {@inheritDoc} <!--workaround-->
3365      */
3366     @ForceInline
3367     @Override
3368     public final ByteVector reinterpretAsBytes() {
3369          // Going to ByteVector, pay close attention to byte order.
3370          assert(REGISTER_ENDIAN == ByteOrder.LITTLE_ENDIAN);
3371          return asByteVectorRaw();
3372          //return asByteVectorRaw().rearrange(swapBytesShuffle());
3373     }
3374 
3375     /**
3376      * {@inheritDoc} <!--workaround-->
3377      */
3378     @ForceInline
3379     @Override
3380     public final IntVector viewAsIntegralLanes() {
3381         return this;
3382     }
3383 
3384     /**
3385      * {@inheritDoc} <!--workaround-->
3386      */
3387     @ForceInline
3388     @Override
3389     public final
3390     FloatVector
3391     viewAsFloatingLanes() {
3392         LaneType flt = LaneType.INT.asFloating();
3393         return (FloatVector) asVectorRaw(flt);
3394     }
3395 
3396     // ================================================
3397 
3398     /// Object methods: toString, equals, hashCode
3399     //
3400     // Object methods are defined as if via Arrays.toString, etc.,
3401     // is applied to the array of elements.  Two equal vectors
3402     // are required to have equal species and equal lane values.
3403 
3404     /**
3405      * Returns a string representation of this vector, of the form
3406      * {@code "[0,1,2...]"}, reporting the lane values of this vector,
3407      * in lane order.
3408      *
3409      * The string is produced as if by a call to {@link
3410      * java.util.Arrays#toString(int[]) Arrays.toString()},
3411      * as appropriate to the {@code int} array returned by
3412      * {@link #toArray this.toArray()}.
3413      *
3414      * @return a string of the form {@code "[0,1,2...]"}
3415      * reporting the lane values of this vector
3416      */
3417     @Override
3418     @ForceInline
3419     public final
3420     String toString() {
3421         // now that toArray is strongly typed, we can define this
3422         return Arrays.toString(toArray());
3423     }
3424 
3425     /**
3426      * {@inheritDoc} <!--workaround-->
3427      */
3428     @Override
3429     @ForceInline
3430     public final
3431     boolean equals(Object obj) {
3432         if (obj instanceof Vector) {
3433             Vector<?> that = (Vector<?>) obj;
3434             if (this.species().equals(that.species())) {
3435                 return this.eq(that.check(this.species())).allTrue();
3436             }
3437         }
3438         return false;
3439     }
3440 
3441     /**
3442      * {@inheritDoc} <!--workaround-->
3443      */
3444     @Override
3445     @ForceInline
3446     public final
3447     int hashCode() {
3448         // now that toArray is strongly typed, we can define this
3449         return Objects.hash(species(), Arrays.hashCode(toArray()));
3450     }
3451 
3452     // ================================================
3453 
3454     // Species
3455 
3456     /**
3457      * Class representing {@link IntVector}'s of the same {@link VectorShape VectorShape}.
3458      */
3459     /*package-private*/
3460     static final class IntSpecies extends AbstractSpecies<Integer> {
3461         private IntSpecies(VectorShape shape,
3462                 Class<? extends IntVector> vectorType,
3463                 Class<? extends AbstractMask<Integer>> maskType,
3464                 Function<Object, IntVector> vectorFactory) {
3465             super(shape, LaneType.of(int.class),
3466                   vectorType, maskType,
3467                   vectorFactory);
3468             assert(this.elementSize() == Integer.SIZE);
3469         }
3470 
3471         // Specializing overrides:
3472 
3473         @Override
3474         @ForceInline
3475         public final Class<Integer> elementType() {
3476             return int.class;
3477         }
3478 
3479         @Override
3480         @ForceInline
3481         final Class<Integer> genericElementType() {
3482             return Integer.class;
3483         }
3484 
3485         @SuppressWarnings("unchecked")
3486         @Override
3487         @ForceInline
3488         public final Class<? extends IntVector> vectorType() {
3489             return (Class<? extends IntVector>) vectorType;
3490         }
3491 
3492         @Override
3493         @ForceInline
3494         public final long checkValue(long e) {
3495             longToElementBits(e);  // only for exception
3496             return e;
3497         }
3498 
3499         /*package-private*/
3500         @Override
3501         @ForceInline
3502         final IntVector broadcastBits(long bits) {
3503             return (IntVector)
3504                 VectorSupport.broadcastCoerced(
3505                     vectorType, int.class, laneCount,
3506                     bits, this,
3507                     (bits_, s_) -> s_.rvOp(i -> bits_));
3508         }
3509 
3510         /*package-private*/
3511         @ForceInline
3512         final IntVector broadcast(int e) {
3513             return broadcastBits(toBits(e));
3514         }
3515 
3516         @Override
3517         @ForceInline
3518         public final IntVector broadcast(long e) {
3519             return broadcastBits(longToElementBits(e));
3520         }
3521 
3522         /*package-private*/
3523         final @Override
3524         @ForceInline
3525         long longToElementBits(long value) {
3526             // Do the conversion, and then test it for failure.
3527             int e = (int) value;
3528             if ((long) e != value) {
3529                 throw badElementBits(value, e);
3530             }
3531             return toBits(e);
3532         }
3533 
3534         /*package-private*/
3535         @ForceInline
3536         static long toIntegralChecked(int e, boolean convertToInt) {
3537             long value = convertToInt ? (int) e : (long) e;
3538             if ((int) value != e) {
3539                 throw badArrayBits(e, convertToInt, value);
3540             }
3541             return value;
3542         }
3543 
3544         /* this non-public one is for internal conversions */
3545         @Override
3546         @ForceInline
3547         final IntVector fromIntValues(int[] values) {
3548             VectorIntrinsics.requireLength(values.length, laneCount);
3549             int[] va = new int[laneCount()];
3550             for (int i = 0; i < va.length; i++) {
3551                 int lv = values[i];
3552                 int v = (int) lv;
3553                 va[i] = v;
3554                 if ((int)v != lv) {
3555                     throw badElementBits(lv, v);
3556                 }
3557             }
3558             return dummyVector().fromArray0(va, 0);
3559         }
3560 
3561         // Virtual constructors
3562 
3563         @ForceInline
3564         @Override final
3565         public IntVector fromArray(Object a, int offset) {
3566             // User entry point:  Be careful with inputs.
3567             return IntVector
3568                 .fromArray(this, (int[]) a, offset);
3569         }
3570 
3571         @ForceInline
3572         @Override final
3573         IntVector dummyVector() {
3574             return (IntVector) super.dummyVector();
3575         }
3576 
3577         /*package-private*/
3578         final @Override
3579         @ForceInline
3580         IntVector rvOp(RVOp f) {
3581             int[] res = new int[laneCount()];
3582             for (int i = 0; i < res.length; i++) {
3583                 int bits = (int) f.apply(i);
3584                 res[i] = fromBits(bits);
3585             }
3586             return dummyVector().vectorFactory(res);
3587         }
3588 
3589         IntVector vOp(FVOp f) {
3590             int[] res = new int[laneCount()];
3591             for (int i = 0; i < res.length; i++) {
3592                 res[i] = f.apply(i);
3593             }
3594             return dummyVector().vectorFactory(res);
3595         }
3596 
3597         IntVector vOp(VectorMask<Integer> m, FVOp f) {
3598             int[] res = new int[laneCount()];
3599             boolean[] mbits = ((AbstractMask<Integer>)m).getBits();
3600             for (int i = 0; i < res.length; i++) {
3601                 if (mbits[i]) {
3602                     res[i] = f.apply(i);
3603                 }
3604             }
3605             return dummyVector().vectorFactory(res);
3606         }
3607 
3608         /*package-private*/
3609         @ForceInline
3610         <M> IntVector ldOp(M memory, int offset,
3611                                       FLdOp<M> f) {
3612             return dummyVector().ldOp(memory, offset, f);
3613         }
3614 
3615         /*package-private*/
3616         @ForceInline
3617         <M> IntVector ldOp(M memory, int offset,
3618                                       AbstractMask<Integer> m,
3619                                       FLdOp<M> f) {
3620             return dummyVector().ldOp(memory, offset, m, f);
3621         }
3622 
3623         /*package-private*/
3624         @ForceInline
3625         <M> void stOp(M memory, int offset, FStOp<M> f) {
3626             dummyVector().stOp(memory, offset, f);
3627         }
3628 
3629         /*package-private*/
3630         @ForceInline
3631         <M> void stOp(M memory, int offset,
3632                       AbstractMask<Integer> m,
3633                       FStOp<M> f) {
3634             dummyVector().stOp(memory, offset, m, f);
3635         }
3636 
3637         // N.B. Make sure these constant vectors and
3638         // masks load up correctly into registers.
3639         //
3640         // Also, see if we can avoid all that switching.
3641         // Could we cache both vectors and both masks in
3642         // this species object?
3643 
3644         // Zero and iota vector access
3645         @Override
3646         @ForceInline
3647         public final IntVector zero() {
3648             if ((Class<?>) vectorType() == IntMaxVector.class)
3649                 return IntMaxVector.ZERO;
3650             switch (vectorBitSize()) {
3651                 case 64: return Int64Vector.ZERO;
3652                 case 128: return Int128Vector.ZERO;
3653                 case 256: return Int256Vector.ZERO;
3654                 case 512: return Int512Vector.ZERO;
3655             }
3656             throw new AssertionError();
3657         }
3658 
3659         @Override
3660         @ForceInline
3661         public final IntVector iota() {
3662             if ((Class<?>) vectorType() == IntMaxVector.class)
3663                 return IntMaxVector.IOTA;
3664             switch (vectorBitSize()) {
3665                 case 64: return Int64Vector.IOTA;
3666                 case 128: return Int128Vector.IOTA;
3667                 case 256: return Int256Vector.IOTA;
3668                 case 512: return Int512Vector.IOTA;
3669             }
3670             throw new AssertionError();
3671         }
3672 
3673         // Mask access
3674         @Override
3675         @ForceInline
3676         public final VectorMask<Integer> maskAll(boolean bit) {
3677             if ((Class<?>) vectorType() == IntMaxVector.class)
3678                 return IntMaxVector.IntMaxMask.maskAll(bit);
3679             switch (vectorBitSize()) {
3680                 case 64: return Int64Vector.Int64Mask.maskAll(bit);
3681                 case 128: return Int128Vector.Int128Mask.maskAll(bit);
3682                 case 256: return Int256Vector.Int256Mask.maskAll(bit);
3683                 case 512: return Int512Vector.Int512Mask.maskAll(bit);
3684             }
3685             throw new AssertionError();
3686         }
3687     }
3688 
3689     /**
3690      * Finds a species for an element type of {@code int} and shape.
3691      *
3692      * @param s the shape
3693      * @return a species for an element type of {@code int} and shape
3694      * @throws IllegalArgumentException if no such species exists for the shape
3695      */
3696     static IntSpecies species(VectorShape s) {
3697         Objects.requireNonNull(s);
3698         switch (s) {
3699             case S_64_BIT: return (IntSpecies) SPECIES_64;
3700             case S_128_BIT: return (IntSpecies) SPECIES_128;
3701             case S_256_BIT: return (IntSpecies) SPECIES_256;
3702             case S_512_BIT: return (IntSpecies) SPECIES_512;
3703             case S_Max_BIT: return (IntSpecies) SPECIES_MAX;
3704             default: throw new IllegalArgumentException("Bad shape: " + s);
3705         }
3706     }
3707 
3708     /** Species representing {@link IntVector}s of {@link VectorShape#S_64_BIT VectorShape.S_64_BIT}. */
3709     public static final VectorSpecies<Integer> SPECIES_64
3710         = new IntSpecies(VectorShape.S_64_BIT,
3711                             Int64Vector.class,
3712                             Int64Vector.Int64Mask.class,
3713                             Int64Vector::new);
3714 
3715     /** Species representing {@link IntVector}s of {@link VectorShape#S_128_BIT VectorShape.S_128_BIT}. */
3716     public static final VectorSpecies<Integer> SPECIES_128
3717         = new IntSpecies(VectorShape.S_128_BIT,
3718                             Int128Vector.class,
3719                             Int128Vector.Int128Mask.class,
3720                             Int128Vector::new);
3721 
3722     /** Species representing {@link IntVector}s of {@link VectorShape#S_256_BIT VectorShape.S_256_BIT}. */
3723     public static final VectorSpecies<Integer> SPECIES_256
3724         = new IntSpecies(VectorShape.S_256_BIT,
3725                             Int256Vector.class,
3726                             Int256Vector.Int256Mask.class,
3727                             Int256Vector::new);
3728 
3729     /** Species representing {@link IntVector}s of {@link VectorShape#S_512_BIT VectorShape.S_512_BIT}. */
3730     public static final VectorSpecies<Integer> SPECIES_512
3731         = new IntSpecies(VectorShape.S_512_BIT,
3732                             Int512Vector.class,
3733                             Int512Vector.Int512Mask.class,
3734                             Int512Vector::new);
3735 
3736     /** Species representing {@link IntVector}s of {@link VectorShape#S_Max_BIT VectorShape.S_Max_BIT}. */
3737     public static final VectorSpecies<Integer> SPECIES_MAX
3738         = new IntSpecies(VectorShape.S_Max_BIT,
3739                             IntMaxVector.class,
3740                             IntMaxVector.IntMaxMask.class,
3741                             IntMaxVector::new);
3742 
3743     /**
3744      * Preferred species for {@link IntVector}s.
3745      * A preferred species is a species of maximal bit-size for the platform.
3746      */
3747     public static final VectorSpecies<Integer> SPECIES_PREFERRED
3748         = (IntSpecies) VectorSpecies.ofPreferred(int.class);
3749 }
3750