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 Double128Vector extends DoubleVector<Shapes.S128Bit> {
  35     static final Double128Species SPECIES = new Double128Species();
  36 
  37     static final Double128Vector ZERO = new Double128Vector();
  38 
  39     static final int LENGTH = SPECIES.length();
  40 
  41     private final double[] vec; // Don't access directly, use getElements() instead.
  42 
  43     private double[] getElements() {
  44         return VectorIntrinsics.maybeRebox(this).vec;
  45     }
  46 
  47     Double128Vector() {
  48         vec = new double[SPECIES.length()];
  49     }
  50 
  51     Double128Vector(double[] v) {
  52         vec = v;
  53     }
  54 
  55     @Override
  56     public int length() { return LENGTH; }
  57 
  58     // Unary operator
  59 
  60     @Override
  61     Double128Vector uOp(FUnOp f) {
  62         double[] vec = getElements();
  63         double[] res = new double[length()];
  64         for (int i = 0; i < length(); i++) {
  65             res[i] = f.apply(i, vec[i]);
  66         }
  67         return new Double128Vector(res);
  68     }
  69 
  70     @Override
  71     Double128Vector uOp(Mask<Double, Shapes.S128Bit> o, FUnOp f) {
  72         double[] vec = getElements();
  73         double[] res = new double[length()];
  74         boolean[] mbits = ((Double128Mask)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 Double128Vector(res);
  79     }
  80 
  81     // Binary operator
  82 
  83     @Override
  84     Double128Vector bOp(Vector<Double, Shapes.S128Bit> o, FBinOp f) {
  85         double[] res = new double[length()];
  86         double[] vec1 = this.getElements();
  87         double[] vec2 = ((Double128Vector)o).getElements();
  88         for (int i = 0; i < length(); i++) {
  89             res[i] = f.apply(i, vec1[i], vec2[i]);
  90         }
  91         return new Double128Vector(res);
  92     }
  93 
  94     @Override
  95     Double128Vector bOp(Vector<Double, Shapes.S128Bit> o1, Mask<Double, Shapes.S128Bit> o2, FBinOp f) {
  96         double[] res = new double[length()];
  97         double[] vec1 = this.getElements();
  98         double[] vec2 = ((Double128Vector)o1).getElements();
  99         boolean[] mbits = ((Double128Mask)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 Double128Vector(res);
 104     }
 105 
 106     // Trinary operator
 107 
 108     @Override
 109     Double128Vector tOp(Vector<Double, Shapes.S128Bit> o1, Vector<Double, Shapes.S128Bit> o2, FTriOp f) {
 110         double[] res = new double[length()];
 111         double[] vec1 = this.getElements();
 112         double[] vec2 = ((Double128Vector)o1).getElements();
 113         double[] vec3 = ((Double128Vector)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 Double128Vector(res);
 118     }
 119 
 120     @Override
 121     Double128Vector tOp(Vector<Double, Shapes.S128Bit> o1, Vector<Double, Shapes.S128Bit> o2, Mask<Double, Shapes.S128Bit> o3, FTriOp f) {
 122         double[] res = new double[length()];
 123         double[] vec1 = getElements();
 124         double[] vec2 = ((Double128Vector)o1).getElements();
 125         double[] vec3 = ((Double128Vector)o2).getElements();
 126         boolean[] mbits = ((Double128Mask)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 Double128Vector(res);
 131     }
 132 
 133     @Override
 134     double rOp(double v, FBinOp f) {
 135         double[] 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 DoubleVector<Shapes.S128Bit> add(double o) {
 147         return add(SPECIES.broadcast(o));
 148     }
 149 
 150     @Override
 151     @ForceInline
 152     public DoubleVector<Shapes.S128Bit> add(double o, Mask<Double,Shapes.S128Bit> m) {
 153         return add(SPECIES.broadcast(o), m);
 154     }
 155 
 156     @Override
 157     @ForceInline
 158     public DoubleVector<Shapes.S128Bit> addSaturate(double o) {
 159         return addSaturate(SPECIES.broadcast(o));
 160     }
 161 
 162     @Override
 163     @ForceInline
 164     public DoubleVector<Shapes.S128Bit> addSaturate(double o, Mask<Double,Shapes.S128Bit> m) {
 165         return addSaturate(SPECIES.broadcast(o), m);
 166     }
 167 
 168     @Override
 169     @ForceInline
 170     public DoubleVector<Shapes.S128Bit> sub(double o) {
 171         return sub(SPECIES.broadcast(o));
 172     }
 173 
 174     @Override
 175     @ForceInline
 176     public DoubleVector<Shapes.S128Bit> sub(double o, Mask<Double,Shapes.S128Bit> m) {
 177         return sub(SPECIES.broadcast(o), m);
 178     }
 179 
 180     @Override
 181     @ForceInline
 182     public DoubleVector<Shapes.S128Bit> subSaturate(double o) {
 183         return subSaturate(SPECIES.broadcast(o));
 184     }
 185 
 186     @Override
 187     @ForceInline
 188     public DoubleVector<Shapes.S128Bit> subSaturate(double o, Mask<Double,Shapes.S128Bit> m) {
 189         return subSaturate(SPECIES.broadcast(o), m);
 190     }
 191 
 192     @Override
 193     @ForceInline
 194     public DoubleVector<Shapes.S128Bit> mul(double o) {
 195         return mul(SPECIES.broadcast(o));
 196     }
 197 
 198     @Override
 199     @ForceInline
 200     public DoubleVector<Shapes.S128Bit> mul(double o, Mask<Double,Shapes.S128Bit> m) {
 201         return mul(SPECIES.broadcast(o), m);
 202     }
 203 
 204     @Override
 205     @ForceInline
 206     public DoubleVector<Shapes.S128Bit> min(double o) {
 207         return min(SPECIES.broadcast(o));
 208     }
 209 
 210     @Override
 211     @ForceInline
 212     public DoubleVector<Shapes.S128Bit> max(double o) {
 213         return max(SPECIES.broadcast(o));
 214     }
 215 
 216     @Override
 217     @ForceInline
 218     public Mask<Double, Shapes.S128Bit> equal(double o) {
 219         return equal(SPECIES.broadcast(o));
 220     }
 221 
 222     @Override
 223     @ForceInline
 224     public Mask<Double, Shapes.S128Bit> notEqual(double o) {
 225         return notEqual(SPECIES.broadcast(o));
 226     }
 227 
 228     @Override
 229     @ForceInline
 230     public Mask<Double, Shapes.S128Bit> lessThan(double o) {
 231         return lessThan(SPECIES.broadcast(o));
 232     }
 233 
 234     @Override
 235     @ForceInline
 236     public Mask<Double, Shapes.S128Bit> lessThanEq(double o) {
 237         return lessThanEq(SPECIES.broadcast(o));
 238     }
 239 
 240     @Override
 241     @ForceInline
 242     public Mask<Double, Shapes.S128Bit> greaterThan(double o) {
 243         return greaterThan(SPECIES.broadcast(o));
 244     }
 245 
 246     @Override
 247     @ForceInline
 248     public Mask<Double, Shapes.S128Bit> greaterThanEq(double o) {
 249         return greaterThanEq(SPECIES.broadcast(o));
 250     }
 251 
 252     @Override
 253     @ForceInline
 254     public DoubleVector<Shapes.S128Bit> blend(double o, Mask<Double,Shapes.S128Bit> m) {
 255         return blend(SPECIES.broadcast(o), m);
 256     }
 257 
 258     @Override
 259     @ForceInline
 260     public DoubleVector<Shapes.S128Bit> div(double o) {
 261         return div(SPECIES.broadcast(o));
 262     }
 263 
 264     @Override
 265     @ForceInline
 266     public DoubleVector<Shapes.S128Bit> div(double o, Mask<Double,Shapes.S128Bit> m) {
 267         return div(SPECIES.broadcast(o), m);
 268     }
 269 
 270     @Override
 271     @ForceInline
 272     public DoubleVector<Shapes.S128Bit> atan2(double o) {
 273         return atan2(SPECIES.broadcast(o));
 274     }
 275 
 276     @Override
 277     @ForceInline
 278     public DoubleVector<Shapes.S128Bit> atan2(double o, Mask<Double,Shapes.S128Bit> m) {
 279         return atan2(SPECIES.broadcast(o), m);
 280     }
 281 
 282     @Override
 283     @ForceInline
 284     public DoubleVector<Shapes.S128Bit> pow(double o) {
 285         return pow(SPECIES.broadcast(o));
 286     }
 287 
 288     @Override
 289     @ForceInline
 290     public DoubleVector<Shapes.S128Bit> pow(double o, Mask<Double,Shapes.S128Bit> m) {
 291         return pow(SPECIES.broadcast(o), m);
 292     }
 293 
 294     @Override
 295     @ForceInline
 296     public DoubleVector<Shapes.S128Bit> fma(double o1, double o2) {
 297         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
 298     }
 299 
 300     @Override
 301     @ForceInline
 302     public DoubleVector<Shapes.S128Bit> fma(double o1, double o2, Mask<Double,Shapes.S128Bit> m) {
 303         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
 304     }
 305 
 306     @Override
 307     @ForceInline
 308     public DoubleVector<Shapes.S128Bit> hypot(double o) {
 309         return hypot(SPECIES.broadcast(o));
 310     }
 311 
 312     @Override
 313     @ForceInline
 314     public DoubleVector<Shapes.S128Bit> hypot(double o, Mask<Double,Shapes.S128Bit> m) {
 315         return hypot(SPECIES.broadcast(o), m);
 316     }
 317 
 318 
 319 
 320     // Unary operations
 321 
 322     @Override
 323     @ForceInline
 324     public Double128Vector abs() {
 325         return (Double128Vector) VectorIntrinsics.unaryOp(
 326             VECTOR_OP_ABS, Double128Vector.class, double.class, LENGTH,
 327             this,
 328             v1 -> ((Double128Vector)v1).uOp((i, a) -> (double) Math.abs(a)));
 329     }
 330 
 331     @Override
 332     @ForceInline
 333     public Double128Vector neg() {
 334         return (Double128Vector) VectorIntrinsics.unaryOp(
 335             VECTOR_OP_NEG, Double128Vector.class, double.class, LENGTH,
 336             this,
 337             v1 -> ((Double128Vector)v1).uOp((i, a) -> (double) -a));
 338     }
 339 
 340     @Override
 341     @ForceInline
 342     public Double128Vector div(Vector<Double,Shapes.S128Bit> o) {
 343         Objects.requireNonNull(o);
 344         Double128Vector v = (Double128Vector)o;
 345         return (Double128Vector) VectorIntrinsics.binaryOp(
 346             VECTOR_OP_DIV, Double128Vector.class, double.class, LENGTH,
 347             this, v,
 348             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double)(a / b)));
 349     }
 350 
 351     @Override
 352     @ForceInline
 353     public Double128Vector sqrt() {
 354         return (Double128Vector) VectorIntrinsics.unaryOp(
 355             VECTOR_OP_SQRT, Double128Vector.class, double.class, LENGTH,
 356             this,
 357             v1 -> ((Double128Vector)v1).uOp((i, a) -> (double) Math.sqrt((double) a)));
 358     }
 359 
 360     // Binary operations
 361 
 362     @Override
 363     @ForceInline
 364     public Double128Vector add(Vector<Double,Shapes.S128Bit> o) {
 365         Objects.requireNonNull(o);
 366         Double128Vector v = (Double128Vector)o;
 367         return (Double128Vector) VectorIntrinsics.binaryOp(
 368             VECTOR_OP_ADD, Double128Vector.class, double.class, LENGTH,
 369             this, v,
 370             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double)(a + b)));
 371     }
 372 
 373     @Override
 374     @ForceInline
 375     public Double128Vector sub(Vector<Double,Shapes.S128Bit> o) {
 376         Objects.requireNonNull(o);
 377         Double128Vector v = (Double128Vector)o;
 378         return (Double128Vector) VectorIntrinsics.binaryOp(
 379             VECTOR_OP_SUB, Double128Vector.class, double.class, LENGTH,
 380             this, v,
 381             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double)(a - b)));
 382     }
 383 
 384     @Override
 385     @ForceInline
 386     public Double128Vector mul(Vector<Double,Shapes.S128Bit> o) {
 387         Objects.requireNonNull(o);
 388         Double128Vector v = (Double128Vector)o;
 389         return (Double128Vector) VectorIntrinsics.binaryOp(
 390             VECTOR_OP_MUL, Double128Vector.class, double.class, LENGTH,
 391             this, v,
 392             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double)(a * b)));
 393     }
 394 
 395     @Override
 396     @ForceInline
 397     public Double128Vector min(Vector<Double,Shapes.S128Bit> o) {
 398         Objects.requireNonNull(o);
 399         Double128Vector v = (Double128Vector)o;
 400         return (Double128Vector) VectorIntrinsics.binaryOp(
 401             VECTOR_OP_MIN, Double128Vector.class, double.class, LENGTH,
 402             this, v,
 403             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double) ((a < b) ? a : b)));
 404     }
 405 
 406     @Override
 407     @ForceInline
 408     public Double128Vector max(Vector<Double,Shapes.S128Bit> o) {
 409         Objects.requireNonNull(o);
 410         Double128Vector v = (Double128Vector)o;
 411         return (Double128Vector) VectorIntrinsics.binaryOp(
 412             VECTOR_OP_MAX, Double128Vector.class, double.class, LENGTH,
 413             this, v,
 414             (v1, v2) -> ((Double128Vector)v1).bOp(v2, (i, a, b) -> (double) ((a > b) ? a : b)));
 415         }
 416 
 417     @Override
 418     @ForceInline
 419     public Double128Vector add(Vector<Double,Shapes.S128Bit> v, Mask<Double, Shapes.S128Bit> m) {
 420         // TODO: use better default impl: bOp(o, m, (i, a, b) -> (double)(a + b));
 421         return blend(add(v), m);
 422     }
 423 
 424     @Override
 425     @ForceInline
 426     public Double128Vector sub(Vector<Double,Shapes.S128Bit> v, Mask<Double, Shapes.S128Bit> m) {
 427         // TODO: use better default impl: bOp(o, m, (i, a, b) -> (double)(a - b));
 428         return blend(sub(v), m);
 429     }
 430 
 431     @Override
 432     @ForceInline
 433     public Double128Vector mul(Vector<Double,Shapes.S128Bit> v, Mask<Double, Shapes.S128Bit> m) {
 434         // TODO: use better default impl: bOp(o, m, (i, a, b) -> (double)(a * b));
 435         return blend(mul(v), m);
 436     }
 437 
 438     @Override
 439     @ForceInline
 440     public Double128Vector div(Vector<Double,Shapes.S128Bit> v, Mask<Double, Shapes.S128Bit> m) {
 441         // TODO: use better default impl: bOp(o, m, (i, a, b) -> (double)(a / b));
 442         return blend(div(v), m);
 443     }
 444 
 445 
 446     // Ternary operations
 447 
 448     @Override
 449     @ForceInline
 450     public Double128Vector fma(Vector<Double,Shapes.S128Bit> o1, Vector<Double,Shapes.S128Bit> o2) {
 451         Objects.requireNonNull(o1);
 452         Objects.requireNonNull(o2);
 453         Double128Vector v1 = (Double128Vector)o1;
 454         Double128Vector v2 = (Double128Vector)o2;
 455         return (Double128Vector) VectorIntrinsics.ternaryOp(
 456             VECTOR_OP_FMA, Double128Vector.class, double.class, LENGTH,
 457             this, v1, v2,
 458             (w1, w2, w3) -> w1.tOp(w2, w3, (i, a, b, c) -> Math.fma(a, b, c)));
 459     }
 460 
 461     // Type specific horizontal reductions
 462 
 463     @Override
 464     @ForceInline
 465     public double addAll() {
 466         long bits = (long) VectorIntrinsics.reductionCoerced(
 467                                 VECTOR_OP_ADD, Double128Vector.class, double.class, LENGTH,
 468                                 this,
 469                                 v -> {
 470                                     double r = v.rOp((double) 0, (i, a, b) -> (double) (a + b));
 471                                     return (long)Double.doubleToLongBits(r);
 472                                 });
 473         return Double.longBitsToDouble(bits);
 474     }
 475 
 476     @Override
 477     @ForceInline
 478     public double mulAll() {
 479         long bits = (long) VectorIntrinsics.reductionCoerced(
 480                                 VECTOR_OP_MUL, Double128Vector.class, double.class, LENGTH,
 481                                 this,
 482                                 v -> {
 483                                     double r = v.rOp((double) 1, (i, a, b) -> (double) (a * b));
 484                                     return (long)Double.doubleToLongBits(r);
 485                                 });
 486         return Double.longBitsToDouble(bits);
 487     }
 488 
 489     // Memory operations
 490 
 491     @Override
 492     @ForceInline
 493     public void intoArray(double[] a, int ix) {
 494         Objects.requireNonNull(a);
 495         ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
 496         VectorIntrinsics.store(Double128Vector.class, double.class, LENGTH,
 497                                a, ix, this,
 498                                (arr, idx, v) -> v.forEach((i, a_) -> ((double[])arr)[idx + i] = a_));
 499     }
 500 
 501     @Override
 502     @ForceInline
 503     public void intoArray(double[] a, int ax, Mask<Double, Shapes.S128Bit> m) {
 504         // TODO: use better default impl: forEach(m, (i, a_) -> a[ax + i] = a_);
 505         Double128Vector oldVal = SPECIES.fromArray(a, ax);
 506         Double128Vector newVal = oldVal.blend(this, m);
 507         newVal.intoArray(a, ax);
 508     }
 509 
 510     //
 511 
 512     @Override
 513     public String toString() {
 514         return Arrays.toString(getElements());
 515     }
 516 
 517     @Override
 518     public boolean equals(Object o) {
 519         if (this == o) return true;
 520         if (o == null || this.getClass() != o.getClass()) return false;
 521 
 522         Double128Vector that = (Double128Vector) o;
 523         return Arrays.equals(this.getElements(), that.getElements());
 524     }
 525 
 526     @Override
 527     public int hashCode() {
 528         return Arrays.hashCode(vec);
 529     }
 530 
 531     // Binary test
 532 
 533     @Override
 534     Double128Mask bTest(Vector<Double, Shapes.S128Bit> o, FBinTest f) {
 535         double[] vec1 = getElements();
 536         double[] vec2 = ((Double128Vector)o).getElements();
 537         boolean[] bits = new boolean[length()];
 538         for (int i = 0; i < length(); i++){
 539             bits[i] = f.apply(i, vec1[i], vec2[i]);
 540         }
 541         return new Double128Mask(bits);
 542     }
 543 
 544     // Comparisons
 545 
 546     @Override
 547     @ForceInline
 548     public Double128Mask equal(Vector<Double, Shapes.S128Bit> o) {
 549         Objects.requireNonNull(o);
 550         Double128Vector v = (Double128Vector)o;
 551 
 552         return (Double128Mask) VectorIntrinsics.compare(
 553             BT_eq, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 554             this, v,
 555             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a == b));
 556     }
 557 
 558     @Override
 559     @ForceInline
 560     public Double128Mask notEqual(Vector<Double, Shapes.S128Bit> o) {
 561         Objects.requireNonNull(o);
 562         Double128Vector v = (Double128Vector)o;
 563 
 564         return (Double128Mask) VectorIntrinsics.compare(
 565             BT_ne, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 566             this, v,
 567             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a != b));
 568     }
 569 
 570     @Override
 571     @ForceInline
 572     public Double128Mask lessThan(Vector<Double, Shapes.S128Bit> o) {
 573         Objects.requireNonNull(o);
 574         Double128Vector v = (Double128Vector)o;
 575 
 576         return (Double128Mask) VectorIntrinsics.compare(
 577             BT_lt, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 578             this, v,
 579             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a < b));
 580     }
 581 
 582     @Override
 583     @ForceInline
 584     public Double128Mask lessThanEq(Vector<Double, Shapes.S128Bit> o) {
 585         Objects.requireNonNull(o);
 586         Double128Vector v = (Double128Vector)o;
 587 
 588         return (Double128Mask) VectorIntrinsics.compare(
 589             BT_le, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 590             this, v,
 591             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a <= b));
 592     }
 593 
 594     @Override
 595     @ForceInline
 596     public Double128Mask greaterThan(Vector<Double, Shapes.S128Bit> o) {
 597         Objects.requireNonNull(o);
 598         Double128Vector v = (Double128Vector)o;
 599 
 600         return (Double128Mask) VectorIntrinsics.compare(
 601             BT_gt, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 602             this, v,
 603             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a > b));
 604     }
 605 
 606     @Override
 607     @ForceInline
 608     public Double128Mask greaterThanEq(Vector<Double, Shapes.S128Bit> o) {
 609         Objects.requireNonNull(o);
 610         Double128Vector v = (Double128Vector)o;
 611 
 612         return (Double128Mask) VectorIntrinsics.compare(
 613             BT_ge, Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 614             this, v,
 615             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a >= b));
 616     }
 617 
 618     // Foreach
 619 
 620     @Override
 621     void forEach(FUnCon f) {
 622         double[] vec = getElements();
 623         for (int i = 0; i < length(); i++) {
 624             f.apply(i, vec[i]);
 625         }
 626     }
 627 
 628     @Override
 629     void forEach(Mask<Double, Shapes.S128Bit> o, FUnCon f) {
 630         boolean[] mbits = ((Double128Mask)o).getBits();
 631         forEach((i, a) -> {
 632             if (mbits[i]) { f.apply(i, a); }
 633         });
 634     }
 635 
 636     Long128Vector toBits() {
 637         double[] vec = getElements();
 638         long[] res = new long[this.species().length()];
 639         for(int i = 0; i < this.species().length(); i++){
 640             res[i] = Double.doubleToLongBits(vec[i]);
 641         }
 642         return new Long128Vector(res);
 643     }
 644 
 645 
 646     @Override
 647     public Double128Vector rotateEL(int j) {
 648         double[] vec = getElements();
 649         double[] res = new double[length()];
 650         for (int i = 0; i < length(); i++){
 651             res[(j + i) % length()] = vec[i];
 652         }
 653         return new Double128Vector(res);
 654     }
 655 
 656     @Override
 657     public Double128Vector rotateER(int j) {
 658         double[] vec = getElements();
 659         double[] res = new double[length()];
 660         for (int i = 0; i < length(); i++){
 661             int z = i - j;
 662             if(j < 0) {
 663                 res[length() + z] = vec[i];
 664             } else {
 665                 res[z] = vec[i];
 666             }
 667         }
 668         return new Double128Vector(res);
 669     }
 670 
 671     @Override
 672     public Double128Vector shiftEL(int j) {
 673         double[] vec = getElements();
 674         double[] res = new double[length()];
 675         for (int i = 0; i < length() - j; i++) {
 676             res[i] = vec[i + j];
 677         }
 678         return new Double128Vector(res);
 679     }
 680 
 681     @Override
 682     public Double128Vector shiftER(int j) {
 683         double[] vec = getElements();
 684         double[] res = new double[length()];
 685         for (int i = 0; i < length() - j; i++){
 686             res[i + j] = vec[i];
 687         }
 688         return new Double128Vector(res);
 689     }
 690 
 691     @Override
 692     public Double128Vector shuffle(Vector<Double, Shapes.S128Bit> o, Shuffle<Double, Shapes.S128Bit> s) {
 693         Double128Vector v = (Double128Vector) o;
 694         return uOp((i, a) -> {
 695             double[] vec = this.getElements();
 696             int e = s.getElement(i);
 697             if(e >= 0 && e < length()) {
 698                 //from this
 699                 return vec[e];
 700             } else if(e < length() * 2) {
 701                 //from o
 702                 return v.getElements()[e - length()];
 703             } else {
 704                 throw new ArrayIndexOutOfBoundsException("Bad reordering for shuffle");
 705             }
 706         });
 707     }
 708 
 709     @Override
 710     public Double128Vector swizzle(Shuffle<Double, Shapes.S128Bit> s) {
 711         return uOp((i, a) -> {
 712             double[] vec = this.getElements();
 713             int e = s.getElement(i);
 714             if(e >= 0 && e < length()) {
 715                 return vec[e];
 716             } else {
 717                 throw new ArrayIndexOutOfBoundsException("Bad reordering for shuffle");
 718             }
 719         });
 720     }
 721 
 722     @Override
 723     @ForceInline
 724     public Double128Vector blend(Vector<Double, Shapes.S128Bit> o1, Mask<Double, Shapes.S128Bit> o2) {
 725         Objects.requireNonNull(o1);
 726         Objects.requireNonNull(o2);
 727         Double128Vector v = (Double128Vector)o1;
 728         Double128Mask   m = (Double128Mask)o2;
 729 
 730         return (Double128Vector) VectorIntrinsics.blend(
 731             Double128Vector.class, Double128Mask.class, double.class, LENGTH,
 732             this, v, m,
 733             (v1, v2, m_) -> v1.bOp(v2, (i, a, b) -> m_.getElement(i) ? b : a));
 734     }
 735 
 736     // Accessors
 737 
 738     @Override
 739     public double get(int i) {
 740         double[] vec = getElements();
 741         return vec[i];
 742     }
 743 
 744     @Override
 745     public Double128Vector with(int i, double e) {
 746         double[] res = vec.clone();
 747         res[i] = e;
 748         return new Double128Vector(res);
 749     }
 750 
 751     // Mask
 752 
 753     static final class Double128Mask extends AbstractMask<Double, Shapes.S128Bit> {
 754         static final Double128Mask TRUE_MASK = new Double128Mask(true);
 755         static final Double128Mask FALSE_MASK = new Double128Mask(false);
 756 
 757         // FIXME: was temporarily put here to simplify rematerialization support in the JVM
 758         private final boolean[] bits; // Don't access directly, use getBits() instead.
 759 
 760         public Double128Mask(boolean[] bits) {
 761             this(bits, 0);
 762         }
 763 
 764         public Double128Mask(boolean[] bits, int i) {
 765             this.bits = Arrays.copyOfRange(bits, i, i + species().length());
 766         }
 767 
 768         public Double128Mask(boolean val) {
 769             boolean[] bits = new boolean[species().length()];
 770             Arrays.fill(bits, val);
 771             this.bits = bits;
 772         }
 773 
 774         boolean[] getBits() {
 775             return VectorIntrinsics.maybeRebox(this).bits;
 776         }
 777 
 778         @Override
 779         Double128Mask uOp(MUnOp f) {
 780             boolean[] res = new boolean[species().length()];
 781             boolean[] bits = getBits();
 782             for (int i = 0; i < species().length(); i++) {
 783                 res[i] = f.apply(i, bits[i]);
 784             }
 785             return new Double128Mask(res);
 786         }
 787 
 788         @Override
 789         Double128Mask bOp(Mask<Double, Shapes.S128Bit> o, MBinOp f) {
 790             boolean[] res = new boolean[species().length()];
 791             boolean[] bits = getBits();
 792             boolean[] mbits = ((Double128Mask)o).getBits();
 793             for (int i = 0; i < species().length(); i++) {
 794                 res[i] = f.apply(i, bits[i], mbits[i]);
 795             }
 796             return new Double128Mask(res);
 797         }
 798 
 799         @Override
 800         public Double128Species species() {
 801             return SPECIES;
 802         }
 803 
 804         @Override
 805         public Double128Vector toVector() {
 806             double[] res = new double[species().length()];
 807             boolean[] bits = getBits();
 808             for (int i = 0; i < species().length(); i++) {
 809                 res[i] = (double) (bits[i] ? -1 : 0);
 810             }
 811             return new Double128Vector(res);
 812         }
 813 
 814         @Override
 815         @ForceInline
 816         @SuppressWarnings("unchecked")
 817         public <Z> Mask<Z, Shapes.S128Bit> rebracket(Species<Z, Shapes.S128Bit> species) {
 818             Objects.requireNonNull(species);
 819             // TODO: check proper element type
 820             return VectorIntrinsics.reinterpret(
 821                 Double128Mask.class, double.class, LENGTH,
 822                 species.elementType(), species.length(), this,
 823                 (m, t) -> m.reshape(species)
 824             );
 825         }
 826 
 827         // Unary operations
 828 
 829         //Mask<E, S> not();
 830 
 831         // Binary operations
 832 
 833         @Override
 834         @ForceInline
 835         public Double128Mask and(Mask<Double,Shapes.S128Bit> o) {
 836             Objects.requireNonNull(o);
 837             Double128Mask m = (Double128Mask)o;
 838             return VectorIntrinsics.binaryOp(VECTOR_OP_AND, Double128Mask.class, long.class, LENGTH,
 839                                              this, m,
 840                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a & b));
 841         }
 842 
 843         @Override
 844         @ForceInline
 845         public Double128Mask or(Mask<Double,Shapes.S128Bit> o) {
 846             Objects.requireNonNull(o);
 847             Double128Mask m = (Double128Mask)o;
 848             return VectorIntrinsics.binaryOp(VECTOR_OP_OR, Double128Mask.class, long.class, LENGTH,
 849                                              this, m,
 850                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a | b));
 851         }
 852 
 853         // Reductions
 854 
 855         @Override
 856         @ForceInline
 857         public boolean anyTrue() {
 858             return VectorIntrinsics.test(COND_notZero, Double128Mask.class, long.class, LENGTH,
 859                                          this, this,
 860                                          (m1, m2) -> super.anyTrue());
 861         }
 862 
 863         @Override
 864         @ForceInline
 865         public boolean allTrue() {
 866             return VectorIntrinsics.test(COND_carrySet, Double128Mask.class, long.class, LENGTH,
 867                                          this, species().maskAllTrue(),
 868                                          (m1, m2) -> super.allTrue());
 869         }
 870     }
 871 
 872     // Shuffle
 873 
 874     static final class Double128Shuffle extends AbstractShuffle<Double, Shapes.S128Bit> {
 875         static final IntVector.IntSpecies<Shapes.S128Bit> INT_SPECIES = IntVector.speciesInstance(Shapes.S_128_BIT);
 876 
 877         public Double128Shuffle(int[] reorder) {
 878             super(reorder);
 879         }
 880 
 881         public Double128Shuffle(int[] reorder, int i) {
 882             super(reorder, i);
 883         }
 884 
 885         @Override
 886         public Double128Species species() {
 887             return SPECIES;
 888         }
 889 
 890         @Override
 891         public IntVector.IntSpecies<Shapes.S128Bit> intSpecies() {
 892             return INT_SPECIES;
 893         }
 894     }
 895 
 896     // Species
 897 
 898     @Override
 899     public Double128Species species() {
 900         return SPECIES;
 901     }
 902 
 903     static final class Double128Species extends DoubleSpecies<Shapes.S128Bit> {
 904         static final int BIT_SIZE = Shapes.S_128_BIT.bitSize();
 905 
 906         static final int LENGTH = BIT_SIZE / Double.SIZE;
 907 
 908         @Override
 909         public String toString() {
 910            StringBuilder sb = new StringBuilder("Shape[");
 911            sb.append(bitSize()).append(" bits, ");
 912            sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
 913            sb.append(elementSize()).append(" bits");
 914            sb.append("]");
 915            return sb.toString();
 916         }
 917 
 918         @Override
 919         @ForceInline
 920         public int bitSize() {
 921             return BIT_SIZE;
 922         }
 923 
 924         @Override
 925         @ForceInline
 926         public int length() {
 927             return LENGTH;
 928         }
 929 
 930         @Override
 931         @ForceInline
 932         public Class<Double> elementType() {
 933             return double.class;
 934         }
 935 
 936         @Override
 937         @ForceInline
 938         public int elementSize() {
 939             return Double.SIZE;
 940         }
 941 
 942         @Override
 943         @ForceInline
 944         public Shapes.S128Bit shape() {
 945             return Shapes.S_128_BIT;
 946         }
 947 
 948         @Override
 949         Double128Vector op(FOp f) {
 950             double[] res = new double[length()];
 951             for (int i = 0; i < length(); i++) {
 952                 res[i] = f.apply(i);
 953             }
 954             return new Double128Vector(res);
 955         }
 956 
 957         @Override
 958         Double128Vector op(Mask<Double, Shapes.S128Bit> o, FOp f) {
 959             double[] res = new double[length()];
 960             boolean[] mbits = ((Double128Mask)o).getBits();
 961             for (int i = 0; i < length(); i++) {
 962                 if (mbits[i]) {
 963                     res[i] = f.apply(i);
 964                 }
 965             }
 966             return new Double128Vector(res);
 967         }
 968 
 969         // Factories
 970 
 971         @Override
 972         public Double128Mask maskFromValues(boolean... bits) {
 973             return new Double128Mask(bits);
 974         }
 975 
 976         @Override
 977         public Double128Mask maskFromArray(boolean[] bits, int i) {
 978             return new Double128Mask(bits, i);
 979         }
 980 
 981         @Override
 982         public Double128Shuffle shuffleFromValues(int... ixs) {
 983             return new Double128Shuffle(ixs);
 984         }
 985 
 986         @Override
 987         public Double128Shuffle shuffleFromArray(int[] ixs, int i) {
 988             return new Double128Shuffle(ixs, i);
 989         }
 990 
 991         @Override
 992         public Double128Shuffle shuffleFromVector(Vector<Integer, Shapes.S128Bit> v) {
 993             int[] a = ((IntVector<Shapes.S128Bit>) v).toArray();
 994             return new Double128Shuffle(a, 0);
 995         }
 996 
 997         @Override
 998         @ForceInline
 999         public Double128Vector zero() {
1000             return VectorIntrinsics.broadcastCoerced(Double128Vector.class, double.class, LENGTH,
1001                                                      Double.doubleToLongBits(0.0f),
1002                                                      (z -> ZERO));
1003         }
1004 
1005         @Override
1006         @ForceInline
1007         public Double128Vector broadcast(double e) {
1008             return VectorIntrinsics.broadcastCoerced(
1009                 Double128Vector.class, double.class, LENGTH,
1010                 Double.doubleToLongBits(e),
1011                 ((long bits) -> SPECIES.op(i -> Double.longBitsToDouble((long)bits))));
1012         }
1013 
1014         @Override
1015         @ForceInline
1016         public Double128Mask maskAllTrue() {
1017             return VectorIntrinsics.broadcastCoerced(Double128Mask.class, long.class, LENGTH,
1018                                                      (long)-1,
1019                                                      (z -> Double128Mask.TRUE_MASK));
1020         }
1021 
1022         @Override
1023         @ForceInline
1024         public Double128Mask maskAllFalse() {
1025             return VectorIntrinsics.broadcastCoerced(Double128Mask.class, long.class, LENGTH,
1026                                                      0,
1027                                                      (z -> Double128Mask.FALSE_MASK));
1028         }
1029 
1030         @Override
1031         @ForceInline
1032         public Double128Vector fromArray(double[] a, int ix) {
1033             Objects.requireNonNull(a);
1034             ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
1035             return (Double128Vector) VectorIntrinsics.load(Double128Vector.class, double.class, LENGTH,
1036                                                         a, ix,
1037                                                         (arr, idx) -> super.fromArray((double[]) arr, idx));
1038         }
1039 
1040         @Override
1041         @ForceInline
1042         public Double128Vector fromArray(double[] a, int ax, Mask<Double, Shapes.S128Bit> m) {
1043             return zero().blend(fromArray(a, ax), m); // TODO: use better default impl: op(m, i -> a[ax + i]);
1044         }
1045 
1046         @Override
1047         @ForceInline
1048         @SuppressWarnings("unchecked")
1049         public <F> Double128Vector rebracket(Vector<F, Shapes.S128Bit> o) {
1050             Objects.requireNonNull(o);
1051             if (o.elementType() == byte.class) {
1052                 Byte128Vector so = (Byte128Vector)o;
1053                 return VectorIntrinsics.reinterpret(
1054                     Byte128Vector.class, byte.class, so.length(),
1055                     double.class, LENGTH, so,
1056                     (v, t) -> (Double128Vector)reshape(v)
1057                 );
1058             } else if (o.elementType() == short.class) {
1059                 Short128Vector so = (Short128Vector)o;
1060                 return VectorIntrinsics.reinterpret(
1061                     Short128Vector.class, short.class, so.length(),
1062                     double.class, LENGTH, so,
1063                     (v, t) -> (Double128Vector)reshape(v)
1064                 );
1065             } else if (o.elementType() == int.class) {
1066                 Int128Vector so = (Int128Vector)o;
1067                 return VectorIntrinsics.reinterpret(
1068                     Int128Vector.class, int.class, so.length(),
1069                     double.class, LENGTH, so,
1070                     (v, t) -> (Double128Vector)reshape(v)
1071                 );
1072             } else if (o.elementType() == long.class) {
1073                 Long128Vector so = (Long128Vector)o;
1074                 return VectorIntrinsics.reinterpret(
1075                     Long128Vector.class, long.class, so.length(),
1076                     double.class, LENGTH, so,
1077                     (v, t) -> (Double128Vector)reshape(v)
1078                 );
1079             } else if (o.elementType() == float.class) {
1080                 Float128Vector so = (Float128Vector)o;
1081                 return VectorIntrinsics.reinterpret(
1082                     Float128Vector.class, float.class, so.length(),
1083                     double.class, LENGTH, so,
1084                     (v, t) -> (Double128Vector)reshape(v)
1085                 );
1086             } else if (o.elementType() == double.class) {
1087                 Double128Vector so = (Double128Vector)o;
1088                 return VectorIntrinsics.reinterpret(
1089                     Double128Vector.class, double.class, so.length(),
1090                     double.class, LENGTH, so,
1091                     (v, t) -> (Double128Vector)reshape(v)
1092                 );
1093             } else {
1094                 throw new InternalError("Unimplemented size");
1095             }
1096         }
1097 
1098         @Override
1099         @ForceInline
1100         @SuppressWarnings("unchecked")
1101         public <T extends Shape> Double128Vector resize(Vector<Double, T> o) {
1102             Objects.requireNonNull(o);
1103             if (o.bitSize() == 64) {
1104                 Double64Vector so = (Double64Vector)o;
1105                 return VectorIntrinsics.reinterpret(
1106                     Double64Vector.class, double.class, so.length(),
1107                     double.class, LENGTH, so,
1108                     (v, t) -> (Double128Vector)reshape(v)
1109                 );
1110             } else if (o.bitSize() == 128) {
1111                 Double128Vector so = (Double128Vector)o;
1112                 return VectorIntrinsics.reinterpret(
1113                     Double128Vector.class, double.class, so.length(),
1114                     double.class, LENGTH, so,
1115                     (v, t) -> (Double128Vector)reshape(v)
1116                 );
1117             } else if (o.bitSize() == 256) {
1118                 Double256Vector so = (Double256Vector)o;
1119                 return VectorIntrinsics.reinterpret(
1120                     Double256Vector.class, double.class, so.length(),
1121                     double.class, LENGTH, so,
1122                     (v, t) -> (Double128Vector)reshape(v)
1123                 );
1124             } else if (o.bitSize() == 512) {
1125                 Double512Vector so = (Double512Vector)o;
1126                 return VectorIntrinsics.reinterpret(
1127                     Double512Vector.class, double.class, so.length(),
1128                     double.class, LENGTH, so,
1129                     (v, t) -> (Double128Vector)reshape(v)
1130                 );
1131             } else {
1132                 throw new InternalError("Unimplemented size");
1133             }
1134         }
1135     }
1136 }