1 /*
   2  * Copyright (c) 2017, 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
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.nio.ByteOrder;
  29 import java.util.Objects;
  30 import java.util.function.IntUnaryOperator;
  31 import java.util.concurrent.ThreadLocalRandom;
  32 
  33 import jdk.internal.misc.Unsafe;
  34 import jdk.internal.vm.annotation.ForceInline;
  35 import static jdk.incubator.vector.VectorIntrinsics.*;
  36 
  37 
  38 /**
  39  * A specialized {@link Vector} representing an ordered immutable sequence of
  40  * {@code byte} values.
  41  */
  42 @SuppressWarnings("cast")
  43 public abstract class ByteVector extends Vector<Byte> {
  44 
  45     ByteVector() {}
  46 
  47     private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_BYTE_INDEX_SCALE);
  48 
  49     // Unary operator
  50 
  51     interface FUnOp {
  52         byte apply(int i, byte a);
  53     }
  54 
  55     abstract ByteVector uOp(FUnOp f);
  56 
  57     abstract ByteVector uOp(Mask<Byte> m, FUnOp f);
  58 
  59     // Binary operator
  60 
  61     interface FBinOp {
  62         byte apply(int i, byte a, byte b);
  63     }
  64 
  65     abstract ByteVector bOp(Vector<Byte> v, FBinOp f);
  66 
  67     abstract ByteVector bOp(Vector<Byte> v, Mask<Byte> m, FBinOp f);
  68 
  69     // Trinary operator
  70 
  71     interface FTriOp {
  72         byte apply(int i, byte a, byte b, byte c);
  73     }
  74 
  75     abstract ByteVector tOp(Vector<Byte> v1, Vector<Byte> v2, FTriOp f);
  76 
  77     abstract ByteVector tOp(Vector<Byte> v1, Vector<Byte> v2, Mask<Byte> m, FTriOp f);
  78 
  79     // Reduction operator
  80 
  81     abstract byte rOp(byte v, FBinOp f);
  82 
  83     // Binary test
  84 
  85     interface FBinTest {
  86         boolean apply(int i, byte a, byte b);
  87     }
  88 
  89     abstract Mask<Byte> bTest(Vector<Byte> v, FBinTest f);
  90 
  91     // Foreach
  92 
  93     interface FUnCon {
  94         void apply(int i, byte a);
  95     }
  96 
  97     abstract void forEach(FUnCon f);
  98 
  99     abstract void forEach(Mask<Byte> m, FUnCon f);
 100 
 101     // Static factories
 102 
 103     /**
 104      * Returns a vector where all lane elements are set to the default
 105      * primitive value.
 106      *
 107      * @return a zero vector
 108      */
 109     @ForceInline
 110     @SuppressWarnings("unchecked")
 111     public static ByteVector zero(ByteSpecies species) {
 112         return species.zero();
 113     }
 114 
 115     /**
 116      * Loads a vector from a byte array starting at an offset.
 117      * <p>
 118      * Bytes are composed into primitive lane elements according to the
 119      * native byte order of the underlying platform
 120      * <p>
 121      * This method behaves as if it returns the result of calling the
 122      * byte buffer, offset, and mask accepting
 123      * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask) method} as follows:
 124      * <pre>{@code
 125      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
 126      * }</pre>
 127      *
 128      * @param a the byte array
 129      * @param ix the offset into the array
 130      * @return a vector loaded from a byte array
 131      * @throws IndexOutOfBoundsException if {@code i < 0} or
 132      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 133      */
 134     @ForceInline
 135     @SuppressWarnings("unchecked")
 136     public static ByteVector fromByteArray(ByteSpecies species, byte[] a, int ix) {
 137         Objects.requireNonNull(a);
 138         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
 139         return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(),
 140                                      a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 141                                      a, ix, species,
 142                                      (c, idx, s) -> {
 143                                          ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
 144                                          ByteBuffer tb = bbc;
 145                                          return ((ByteSpecies)s).op(i -> tb.get());
 146                                      });
 147     }
 148 
 149     /**
 150      * Loads a vector from a byte array starting at an offset and using a
 151      * mask.
 152      * <p>
 153      * Bytes are composed into primitive lane elements according to the
 154      * native byte order of the underlying platform.
 155      * <p>
 156      * This method behaves as if it returns the result of calling the
 157      * byte buffer, offset, and mask accepting
 158      * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask) method} as follows:
 159      * <pre>{@code
 160      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
 161      * }</pre>
 162      *
 163      * @param a the byte array
 164      * @param ix the offset into the array
 165      * @param m the mask
 166      * @return a vector loaded from a byte array
 167      * @throws IndexOutOfBoundsException if {@code i < 0} or
 168      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 169      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 170      * or {@code > a.length},
 171      * for any vector lane index {@code N} where the mask at lane {@code N}
 172      * is set
 173      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
 174      */
 175     @ForceInline
 176     public static ByteVector fromByteArray(ByteSpecies species, byte[] a, int ix, Mask<Byte> m) {
 177         return zero(species).blend(fromByteArray(species, a, ix), m);
 178     }
 179 
 180     /**
 181      * Loads a vector from an array starting at offset.
 182      * <p>
 183      * For each vector lane, where {@code N} is the vector lane index, the
 184      * array element at index {@code i + N} is placed into the
 185      * resulting vector at lane index {@code N}.
 186      *
 187      * @param a the array
 188      * @param i the offset into the array
 189      * @return the vector loaded from an array
 190      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 191      * {@code i > a.length - this.length()}
 192      */
 193     @ForceInline
 194     @SuppressWarnings("unchecked")
 195     public static ByteVector fromArray(ByteSpecies species, byte[] a, int i){
 196         Objects.requireNonNull(a);
 197         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
 198         return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(),
 199                                      a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 200                                      a, i, species,
 201                                      (c, idx, s) -> ((ByteSpecies)s).op(n -> c[idx + n]));
 202     }
 203 
 204 
 205     /**
 206      * Loads a vector from an array starting at offset and using a mask.
 207      * <p>
 208      * For each vector lane, where {@code N} is the vector lane index,
 209      * if the mask lane at index {@code N} is set then the array element at
 210      * index {@code i + N} is placed into the resulting vector at lane index
 211      * {@code N}, otherwise the default element value is placed into the
 212      * resulting vector at lane index {@code N}.
 213      *
 214      * @param a the array
 215      * @param i the offset into the array
 216      * @param m the mask
 217      * @return the vector loaded from an array
 218      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 219      * for any vector lane index {@code N} where the mask at lane {@code N}
 220      * is set {@code i > a.length - N}
 221      */
 222     @ForceInline
 223     public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, Mask<Byte> m) {
 224         return zero(species).blend(fromArray(species, a, i), m);
 225     }
 226 
 227     /**
 228      * Loads a vector from an array using indexes obtained from an index
 229      * map.
 230      * <p>
 231      * For each vector lane, where {@code N} is the vector lane index, the
 232      * array element at index {@code i + indexMap[j + N]} is placed into the
 233      * resulting vector at lane index {@code N}.
 234      *
 235      * @param a the array
 236      * @param i the offset into the array, may be negative if relative
 237      * indexes in the index map compensate to produce a value within the
 238      * array bounds
 239      * @param indexMap the index map
 240      * @param j the offset into the index map
 241      * @return the vector loaded from an array
 242      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 243      * {@code j > indexMap.length - this.length()},
 244      * or for any vector lane index {@code N} the result of
 245      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 246      */
 247     public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, int[] indexMap, int j) {
 248         return species.op(n -> a[i + indexMap[j + n]]);
 249     }
 250     /**
 251      * Loads a vector from an array using indexes obtained from an index
 252      * map and using a mask.
 253      * <p>
 254      * For each vector lane, where {@code N} is the vector lane index,
 255      * if the mask lane at index {@code N} is set then the array element at
 256      * index {@code i + indexMap[j + N]} is placed into the resulting vector
 257      * at lane index {@code N}.
 258      *
 259      * @param a the array
 260      * @param i the offset into the array, may be negative if relative
 261      * indexes in the index map compensate to produce a value within the
 262      * array bounds
 263      * @param indexMap the index map
 264      * @param j the offset into the index map
 265      * @return the vector loaded from an array
 266      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 267      * {@code j > indexMap.length - this.length()},
 268      * or for any vector lane index {@code N} where the mask at lane
 269      * {@code N} is set the result of {@code i + indexMap[j + N]} is
 270      * {@code < 0} or {@code >= a.length}
 271      */
 272     public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) {
 273         return species.op(m, n -> a[i + indexMap[j + n]]);
 274     }
 275 
 276     /**
 277      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 278      * offset into the byte buffer.
 279      * <p>
 280      * Bytes are composed into primitive lane elements according to the
 281      * native byte order of the underlying platform.
 282      * <p>
 283      * This method behaves as if it returns the result of calling the
 284      * byte buffer, offset, and mask accepting
 285      * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask)} method} as follows:
 286      * <pre>{@code
 287      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
 288      * }</pre>
 289      *
 290      * @param bb the byte buffer
 291      * @param ix the offset into the byte buffer
 292      * @return a vector loaded from a byte buffer
 293      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 294      * or {@code > b.limit()},
 295      * or if there are fewer than
 296      * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
 297      * remaining in the byte buffer from the given offset
 298      */
 299     @ForceInline
 300     @SuppressWarnings("unchecked")
 301     public static ByteVector fromByteBuffer(ByteSpecies species, ByteBuffer bb, int ix) {
 302         if (bb.order() != ByteOrder.nativeOrder()) {
 303             throw new IllegalArgumentException();
 304         }
 305         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
 306         return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(),
 307                                      U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
 308                                      bb, ix, species,
 309                                      (c, idx, s) -> {
 310                                          ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
 311                                          ByteBuffer tb = bbc;
 312                                          return ((ByteSpecies)s).op(i -> tb.get());
 313                                      });
 314     }
 315 
 316     /**
 317      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 318      * offset into the byte buffer and using a mask.
 319      * <p>
 320      * This method behaves as if the byte buffer is viewed as a primitive
 321      * {@link java.nio.Buffer buffer} for the primitive element type,
 322      * according to the native byte order of the underlying platform, and
 323      * the returned vector is loaded with a mask from a primitive array
 324      * obtained from the primitive buffer.
 325      * The following pseudocode expresses the behaviour, where
 326      * {@coce EBuffer} is the primitive buffer type, {@code e} is the
 327      * primitive element type, and {@code ESpecies<S>} is the primitive
 328      * species for {@code e}:
 329      * <pre>{@code
 330      * EBuffer eb = b.duplicate().
 331      *     order(ByteOrder.nativeOrder()).position(i).
 332      *     asEBuffer();
 333      * e[] es = new e[this.length()];
 334      * for (int n = 0; n < t.length; n++) {
 335      *     if (m.isSet(n))
 336      *         es[n] = eb.get(n);
 337      * }
 338      * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
 339      * }</pre>
 340      *
 341      * @param bb the byte buffer
 342      * @param ix the offset into the byte buffer
 343      * @return a vector loaded from a byte buffer
 344      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 345      * or {@code > b.limit()},
 346      * for any vector lane index {@code N} where the mask at lane {@code N}
 347      * is set
 348      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
 349      */
 350     @ForceInline
 351     public static ByteVector fromByteBuffer(ByteSpecies species, ByteBuffer bb, int ix, Mask<Byte> m) {
 352         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
 353     }
 354 
 355     @ForceInline
 356     public static Mask<Byte> maskFromValues(ByteSpecies species, boolean... bits) {
 357         if (species.boxType() == ByteMaxVector.class)
 358             return new ByteMaxVector.ByteMaxMask(bits);
 359         switch (species.bitSize()) {
 360             case 64: return new Byte64Vector.Byte64Mask(bits);
 361             case 128: return new Byte128Vector.Byte128Mask(bits);
 362             case 256: return new Byte256Vector.Byte256Mask(bits);
 363             case 512: return new Byte512Vector.Byte512Mask(bits);
 364             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 365         }
 366     }
 367 
 368     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
 369     static Mask<Byte> trueMask(ByteSpecies species) {
 370         if (species.boxType() == ByteMaxVector.class)
 371             return ByteMaxVector.ByteMaxMask.TRUE_MASK;
 372         switch (species.bitSize()) {
 373             case 64: return Byte64Vector.Byte64Mask.TRUE_MASK;
 374             case 128: return Byte128Vector.Byte128Mask.TRUE_MASK;
 375             case 256: return Byte256Vector.Byte256Mask.TRUE_MASK;
 376             case 512: return Byte512Vector.Byte512Mask.TRUE_MASK;
 377             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 378         }
 379     }
 380 
 381     static Mask<Byte> falseMask(ByteSpecies species) {
 382         if (species.boxType() == ByteMaxVector.class)
 383             return ByteMaxVector.ByteMaxMask.FALSE_MASK;
 384         switch (species.bitSize()) {
 385             case 64: return Byte64Vector.Byte64Mask.FALSE_MASK;
 386             case 128: return Byte128Vector.Byte128Mask.FALSE_MASK;
 387             case 256: return Byte256Vector.Byte256Mask.FALSE_MASK;
 388             case 512: return Byte512Vector.Byte512Mask.FALSE_MASK;
 389             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 390         }
 391     }
 392 
 393     @ForceInline
 394     @SuppressWarnings("unchecked")
 395     public static Mask<Byte> maskFromArray(ByteSpecies species, boolean[] bits, int ix) {
 396         Objects.requireNonNull(bits);
 397         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
 398         return VectorIntrinsics.load((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
 399                                      bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
 400                                      bits, ix, species,
 401                                      (c, idx, s) -> (Mask<Byte>) ((ByteSpecies)s).opm(n -> c[idx + n]));
 402     }
 403 
 404     @ForceInline
 405     @SuppressWarnings("unchecked")
 406     public static Mask<Byte> maskAllTrue(ByteSpecies species) {
 407         return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
 408                                                  (byte)-1,  species,
 409                                                  ((z, s) -> trueMask((ByteSpecies)s)));
 410     }
 411 
 412     @ForceInline
 413     @SuppressWarnings("unchecked")
 414     public static Mask<Byte> maskAllFalse(ByteSpecies species) {
 415         return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
 416                                                  0, species, 
 417                                                  ((z, s) -> falseMask((ByteSpecies)s)));
 418     }
 419 
 420     @ForceInline
 421     public static Shuffle<Byte> shuffle(ByteSpecies species, IntUnaryOperator f) {
 422         if (species.boxType() == ByteMaxVector.class)
 423             return new ByteMaxVector.ByteMaxShuffle(f);
 424         switch (species.bitSize()) {
 425             case 64: return new Byte64Vector.Byte64Shuffle(f);
 426             case 128: return new Byte128Vector.Byte128Shuffle(f);
 427             case 256: return new Byte256Vector.Byte256Shuffle(f);
 428             case 512: return new Byte512Vector.Byte512Shuffle(f);
 429             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 430         }
 431     }
 432 
 433     @ForceInline
 434     public static Shuffle<Byte> shuffleIota(ByteSpecies species) {
 435         if (species.boxType() == ByteMaxVector.class)
 436             return new ByteMaxVector.ByteMaxShuffle(AbstractShuffle.IDENTITY);
 437         switch (species.bitSize()) {
 438             case 64: return new Byte64Vector.Byte64Shuffle(AbstractShuffle.IDENTITY);
 439             case 128: return new Byte128Vector.Byte128Shuffle(AbstractShuffle.IDENTITY);
 440             case 256: return new Byte256Vector.Byte256Shuffle(AbstractShuffle.IDENTITY);
 441             case 512: return new Byte512Vector.Byte512Shuffle(AbstractShuffle.IDENTITY);
 442             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 443         }
 444     }
 445 
 446     @ForceInline
 447     public static Shuffle<Byte> shuffleFromValues(ByteSpecies species, int... ixs) {
 448         if (species.boxType() == ByteMaxVector.class)
 449             return new ByteMaxVector.ByteMaxShuffle(ixs);
 450         switch (species.bitSize()) {
 451             case 64: return new Byte64Vector.Byte64Shuffle(ixs);
 452             case 128: return new Byte128Vector.Byte128Shuffle(ixs);
 453             case 256: return new Byte256Vector.Byte256Shuffle(ixs);
 454             case 512: return new Byte512Vector.Byte512Shuffle(ixs);
 455             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 456         }
 457     }
 458 
 459     @ForceInline
 460     public static Shuffle<Byte> shuffleFromArray(ByteSpecies species, int[] ixs, int i) {
 461         if (species.boxType() == ByteMaxVector.class)
 462             return new ByteMaxVector.ByteMaxShuffle(ixs, i);
 463         switch (species.bitSize()) {
 464             case 64: return new Byte64Vector.Byte64Shuffle(ixs, i);
 465             case 128: return new Byte128Vector.Byte128Shuffle(ixs, i);
 466             case 256: return new Byte256Vector.Byte256Shuffle(ixs, i);
 467             case 512: return new Byte512Vector.Byte512Shuffle(ixs, i);
 468             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 469         }
 470     }
 471 
 472 
 473     // Ops
 474 
 475     @Override
 476     public abstract ByteVector add(Vector<Byte> v);
 477 
 478     /**
 479      * Adds this vector to the broadcast of an input scalar.
 480      * <p>
 481      * This is a vector binary operation where the primitive addition operation
 482      * ({@code +}) is applied to lane elements.
 483      *
 484      * @param s the input scalar
 485      * @return the result of adding this vector to the broadcast of an input
 486      * scalar
 487      */
 488     public abstract ByteVector add(byte s);
 489 
 490     @Override
 491     public abstract ByteVector add(Vector<Byte> v, Mask<Byte> m);
 492 
 493     /**
 494      * Adds this vector to broadcast of an input scalar,
 495      * selecting lane elements controlled by a mask.
 496      * <p>
 497      * This is a vector binary operation where the primitive addition operation
 498      * ({@code +}) is applied to lane elements.
 499      *
 500      * @param s the input scalar
 501      * @param m the mask controlling lane selection
 502      * @return the result of adding this vector to the broadcast of an input
 503      * scalar
 504      */
 505     public abstract ByteVector add(byte s, Mask<Byte> m);
 506 
 507     @Override
 508     public abstract ByteVector sub(Vector<Byte> v);
 509 
 510     /**
 511      * Subtracts the broadcast of an input scalar from this vector.
 512      * <p>
 513      * This is a vector binary operation where the primitive subtraction
 514      * operation ({@code -}) is applied to lane elements.
 515      *
 516      * @param s the input scalar
 517      * @return the result of subtracting the broadcast of an input
 518      * scalar from this vector
 519      */
 520     public abstract ByteVector sub(byte s);
 521 
 522     @Override
 523     public abstract ByteVector sub(Vector<Byte> v, Mask<Byte> m);
 524 
 525     /**
 526      * Subtracts the broadcast of an input scalar from this vector, selecting
 527      * lane elements controlled by a mask.
 528      * <p>
 529      * This is a vector binary operation where the primitive subtraction
 530      * operation ({@code -}) is applied to lane elements.
 531      *
 532      * @param s the input scalar
 533      * @param m the mask controlling lane selection
 534      * @return the result of subtracting the broadcast of an input
 535      * scalar from this vector
 536      */
 537     public abstract ByteVector sub(byte s, Mask<Byte> m);
 538 
 539     @Override
 540     public abstract ByteVector mul(Vector<Byte> v);
 541 
 542     /**
 543      * Multiplies this vector with the broadcast of an input scalar.
 544      * <p>
 545      * This is a vector binary operation where the primitive multiplication
 546      * operation ({@code *}) is applied to lane elements.
 547      *
 548      * @param s the input scalar
 549      * @return the result of multiplying this vector with the broadcast of an
 550      * input scalar
 551      */
 552     public abstract ByteVector mul(byte s);
 553 
 554     @Override
 555     public abstract ByteVector mul(Vector<Byte> v, Mask<Byte> m);
 556 
 557     /**
 558      * Multiplies this vector with the broadcast of an input scalar, selecting
 559      * lane elements controlled by a mask.
 560      * <p>
 561      * This is a vector binary operation where the primitive multiplication
 562      * operation ({@code *}) is applied to lane elements.
 563      *
 564      * @param s the input scalar
 565      * @param m the mask controlling lane selection
 566      * @return the result of multiplying this vector with the broadcast of an
 567      * input scalar
 568      */
 569     public abstract ByteVector mul(byte s, Mask<Byte> m);
 570 
 571     @Override
 572     public abstract ByteVector neg();
 573 
 574     @Override
 575     public abstract ByteVector neg(Mask<Byte> m);
 576 
 577     @Override
 578     public abstract ByteVector abs();
 579 
 580     @Override
 581     public abstract ByteVector abs(Mask<Byte> m);
 582 
 583     @Override
 584     public abstract ByteVector min(Vector<Byte> v);
 585 
 586     @Override
 587     public abstract ByteVector min(Vector<Byte> v, Mask<Byte> m);
 588 
 589     /**
 590      * Returns the minimum of this vector and the broadcast of an input scalar.
 591      * <p>
 592      * This is a vector binary operation where the operation
 593      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements.
 594      *
 595      * @param s the input scalar
 596      * @return the minimum of this vector and the broadcast of an input scalar
 597      */
 598     public abstract ByteVector min(byte s);
 599 
 600     @Override
 601     public abstract ByteVector max(Vector<Byte> v);
 602 
 603     @Override
 604     public abstract ByteVector max(Vector<Byte> v, Mask<Byte> m);
 605 
 606     /**
 607      * Returns the maximum of this vector and the broadcast of an input scalar.
 608      * <p>
 609      * This is a vector binary operation where the operation
 610      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements.
 611      *
 612      * @param s the input scalar
 613      * @return the maximum of this vector and the broadcast of an input scalar
 614      */
 615     public abstract ByteVector max(byte s);
 616 
 617     @Override
 618     public abstract Mask<Byte> equal(Vector<Byte> v);
 619 
 620     /**
 621      * Tests if this vector is equal to the broadcast of an input scalar.
 622      * <p>
 623      * This is a vector binary test operation where the primitive equals
 624      * operation ({@code ==}) is applied to lane elements.
 625      *
 626      * @param s the input scalar
 627      * @return the result mask of testing if this vector is equal to the
 628      * broadcast of an input scalar
 629      */
 630     public abstract Mask<Byte> equal(byte s);
 631 
 632     @Override
 633     public abstract Mask<Byte> notEqual(Vector<Byte> v);
 634 
 635     /**
 636      * Tests if this vector is not equal to the broadcast of an input scalar.
 637      * <p>
 638      * This is a vector binary test operation where the primitive not equals
 639      * operation ({@code !=}) is applied to lane elements.
 640      *
 641      * @param s the input scalar
 642      * @return the result mask of testing if this vector is not equal to the
 643      * broadcast of an input scalar
 644      */
 645     public abstract Mask<Byte> notEqual(byte s);
 646 
 647     @Override
 648     public abstract Mask<Byte> lessThan(Vector<Byte> v);
 649 
 650     /**
 651      * Tests if this vector is less than the broadcast of an input scalar.
 652      * <p>
 653      * This is a vector binary test operation where the primitive less than
 654      * operation ({@code <}) is applied to lane elements.
 655      *
 656      * @param s the input scalar
 657      * @return the mask result of testing if this vector is less than the
 658      * broadcast of an input scalar
 659      */
 660     public abstract Mask<Byte> lessThan(byte s);
 661 
 662     @Override
 663     public abstract Mask<Byte> lessThanEq(Vector<Byte> v);
 664 
 665     /**
 666      * Tests if this vector is less or equal to the broadcast of an input scalar.
 667      * <p>
 668      * This is a vector binary test operation where the primitive less than
 669      * or equal to operation ({@code <=}) is applied to lane elements.
 670      *
 671      * @param s the input scalar
 672      * @return the mask result of testing if this vector is less than or equal
 673      * to the broadcast of an input scalar
 674      */
 675     public abstract Mask<Byte> lessThanEq(byte s);
 676 
 677     @Override
 678     public abstract Mask<Byte> greaterThan(Vector<Byte> v);
 679 
 680     /**
 681      * Tests if this vector is greater than the broadcast of an input scalar.
 682      * <p>
 683      * This is a vector binary test operation where the primitive greater than
 684      * operation ({@code >}) is applied to lane elements.
 685      *
 686      * @param s the input scalar
 687      * @return the mask result of testing if this vector is greater than the
 688      * broadcast of an input scalar
 689      */
 690     public abstract Mask<Byte> greaterThan(byte s);
 691 
 692     @Override
 693     public abstract Mask<Byte> greaterThanEq(Vector<Byte> v);
 694 
 695     /**
 696      * Tests if this vector is greater than or equal to the broadcast of an
 697      * input scalar.
 698      * <p>
 699      * This is a vector binary test operation where the primitive greater than
 700      * or equal to operation ({@code >=}) is applied to lane elements.
 701      *
 702      * @param s the input scalar
 703      * @return the mask result of testing if this vector is greater than or
 704      * equal to the broadcast of an input scalar
 705      */
 706     public abstract Mask<Byte> greaterThanEq(byte s);
 707 
 708     @Override
 709     public abstract ByteVector blend(Vector<Byte> v, Mask<Byte> m);
 710 
 711     /**
 712      * Blends the lane elements of this vector with those of the broadcast of an
 713      * input scalar, selecting lanes controlled by a mask.
 714      * <p>
 715      * For each lane of the mask, at lane index {@code N}, if the mask lane
 716      * is set then the lane element at {@code N} from the input vector is
 717      * selected and placed into the resulting vector at {@code N},
 718      * otherwise the the lane element at {@code N} from this input vector is
 719      * selected and placed into the resulting vector at {@code N}.
 720      *
 721      * @param s the input scalar
 722      * @param m the mask controlling lane selection
 723      * @return the result of blending the lane elements of this vector with
 724      * those of the broadcast of an input scalar
 725      */
 726     public abstract ByteVector blend(byte s, Mask<Byte> m);
 727 
 728     @Override
 729     public abstract ByteVector rearrange(Vector<Byte> v,
 730                                                       Shuffle<Byte> s, Mask<Byte> m);
 731 
 732     @Override
 733     public abstract ByteVector rearrange(Shuffle<Byte> m);
 734 
 735     @Override
 736     public abstract ByteVector reshape(Species<Byte> s);
 737 
 738     @Override
 739     public abstract ByteVector rotateEL(int i);
 740 
 741     @Override
 742     public abstract ByteVector rotateER(int i);
 743 
 744     @Override
 745     public abstract ByteVector shiftEL(int i);
 746 
 747     @Override
 748     public abstract ByteVector shiftER(int i);
 749 
 750 
 751 
 752     /**
 753      * Bitwise ANDs this vector with an input vector.
 754      * <p>
 755      * This is a vector binary operation where the primitive bitwise AND
 756      * operation ({@code &}) is applied to lane elements.
 757      *
 758      * @param v the input vector
 759      * @return the bitwise AND of this vector with the input vector
 760      */
 761     public abstract ByteVector and(Vector<Byte> v);
 762 
 763     /**
 764      * Bitwise ANDs this vector with the broadcast of an input scalar.
 765      * <p>
 766      * This is a vector binary operation where the primitive bitwise AND
 767      * operation ({@code &}) is applied to lane elements.
 768      *
 769      * @param s the input scalar
 770      * @return the bitwise AND of this vector with the broadcast of an input
 771      * scalar
 772      */
 773     public abstract ByteVector and(byte s);
 774 
 775     /**
 776      * Bitwise ANDs this vector with an input vector, selecting lane elements
 777      * controlled by a mask.
 778      * <p>
 779      * This is a vector binary operation where the primitive bitwise AND
 780      * operation ({@code &}) is applied to lane elements.
 781      *
 782      * @param v the input vector
 783      * @param m the mask controlling lane selection
 784      * @return the bitwise AND of this vector with the input vector
 785      */
 786     public abstract ByteVector and(Vector<Byte> v, Mask<Byte> m);
 787 
 788     /**
 789      * Bitwise ANDs this vector with the broadcast of an input scalar, selecting
 790      * lane elements controlled by a mask.
 791      * <p>
 792      * This is a vector binary operation where the primitive bitwise AND
 793      * operation ({@code &}) is applied to lane elements.
 794      *
 795      * @param s the input scalar
 796      * @param m the mask controlling lane selection
 797      * @return the bitwise AND of this vector with the broadcast of an input
 798      * scalar
 799      */
 800     public abstract ByteVector and(byte s, Mask<Byte> m);
 801 
 802     /**
 803      * Bitwise ORs this vector with an input vector.
 804      * <p>
 805      * This is a vector binary operation where the primitive bitwise OR
 806      * operation ({@code |}) is applied to lane elements.
 807      *
 808      * @param v the input vector
 809      * @return the bitwise OR of this vector with the input vector
 810      */
 811     public abstract ByteVector or(Vector<Byte> v);
 812 
 813     /**
 814      * Bitwise ORs this vector with the broadcast of an input scalar.
 815      * <p>
 816      * This is a vector binary operation where the primitive bitwise OR
 817      * operation ({@code |}) is applied to lane elements.
 818      *
 819      * @param s the input scalar
 820      * @return the bitwise OR of this vector with the broadcast of an input
 821      * scalar
 822      */
 823     public abstract ByteVector or(byte s);
 824 
 825     /**
 826      * Bitwise ORs this vector with an input vector, selecting lane elements
 827      * controlled by a mask.
 828      * <p>
 829      * This is a vector binary operation where the primitive bitwise OR
 830      * operation ({@code |}) is applied to lane elements.
 831      *
 832      * @param v the input vector
 833      * @param m the mask controlling lane selection
 834      * @return the bitwise OR of this vector with the input vector
 835      */
 836     public abstract ByteVector or(Vector<Byte> v, Mask<Byte> m);
 837 
 838     /**
 839      * Bitwise ORs this vector with the broadcast of an input scalar, selecting
 840      * lane elements controlled by a mask.
 841      * <p>
 842      * This is a vector binary operation where the primitive bitwise OR
 843      * operation ({@code |}) is applied to lane elements.
 844      *
 845      * @param s the input scalar
 846      * @param m the mask controlling lane selection
 847      * @return the bitwise OR of this vector with the broadcast of an input
 848      * scalar
 849      */
 850     public abstract ByteVector or(byte s, Mask<Byte> m);
 851 
 852     /**
 853      * Bitwise XORs this vector with an input vector.
 854      * <p>
 855      * This is a vector binary operation where the primitive bitwise XOR
 856      * operation ({@code ^}) is applied to lane elements.
 857      *
 858      * @param v the input vector
 859      * @return the bitwise XOR of this vector with the input vector
 860      */
 861     public abstract ByteVector xor(Vector<Byte> v);
 862 
 863     /**
 864      * Bitwise XORs this vector with the broadcast of an input scalar.
 865      * <p>
 866      * This is a vector binary operation where the primitive bitwise XOR
 867      * operation ({@code ^}) is applied to lane elements.
 868      *
 869      * @param s the input scalar
 870      * @return the bitwise XOR of this vector with the broadcast of an input
 871      * scalar
 872      */
 873     public abstract ByteVector xor(byte s);
 874 
 875     /**
 876      * Bitwise XORs this vector with an input vector, selecting lane elements
 877      * controlled by a mask.
 878      * <p>
 879      * This is a vector binary operation where the primitive bitwise XOR
 880      * operation ({@code ^}) is applied to lane elements.
 881      *
 882      * @param v the input vector
 883      * @param m the mask controlling lane selection
 884      * @return the bitwise XOR of this vector with the input vector
 885      */
 886     public abstract ByteVector xor(Vector<Byte> v, Mask<Byte> m);
 887 
 888     /**
 889      * Bitwise XORs this vector with the broadcast of an input scalar, selecting
 890      * lane elements controlled by a mask.
 891      * <p>
 892      * This is a vector binary operation where the primitive bitwise XOR
 893      * operation ({@code ^}) is applied to lane elements.
 894      *
 895      * @param s the input scalar
 896      * @param m the mask controlling lane selection
 897      * @return the bitwise XOR of this vector with the broadcast of an input
 898      * scalar
 899      */
 900     public abstract ByteVector xor(byte s, Mask<Byte> m);
 901 
 902     /**
 903      * Bitwise NOTs this vector.
 904      * <p>
 905      * This is a vector unary operation where the primitive bitwise NOT
 906      * operation ({@code ~}) is applied to lane elements.
 907      *
 908      * @return the bitwise NOT of this vector
 909      */
 910     public abstract ByteVector not();
 911 
 912     /**
 913      * Bitwise NOTs this vector, selecting lane elements controlled by a mask.
 914      * <p>
 915      * This is a vector unary operation where the primitive bitwise NOT
 916      * operation ({@code ~}) is applied to lane elements.
 917      *
 918      * @param m the mask controlling lane selection
 919      * @return the bitwise NOT of this vector
 920      */
 921     public abstract ByteVector not(Mask<Byte> m);
 922 
 923     /**
 924      * Logically left shifts this vector by the broadcast of an input scalar.
 925      * <p>
 926      * This is a vector binary operation where the primitive logical left shift
 927      * operation ({@code <<}) is applied to lane elements to left shift the
 928      * element by shift value as specified by the input scalar. Only the 3
 929      * lowest-order bits of shift value are used. It is as if the shift value
 930      * were subjected to a bitwise logical AND operator & with the mask value 0x7.
 931      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
 932      *
 933      * @param s the input scalar; the number of the bits to left shift
 934      * @return the result of logically left shifting left this vector by the
 935      * broadcast of an input scalar
 936      */
 937     public abstract ByteVector shiftL(int s);
 938 
 939     /**
 940      * Logically left shifts this vector by the broadcast of an input scalar,
 941      * selecting lane elements controlled by a mask.
 942      * <p>
 943      * This is a vector binary operation where the primitive logical left shift
 944      * operation ({@code <<}) is applied to lane elements to left shift the
 945      * element by shift value as specified by the input scalar. Only the 3
 946      * lowest-order bits of shift value are used. It is as if the shift value
 947      * were subjected to a bitwise logical AND operator & with the mask value 0x7.
 948      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
 949      *
 950      * @param s the input scalar; the number of the bits to left shift
 951      * @param m the mask controlling lane selection
 952      * @return the result of logically left shifting left this vector by the
 953      * broadcast of an input scalar
 954      */
 955     public abstract ByteVector shiftL(int s, Mask<Byte> m);
 956 
 957 
 958     // logical, or unsigned, shift right
 959 
 960      /**
 961      * Logically right shifts (or unsigned right shifts) this vector by the
 962      * broadcast of an input scalar.
 963      * <p>
 964      * This is a vector binary operation where the primitive logical right shift
 965      * operation ({@code >>>}) is applied to lane elements to logically right shift the
 966      * element by shift value as specified by the input scalar. Only the 3
 967      * lowest-order bits of shift value are used. It is as if the shift value
 968      * were subjected to a bitwise logical AND operator & with the mask value 0x7.
 969      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
 970      *
 971      * @param s the input scalar; the number of the bits to right shift
 972      * @return the result of logically right shifting this vector by the
 973      * broadcast of an input scalar
 974      */
 975     public abstract ByteVector shiftR(int s);
 976 
 977      /**
 978      * Logically right shifts (or unsigned right shifts) this vector by the
 979      * broadcast of an input scalar, selecting lane elements controlled by a
 980      * mask.
 981      * <p>
 982      * This is a vector binary operation where the primitive logical right shift
 983      * operation ({@code >>>}) is applied to lane elements to logically right shift the
 984      * element by shift value as specified by the input scalar. Only the 3
 985      * lowest-order bits of shift value are used. It is as if the shift value
 986      * were subjected to a bitwise logical AND operator & with the mask value 0x7.
 987      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
 988      *
 989      * @param s the input scalar; the number of the bits to right shift
 990      * @return the result of logically right shifting this vector by the
 991      * broadcast of an input scalar
 992      */
 993     public abstract ByteVector shiftR(int s, Mask<Byte> m);
 994 
 995 
 996     /**
 997      * Arithmetically right shifts (or signed right shifts) this vector by the
 998      * broadcast of an input scalar.
 999      * <p>
1000      * This is a vector binary operation where the primitive arithmetic right
1001      * shift operation ({@code >>}) is applied to lane elements  to arithmetically
1002      * right shift the element by shift value as specified by the input scalar.
1003      * Only the 3 lowest-order bits of shift value are used. It is as if the shift
1004      * value were subjected to a bitwise logical AND operator & with the mask value 0x7.
1005      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
1006      *
1007      * @param s the input scalar; the number of the bits to right shift
1008      * @return the result of arithmetically right shifting this vector by the
1009      * broadcast of an input scalar
1010      */
1011     public abstract ByteVector aShiftR(int s);
1012 
1013     /**
1014      * Arithmetically right shifts (or signed right shifts) this vector by the
1015      * broadcast of an input scalar, selecting lane elements controlled by a
1016      * mask.
1017      * <p>
1018      * This is a vector binary operation where the primitive arithmetic right
1019      * shift operation ({@code >>}) is applied to lane elements  to arithmetically
1020      * right shift the element by shift value as specified by the input scalar.
1021      * Only the 3 lowest-order bits of shift value are used. It is as if the shift
1022      * value were subjected to a bitwise logical AND operator & with the mask value 0x7.
1023      * The shift distance actually used is therefore always in the range 0 to 7, inclusive.
1024      *
1025      * @param s the input scalar; the number of the bits to right shift
1026      * @param m the mask controlling lane selection
1027      * @return the result of arithmetically right shifting this vector by the
1028      * broadcast of an input scalar
1029      */
1030     public abstract ByteVector aShiftR(int s, Mask<Byte> m);
1031 
1032 
1033     @Override
1034     public abstract void intoByteArray(byte[] a, int ix);
1035 
1036     @Override
1037     public abstract void intoByteArray(byte[] a, int ix, Mask<Byte> m);
1038 
1039     @Override
1040     public abstract void intoByteBuffer(ByteBuffer bb, int ix);
1041 
1042     @Override
1043     public abstract void intoByteBuffer(ByteBuffer bb, int ix, Mask<Byte> m);
1044 
1045 
1046     // Type specific horizontal reductions
1047 
1048     /**
1049      * Adds all lane elements of this vector.
1050      * <p>
1051      * This is an associative vector reduction operation where the addition
1052      * operation ({@code +}) is applied to lane elements,
1053      * and the identity value is {@code 0}.
1054      *
1055      * @return the addition of all the lane elements of this vector
1056      */
1057     public abstract byte addAll();
1058 
1059     /**
1060      * Adds all lane elements of this vector, selecting lane elements
1061      * controlled by a mask.
1062      * <p>
1063      * This is an associative vector reduction operation where the addition
1064      * operation ({@code +}) is applied to lane elements,
1065      * and the identity value is {@code 0}.
1066      *
1067      * @param m the mask controlling lane selection
1068      * @return the addition of all the lane elements of this vector
1069      */
1070     public abstract byte addAll(Mask<Byte> m);
1071 
1072     /**
1073      * Subtracts all lane elements of this vector.
1074      * <p>
1075      * This is an associative vector reduction operation where the subtraction
1076      * operation ({@code -}) is applied to lane elements,
1077      * and the identity value is {@code 0}.
1078      *
1079      * @return the subtraction of all the lane elements of this vector
1080      */
1081     public abstract byte subAll();
1082 
1083     /**
1084      * Subtracts all lane elements of this vector, selecting lane elements
1085      * controlled by a mask.
1086      * <p>
1087      * This is an associative vector reduction operation where the subtraction
1088      * operation ({@code -}) is applied to lane elements,
1089      * and the identity value is {@code 0}.
1090      *
1091      * @param m the mask controlling lane selection
1092      * @return the subtraction of all the lane elements of this vector
1093      */
1094     public abstract byte subAll(Mask<Byte> m);
1095 
1096     /**
1097      * Multiplies all lane elements of this vector.
1098      * <p>
1099      * This is an associative vector reduction operation where the
1100      * multiplication operation ({@code *}) is applied to lane elements,
1101      * and the identity value is {@code 1}.
1102      *
1103      * @return the multiplication of all the lane elements of this vector
1104      */
1105     public abstract byte mulAll();
1106 
1107     /**
1108      * Multiplies all lane elements of this vector, selecting lane elements
1109      * controlled by a mask.
1110      * <p>
1111      * This is an associative vector reduction operation where the
1112      * multiplication operation ({@code *}) is applied to lane elements,
1113      * and the identity value is {@code 1}.
1114      *
1115      * @param m the mask controlling lane selection
1116      * @return the multiplication of all the lane elements of this vector
1117      */
1118     public abstract byte mulAll(Mask<Byte> m);
1119 
1120     /**
1121      * Returns the minimum lane element of this vector.
1122      * <p>
1123      * This is an associative vector reduction operation where the operation
1124      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements,
1125      * and the identity value is {@link Byte#MAX_VALUE}.
1126      *
1127      * @return the minimum lane element of this vector
1128      */
1129     public abstract byte minAll();
1130 
1131     /**
1132      * Returns the minimum lane element of this vector, selecting lane elements
1133      * controlled by a mask.
1134      * <p>
1135      * This is an associative vector reduction operation where the operation
1136      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements,
1137      * and the identity value is {@link Byte#MAX_VALUE}.
1138      *
1139      * @param m the mask controlling lane selection
1140      * @return the minimum lane element of this vector
1141      */
1142     public abstract byte minAll(Mask<Byte> m);
1143 
1144     /**
1145      * Returns the maximum lane element of this vector.
1146      * <p>
1147      * This is an associative vector reduction operation where the operation
1148      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements,
1149      * and the identity value is {@link Byte#MIN_VALUE}.
1150      *
1151      * @return the maximum lane element of this vector
1152      */
1153     public abstract byte maxAll();
1154 
1155     /**
1156      * Returns the maximum lane element of this vector, selecting lane elements
1157      * controlled by a mask.
1158      * <p>
1159      * This is an associative vector reduction operation where the operation
1160      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements,
1161      * and the identity value is {@link Byte#MIN_VALUE}.
1162      *
1163      * @param m the mask controlling lane selection
1164      * @return the maximum lane element of this vector
1165      */
1166     public abstract byte maxAll(Mask<Byte> m);
1167 
1168     /**
1169      * Logically ORs all lane elements of this vector.
1170      * <p>
1171      * This is an associative vector reduction operation where the logical OR
1172      * operation ({@code |}) is applied to lane elements,
1173      * and the identity value is {@code 0}.
1174      *
1175      * @return the logical OR all the lane elements of this vector
1176      */
1177     public abstract byte orAll();
1178 
1179     /**
1180      * Logically ORs all lane elements of this vector, selecting lane elements
1181      * controlled by a mask.
1182      * <p>
1183      * This is an associative vector reduction operation where the logical OR
1184      * operation ({@code |}) is applied to lane elements,
1185      * and the identity value is {@code 0}.
1186      *
1187      * @param m the mask controlling lane selection
1188      * @return the logical OR all the lane elements of this vector
1189      */
1190     public abstract byte orAll(Mask<Byte> m);
1191 
1192     /**
1193      * Logically ANDs all lane elements of this vector.
1194      * <p>
1195      * This is an associative vector reduction operation where the logical AND
1196      * operation ({@code |}) is applied to lane elements,
1197      * and the identity value is {@code -1}.
1198      *
1199      * @return the logical AND all the lane elements of this vector
1200      */
1201     public abstract byte andAll();
1202 
1203     /**
1204      * Logically ANDs all lane elements of this vector, selecting lane elements
1205      * controlled by a mask.
1206      * <p>
1207      * This is an associative vector reduction operation where the logical AND
1208      * operation ({@code |}) is applied to lane elements,
1209      * and the identity value is {@code -1}.
1210      *
1211      * @param m the mask controlling lane selection
1212      * @return the logical AND all the lane elements of this vector
1213      */
1214     public abstract byte andAll(Mask<Byte> m);
1215 
1216     /**
1217      * Logically XORs all lane elements of this vector.
1218      * <p>
1219      * This is an associative vector reduction operation where the logical XOR
1220      * operation ({@code ^}) is applied to lane elements,
1221      * and the identity value is {@code 0}.
1222      *
1223      * @return the logical XOR all the lane elements of this vector
1224      */
1225     public abstract byte xorAll();
1226 
1227     /**
1228      * Logically XORs all lane elements of this vector, selecting lane elements
1229      * controlled by a mask.
1230      * <p>
1231      * This is an associative vector reduction operation where the logical XOR
1232      * operation ({@code ^}) is applied to lane elements,
1233      * and the identity value is {@code 0}.
1234      *
1235      * @param m the mask controlling lane selection
1236      * @return the logical XOR all the lane elements of this vector
1237      */
1238     public abstract byte xorAll(Mask<Byte> m);
1239 
1240     // Type specific accessors
1241 
1242     /**
1243      * Gets the lane element at lane index {@code i}
1244      *
1245      * @param i the lane index
1246      * @return the lane element at lane index {@code i}
1247      * @throws IllegalArgumentException if the index is is out of range
1248      * ({@code < 0 || >= length()})
1249      */
1250     public abstract byte get(int i);
1251 
1252     /**
1253      * Replaces the lane element of this vector at lane index {@code i} with
1254      * value {@code e}.
1255      * <p>
1256      * This is a cross-lane operation and behaves as if it returns the result
1257      * of blending this vector with an input vector that is the result of
1258      * broadcasting {@code e} and a mask that has only one lane set at lane
1259      * index {@code i}.
1260      *
1261      * @param i the lane index of the lane element to be replaced
1262      * @param e the value to be placed
1263      * @return the result of replacing the lane element of this vector at lane
1264      * index {@code i} with value {@code e}.
1265      * @throws IllegalArgumentException if the index is is out of range
1266      * ({@code < 0 || >= length()})
1267      */
1268     public abstract ByteVector with(int i, byte e);
1269 
1270     // Type specific extractors
1271 
1272     /**
1273      * Returns an array containing the lane elements of this vector.
1274      * <p>
1275      * This method behaves as if it {@link #intoArray(byte[], int)} stores}
1276      * this vector into an allocated array and returns the array as follows:
1277      * <pre>{@code
1278      *   byte[] a = new byte[this.length()];
1279      *   this.intoArray(a, 0);
1280      *   return a;
1281      * }</pre>
1282      *
1283      * @return an array containing the the lane elements of this vector
1284      */
1285     @ForceInline
1286     public final byte[] toArray() {
1287         byte[] a = new byte[species().length()];
1288         intoArray(a, 0);
1289         return a;
1290     }
1291 
1292     /**
1293      * Stores this vector into an array starting at offset.
1294      * <p>
1295      * For each vector lane, where {@code N} is the vector lane index,
1296      * the lane element at index {@code N} is stored into the array at index
1297      * {@code i + N}.
1298      *
1299      * @param a the array
1300      * @param i the offset into the array
1301      * @throws IndexOutOfBoundsException if {@code i < 0}, or
1302      * {@code i > a.length - this.length()}
1303      */
1304     public abstract void intoArray(byte[] a, int i);
1305 
1306     /**
1307      * Stores this vector into an array starting at offset and using a mask.
1308      * <p>
1309      * For each vector lane, where {@code N} is the vector lane index,
1310      * if the mask lane at index {@code N} is set then the lane element at
1311      * index {@code N} is stored into the array index {@code i + N}.
1312      *
1313      * @param a the array
1314      * @param i the offset into the array
1315      * @param m the mask
1316      * @throws IndexOutOfBoundsException if {@code i < 0}, or
1317      * for any vector lane index {@code N} where the mask at lane {@code N}
1318      * is set {@code i >= a.length - N}
1319      */
1320     public abstract void intoArray(byte[] a, int i, Mask<Byte> m);
1321 
1322     /**
1323      * Stores this vector into an array using indexes obtained from an index
1324      * map.
1325      * <p>
1326      * For each vector lane, where {@code N} is the vector lane index, the
1327      * lane element at index {@code N} is stored into the array at index
1328      * {@code i + indexMap[j + N]}.
1329      *
1330      * @param a the array
1331      * @param i the offset into the array, may be negative if relative
1332      * indexes in the index map compensate to produce a value within the
1333      * array bounds
1334      * @param indexMap the index map
1335      * @param j the offset into the index map
1336      * @throws IndexOutOfBoundsException if {@code j < 0}, or
1337      * {@code j > indexMap.length - this.length()},
1338      * or for any vector lane index {@code N} the result of
1339      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
1340      */
1341     public void intoArray(byte[] a, int i, int[] indexMap, int j) {
1342         forEach((n, e) -> a[i + indexMap[j + n]] = e);
1343     }
1344 
1345     /**
1346      * Stores this vector into an array using indexes obtained from an index
1347      * map and using a mask.
1348      * <p>
1349      * For each vector lane, where {@code N} is the vector lane index,
1350      * if the mask lane at index {@code N} is set then the lane element at
1351      * index {@code N} is stored into the array at index
1352      * {@code i + indexMap[j + N]}.
1353      *
1354      * @param a the array
1355      * @param i the offset into the array, may be negative if relative
1356      * indexes in the index map compensate to produce a value within the
1357      * array bounds
1358      * @param m the mask
1359      * @param indexMap the index map
1360      * @param j the offset into the index map
1361      * @throws IndexOutOfBoundsException if {@code j < 0}, or
1362      * {@code j > indexMap.length - this.length()},
1363      * or for any vector lane index {@code N} where the mask at lane
1364      * {@code N} is set the result of {@code i + indexMap[j + N]} is
1365      * {@code < 0} or {@code >= a.length}
1366      */
1367     public void intoArray(byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) {
1368         forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
1369     }
1370     // Species
1371 
1372     @Override
1373     public abstract ByteSpecies species();
1374 
1375     /**
1376      * A specialized factory for creating {@link ByteVector} value of the same
1377      * shape, and a {@link Mask} and {@link Shuffle} values of the same shape
1378      * and {@code int} element type.
1379      */
1380     public static abstract class ByteSpecies extends Vector.Species<Byte> {
1381         interface FOp {
1382             byte apply(int i);
1383         }
1384 
1385         abstract ByteVector op(FOp f);
1386 
1387         abstract ByteVector op(Mask<Byte> m, FOp f);
1388 
1389         interface FOpm {
1390             boolean apply(int i);
1391         }
1392 
1393         abstract Mask<Byte> opm(FOpm f);
1394 
1395 
1396 
1397         // Factories
1398 
1399         @Override
1400         public abstract ByteVector zero();
1401 
1402         /**
1403          * Returns a vector where all lane elements are set to the primitive
1404          * value {@code e}.
1405          *
1406          * @param e the value
1407          * @return a vector of vector where all lane elements are set to
1408          * the primitive value {@code e}
1409          */
1410         public abstract ByteVector broadcast(byte e);
1411 
1412         /**
1413          * Returns a vector where the first lane element is set to the primtive
1414          * value {@code e}, all other lane elements are set to the default
1415          * value.
1416          *
1417          * @param e the value
1418          * @return a vector where the first lane element is set to the primitive
1419          * value {@code e}
1420          */
1421         @ForceInline
1422         public final ByteVector single(byte e) {
1423             return zero().with(0, e);
1424         }
1425 
1426         /**
1427          * Returns a vector where each lane element is set to a randomly
1428          * generated primitive value.
1429          *
1430          * The semantics are equivalent to calling
1431          * {@link (byte)ThreadLocalRandom#nextInt() }
1432          *
1433          * @return a vector where each lane elements is set to a randomly
1434          * generated primitive value
1435          */
1436         public ByteVector random() {
1437             ThreadLocalRandom r = ThreadLocalRandom.current();
1438             return op(i -> (byte) r.nextInt());
1439         }
1440 
1441         /**
1442          * Returns a vector where each lane element is set to a given
1443          * primitive value.
1444          * <p>
1445          * For each vector lane, where {@code N} is the vector lane index, the
1446          * the primitive value at index {@code N} is placed into the resulting
1447          * vector at lane index {@code N}.
1448          *
1449          * @param es the given primitive values
1450          * @return a vector where each lane element is set to a given primitive
1451          * value
1452          * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
1453          */
1454         public abstract ByteVector scalars(byte... es);
1455     }
1456 
1457     /**
1458      * Finds the preferred species for an element type of {@code byte}.
1459      * <p>
1460      * A preferred species is a species chosen by the platform that has a
1461      * shape of maximal bit size.  A preferred species for different element
1462      * types will have the same shape, and therefore vectors, masks, and
1463      * shuffles created from such species will be shape compatible.
1464      *
1465      * @return the preferred species for an element type of {@code byte}
1466      */
1467     @SuppressWarnings("unchecked")
1468     public static ByteSpecies preferredSpecies() {
1469         return (ByteSpecies) Species.ofPreferred(byte.class);
1470     }
1471 
1472     /**
1473      * Finds a species for an element type of {@code byte} and shape.
1474      *
1475      * @param s the shape
1476      * @return a species for an element type of {@code byte} and shape
1477      * @throws IllegalArgumentException if no such species exists for the shape
1478      */
1479     @SuppressWarnings("unchecked")
1480     public static ByteSpecies species(Vector.Shape s) {
1481         Objects.requireNonNull(s);
1482         switch (s) {
1483             case S_64_BIT: return Byte64Vector.SPECIES;
1484             case S_128_BIT: return Byte128Vector.SPECIES;
1485             case S_256_BIT: return Byte256Vector.SPECIES;
1486             case S_512_BIT: return Byte512Vector.SPECIES;
1487             case S_Max_BIT: return ByteMaxVector.SPECIES;
1488             default: throw new IllegalArgumentException("Bad shape: " + s);
1489         }
1490     }
1491 }