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 jdk.internal.vm.annotation.ForceInline;
  28 
  29 import java.nio.ByteBuffer;
  30 import java.nio.ByteOrder;
  31 import java.nio.ShortBuffer;
  32 import java.util.Objects;
  33 import java.util.concurrent.ThreadLocalRandom;
  34 
  35 
  36 /**
  37  * A specialized {@link Vector} representing an ordered immutable sequence of
  38  * {@code short} values.
  39  *
  40  * @param <S> the type of shape of this vector
  41  */
  42 @SuppressWarnings("cast")
  43 public abstract class ShortVector<S extends Vector.Shape> extends Vector<Short,S> {
  44 
  45     ShortVector() {}
  46 
  47     // Unary operator
  48 
  49     interface FUnOp {
  50         short apply(int i, short a);
  51     }
  52 
  53     abstract ShortVector<S> uOp(FUnOp f);
  54 
  55     abstract ShortVector<S> uOp(Mask<Short, S> m, FUnOp f);
  56 
  57     // Binary operator
  58 
  59     interface FBinOp {
  60         short apply(int i, short a, short b);
  61     }
  62 
  63     abstract ShortVector<S> bOp(Vector<Short,S> o, FBinOp f);
  64 
  65     abstract ShortVector<S> bOp(Vector<Short,S> o, Mask<Short, S> m, FBinOp f);
  66 
  67     // Trinary operator
  68 
  69     interface FTriOp {
  70         short apply(int i, short a, short b, short c);
  71     }
  72 
  73     abstract ShortVector<S> tOp(Vector<Short,S> o1, Vector<Short,S> o2, FTriOp f);
  74 
  75     abstract ShortVector<S> tOp(Vector<Short,S> o1, Vector<Short,S> o2, Mask<Short, S> m, FTriOp f);
  76 
  77     // Reduction operator
  78 
  79     abstract short rOp(short v, FBinOp f);
  80 
  81     // Binary test
  82 
  83     interface FBinTest {
  84         boolean apply(int i, short a, short b);
  85     }
  86 
  87     abstract Mask<Short, S> bTest(Vector<Short,S> o, FBinTest f);
  88 
  89     // Foreach
  90 
  91     interface FUnCon {
  92         void apply(int i, short a);
  93     }
  94 
  95     abstract void forEach(FUnCon f);
  96 
  97     abstract void forEach(Mask<Short, S> m, FUnCon f);
  98 
  99     //
 100 
 101     @Override
 102     public ShortVector<S> add(Vector<Short,S> o) {
 103         return bOp(o, (i, a, b) -> (short) (a + b));
 104     }
 105 
 106     /**
 107      * Adds this vector to the result of broadcasting an input scalar.
 108      * <p>
 109      * This is a vector binary operation where the primitive addition operation
 110      * ({@code +}) is applied to lane elements.
 111      *
 112      * @param b the input scalar
 113      * @return the result of adding this vector to the broadcast of an input
 114      * scalar
 115      */
 116     public abstract ShortVector<S> add(short b);
 117 
 118     @Override
 119     public ShortVector<S> add(Vector<Short,S> o, Mask<Short, S> m) {
 120         return bOp(o, m, (i, a, b) -> (short) (a + b));
 121     }
 122 
 123     /**
 124      * Adds this vector to the result of broadcasting an input scalar,
 125      * selecting lane elements controlled by a mask.
 126      * <p>
 127      * This is a vector binary operation where the primitive addition operation
 128      * ({@code +}) is applied to lane elements.
 129      *
 130      * @param b the input vector
 131      * @param m the mask controlling lane selection
 132      * @return the result of adding this vector to the broadcast of an input
 133      * scalar
 134      */
 135     public abstract ShortVector<S> add(short b, Mask<Short, S> m);
 136 
 137     @Override
 138     public ShortVector<S> addSaturate(Vector<Short,S> o) {
 139         return bOp(o, (i, a, b) -> (short) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b));
 140     }
 141 
 142     public abstract ShortVector<S> addSaturate(short o);
 143 
 144     @Override
 145     public ShortVector<S> addSaturate(Vector<Short,S> o, Mask<Short, S> m) {
 146         return bOp(o, m, (i, a, b) -> (short) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b));
 147     }
 148 
 149     public abstract ShortVector<S> addSaturate(short o, Mask<Short, S> m);
 150 
 151     @Override
 152     public ShortVector<S> sub(Vector<Short,S> o) {
 153         return bOp(o, (i, a, b) -> (short) (a - b));
 154     }
 155 
 156     public abstract ShortVector<S> sub(short o);
 157 
 158     @Override
 159     public ShortVector<S> sub(Vector<Short,S> o, Mask<Short, S> m) {
 160         return bOp(o, m, (i, a, b) -> (short) (a - b));
 161     }
 162 
 163     public abstract ShortVector<S> sub(short o, Mask<Short, S> m);
 164 
 165     @Override
 166     public ShortVector<S> subSaturate(Vector<Short,S> o) {
 167         return bOp(o, (i, a, b) -> (short) ((a >= Integer.MIN_VALUE || Integer.MIN_VALUE + b > a) ? Integer.MAX_VALUE : a - b));
 168     }
 169 
 170     public abstract ShortVector<S> subSaturate(short o);
 171 
 172     @Override
 173     public ShortVector<S> subSaturate(Vector<Short,S> o, Mask<Short, S> m) {
 174         return bOp(o, m, (i, a, b) -> (short) ((a >= Integer.MIN_VALUE || Integer.MIN_VALUE + b > a) ? Integer.MAX_VALUE : a - b));
 175     }
 176 
 177     public abstract ShortVector<S> subSaturate(short o, Mask<Short, S> m);
 178 
 179     @Override
 180     public ShortVector<S> mul(Vector<Short,S> o) {
 181         return bOp(o, (i, a, b) -> (short) (a * b));
 182     }
 183 
 184     public abstract ShortVector<S> mul(short o);
 185 
 186     @Override
 187     public ShortVector<S> mul(Vector<Short,S> o, Mask<Short, S> m) {
 188         return bOp(o, m, (i, a, b) -> (short) (a * b));
 189     }
 190 
 191     public abstract ShortVector<S> mul(short o, Mask<Short, S> m);
 192 
 193     @Override
 194     public ShortVector<S> neg() {
 195         return uOp((i, a) -> (short) (-a));
 196     }
 197 
 198     @Override
 199     public ShortVector<S> neg(Mask<Short, S> m) {
 200         return uOp(m, (i, a) -> (short) (-a));
 201     }
 202 
 203     @Override
 204     public ShortVector<S> abs() {
 205         return uOp((i, a) -> (short) Math.abs(a));
 206     }
 207 
 208     @Override
 209     public ShortVector<S> abs(Mask<Short, S> m) {
 210         return uOp(m, (i, a) -> (short) Math.abs(a));
 211     }
 212 
 213     @Override
 214     public ShortVector<S> min(Vector<Short,S> o) {
 215         return bOp(o, (i, a, b) -> (a <= b) ? a : b);
 216     }
 217 
 218     public abstract ShortVector<S> min(short o);
 219 
 220     @Override
 221     public ShortVector<S> max(Vector<Short,S> o) {
 222         return bOp(o, (i, a, b) -> (a >= b) ? a : b);
 223     }
 224 
 225     public abstract ShortVector<S> max(short o);
 226 
 227     @Override
 228     public Mask<Short, S> equal(Vector<Short,S> o) {
 229         return bTest(o, (i, a, b) -> a == b);
 230     }
 231 
 232     public abstract Mask<Short, S> equal(short o);
 233 
 234     @Override
 235     public Mask<Short, S> notEqual(Vector<Short,S> o) {
 236         return bTest(o, (i, a, b) -> a != b);
 237     }
 238 
 239     public abstract Mask<Short, S> notEqual(short o);
 240 
 241     @Override
 242     public Mask<Short, S> lessThan(Vector<Short,S> o) {
 243         return bTest(o, (i, a, b) -> a < b);
 244     }
 245 
 246     public abstract Mask<Short, S> lessThan(short o);
 247 
 248     @Override
 249     public Mask<Short, S> lessThanEq(Vector<Short,S> o) {
 250         return bTest(o, (i, a, b) -> a <= b);
 251     }
 252 
 253     public abstract Mask<Short, S> lessThanEq(short o);
 254 
 255     @Override
 256     public Mask<Short, S> greaterThan(Vector<Short,S> o) {
 257         return bTest(o, (i, a, b) -> a > b);
 258     }
 259 
 260     public abstract Mask<Short, S> greaterThan(short o);
 261 
 262     @Override
 263     public Mask<Short, S> greaterThanEq(Vector<Short,S> o) {
 264         return bTest(o, (i, a, b) -> a >= b);
 265     }
 266 
 267     public abstract Mask<Short, S> greaterThanEq(short o);
 268 
 269     @Override
 270     public ShortVector<S> blend(Vector<Short,S> o, Mask<Short, S> m) {
 271         return bOp(o, (i, a, b) -> m.getElement(i) ? b : a);
 272     }
 273 
 274     public abstract ShortVector<S> blend(short o, Mask<Short, S> m);
 275 
 276     @Override
 277     public abstract ShortVector<S> shuffle(Vector<Short,S> o, Shuffle<Short, S> m);
 278 
 279     @Override
 280     public abstract ShortVector<S> swizzle(Shuffle<Short, S> m);
 281 
 282     @Override
 283     @ForceInline
 284     public <T extends Shape> ShortVector<T> resize(Species<Short, T> species) {
 285         return (ShortVector<T>) species.reshape(this);
 286     }
 287 
 288     @Override
 289     public abstract ShortVector<S> rotateEL(int i);
 290 
 291     @Override
 292     public abstract ShortVector<S> rotateER(int i);
 293 
 294     @Override
 295     public abstract ShortVector<S> shiftEL(int i);
 296 
 297     @Override
 298     public abstract ShortVector<S> shiftER(int i);
 299 
 300 
 301     public ShortVector<S> and(Vector<Short,S> o) {
 302         return bOp(o, (i, a, b) -> (short) (a & b));
 303     }
 304 
 305     public abstract ShortVector<S> and(short o);
 306 
 307     public ShortVector<S> and(Vector<Short,S> o, Mask<Short, S> m) {
 308         return bOp(o, m, (i, a, b) -> (short) (a & b));
 309     }
 310 
 311     public abstract ShortVector<S> and(short o, Mask<Short, S> m);
 312 
 313     public ShortVector<S> or(Vector<Short,S> o) {
 314         return bOp(o, (i, a, b) -> (short) (a | b));
 315     }
 316 
 317     public abstract ShortVector<S> or(short o);
 318 
 319     public ShortVector<S> or(Vector<Short,S> o, Mask<Short, S> m) {
 320         return bOp(o, m, (i, a, b) -> (short) (a | b));
 321     }
 322 
 323     public abstract ShortVector<S> or(short o, Mask<Short, S> m);
 324 
 325     public ShortVector<S> xor(Vector<Short,S> o) {
 326         return bOp(o, (i, a, b) -> (short) (a ^ b));
 327     }
 328 
 329     public abstract ShortVector<S> xor(short o);
 330 
 331     public ShortVector<S> xor(Vector<Short,S> o, Mask<Short, S> m) {
 332         return bOp(o, m, (i, a, b) -> (short) (a ^ b));
 333     }
 334 
 335     public abstract ShortVector<S> xor(short o, Mask<Short, S> m);
 336 
 337     public ShortVector<S> not() {
 338         return uOp((i, a) -> (short) (~a));
 339     }
 340 
 341     public ShortVector<S> not(Mask<Short, S> m) {
 342         return uOp(m, (i, a) -> (short) (~a));
 343     }
 344 
 345     // logical shift left
 346     public ShortVector<S> shiftL(int s) {
 347         return uOp((i, a) -> (short) (a << s));
 348     }
 349 
 350     public ShortVector<S> shiftL(int s, Mask<Short, S> m) {
 351         return uOp(m, (i, a) -> (short) (a << s));
 352     }
 353 
 354 
 355     // logical, or unsigned, shift right
 356     public ShortVector<S> shiftR(int s) {
 357         return uOp((i, a) -> (short) (a >>> s));
 358     }
 359 
 360     public ShortVector<S> shiftR(int s, Mask<Short, S> m) {
 361         return uOp(m, (i, a) -> (short) (a >>> s));
 362     }
 363 
 364 
 365     // arithmetic, or signed, shift right
 366     public ShortVector<S> aShiftR(int s) {
 367         return uOp((i, a) -> (short) (a >> s));
 368     }
 369 
 370     public ShortVector<S> aShiftR(int s, Mask<Short, S> m) {
 371         return uOp(m, (i, a) -> (short) (a >> s));
 372     }
 373 
 374 
 375     public ShortVector<S> rotateL(int j) {
 376         return uOp((i, a) -> (short) Integer.rotateLeft(a, j));
 377     }
 378 
 379     public ShortVector<S> rotateR(int j) {
 380         return uOp((i, a) -> (short) Integer.rotateRight(a, j));
 381     }
 382 
 383     @Override
 384     public void intoByteArray(byte[] a, int ix) {
 385         ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder());
 386         intoByteBuffer(bb);
 387     }
 388 
 389     @Override
 390     public void intoByteArray(byte[] a, int ix, Mask<Short, S> m) {
 391         ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder());
 392         intoByteBuffer(bb, m);
 393     }
 394 
 395     @Override
 396     public void intoByteBuffer(ByteBuffer bb) {
 397         ShortBuffer fb = bb.asShortBuffer();
 398         forEach((i, a) -> fb.put(a));
 399     }
 400 
 401     @Override
 402     public void intoByteBuffer(ByteBuffer bb, Mask<Short, S> m) {
 403         ShortBuffer fb = bb.asShortBuffer();
 404         forEach((i, a) -> {
 405             if (m.getElement(i))
 406                 fb.put(a);
 407             else
 408                 fb.position(fb.position() + 1);
 409         });
 410     }
 411 
 412     @Override
 413     public void intoByteBuffer(ByteBuffer bb, int ix) {
 414         bb = bb.duplicate().position(ix);
 415         ShortBuffer fb = bb.asShortBuffer();
 416         forEach((i, a) -> fb.put(i, a));
 417     }
 418 
 419     @Override
 420     public void intoByteBuffer(ByteBuffer bb, int ix, Mask<Short, S> m) {
 421         bb = bb.duplicate().position(ix);
 422         ShortBuffer fb = bb.asShortBuffer();
 423         forEach(m, (i, a) -> fb.put(i, a));
 424     }
 425 
 426 
 427     // Type specific horizontal reductions
 428 
 429     /**
 430      * Sums all lane elements of this vector.
 431      * <p>
 432      * This is an associative vector reduction operation where the addition
 433      * operation ({@code +}) is applied to lane elements, and the identity value
 434      * is {@code 0}.
 435      *
 436      * @return the sum of all the lane elements of this vector
 437      */
 438     public short addAll() {
 439         return rOp((short) 0, (i, a, b) -> (short) (a + b));
 440     }
 441 
 442     public short subAll() {
 443         return rOp((short) 0, (i, a, b) -> (short) (a - b));
 444     }
 445 
 446     public short mulAll() {
 447         return rOp((short) 1, (i, a, b) -> (short) (a * b));
 448     }
 449 
 450     public short minAll() {
 451         return rOp(Short.MAX_VALUE, (i, a, b) -> a > b ? b : a);
 452     }
 453 
 454     public short maxAll() {
 455         return rOp(Short.MIN_VALUE, (i, a, b) -> a < b ? b : a);
 456     }
 457 
 458     public short orAll() {
 459         return rOp((short) 0, (i, a, b) -> (short) (a | b));
 460     }
 461 
 462     public short andAll() {
 463         return rOp((short) -1, (i, a, b) -> (short) (a & b));
 464     }
 465 
 466     public short xorAll() {
 467         return rOp((short) 0, (i, a, b) -> (short) (a ^ b));
 468     }
 469 
 470     // Type specific accessors
 471 
 472     /**
 473      * Gets the lane element at lane index {@code i}
 474      *
 475      * @param i the lane index
 476      * @return the lane element at lane index {@code i}
 477      */
 478     public abstract short get(int i);
 479 
 480     /**
 481      * Replaces the lane element of this vector at lane index {@code i} with
 482      * value {@code e}.
 483      * <p>
 484      * This is a cross-lane operation and behaves it returns the result of
 485      * blending this vector with an input vector that is the result of
 486      * broadcasting {@code e} and a mask that has only one lane set at lane
 487      * index {@code i}.
 488      *
 489      * @param i the lane index of the lane element to be replaced
 490      * @param e the value to be placed
 491      * @return the result of replacing the lane element of this vector at lane
 492      * index {@code i} with value {@code e}.
 493      */
 494     public abstract ShortVector<S> with(int i, short e);
 495 
 496     // Type specific extractors
 497 
 498     /**
 499      * Returns an array containing the lane elements of this vector.
 500      * <p>
 501      * This method behaves as if it {@link #intoArray(short[], int)} stores}
 502      * this vector into an allocated array and returns the array as follows:
 503      * <pre>{@code
 504      *   short[] a = new short[this.length()];
 505      *   this.intoArray(a, 0);
 506      *   return a;
 507      * }</pre>
 508      *
 509      * @return an array containing the the lane elements of this vector
 510      */
 511     @ForceInline
 512     public short[] toArray() {
 513         short[] a = new short[species().length()];
 514         intoArray(a, 0);
 515         return a;
 516     }
 517 
 518     /**
 519      * Stores this vector into an array starting at offset.
 520      * <p>
 521      * For each vector lane, where {@code N} is the vector lane index,
 522      * the lane element at index {@code N} is stored into the array at index
 523      * {@code i + N}.
 524      *
 525      * @param a the array
 526      * @param i the offset into the array
 527      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 528      * {@code i > a.length - this.length()}
 529      */
 530     public void intoArray(short[] a, int i) {
 531         forEach((n, e) -> a[i + n] = e);
 532     }
 533 
 534     /**
 535      * Stores this vector into an array starting at offset and using a mask.
 536      * <p>
 537      * For each vector lane, where {@code N} is the vector lane index,
 538      * if the mask lane at index {@code N} is set then the lane element at
 539      * index {@code N} is stored into the array index {@code i + N}.
 540      *
 541      * @param a the array
 542      * @param i the offset into the array
 543      * @param m the mask
 544      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 545      * for any vector lane index {@code N} where the mask at lane {@code N}
 546      * is set {@code i >= a.length - N}
 547      */
 548     public void intoArray(short[] a, int i, Mask<Short, S> m) {
 549         forEach(m, (n, e) -> a[i + n] = e);
 550     }
 551 
 552     /**
 553      * Stores this vector into an array using indexes obtained from an index
 554      * map.
 555      * <p>
 556      * For each vector lane, where {@code N} is the vector lane index, the
 557      * lane element at index {@code N} is stored into the array at index
 558      * {@code i + indexMap[j + N]}.
 559      *
 560      * @param a the array
 561      * @param i the offset into the array, may be negative if relative
 562      * indexes in the index map compensate to produce a value within the
 563      * array bounds
 564      * @param indexMap the index map
 565      * @param j the offset into the index map
 566      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 567      * {@code j > indexMap.length - this.length()},
 568      * or for any vector lane index {@code N} the result of
 569      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 570      */
 571     public void intoArray(short[] a, int i, int[] indexMap, int j) {
 572         forEach((n, e) -> a[i + indexMap[j + n]] = e);
 573     }
 574 
 575     /**
 576      * Stores this vector into an array using indexes obtained from an index
 577      * map and using a mask.
 578      * <p>
 579      * For each vector lane, where {@code N} is the vector lane index,
 580      * if the mask lane at index {@code N} is set then the lane element at
 581      * index {@code N} is stored into the array at index
 582      * {@code i + indexMap[j + N]}.
 583      *
 584      * @param a the array
 585      * @param i the offset into the array, may be negative if relative
 586      * indexes in the index map compensate to produce a value within the
 587      * array bounds
 588      * @param m the mask
 589      * @param indexMap the index map
 590      * @param j the offset into the index map
 591      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 592      * {@code j > indexMap.length - this.length()},
 593      * or for any vector lane index {@code N} where the mask at lane
 594      * {@code N} is set the result of {@code i + indexMap[j + N]} is
 595      * {@code < 0} or {@code >= a.length}
 596      */
 597     public void intoArray(short[] a, int i, Mask<Short, S> m, int[] indexMap, int j) {
 598         forEach(m, (n, e) -> a[i + indexMap[j + n]] = e);
 599     }
 600 
 601     // Species
 602 
 603     @Override
 604     public abstract ShortSpecies<S> species();
 605 
 606     /**
 607      * A specialized factory for creating {@link ShortVector} value of the same
 608      * shape, and a {@link Mask} and {@link Shuffle} values of the same shape
 609      * and {@code int} element type.
 610      *
 611      * @param <S> the type of shape of this species
 612      */
 613     public static abstract class ShortSpecies<S extends Vector.Shape> extends Vector.Species<Short, S> {
 614         interface FOp {
 615             short apply(int i);
 616         }
 617 
 618         abstract ShortVector<S> op(FOp f);
 619 
 620         abstract ShortVector<S> op(Mask<Short, S> m, FOp f);
 621 
 622         // Factories
 623 
 624         @Override
 625         public ShortVector<S> zero() {
 626             return op(i -> 0);
 627         }
 628 
 629         /**
 630          * Returns a vector where all lane elements are set to the primitive
 631          * value {@code e}.
 632          *
 633          * @param e the value
 634          * @return a vector of vector where all lane elements are set to
 635          * the primitive value {@code e}
 636          */
 637         public ShortVector<S> broadcast(short e) {
 638             return op(i -> e);
 639         }
 640 
 641         /**
 642          * Returns a vector where the first lane element is set to the primtive
 643          * value {@code e}, all other lane elements are set to the default
 644          * value.
 645          *
 646          * @param e the value
 647          * @return a vector where the first lane element is set to the primitive
 648          * value {@code e}
 649          */
 650         public ShortVector<S> single(short e) {
 651             return op(i -> i == 0 ? e : (short) 0);
 652         }
 653 
 654         /**
 655          * Returns a vector where each lane element is set to a randomly
 656          * generated primitive value.
 657          * @@@ what are the properties of the random number generator?
 658          *
 659          * @return a vector where each lane elements is set to a randomly
 660          * generated primitive value
 661          */
 662         public ShortVector<S> random() {
 663             ThreadLocalRandom r = ThreadLocalRandom.current();
 664             return op(i -> (short) r.nextInt());
 665         }
 666 
 667         /**
 668          * Returns a vector where each lane element is set to a given
 669          * primitive value.
 670          * <p>
 671          * For each vector lane, where {@code N} is the vector lane index, the
 672          * the primitive value at index {@code N} is placed into the resulting
 673          * vector at lane index {@code N}.
 674          *
 675          * @@@ What should happen if es.length < this.length() ? use the default
 676          * value or throw IndexOutOfBoundsException
 677          *
 678          * @param es the given primitive values
 679          * @return a vector where each lane element is set to a given primitive
 680          * value
 681          */
 682         public ShortVector<S> scalars(short... es) {
 683             return op(i -> es[i]);
 684         }
 685 
 686         /**
 687          * Loads a vector from an array starting at offset.
 688          * <p>
 689          * For each vector lane, where {@code N} is the vector lane index, the
 690          * array element at index {@code i + N} is placed into the
 691          * resulting vector at lane index {@code N}.
 692          *
 693          * @param a the array
 694          * @param i the offset into the array
 695          * @return the vector loaded from an array
 696          * @throws IndexOutOfBoundsException if {@code i < 0}, or
 697          * {@code i > a.length - this.length()}
 698          */
 699         public ShortVector<S> fromArray(short[] a, int i) {
 700             return op(n -> a[i + n]);
 701         }
 702 
 703         /**
 704          * Loads a vector from an array starting at offset and using a mask.
 705          * <p>
 706          * For each vector lane, where {@code N} is the vector lane index,
 707          * if the mask lane at index {@code N} is set then the array element at
 708          * index {@code i + N} is placed into the resulting vector at lane index
 709          * {@code N}, otherwise the default element value is placed into the
 710          * resulting vector at lane index {@code N}.
 711          *
 712          * @param a the array
 713          * @param i the offset into the array
 714          * @param m the mask
 715          * @return the vector loaded from an array
 716          * @throws IndexOutOfBoundsException if {@code i < 0}, or
 717          * for any vector lane index {@code N} where the mask at lane {@code N}
 718          * is set {@code i > a.length - N}
 719          */
 720         public ShortVector<S> fromArray(short[] a, int i, Mask<Short, S> m) {
 721             return op(m, n -> a[i + n]);
 722         }
 723 
 724         /**
 725          * Loads a vector from an array using indexes obtained from an index
 726          * map.
 727          * <p>
 728          * For each vector lane, where {@code N} is the vector lane index, the
 729          * array element at index {@code i + indexMap[j + N]} is placed into the
 730          * resulting vector at lane index {@code N}.
 731          *
 732          * @param a the array
 733          * @param i the offset into the array, may be negative if relative
 734          * indexes in the index map compensate to produce a value within the
 735          * array bounds
 736          * @param indexMap the index map
 737          * @param j the offset into the index map
 738          * @return the vector loaded from an array
 739          * @throws IndexOutOfBoundsException if {@code j < 0}, or
 740          * {@code j > indexMap.length - this.length()},
 741          * or for any vector lane index {@code N} the result of
 742          * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 743          */
 744         public ShortVector<S> fromArray(short[] a, int i, int[] indexMap, int j) {
 745             return op(n -> a[i + indexMap[j + n]]);
 746         }
 747 
 748         /**
 749          * Loads a vector from an array using indexes obtained from an index
 750          * map and using a mask.
 751          * <p>
 752          * For each vector lane, where {@code N} is the vector lane index,
 753          * if the mask lane at index {@code N} is set then the array element at
 754          * index {@code i + indexMap[j + N]} is placed into the resulting vector
 755          * at lane index {@code N}.
 756          *
 757          * @param a the array
 758          * @param i the offset into the array, may be negative if relative
 759          * indexes in the index map compensate to produce a value within the
 760          * array bounds
 761          * @param indexMap the index map
 762          * @param j the offset into the index map
 763          * @return the vector loaded from an array
 764          * @throws IndexOutOfBoundsException if {@code j < 0}, or
 765          * {@code j > indexMap.length - this.length()},
 766          * or for any vector lane index {@code N} where the mask at lane
 767          * {@code N} is set the result of {@code i + indexMap[j + N]} is
 768          * {@code < 0} or {@code >= a.length}
 769          */
 770         public ShortVector<S> fromArray(short[] a, int i, Mask<Short, S> m, int[] indexMap, int j) {
 771             return op(m, n -> a[i + indexMap[j + n]]);
 772         }
 773 
 774         @Override
 775         public ShortVector<S> fromByteArray(byte[] a, int ix) {
 776             ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder());
 777             return fromByteBuffer(bb);
 778         }
 779 
 780         @Override
 781         public ShortVector<S> fromByteArray(byte[] a, int ix, Mask<Short, S> m) {
 782             ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder());
 783             return fromByteBuffer(bb, m);
 784         }
 785 
 786         @Override
 787         public ShortVector<S> fromByteBuffer(ByteBuffer bb) {
 788             ShortBuffer fb = bb.asShortBuffer();
 789             return op(i -> fb.get());
 790         }
 791 
 792         @Override
 793         public ShortVector<S> fromByteBuffer(ByteBuffer bb, Mask<Short, S> m) {
 794             ShortBuffer fb = bb.asShortBuffer();
 795             return op(i -> {
 796                 if(m.getElement(i))
 797                     return fb.get();
 798                 else {
 799                     fb.position(fb.position() + 1);
 800                     return (short) 0;
 801                 }
 802             });
 803         }
 804 
 805         @Override
 806         public ShortVector<S> fromByteBuffer(ByteBuffer bb, int ix) {
 807             bb = bb.duplicate().order(ByteOrder.nativeOrder()).position(ix);
 808             ShortBuffer fb = bb.asShortBuffer();
 809             return op(i -> fb.get(i));
 810         }
 811 
 812         @Override
 813         public ShortVector<S> fromByteBuffer(ByteBuffer bb, int ix, Mask<Short, S> m) {
 814             bb = bb.duplicate().order(ByteOrder.nativeOrder()).position(ix);
 815             ShortBuffer fb = bb.asShortBuffer();
 816             return op(m, i -> fb.get(i));
 817         }
 818 
 819         @Override
 820         public <F, T extends Shape> ShortVector<S> reshape(Vector<F, T> o) {
 821             int blen = Math.max(o.species().bitSize(), bitSize()) / Byte.SIZE;
 822             ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder());
 823             o.intoByteBuffer(bb, 0);
 824             return fromByteBuffer(bb, 0);
 825         }
 826 
 827         @Override
 828         @ForceInline
 829         public <F> ShortVector<S> rebracket(Vector<F, S> o) {
 830             return reshape(o);
 831         }
 832 
 833         @Override
 834         @ForceInline
 835         public <T extends Shape> ShortVector<S> resize(Vector<Short, T> o) {
 836             return reshape(o);
 837         }
 838 
 839         @Override
 840         @SuppressWarnings("unchecked")
 841         public <F, T extends Shape> ShortVector<S> cast(Vector<F, T> v) {
 842             // Allocate array of required size
 843             short[] a = new short[length()];
 844 
 845             Class<?> vtype = v.species().elementType();
 846             int limit = Math.min(v.species().length(), length());
 847             if (vtype == byte.class) {
 848                 ByteVector<T> tv = (ByteVector<T>)v;
 849                 for (int i = 0; i < limit; i++) {
 850                     a[i] = (short) tv.get(i);
 851                 }
 852             } else if (vtype == short.class) {
 853                 ShortVector<T> tv = (ShortVector<T>)v;
 854                 for (int i = 0; i < limit; i++) {
 855                     a[i] = (short) tv.get(i);
 856                 }
 857             } else if (vtype == int.class) {
 858                 IntVector<T> tv = (IntVector<T>)v;
 859                 for (int i = 0; i < limit; i++) {
 860                     a[i] = (short) tv.get(i);
 861                 }
 862             } else if (vtype == long.class){
 863                 LongVector<T> tv = (LongVector<T>)v;
 864                 for (int i = 0; i < limit; i++) {
 865                     a[i] = (short) tv.get(i);
 866                 }
 867             } else if (vtype == float.class){
 868                 FloatVector<T> tv = (FloatVector<T>)v;
 869                 for (int i = 0; i < limit; i++) {
 870                     a[i] = (short) tv.get(i);
 871                 }
 872             } else if (vtype == double.class){
 873                 DoubleVector<T> tv = (DoubleVector<T>)v;
 874                 for (int i = 0; i < limit; i++) {
 875                     a[i] = (short) tv.get(i);
 876                 }
 877             } else {
 878                 throw new UnsupportedOperationException("Bad lane type for casting.");
 879             }
 880 
 881             return scalars(a);
 882         }
 883 
 884     }
 885 
 886     /**
 887      * Finds the preferred species for an element type of {@code short}.
 888      * <p>
 889      * A preferred species is a species chosen by the platform that has a
 890      * shape of maximal bit size.  A preferred species for different element
 891      * types will have the same shape, and therefore vectors, masks, and
 892      * shuffles created from such species will be shape compatible.
 893      *
 894      * @return the preferred species for an element type of {@code short}
 895      */
 896     @SuppressWarnings("unchecked")
 897     public static ShortSpecies<?> preferredSpeciesInstance() {
 898         return (ShortSpecies<?>) Vector.preferredSpeciesInstance(short.class);
 899     }
 900 
 901     /**
 902      * Finds a species for an element type of {@code short} and shape.
 903      *
 904      * @param s the shape
 905      * @param <S> the type of shape
 906      * @return a species for an element type of {@code short} and shape
 907      * @throws IllegalArgumentException if no such species exists for the shape
 908      */
 909     @SuppressWarnings("unchecked")
 910     public static <S extends Shape> ShortSpecies<S> speciesInstance(S s) {
 911         Objects.requireNonNull(s);
 912         if (s == Shapes.S_64_BIT) {
 913             return (ShortSpecies<S>) Short64Vector.SPECIES;
 914         } else if (s == Shapes.S_128_BIT) {
 915             return (ShortSpecies<S>) Short128Vector.SPECIES;
 916         } else if (s == Shapes.S_256_BIT) {
 917             return (ShortSpecies<S>) Short256Vector.SPECIES;
 918         } else if (s == Shapes.S_512_BIT) {
 919             return (ShortSpecies<S>) Short512Vector.SPECIES;
 920         } else {
 921             throw new IllegalArgumentException("Bad shape: " + s);
 922         }
 923     }
 924 }