1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.util.Arrays;
  29 import java.util.Objects;
  30 import jdk.internal.vm.annotation.ForceInline;
  31 import static jdk.incubator.vector.VectorIntrinsics.*;
  32 
  33 @SuppressWarnings("cast")
  34 final class $vectortype$ extends $abstractvectortype$<Shapes.$shape$> {
  35     static final $Type$$bits$Species SPECIES = new $Type$$bits$Species();
  36 
  37     static final $vectortype$ ZERO = new $vectortype$();
  38 
  39     static final int LENGTH = SPECIES.length();
  40 
  41     private final $type$[] vec; // Don't access directly, use getElements() instead.
  42 
  43     private $type$[] getElements() {
  44         return VectorIntrinsics.maybeRebox(this).vec;
  45     }
  46 
  47     $vectortype$() {
  48         vec = new $type$[SPECIES.length()];
  49     }
  50 
  51     $vectortype$($type$[] v) {
  52         vec = v;
  53     }
  54 
  55     @Override
  56     public int length() { return LENGTH; }
  57 
  58     // Unary operator
  59 
  60     @Override
  61     $vectortype$ uOp(FUnOp f) {
  62         $type$[] vec = getElements();
  63         $type$[] res = new $type$[length()];
  64         for (int i = 0; i < length(); i++) {
  65             res[i] = f.apply(i, vec[i]);
  66         }
  67         return new $vectortype$(res);
  68     }
  69 
  70     @Override
  71     $vectortype$ uOp(Mask<$Boxtype$, Shapes.$shape$> o, FUnOp f) {
  72         $type$[] vec = getElements();
  73         $type$[] res = new $type$[length()];
  74         boolean[] mbits = (($masktype$)o).getBits();
  75         for (int i = 0; i < length(); i++) {
  76             res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i];
  77         }
  78         return new $vectortype$(res);
  79     }
  80 
  81     // Binary operator
  82 
  83     @Override
  84     $vectortype$ bOp(Vector<$Boxtype$, Shapes.$shape$> o, FBinOp f) {
  85         $type$[] res = new $type$[length()];
  86         $type$[] vec1 = this.getElements();
  87         $type$[] vec2 = (($vectortype$)o).getElements();
  88         for (int i = 0; i < length(); i++) {
  89             res[i] = f.apply(i, vec1[i], vec2[i]);
  90         }
  91         return new $vectortype$(res);
  92     }
  93 
  94     @Override
  95     $vectortype$ bOp(Vector<$Boxtype$, Shapes.$shape$> o1, Mask<$Boxtype$, Shapes.$shape$> o2, FBinOp f) {
  96         $type$[] res = new $type$[length()];
  97         $type$[] vec1 = this.getElements();
  98         $type$[] vec2 = (($vectortype$)o1).getElements();
  99         boolean[] mbits = (($masktype$)o2).getBits();
 100         for (int i = 0; i < length(); i++) {
 101             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i];
 102         }
 103         return new $vectortype$(res);
 104     }
 105 
 106     // Trinary operator
 107 
 108     @Override
 109     $vectortype$ tOp(Vector<$Boxtype$, Shapes.$shape$> o1, Vector<$Boxtype$, Shapes.$shape$> o2, FTriOp f) {
 110         $type$[] res = new $type$[length()];
 111         $type$[] vec1 = this.getElements();
 112         $type$[] vec2 = (($vectortype$)o1).getElements();
 113         $type$[] vec3 = (($vectortype$)o2).getElements();
 114         for (int i = 0; i < length(); i++) {
 115             res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]);
 116         }
 117         return new $vectortype$(res);
 118     }
 119 
 120     @Override
 121     $vectortype$ tOp(Vector<$Boxtype$, Shapes.$shape$> o1, Vector<$Boxtype$, Shapes.$shape$> o2, Mask<$Boxtype$, Shapes.$shape$> o3, FTriOp f) {
 122         $type$[] res = new $type$[length()];
 123         $type$[] vec1 = getElements();
 124         $type$[] vec2 = (($vectortype$)o1).getElements();
 125         $type$[] vec3 = (($vectortype$)o2).getElements();
 126         boolean[] mbits = (($masktype$)o3).getBits();
 127         for (int i = 0; i < length(); i++) {
 128             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i];
 129         }
 130         return new $vectortype$(res);
 131     }
 132 
 133     @Override
 134     $type$ rOp($type$ v, FBinOp f) {
 135         $type$[] vec = getElements();
 136         for (int i = 0; i < length(); i++) {
 137             v = f.apply(i, v, vec[i]);
 138         }
 139         return v;
 140     }
 141 
 142     // Binary operations with scalars
 143 
 144     @Override
 145     @ForceInline
 146     public $abstractvectortype$<Shapes.$shape$> add($type$ o) {
 147         return add(SPECIES.broadcast(o));
 148     }
 149 
 150     @Override
 151     @ForceInline
 152     public $abstractvectortype$<Shapes.$shape$> add($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 153         return add(SPECIES.broadcast(o), m);
 154     }
 155 
 156     @Override
 157     @ForceInline
 158     public $abstractvectortype$<Shapes.$shape$> addSaturate($type$ o) {
 159         return addSaturate(SPECIES.broadcast(o));
 160     }
 161 
 162     @Override
 163     @ForceInline
 164     public $abstractvectortype$<Shapes.$shape$> addSaturate($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 165         return addSaturate(SPECIES.broadcast(o), m);
 166     }
 167 
 168     @Override
 169     @ForceInline
 170     public $abstractvectortype$<Shapes.$shape$> sub($type$ o) {
 171         return sub(SPECIES.broadcast(o));
 172     }
 173 
 174     @Override
 175     @ForceInline
 176     public $abstractvectortype$<Shapes.$shape$> sub($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 177         return sub(SPECIES.broadcast(o), m);
 178     }
 179 
 180     @Override
 181     @ForceInline
 182     public $abstractvectortype$<Shapes.$shape$> subSaturate($type$ o) {
 183         return subSaturate(SPECIES.broadcast(o));
 184     }
 185 
 186     @Override
 187     @ForceInline
 188     public $abstractvectortype$<Shapes.$shape$> subSaturate($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 189         return subSaturate(SPECIES.broadcast(o), m);
 190     }
 191 
 192     @Override
 193     @ForceInline
 194     public $abstractvectortype$<Shapes.$shape$> mul($type$ o) {
 195         return mul(SPECIES.broadcast(o));
 196     }
 197 
 198     @Override
 199     @ForceInline
 200     public $abstractvectortype$<Shapes.$shape$> mul($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 201         return mul(SPECIES.broadcast(o), m);
 202     }
 203 
 204     @Override
 205     @ForceInline
 206     public $abstractvectortype$<Shapes.$shape$> min($type$ o) {
 207         return min(SPECIES.broadcast(o));
 208     }
 209 
 210     @Override
 211     @ForceInline
 212     public $abstractvectortype$<Shapes.$shape$> max($type$ o) {
 213         return max(SPECIES.broadcast(o));
 214     }
 215 
 216     @Override
 217     @ForceInline
 218     public Mask<$Boxtype$, Shapes.$shape$> equal($type$ o) {
 219         return equal(SPECIES.broadcast(o));
 220     }
 221 
 222     @Override
 223     @ForceInline
 224     public Mask<$Boxtype$, Shapes.$shape$> notEqual($type$ o) {
 225         return notEqual(SPECIES.broadcast(o));
 226     }
 227 
 228     @Override
 229     @ForceInline
 230     public Mask<$Boxtype$, Shapes.$shape$> lessThan($type$ o) {
 231         return lessThan(SPECIES.broadcast(o));
 232     }
 233 
 234     @Override
 235     @ForceInline
 236     public Mask<$Boxtype$, Shapes.$shape$> lessThanEq($type$ o) {
 237         return lessThanEq(SPECIES.broadcast(o));
 238     }
 239 
 240     @Override
 241     @ForceInline
 242     public Mask<$Boxtype$, Shapes.$shape$> greaterThan($type$ o) {
 243         return greaterThan(SPECIES.broadcast(o));
 244     }
 245 
 246     @Override
 247     @ForceInline
 248     public Mask<$Boxtype$, Shapes.$shape$> greaterThanEq($type$ o) {
 249         return greaterThanEq(SPECIES.broadcast(o));
 250     }
 251 
 252     @Override
 253     @ForceInline
 254     public $abstractvectortype$<Shapes.$shape$> blend($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 255         return blend(SPECIES.broadcast(o), m);
 256     }
 257 
 258 #if[FP]
 259     @Override
 260     @ForceInline
 261     public $abstractvectortype$<Shapes.$shape$> div($type$ o) {
 262         return div(SPECIES.broadcast(o));
 263     }
 264 
 265     @Override
 266     @ForceInline
 267     public $abstractvectortype$<Shapes.$shape$> div($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 268         return div(SPECIES.broadcast(o), m);
 269     }
 270 
 271     @Override
 272     @ForceInline
 273     public $abstractvectortype$<Shapes.$shape$> atan2($type$ o) {
 274         return atan2(SPECIES.broadcast(o));
 275     }
 276 
 277     @Override
 278     @ForceInline
 279     public $abstractvectortype$<Shapes.$shape$> atan2($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 280         return atan2(SPECIES.broadcast(o), m);
 281     }
 282 
 283     @Override
 284     @ForceInline
 285     public $abstractvectortype$<Shapes.$shape$> pow($type$ o) {
 286         return pow(SPECIES.broadcast(o));
 287     }
 288 
 289     @Override
 290     @ForceInline
 291     public $abstractvectortype$<Shapes.$shape$> pow($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 292         return pow(SPECIES.broadcast(o), m);
 293     }
 294 
 295     @Override
 296     @ForceInline
 297     public $abstractvectortype$<Shapes.$shape$> fma($type$ o1, $type$ o2) {
 298         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
 299     }
 300 
 301     @Override
 302     @ForceInline
 303     public $abstractvectortype$<Shapes.$shape$> fma($type$ o1, $type$ o2, Mask<$Boxtype$,Shapes.$shape$> m) {
 304         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
 305     }
 306 
 307     @Override
 308     @ForceInline
 309     public $abstractvectortype$<Shapes.$shape$> hypot($type$ o) {
 310         return hypot(SPECIES.broadcast(o));
 311     }
 312 
 313     @Override
 314     @ForceInline
 315     public $abstractvectortype$<Shapes.$shape$> hypot($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 316         return hypot(SPECIES.broadcast(o), m);
 317     }
 318 #end[FP]
 319 
 320 #if[BITWISE]
 321     @Override
 322     @ForceInline
 323     public $abstractvectortype$<Shapes.$shape$> and($type$ o) {
 324         return and(SPECIES.broadcast(o));
 325     }
 326 
 327     @Override
 328     @ForceInline
 329     public $abstractvectortype$<Shapes.$shape$> and($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 330         return and(SPECIES.broadcast(o), m);
 331     }
 332 
 333     @Override
 334     @ForceInline
 335     public $abstractvectortype$<Shapes.$shape$> or($type$ o) {
 336         return or(SPECIES.broadcast(o));
 337     }
 338 
 339     @Override
 340     @ForceInline
 341     public $abstractvectortype$<Shapes.$shape$> or($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 342         return or(SPECIES.broadcast(o), m);
 343     }
 344 
 345     @Override
 346     @ForceInline
 347     public $abstractvectortype$<Shapes.$shape$> xor($type$ o) {
 348         return xor(SPECIES.broadcast(o));
 349     }
 350 
 351     @Override
 352     @ForceInline
 353     public $abstractvectortype$<Shapes.$shape$> xor($type$ o, Mask<$Boxtype$,Shapes.$shape$> m) {
 354         return xor(SPECIES.broadcast(o), m);
 355     }
 356 #end[BITWISE]
 357 
 358 
 359     // Unary operations
 360 
 361 #if[intOrFP]
 362     @Override
 363     @ForceInline
 364     public $vectortype$ abs() {
 365         return ($vectortype$) VectorIntrinsics.unaryOp(
 366             VECTOR_OP_ABS, $vectortype$.class, $type$.class, LENGTH,
 367             this,
 368             v1 -> (($vectortype$)v1).uOp((i, a) -> ($type$) Math.abs(a)));
 369     }
 370 
 371     @Override
 372     @ForceInline
 373     public $vectortype$ neg() {
 374         return ($vectortype$) VectorIntrinsics.unaryOp(
 375             VECTOR_OP_NEG, $vectortype$.class, $type$.class, LENGTH,
 376             this,
 377             v1 -> (($vectortype$)v1).uOp((i, a) -> ($type$) -a));
 378     }
 379 #end[intOrFP]
 380 
 381 #if[FP]
 382     @Override
 383     @ForceInline
 384     public $vectortype$ div(Vector<$Boxtype$,Shapes.$shape$> o) {
 385         Objects.requireNonNull(o);
 386         $vectortype$ v = ($vectortype$)o;
 387         return ($vectortype$) VectorIntrinsics.binaryOp(
 388             VECTOR_OP_DIV, $vectortype$.class, $type$.class, LENGTH,
 389             this, v,
 390             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a / b)));
 391     }
 392 
 393     @Override
 394     @ForceInline
 395     public $vectortype$ sqrt() {
 396         return ($vectortype$) VectorIntrinsics.unaryOp(
 397             VECTOR_OP_SQRT, $vectortype$.class, $type$.class, LENGTH,
 398             this,
 399             v1 -> (($vectortype$)v1).uOp((i, a) -> ($type$) Math.sqrt((double) a)));
 400     }
 401 #end[FP]
 402 
 403 #if[BITWISE]
 404     @Override
 405     @ForceInline
 406     public $vectortype$ not() {
 407         return ($vectortype$) VectorIntrinsics.unaryOp(
 408             VECTOR_OP_NOT, $vectortype$.class, $type$.class, LENGTH,
 409             this,
 410             v1 -> (($vectortype$)v1).uOp((i, a) -> ($type$) ~a));
 411     }
 412 #end[BITWISE]
 413     // Binary operations
 414 
 415     @Override
 416     @ForceInline
 417     public $vectortype$ add(Vector<$Boxtype$,Shapes.$shape$> o) {
 418         Objects.requireNonNull(o);
 419         $vectortype$ v = ($vectortype$)o;
 420         return ($vectortype$) VectorIntrinsics.binaryOp(
 421             VECTOR_OP_ADD, $vectortype$.class, $type$.class, LENGTH,
 422             this, v,
 423             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a + b)));
 424     }
 425 
 426     @Override
 427     @ForceInline
 428     public $vectortype$ sub(Vector<$Boxtype$,Shapes.$shape$> o) {
 429         Objects.requireNonNull(o);
 430         $vectortype$ v = ($vectortype$)o;
 431         return ($vectortype$) VectorIntrinsics.binaryOp(
 432             VECTOR_OP_SUB, $vectortype$.class, $type$.class, LENGTH,
 433             this, v,
 434             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a - b)));
 435     }
 436 
 437     @Override
 438     @ForceInline
 439     public $vectortype$ mul(Vector<$Boxtype$,Shapes.$shape$> o) {
 440         Objects.requireNonNull(o);
 441         $vectortype$ v = ($vectortype$)o;
 442         return ($vectortype$) VectorIntrinsics.binaryOp(
 443             VECTOR_OP_MUL, $vectortype$.class, $type$.class, LENGTH,
 444             this, v,
 445             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a * b)));
 446     }
 447 
 448 #if[intOrFP]
 449     @Override
 450     @ForceInline
 451     public $vectortype$ add(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 452         // TODO: use better default impl: bOp(o, m, (i, a, b) -> ($type$)(a + b));
 453         return blend(add(v), m);
 454     }
 455 
 456     @Override
 457     @ForceInline
 458     public $vectortype$ sub(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 459         // TODO: use better default impl: bOp(o, m, (i, a, b) -> ($type$)(a - b));
 460         return blend(sub(v), m);
 461     }
 462 
 463     @Override
 464     @ForceInline
 465     public $vectortype$ mul(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 466         // TODO: use better default impl: bOp(o, m, (i, a, b) -> ($type$)(a * b));
 467         return blend(mul(v), m);
 468     }
 469 #end[intOrFP]
 470 
 471 #if[FP]
 472     @Override
 473     @ForceInline
 474     public $vectortype$ div(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 475         // TODO: use better default impl: bOp(o, m, (i, a, b) -> ($type$)(a / b));
 476         return blend(div(v), m);
 477     }
 478 #end[FP]
 479 
 480 #if[BITWISE]
 481     @Override
 482     @ForceInline
 483     public $vectortype$ and(Vector<$Boxtype$,Shapes.$shape$> o) {
 484         Objects.requireNonNull(o);
 485         $vectortype$ v = ($vectortype$)o;
 486         return ($vectortype$) VectorIntrinsics.binaryOp(
 487             VECTOR_OP_AND, $vectortype$.class, $type$.class, LENGTH,
 488             this, v,
 489             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a & b)));
 490     }
 491 
 492     @Override
 493     @ForceInline
 494     public $vectortype$ or(Vector<$Boxtype$,Shapes.$shape$> o) {
 495         Objects.requireNonNull(o);
 496         $vectortype$ v = ($vectortype$)o;
 497         return ($vectortype$) VectorIntrinsics.binaryOp(
 498             VECTOR_OP_OR, $vectortype$.class, $type$.class, LENGTH,
 499             this, v,
 500             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a | b)));
 501     }
 502 
 503     @Override
 504     @ForceInline
 505     public $vectortype$ xor(Vector<$Boxtype$,Shapes.$shape$> o) {
 506         Objects.requireNonNull(o);
 507         $vectortype$ v = ($vectortype$)o;
 508         return ($vectortype$) VectorIntrinsics.binaryOp(
 509             VECTOR_OP_XOR, $vectortype$.class, $type$.class, LENGTH,
 510             this, v,
 511             (v1, v2) -> (($vectortype$)v1).bOp(v2, (i, a, b) -> ($type$)(a ^ b)));
 512     }
 513 
 514     @Override
 515     @ForceInline
 516     public $vectortype$ and(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 517         return blend(and(v), m);
 518     }
 519 
 520     @Override
 521     @ForceInline
 522     public $vectortype$ or(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 523         return blend(or(v), m);
 524     }
 525 
 526     @Override
 527     @ForceInline
 528     public $vectortype$ xor(Vector<$Boxtype$,Shapes.$shape$> v, Mask<$Boxtype$, Shapes.$shape$> m) {
 529         return blend(xor(v), m);
 530     }
 531 
 532     @Override
 533     @ForceInline
 534     public $vectortype$ shiftL(int s) {
 535         return ($vectortype$) VectorIntrinsics.broadcastInt(
 536             VECTOR_OP_LSHIFT, $vectortype$.class, $type$.class, LENGTH,
 537             this, s,
 538             (v, i) -> v.uOp((__, a) -> ($type$) (a << i)));
 539     }
 540 
 541     @Override
 542     @ForceInline
 543     public $vectortype$ shiftR(int s) {
 544         return ($vectortype$) VectorIntrinsics.broadcastInt(
 545             VECTOR_OP_URSHIFT, $vectortype$.class, $type$.class, LENGTH,
 546             this, s,
 547             (v, i) -> v.uOp((__, a) -> ($type$) (a >>> i)));
 548     }
 549 
 550     @Override
 551     @ForceInline
 552     public $vectortype$ aShiftR(int s) {
 553         return ($vectortype$) VectorIntrinsics.broadcastInt(
 554             VECTOR_OP_RSHIFT, $vectortype$.class, $type$.class, LENGTH,
 555             this, s,
 556             (v, i) -> v.uOp((__, a) -> ($type$) (a >> i)));
 557     }
 558 #end[BITWISE]
 559 
 560     // Ternary operations
 561 
 562 #if[FP]
 563     @Override
 564     @ForceInline
 565     public $vectortype$ fma(Vector<$Boxtype$,Shapes.$shape$> o1, Vector<$Boxtype$,Shapes.$shape$> o2) {
 566         Objects.requireNonNull(o1);
 567         Objects.requireNonNull(o2);
 568         $vectortype$ v1 = ($vectortype$)o1;
 569         $vectortype$ v2 = ($vectortype$)o2;
 570         return ($vectortype$) VectorIntrinsics.ternaryOp(
 571             VECTOR_OP_FMA, $vectortype$.class, $type$.class, LENGTH,
 572             this, v1, v2,
 573             (w1, w2, w3) -> w1.tOp(w2, w3, (i, a, b, c) -> Math.fma(a, b, c)));
 574     }
 575 #end[FP]
 576 
 577     // Type specific horizontal reductions
 578 
 579 #if[intOrlong]
 580     @Override
 581     @ForceInline
 582     public $type$ addAll() {
 583         return ($type$) VectorIntrinsics.reductionCoerced(
 584             VECTOR_OP_ADD, $vectortype$.class, $type$.class, LENGTH,
 585             this,
 586             v -> (long) v.rOp(($type$) 0, (i, a, b) -> ($type$) (a + b)));
 587     }
 588 
 589     @Override
 590     @ForceInline
 591     public $type$ mulAll() {
 592         return ($type$) VectorIntrinsics.reductionCoerced(
 593             VECTOR_OP_MUL, $vectortype$.class, $type$.class, LENGTH,
 594             this,
 595             v -> (long) v.rOp(($type$) 1, (i, a, b) -> ($type$) (a * b)));
 596     }
 597 
 598     @Override
 599     @ForceInline
 600     public $type$ andAll() {
 601         return ($type$) VectorIntrinsics.reductionCoerced(
 602             VECTOR_OP_AND, $vectortype$.class, $type$.class, LENGTH,
 603             this,
 604             v -> (long) v.rOp(($type$) -1, (i, a, b) -> ($type$) (a & b)));
 605     }
 606 #end[intOrlong]
 607 #if[FP]
 608     @Override
 609     @ForceInline
 610     public $type$ addAll() {
 611         $bitstype$ bits = ($bitstype$) VectorIntrinsics.reductionCoerced(
 612                                 VECTOR_OP_ADD, $vectortype$.class, $type$.class, LENGTH,
 613                                 this,
 614                                 v -> {
 615                                     $type$ r = v.rOp(($type$) 0, (i, a, b) -> ($type$) (a + b));
 616                                     return (long)$Type$.$type$To$Bitstype$Bits(r);
 617                                 });
 618         return $Type$.$bitstype$BitsTo$Fptype$(bits);
 619     }
 620 
 621     @Override
 622     @ForceInline
 623     public $type$ mulAll() {
 624         $bitstype$ bits = ($bitstype$) VectorIntrinsics.reductionCoerced(
 625                                 VECTOR_OP_MUL, $vectortype$.class, $type$.class, LENGTH,
 626                                 this,
 627                                 v -> {
 628                                     $type$ r = v.rOp(($type$) 1, (i, a, b) -> ($type$) (a * b));
 629                                     return (long)$Type$.$type$To$Bitstype$Bits(r);
 630                                 });
 631         return $Type$.$bitstype$BitsTo$Fptype$(bits);
 632     }
 633 #end[FP]
 634 
 635     // Memory operations
 636 
 637     @Override
 638     @ForceInline
 639     public void intoArray($type$[] a, int ix) {
 640         Objects.requireNonNull(a);
 641         ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
 642         VectorIntrinsics.store($vectortype$.class, $type$.class, LENGTH,
 643                                a, ix, this,
 644                                (arr, idx, v) -> v.forEach((i, a_) -> (($type$[])arr)[idx + i] = a_));
 645     }
 646 
 647     @Override
 648     @ForceInline
 649     public void intoArray($type$[] a, int ax, Mask<$Boxtype$, Shapes.$shape$> m) {
 650         // TODO: use better default impl: forEach(m, (i, a_) -> a[ax + i] = a_);
 651         $vectortype$ oldVal = SPECIES.fromArray(a, ax);
 652         $vectortype$ newVal = oldVal.blend(this, m);
 653         newVal.intoArray(a, ax);
 654     }
 655 
 656     //
 657 
 658     @Override
 659     public String toString() {
 660         return Arrays.toString(getElements());
 661     }
 662 
 663     @Override
 664     public boolean equals(Object o) {
 665         if (this == o) return true;
 666         if (o == null || this.getClass() != o.getClass()) return false;
 667 
 668         $vectortype$ that = ($vectortype$) o;
 669         return Arrays.equals(this.getElements(), that.getElements());
 670     }
 671 
 672     @Override
 673     public int hashCode() {
 674         return Arrays.hashCode(vec);
 675     }
 676 
 677     // Binary test
 678 
 679     @Override
 680     $masktype$ bTest(Vector<$Boxtype$, Shapes.$shape$> o, FBinTest f) {
 681         $type$[] vec1 = getElements();
 682         $type$[] vec2 = (($vectortype$)o).getElements();
 683         boolean[] bits = new boolean[length()];
 684         for (int i = 0; i < length(); i++){
 685             bits[i] = f.apply(i, vec1[i], vec2[i]);
 686         }
 687         return new $masktype$(bits);
 688     }
 689 
 690     // Comparisons
 691 
 692     @Override
 693     @ForceInline
 694     public $masktype$ equal(Vector<$Boxtype$, Shapes.$shape$> o) {
 695         Objects.requireNonNull(o);
 696         $vectortype$ v = ($vectortype$)o;
 697 
 698         return ($masktype$) VectorIntrinsics.compare(
 699             BT_eq, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 700             this, v,
 701             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a == b));
 702     }
 703 
 704     @Override
 705     @ForceInline
 706     public $masktype$ notEqual(Vector<$Boxtype$, Shapes.$shape$> o) {
 707         Objects.requireNonNull(o);
 708         $vectortype$ v = ($vectortype$)o;
 709 
 710         return ($masktype$) VectorIntrinsics.compare(
 711             BT_ne, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 712             this, v,
 713             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a != b));
 714     }
 715 
 716     @Override
 717     @ForceInline
 718     public $masktype$ lessThan(Vector<$Boxtype$, Shapes.$shape$> o) {
 719         Objects.requireNonNull(o);
 720         $vectortype$ v = ($vectortype$)o;
 721 
 722         return ($masktype$) VectorIntrinsics.compare(
 723             BT_lt, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 724             this, v,
 725             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a < b));
 726     }
 727 
 728     @Override
 729     @ForceInline
 730     public $masktype$ lessThanEq(Vector<$Boxtype$, Shapes.$shape$> o) {
 731         Objects.requireNonNull(o);
 732         $vectortype$ v = ($vectortype$)o;
 733 
 734         return ($masktype$) VectorIntrinsics.compare(
 735             BT_le, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 736             this, v,
 737             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a <= b));
 738     }
 739 
 740     @Override
 741     @ForceInline
 742     public $masktype$ greaterThan(Vector<$Boxtype$, Shapes.$shape$> o) {
 743         Objects.requireNonNull(o);
 744         $vectortype$ v = ($vectortype$)o;
 745 
 746         return ($masktype$) VectorIntrinsics.compare(
 747             BT_gt, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 748             this, v,
 749             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a > b));
 750     }
 751 
 752     @Override
 753     @ForceInline
 754     public $masktype$ greaterThanEq(Vector<$Boxtype$, Shapes.$shape$> o) {
 755         Objects.requireNonNull(o);
 756         $vectortype$ v = ($vectortype$)o;
 757 
 758         return ($masktype$) VectorIntrinsics.compare(
 759             BT_ge, $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 760             this, v,
 761             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a >= b));
 762     }
 763 
 764     // Foreach
 765 
 766     @Override
 767     void forEach(FUnCon f) {
 768         $type$[] vec = getElements();
 769         for (int i = 0; i < length(); i++) {
 770             f.apply(i, vec[i]);
 771         }
 772     }
 773 
 774     @Override
 775     void forEach(Mask<$Boxtype$, Shapes.$shape$> o, FUnCon f) {
 776         boolean[] mbits = (($masktype$)o).getBits();
 777         forEach((i, a) -> {
 778             if (mbits[i]) { f.apply(i, a); }
 779         });
 780     }
 781 
 782 #if[FP]
 783     $bitsvectortype$ toBits() {
 784         $type$[] vec = getElements();
 785         $bitstype$[] res = new $bitstype$[this.species().length()];
 786         for(int i = 0; i < this.species().length(); i++){
 787             res[i] = $Type$.$type$To$Bitstype$Bits(vec[i]);
 788         }
 789         return new $bitsvectortype$(res);
 790     }
 791 #end[FP]
 792 
 793 #if[intOrlong]
 794     $fpvectortype$ toFP() {
 795         $type$[] vec = getElements();
 796         $fptype$[] res = new $fptype$[this.species().length()];
 797         for(int i = 0; i < this.species().length(); i++){
 798             res[i] = $Boxfptype$.$bitstype$BitsTo$Fptype$(vec[i]);
 799         }
 800         return new $fpvectortype$(res);
 801     }
 802 #end[intOrlong]
 803 
 804     @Override
 805     public $vectortype$ rotateEL(int j) {
 806         $type$[] vec = getElements();
 807         $type$[] res = new $type$[length()];
 808         for (int i = 0; i < length(); i++){
 809             res[j + i % length()] = vec[i];
 810         }
 811         return new $vectortype$(res);
 812     }
 813 
 814     @Override
 815     public $vectortype$ rotateER(int j) {
 816         $type$[] vec = getElements();
 817         $type$[] res = new $type$[length()];
 818         for (int i = 0; i < length(); i++){
 819             int z = i - j;
 820             if(j < 0) {
 821                 res[length() + z] = vec[i];
 822             } else {
 823                 res[z] = vec[i];
 824             }
 825         }
 826         return new $vectortype$(res);
 827     }
 828 
 829     @Override
 830     public $vectortype$ shiftEL(int j) {
 831         $type$[] vec = getElements();
 832         $type$[] res = new $type$[length()];
 833         for (int i = 0; i < length() - j; i++) {
 834             res[i] = vec[i + j];
 835         }
 836         return new $vectortype$(res);
 837     }
 838 
 839     @Override
 840     public $vectortype$ shiftER(int j) {
 841         $type$[] vec = getElements();
 842         $type$[] res = new $type$[length()];
 843         for (int i = 0; i < length() - j; i++){
 844             res[i + j] = vec[i];
 845         }
 846         return new $vectortype$(res);
 847     }
 848 
 849     @Override
 850     public $vectortype$ shuffle(Vector<$Boxtype$, Shapes.$shape$> o, Shuffle<$Boxtype$, Shapes.$shape$> s) {
 851         $vectortype$ v = ($vectortype$) o;
 852         return uOp((i, a) -> {
 853             $type$[] vec = this.getElements();
 854             int e = s.getElement(i);
 855             if(e >= 0 && e < length()) {
 856                 //from this
 857                 return vec[e];
 858             } else if(e < length() * 2) {
 859                 //from o
 860                 return v.getElements()[e - length()];
 861             } else {
 862                 throw new ArrayIndexOutOfBoundsException("Bad reordering for shuffle");
 863             }
 864         });
 865     }
 866 
 867     @Override
 868     public $vectortype$ swizzle(Shuffle<$Boxtype$, Shapes.$shape$> s) {
 869         return uOp((i, a) -> {
 870             $type$[] vec = this.getElements();
 871             int e = s.getElement(i);
 872             if(e >= 0 && e < length()) {
 873                 return vec[e];
 874             } else {
 875                 throw new ArrayIndexOutOfBoundsException("Bad reordering for shuffle");
 876             }
 877         });
 878     }
 879 
 880     @Override
 881     @ForceInline
 882     public $vectortype$ blend(Vector<$Boxtype$, Shapes.$shape$> o1, Mask<$Boxtype$, Shapes.$shape$> o2) {
 883         Objects.requireNonNull(o1);
 884         Objects.requireNonNull(o2);
 885         $vectortype$ v = ($vectortype$)o1;
 886         $masktype$   m = ($masktype$)o2;
 887 
 888         return ($vectortype$) VectorIntrinsics.blend(
 889             $vectortype$.class, $masktype$.class, $type$.class, LENGTH,
 890             this, v, m,
 891             (v1, v2, m_) -> v1.bOp(v2, (i, a, b) -> m_.getElement(i) ? b : a));
 892     }
 893 
 894     @Override
 895     @ForceInline
 896     @SuppressWarnings("unchecked")
 897     public <F> Vector<F, Shapes.$shape$> rebracket(Species<F, Shapes.$shape$> species) {
 898         Objects.requireNonNull(species);
 899         // TODO: check proper element type
 900         // TODO: update to pass the two species as an arguments and ideally
 901         // push down intrinsic call into species implementation
 902         return VectorIntrinsics.rebracket(
 903             $vectortype$.class, $type$.class, LENGTH,
 904             species.elementType(), this,
 905             (v, t) -> species.reshape(v)
 906         );
 907     }
 908 
 909     // Accessors
 910 
 911     @Override
 912     public $type$ get(int i) {
 913         $type$[] vec = getElements();
 914         return vec[i];
 915     }
 916 
 917     @Override
 918     public $vectortype$ with(int i, $type$ e) {
 919         $type$[] res = vec.clone();
 920         res[i] = e;
 921         return new $vectortype$(res);
 922     }
 923 
 924     // Mask
 925 
 926     static final class $masktype$ extends AbstractMask<$Boxtype$, Shapes.$shape$> {
 927         static final $masktype$ TRUE_MASK = new $masktype$(true);
 928         static final $masktype$ FALSE_MASK = new $masktype$(false);
 929 
 930         // FIXME: was temporarily put here to simplify rematerialization support in the JVM
 931         private final boolean[] bits; // Don't access directly, use getBits() instead.
 932 
 933         public $masktype$(boolean[] bits) {
 934             this(bits, 0);
 935         }
 936 
 937         public $masktype$(boolean[] bits, int i) {
 938             this.bits = Arrays.copyOfRange(bits, i, i + species().length());
 939         }
 940 
 941         public $masktype$(boolean val) {
 942             boolean[] bits = new boolean[species().length()];
 943             Arrays.fill(bits, val);
 944             this.bits = bits;
 945         }
 946 
 947         boolean[] getBits() {
 948             return VectorIntrinsics.maybeRebox(this).bits;
 949         }
 950 
 951         @Override
 952         $masktype$ uOp(MUnOp f) {
 953             boolean[] res = new boolean[species().length()];
 954             boolean[] bits = getBits();
 955             for (int i = 0; i < species().length(); i++) {
 956                 res[i] = f.apply(i, bits[i]);
 957             }
 958             return new $masktype$(res);
 959         }
 960 
 961         @Override
 962         $masktype$ bOp(Mask<$Boxtype$, Shapes.$shape$> o, MBinOp f) {
 963             boolean[] res = new boolean[species().length()];
 964             boolean[] bits = getBits();
 965             boolean[] mbits = (($masktype$)o).getBits();
 966             for (int i = 0; i < species().length(); i++) {
 967                 res[i] = f.apply(i, bits[i], mbits[i]);
 968             }
 969             return new $masktype$(res);
 970         }
 971 
 972         @Override
 973         public $Type$$bits$Species species() {
 974             return SPECIES;
 975         }
 976 
 977         @Override
 978         public $vectortype$ toVector() {
 979             $type$[] res = new $type$[species().length()];
 980             boolean[] bits = getBits();
 981             for (int i = 0; i < species().length(); i++) {
 982                 res[i] = ($type$) (bits[i] ? -1 : 0);
 983             }
 984             return new $vectortype$(res);
 985         }
 986 
 987         @Override
 988         @ForceInline
 989         @SuppressWarnings("unchecked")
 990         public <Z> Mask<Z, Shapes.$shape$> rebracket(Species<Z, Shapes.$shape$> species) {
 991             Objects.requireNonNull(species);
 992             // TODO: check proper element type
 993             return VectorIntrinsics.rebracket(
 994                 $masktype$.class, $type$.class, LENGTH,
 995                 species.elementType(), this,
 996                 (m, t) -> m.reshape(species)
 997             );
 998         }
 999 
1000         // Unary operations
1001 
1002         //Mask<E, S> not();
1003 
1004         // Binary operations
1005 
1006         @Override
1007         @ForceInline
1008         public $masktype$ and(Mask<$Boxtype$,Shapes.$shape$> o) {
1009             Objects.requireNonNull(o);
1010             $masktype$ m = ($masktype$)o;
1011             return VectorIntrinsics.binaryOp(VECTOR_OP_AND, $masktype$.class, $bitstype$.class, LENGTH,
1012                                              this, m,
1013                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a & b));
1014         }
1015 
1016         @Override
1017         @ForceInline
1018         public $masktype$ or(Mask<$Boxtype$,Shapes.$shape$> o) {
1019             Objects.requireNonNull(o);
1020             $masktype$ m = ($masktype$)o;
1021             return VectorIntrinsics.binaryOp(VECTOR_OP_OR, $masktype$.class, $bitstype$.class, LENGTH,
1022                                              this, m,
1023                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a | b));
1024         }
1025 
1026         // Reductions
1027 
1028         @Override
1029         @ForceInline
1030         public boolean anyTrue() {
1031             return VectorIntrinsics.test(COND_notZero, $masktype$.class, $bitstype$.class, LENGTH,
1032                                          this, this,
1033                                          (m1, m2) -> super.anyTrue());
1034         }
1035 
1036         @Override
1037         @ForceInline
1038         public boolean allTrue() {
1039             return VectorIntrinsics.test(COND_carrySet, $masktype$.class, $bitstype$.class, LENGTH,
1040                                          this, species().maskAllTrue(),
1041                                          (m1, m2) -> super.allTrue());
1042         }
1043     }
1044 
1045     // Shuffle
1046 
1047     static final class $shuffletype$ extends AbstractShuffle<$Boxtype$, Shapes.$shape$> {
1048         static final IntVector.IntSpecies<Shapes.$shape$> INT_SPECIES = (IntVector.IntSpecies<Shapes.$shape$>) Vector.speciesInstance(Integer.class, Shapes.$Shape$);
1049 
1050         public $shuffletype$(int[] reorder) {
1051             super(reorder);
1052         }
1053 
1054         public $shuffletype$(int[] reorder, int i) {
1055             super(reorder, i);
1056         }
1057 
1058         @Override
1059         public $Type$$bits$Species species() {
1060             return SPECIES;
1061         }
1062 
1063         @Override
1064         public IntVector.IntSpecies<Shapes.$shape$> intSpecies() {
1065             return INT_SPECIES;
1066         }
1067     }
1068 
1069     // Species
1070 
1071     @Override
1072     public $Type$$bits$Species species() {
1073         return SPECIES;
1074     }
1075 
1076     static final class $Type$$bits$Species extends $Type$Species<Shapes.$shape$> {
1077         static final int BIT_SIZE = Shapes.$Shape$.bitSize();
1078 
1079         static final int LENGTH = BIT_SIZE / $Boxtype$.SIZE;
1080 
1081         @Override
1082         public String toString() {
1083            StringBuilder sb = new StringBuilder("Shape[");
1084            sb.append(bitSize()).append(" bits, ");
1085            sb.append(length()).append(" ").append($type$.class.getSimpleName()).append("s x ");
1086            sb.append(elementSize()).append(" bits");
1087            sb.append("]");
1088            return sb.toString();
1089         }
1090 
1091         @Override
1092         public int bitSize() {
1093             return BIT_SIZE;
1094         }
1095 
1096         @Override
1097         public int length() {
1098             return LENGTH;
1099         }
1100 
1101         @Override
1102         public Class<$Boxtype$> elementType() {
1103             return $Boxtype$.class;
1104         }
1105 
1106         @Override
1107         public int elementSize() {
1108             return $Boxtype$.SIZE;
1109         }
1110 
1111         @Override
1112         public Shapes.$shape$ shape() {
1113             return Shapes.$Shape$;
1114         }
1115 
1116         @Override
1117         $vectortype$ op(FOp f) {
1118             $type$[] res = new $type$[length()];
1119             for (int i = 0; i < length(); i++) {
1120                 res[i] = f.apply(i);
1121             }
1122             return new $vectortype$(res);
1123         }
1124 
1125         @Override
1126         $vectortype$ op(Mask<$Boxtype$, Shapes.$shape$> o, FOp f) {
1127             $type$[] res = new $type$[length()];
1128             boolean[] mbits = (($masktype$)o).getBits();
1129             for (int i = 0; i < length(); i++) {
1130                 if (mbits[i]) {
1131                     res[i] = f.apply(i);
1132                 }
1133             }
1134             return new $vectortype$(res);
1135         }
1136 
1137         // Factories
1138 
1139         @Override
1140         public $masktype$ maskFromValues(boolean... bits) {
1141             return new $masktype$(bits);
1142         }
1143 
1144         @Override
1145         public $masktype$ maskFromArray(boolean[] bits, int i) {
1146             return new $masktype$(bits, i);
1147         }
1148 
1149         @Override
1150         public $shuffletype$ shuffleFromValues(int... ixs) {
1151             return new $shuffletype$(ixs);
1152         }
1153 
1154         @Override
1155         public $shuffletype$ shuffleFromArray(int[] ixs, int i) {
1156             return new $shuffletype$(ixs, i);
1157         }
1158 
1159 #if[FP]
1160         @Override
1161         @ForceInline
1162         public $vectortype$ zero() {
1163             return VectorIntrinsics.broadcastCoerced($vectortype$.class, $type$.class, LENGTH,
1164                                                      $Type$.$type$To$Bitstype$Bits(0.0f),
1165                                                      (z -> ZERO));
1166         }
1167 
1168         @Override
1169         @ForceInline
1170         public $vectortype$ broadcast($type$ e) {
1171             return VectorIntrinsics.broadcastCoerced(
1172                 $vectortype$.class, $type$.class, LENGTH,
1173                 $Type$.$type$To$Bitstype$Bits(e),
1174                 ((long bits) -> SPECIES.op(i -> $Type$.$bitstype$BitsTo$Type$(($bitstype$)bits))));
1175         }
1176 #end[FP]
1177 #if[BITWISE]
1178         @Override
1179         @ForceInline
1180         public $vectortype$ zero() {
1181             return VectorIntrinsics.broadcastCoerced($vectortype$.class, $type$.class, LENGTH,
1182                                                      0,
1183                                                      (z -> ZERO));
1184         }
1185 
1186         @Override
1187         @ForceInline
1188         public $vectortype$ broadcast($type$ e) {
1189             return VectorIntrinsics.broadcastCoerced(
1190                 $vectortype$.class, $type$.class, LENGTH,
1191                 e,
1192                 ((long bits) -> SPECIES.op(i -> ($type$)bits)));
1193         }
1194 #end[BITWISE]
1195 
1196         @Override
1197         @ForceInline
1198         public $masktype$ maskAllTrue() {
1199             return VectorIntrinsics.broadcastCoerced($masktype$.class, $bitstype$.class, LENGTH,
1200                                                      ($bitstype$)-1,
1201                                                      (z -> $masktype$.TRUE_MASK));
1202         }
1203 
1204         @Override
1205         @ForceInline
1206         public $masktype$ maskAllFalse() {
1207             return VectorIntrinsics.broadcastCoerced($masktype$.class, $bitstype$.class, LENGTH,
1208                                                      0,
1209                                                      (z -> $masktype$.FALSE_MASK));
1210         }
1211 
1212         @Override
1213         @ForceInline
1214         public $vectortype$ fromArray($type$[] a, int ix) {
1215             Objects.requireNonNull(a);
1216             ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
1217             return ($vectortype$) VectorIntrinsics.load($vectortype$.class, $type$.class, LENGTH,
1218                                                         a, ix,
1219                                                         (arr, idx) -> super.fromArray(($type$[]) arr, idx));
1220         }
1221 
1222         @Override
1223         @ForceInline
1224         public $vectortype$ fromArray($type$[] a, int ax, Mask<$Boxtype$, Shapes.$shape$> m) {
1225             return zero().blend(fromArray(a, ax), m); // TODO: use better default impl: op(m, i -> a[ax + i]);
1226         }
1227     }
1228 }