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