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