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