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.nio.ByteOrder;
  29 import java.nio.DoubleBuffer;
  30 import java.nio.ReadOnlyBufferException;
  31 import java.util.Arrays;
  32 import java.util.Objects;
  33 import java.util.function.IntUnaryOperator;
  34 
  35 import jdk.internal.misc.Unsafe;
  36 import jdk.internal.vm.annotation.ForceInline;
  37 import static jdk.incubator.vector.VectorIntrinsics.*;
  38 
  39 @SuppressWarnings("cast")
  40 final class DoubleScalableVector extends DoubleVector<Shapes.SScalableBit> {
  41     static final DoubleScalableSpecies SPECIES = new DoubleScalableSpecies();
  42 
  43     static final DoubleScalableVector ZERO = new DoubleScalableVector();
  44 
  45     static final int LENGTH = SPECIES.length();
  46 
  47     private final double[] vec; // Don't access directly, use getElements() instead.
  48 
  49     private double[] getElements() {
  50         return VectorIntrinsics.maybeRebox(this).vec;
  51     }
  52 
  53     DoubleScalableVector() {
  54         vec = new double[SPECIES.length()];
  55     }
  56 
  57     DoubleScalableVector(double[] v) {
  58         vec = v;
  59     }
  60 
  61     @Override
  62     public int length() { return LENGTH; }
  63 
  64     // Unary operator
  65 
  66     @Override
  67     DoubleScalableVector uOp(FUnOp f) {
  68         double[] vec = getElements();
  69         double[] res = new double[length()];
  70         for (int i = 0; i < length(); i++) {
  71             res[i] = f.apply(i, vec[i]);
  72         }
  73         return new DoubleScalableVector(res);
  74     }
  75 
  76     @Override
  77     DoubleScalableVector uOp(Mask<Double, Shapes.SScalableBit> o, FUnOp f) {
  78         double[] vec = getElements();
  79         double[] res = new double[length()];
  80         boolean[] mbits = ((DoubleScalableMask)o).getBits();
  81         for (int i = 0; i < length(); i++) {
  82             res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i];
  83         }
  84         return new DoubleScalableVector(res);
  85     }
  86 
  87     // Binary operator
  88 
  89     @Override
  90     DoubleScalableVector bOp(Vector<Double, Shapes.SScalableBit> o, FBinOp f) {
  91         double[] res = new double[length()];
  92         double[] vec1 = this.getElements();
  93         double[] vec2 = ((DoubleScalableVector)o).getElements();
  94         for (int i = 0; i < length(); i++) {
  95             res[i] = f.apply(i, vec1[i], vec2[i]);
  96         }
  97         return new DoubleScalableVector(res);
  98     }
  99 
 100     @Override
 101     DoubleScalableVector bOp(Vector<Double, Shapes.SScalableBit> o1, Mask<Double, Shapes.SScalableBit> o2, FBinOp f) {
 102         double[] res = new double[length()];
 103         double[] vec1 = this.getElements();
 104         double[] vec2 = ((DoubleScalableVector)o1).getElements();
 105         boolean[] mbits = ((DoubleScalableMask)o2).getBits();
 106         for (int i = 0; i < length(); i++) {
 107             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i];
 108         }
 109         return new DoubleScalableVector(res);
 110     }
 111 
 112     // Trinary operator
 113 
 114     @Override
 115     DoubleScalableVector tOp(Vector<Double, Shapes.SScalableBit> o1, Vector<Double, Shapes.SScalableBit> o2, FTriOp f) {
 116         double[] res = new double[length()];
 117         double[] vec1 = this.getElements();
 118         double[] vec2 = ((DoubleScalableVector)o1).getElements();
 119         double[] vec3 = ((DoubleScalableVector)o2).getElements();
 120         for (int i = 0; i < length(); i++) {
 121             res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]);
 122         }
 123         return new DoubleScalableVector(res);
 124     }
 125 
 126     @Override
 127     DoubleScalableVector tOp(Vector<Double, Shapes.SScalableBit> o1, Vector<Double, Shapes.SScalableBit> o2, Mask<Double, Shapes.SScalableBit> o3, FTriOp f) {
 128         double[] res = new double[length()];
 129         double[] vec1 = getElements();
 130         double[] vec2 = ((DoubleScalableVector)o1).getElements();
 131         double[] vec3 = ((DoubleScalableVector)o2).getElements();
 132         boolean[] mbits = ((DoubleScalableMask)o3).getBits();
 133         for (int i = 0; i < length(); i++) {
 134             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i];
 135         }
 136         return new DoubleScalableVector(res);
 137     }
 138 
 139     @Override
 140     double rOp(double v, FBinOp f) {
 141         double[] vec = getElements();
 142         for (int i = 0; i < length(); i++) {
 143             v = f.apply(i, v, vec[i]);
 144         }
 145         return v;
 146     }
 147 
 148     // Binary operations with scalars
 149 
 150     @Override
 151     @ForceInline
 152     public DoubleVector<Shapes.SScalableBit> add(double o) {
 153         return add(SPECIES.broadcast(o));
 154     }
 155 
 156     @Override
 157     @ForceInline
 158     public DoubleVector<Shapes.SScalableBit> add(double o, Mask<Double,Shapes.SScalableBit> m) {
 159         return add(SPECIES.broadcast(o), m);
 160     }
 161 
 162     @Override
 163     @ForceInline
 164     public DoubleVector<Shapes.SScalableBit> sub(double o) {
 165         return sub(SPECIES.broadcast(o));
 166     }
 167 
 168     @Override
 169     @ForceInline
 170     public DoubleVector<Shapes.SScalableBit> sub(double o, Mask<Double,Shapes.SScalableBit> m) {
 171         return sub(SPECIES.broadcast(o), m);
 172     }
 173 
 174     @Override
 175     @ForceInline
 176     public DoubleVector<Shapes.SScalableBit> mul(double o) {
 177         return mul(SPECIES.broadcast(o));
 178     }
 179 
 180     @Override
 181     @ForceInline
 182     public DoubleVector<Shapes.SScalableBit> mul(double o, Mask<Double,Shapes.SScalableBit> m) {
 183         return mul(SPECIES.broadcast(o), m);
 184     }
 185 
 186     @Override
 187     @ForceInline
 188     public DoubleVector<Shapes.SScalableBit> min(double o) {
 189         return min(SPECIES.broadcast(o));
 190     }
 191 
 192     @Override
 193     @ForceInline
 194     public DoubleVector<Shapes.SScalableBit> max(double o) {
 195         return max(SPECIES.broadcast(o));
 196     }
 197 
 198     @Override
 199     @ForceInline
 200     public Mask<Double, Shapes.SScalableBit> equal(double o) {
 201         return equal(SPECIES.broadcast(o));
 202     }
 203 
 204     @Override
 205     @ForceInline
 206     public Mask<Double, Shapes.SScalableBit> notEqual(double o) {
 207         return notEqual(SPECIES.broadcast(o));
 208     }
 209 
 210     @Override
 211     @ForceInline
 212     public Mask<Double, Shapes.SScalableBit> lessThan(double o) {
 213         return lessThan(SPECIES.broadcast(o));
 214     }
 215 
 216     @Override
 217     @ForceInline
 218     public Mask<Double, Shapes.SScalableBit> lessThanEq(double o) {
 219         return lessThanEq(SPECIES.broadcast(o));
 220     }
 221 
 222     @Override
 223     @ForceInline
 224     public Mask<Double, Shapes.SScalableBit> greaterThan(double o) {
 225         return greaterThan(SPECIES.broadcast(o));
 226     }
 227 
 228     @Override
 229     @ForceInline
 230     public Mask<Double, Shapes.SScalableBit> greaterThanEq(double o) {
 231         return greaterThanEq(SPECIES.broadcast(o));
 232     }
 233 
 234     @Override
 235     @ForceInline
 236     public DoubleVector<Shapes.SScalableBit> blend(double o, Mask<Double,Shapes.SScalableBit> m) {
 237         return blend(SPECIES.broadcast(o), m);
 238     }
 239 
 240     @Override
 241     @ForceInline
 242     public DoubleVector<Shapes.SScalableBit> div(double o) {
 243         return div(SPECIES.broadcast(o));
 244     }
 245 
 246     @Override
 247     @ForceInline
 248     public DoubleVector<Shapes.SScalableBit> div(double o, Mask<Double,Shapes.SScalableBit> m) {
 249         return div(SPECIES.broadcast(o), m);
 250     }
 251 
 252     @Override
 253     @ForceInline
 254     public DoubleScalableVector div(Vector<Double,Shapes.SScalableBit> v, Mask<Double, Shapes.SScalableBit> m) {
 255         return blend(div(v), m);
 256     }
 257 
 258     @Override
 259     @ForceInline
 260     public DoubleVector<Shapes.SScalableBit> atan2(double o) {
 261         return atan2(SPECIES.broadcast(o));
 262     }
 263 
 264     @Override
 265     @ForceInline
 266     public DoubleVector<Shapes.SScalableBit> atan2(double o, Mask<Double,Shapes.SScalableBit> m) {
 267         return atan2(SPECIES.broadcast(o), m);
 268     }
 269 
 270     @Override
 271     @ForceInline
 272     public DoubleVector<Shapes.SScalableBit> pow(double o) {
 273         return pow(SPECIES.broadcast(o));
 274     }
 275 
 276     @Override
 277     @ForceInline
 278     public DoubleVector<Shapes.SScalableBit> pow(double o, Mask<Double,Shapes.SScalableBit> m) {
 279         return pow(SPECIES.broadcast(o), m);
 280     }
 281 
 282     @Override
 283     @ForceInline
 284     public DoubleVector<Shapes.SScalableBit> fma(double o1, double o2) {
 285         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
 286     }
 287 
 288     @Override
 289     @ForceInline
 290     public DoubleVector<Shapes.SScalableBit> fma(double o1, double o2, Mask<Double,Shapes.SScalableBit> m) {
 291         return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
 292     }
 293 
 294     @Override
 295     @ForceInline
 296     public DoubleVector<Shapes.SScalableBit> hypot(double o) {
 297         return hypot(SPECIES.broadcast(o));
 298     }
 299 
 300     @Override
 301     @ForceInline
 302     public DoubleVector<Shapes.SScalableBit> hypot(double o, Mask<Double,Shapes.SScalableBit> m) {
 303         return hypot(SPECIES.broadcast(o), m);
 304     }
 305 
 306 
 307     // Unary operations
 308 
 309     @ForceInline
 310     @Override
 311     public DoubleScalableVector neg(Mask<Double, Shapes.SScalableBit> m) {
 312         return blend(neg(), m);
 313     }
 314 
 315     @Override
 316     @ForceInline
 317     public DoubleScalableVector abs() {
 318         return VectorIntrinsics.unaryOp(
 319             VECTOR_OP_ABS, DoubleScalableVector.class, double.class, LENGTH,
 320             this,
 321             v1 -> v1.uOp((i, a) -> (double) Math.abs(a)));
 322     }
 323 
 324     @ForceInline
 325     @Override
 326     public DoubleScalableVector abs(Mask<Double, Shapes.SScalableBit> m) {
 327         return blend(abs(), m);
 328     }
 329 
 330     @Override
 331     @ForceInline
 332     public DoubleScalableVector neg() {
 333         return VectorIntrinsics.unaryOp(
 334             VECTOR_OP_NEG, DoubleScalableVector.class, double.class, LENGTH,
 335             this,
 336             v1 -> v1.uOp((i, a) -> (double) -a));
 337     }
 338 
 339     @Override
 340     @ForceInline
 341     public DoubleScalableVector div(Vector<Double,Shapes.SScalableBit> o) {
 342         Objects.requireNonNull(o);
 343         DoubleScalableVector v = (DoubleScalableVector)o;
 344         return VectorIntrinsics.binaryOp(
 345             VECTOR_OP_DIV, DoubleScalableVector.class, double.class, LENGTH,
 346             this, v,
 347             (v1, v2) -> v1.bOp(v2, (i, a, b) -> (double)(a / b)));
 348     }
 349 
 350     @Override
 351     @ForceInline
 352     public DoubleScalableVector sqrt() {
 353         return VectorIntrinsics.unaryOp(
 354             VECTOR_OP_SQRT, DoubleScalableVector.class, double.class, LENGTH,
 355             this,
 356             v1 -> v1.uOp((i, a) -> (double) Math.sqrt((double) a)));
 357     }
 358 
 359     @Override
 360     @ForceInline
 361     public DoubleScalableVector exp() {
 362         return (DoubleScalableVector) VectorIntrinsics.unaryOp(
 363             VECTOR_OP_EXP, DoubleScalableVector.class, double.class, LENGTH,
 364             this,
 365             v1 -> ((DoubleScalableVector)v1).uOp((i, a) -> (double) Math.exp((double) a)));
 366     }
 367 
 368     // Binary operations
 369 
 370     @Override
 371     @ForceInline
 372     public DoubleScalableVector add(Vector<Double,Shapes.SScalableBit> o) {
 373         Objects.requireNonNull(o);
 374         DoubleScalableVector v = (DoubleScalableVector)o;
 375         return VectorIntrinsics.binaryOp(
 376             VECTOR_OP_ADD, DoubleScalableVector.class, double.class, LENGTH,
 377             this, v,
 378             (v1, v2) -> v1.bOp(v2, (i, a, b) -> (double)(a + b)));
 379     }
 380 
 381     @Override
 382     @ForceInline
 383     public DoubleScalableVector add(Vector<Double,Shapes.SScalableBit> v, Mask<Double, Shapes.SScalableBit> m) {
 384         return blend(add(v), m);
 385     }
 386 
 387     @Override
 388     @ForceInline
 389     public DoubleScalableVector sub(Vector<Double,Shapes.SScalableBit> o) {
 390         Objects.requireNonNull(o);
 391         DoubleScalableVector v = (DoubleScalableVector)o;
 392         return VectorIntrinsics.binaryOp(
 393             VECTOR_OP_SUB, DoubleScalableVector.class, double.class, LENGTH,
 394             this, v,
 395             (v1, v2) -> v1.bOp(v2, (i, a, b) -> (double)(a - b)));
 396     }
 397 
 398     @Override
 399     @ForceInline
 400     public DoubleScalableVector sub(Vector<Double,Shapes.SScalableBit> v, Mask<Double, Shapes.SScalableBit> m) {
 401         return blend(sub(v), m);
 402     }
 403 
 404     @Override
 405     @ForceInline
 406     public DoubleScalableVector mul(Vector<Double,Shapes.SScalableBit> o) {
 407         Objects.requireNonNull(o);
 408         DoubleScalableVector v = (DoubleScalableVector)o;
 409         return VectorIntrinsics.binaryOp(
 410             VECTOR_OP_MUL, DoubleScalableVector.class, double.class, LENGTH,
 411             this, v,
 412             (v1, v2) -> v1.bOp(v2, (i, a, b) -> (double)(a * b)));
 413     }
 414 
 415     @Override
 416     @ForceInline
 417     public DoubleScalableVector mul(Vector<Double,Shapes.SScalableBit> v, Mask<Double, Shapes.SScalableBit> m) {
 418         return blend(mul(v), m);
 419     }
 420 
 421     @Override
 422     @ForceInline
 423     public DoubleScalableVector min(Vector<Double,Shapes.SScalableBit> o) {
 424         Objects.requireNonNull(o);
 425         DoubleScalableVector v = (DoubleScalableVector)o;
 426         return (DoubleScalableVector) VectorIntrinsics.binaryOp(
 427             VECTOR_OP_MIN, DoubleScalableVector.class, double.class, LENGTH,
 428             this, v,
 429             (v1, v2) -> ((DoubleScalableVector)v1).bOp(v2, (i, a, b) -> (double) ((a < b) ? a : b)));
 430     }
 431 
 432     @Override
 433     @ForceInline
 434     public DoubleScalableVector max(Vector<Double,Shapes.SScalableBit> o) {
 435         Objects.requireNonNull(o);
 436         DoubleScalableVector v = (DoubleScalableVector)o;
 437         return VectorIntrinsics.binaryOp(
 438             VECTOR_OP_MAX, DoubleScalableVector.class, double.class, LENGTH,
 439             this, v,
 440             (v1, v2) -> v1.bOp(v2, (i, a, b) -> (double) ((a > b) ? a : b)));
 441         }
 442 
 443 
 444     // Ternary operations
 445 
 446     @Override
 447     @ForceInline
 448     public DoubleScalableVector fma(Vector<Double,Shapes.SScalableBit> o1, Vector<Double,Shapes.SScalableBit> o2) {
 449         Objects.requireNonNull(o1);
 450         Objects.requireNonNull(o2);
 451         DoubleScalableVector v1 = (DoubleScalableVector)o1;
 452         DoubleScalableVector v2 = (DoubleScalableVector)o2;
 453         return VectorIntrinsics.ternaryOp(
 454             VECTOR_OP_FMA, DoubleScalableVector.class, double.class, LENGTH,
 455             this, v1, v2,
 456             (w1, w2, w3) -> w1.tOp(w2, w3, (i, a, b, c) -> Math.fma(a, b, c)));
 457     }
 458 
 459     // Type specific horizontal reductions
 460 
 461     @Override
 462     @ForceInline
 463     public double addAll() {
 464         long bits = (long) VectorIntrinsics.reductionCoerced(
 465                                 VECTOR_OP_ADD, DoubleScalableVector.class, double.class, LENGTH,
 466                                 this,
 467                                 v -> {
 468                                     double r = v.rOp((double) 0, (i, a, b) -> (double) (a + b));
 469                                     return (long)Double.doubleToLongBits(r);
 470                                 });
 471         return Double.longBitsToDouble(bits);
 472     }
 473 
 474     @Override
 475     @ForceInline
 476     public double subAll() {
 477         long bits = (long) VectorIntrinsics.reductionCoerced(
 478                                 VECTOR_OP_SUB, DoubleScalableVector.class, double.class, LENGTH,
 479                                 this,
 480                                 v -> {
 481                                     double r = v.rOp((double) 0, (i, a, b) -> (double) (a - b));
 482                                     return (long)Double.doubleToLongBits(r);
 483                                 });
 484         return Double.longBitsToDouble(bits);
 485     }
 486 
 487     @Override
 488     @ForceInline
 489     public double mulAll() {
 490         long bits = (long) VectorIntrinsics.reductionCoerced(
 491                                 VECTOR_OP_MUL, DoubleScalableVector.class, double.class, LENGTH,
 492                                 this,
 493                                 v -> {
 494                                     double r = v.rOp((double) 1, (i, a, b) -> (double) (a * b));
 495                                     return (long)Double.doubleToLongBits(r);
 496                                 });
 497         return Double.longBitsToDouble(bits);
 498     }
 499 
 500     @Override
 501     @ForceInline
 502     public double minAll() {
 503         long bits = (long) VectorIntrinsics.reductionCoerced(
 504                                 VECTOR_OP_MIN, DoubleScalableVector.class, double.class, LENGTH,
 505                                 this,
 506                                 v -> {
 507                                     double r = v.rOp(Double.MAX_VALUE , (i, a, b) -> (double) ((a < b) ? a : b));
 508                                     return (long)Double.doubleToLongBits(r);
 509                                 });
 510         return Double.longBitsToDouble(bits);
 511     }
 512 
 513     @Override
 514     @ForceInline
 515     public double maxAll() {
 516         long bits = (long) VectorIntrinsics.reductionCoerced(
 517                                 VECTOR_OP_MAX, DoubleScalableVector.class, double.class, LENGTH,
 518                                 this,
 519                                 v -> {
 520                                     double r = v.rOp(Double.MIN_VALUE , (i, a, b) -> (double) ((a > b) ? a : b));
 521                                     return (long)Double.doubleToLongBits(r);
 522                                 });
 523         return Double.longBitsToDouble(bits);
 524     }
 525 
 526 
 527     @Override
 528     @ForceInline
 529     public double addAll(Mask<Double, Shapes.SScalableBit> m) {
 530         return blend(SPECIES.broadcast((double) 0), m).addAll();
 531     }
 532 
 533     @Override
 534     @ForceInline
 535     public double subAll(Mask<Double, Shapes.SScalableBit> m) {
 536         return blend(SPECIES.broadcast((double) 0), m).subAll();
 537     }
 538 
 539     @Override
 540     @ForceInline
 541     public double mulAll(Mask<Double, Shapes.SScalableBit> m) {
 542         return blend(SPECIES.broadcast((double) 1), m).mulAll();
 543     }
 544 
 545     @Override
 546     @ForceInline
 547     public double minAll(Mask<Double, Shapes.SScalableBit> m) {
 548         return blend(SPECIES.broadcast(Double.MAX_VALUE), m).minAll();
 549     }
 550 
 551     @Override
 552     @ForceInline
 553     public double maxAll(Mask<Double, Shapes.SScalableBit> m) {
 554         return blend(SPECIES.broadcast(Double.MIN_VALUE), m).maxAll();
 555     }
 556 
 557     @Override
 558     @ForceInline
 559     public Shuffle<Double, Shapes.SScalableBit> toShuffle() {
 560         double[] a = toArray();
 561         int[] sa = new int[a.length];
 562         for (int i = 0; i < a.length; i++) {
 563             sa[i] = (int) a[i];
 564         }
 565         return SPECIES.shuffleFromArray(sa, 0);
 566     }
 567 
 568     // Memory operations
 569 
 570     private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
 571 
 572     @Override
 573     @ForceInline
 574     public void intoArray(double[] a, int ix) {
 575         Objects.requireNonNull(a);
 576         ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
 577         VectorIntrinsics.store(DoubleScalableVector.class, double.class, LENGTH,
 578                                a, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
 579                                this,
 580                                a, ix,
 581                                (arr, idx, v) -> v.forEach((i, e) -> arr[idx + i] = e));
 582     }
 583 
 584     @Override
 585     @ForceInline
 586     public final void intoArray(double[] a, int ax, Mask<Double, Shapes.SScalableBit> m) {
 587         // @@@ This can result in out of bounds errors for unset mask lanes
 588         DoubleScalableVector oldVal = SPECIES.fromArray(a, ax);
 589         DoubleScalableVector newVal = oldVal.blend(this, m);
 590         newVal.intoArray(a, ax);
 591     }
 592 
 593     @Override
 594     @ForceInline
 595     public void intoByteArray(byte[] a, int ix) {
 596         // @@@ Endianess
 597         Objects.requireNonNull(a);
 598         ix = VectorIntrinsics.checkIndex(ix, a.length, bitSize() / Byte.SIZE);
 599         VectorIntrinsics.store(DoubleScalableVector.class, double.class, LENGTH,
 600                                a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 601                                this,
 602                                a, ix,
 603                                (c, idx, v) -> {
 604                                    ByteBuffer bbc = ByteBuffer.wrap(c, idx, c.length - idx).order(ByteOrder.nativeOrder());
 605                                    DoubleBuffer tb = bbc.asDoubleBuffer();
 606                                    v.forEach((i, e) -> tb.put(e));
 607                                });
 608     }
 609 
 610     @Override
 611     @ForceInline
 612     public final void intoByteArray(byte[] a, int ix, Mask<Double, Shapes.SScalableBit> m) {
 613         // @@@ This can result in out of bounds errors for unset mask lanes
 614         DoubleScalableVector oldVal = SPECIES.fromByteArray(a, ix);
 615         DoubleScalableVector newVal = oldVal.blend(this, m);
 616         newVal.intoByteArray(a, ix);
 617     }
 618 
 619     @Override
 620     @ForceInline
 621     public void intoByteBuffer(ByteBuffer bb, int ix) {
 622         // @@@ Endianess
 623         if (bb.order() != ByteOrder.nativeOrder()) {
 624             throw new IllegalArgumentException();
 625         }
 626         if (bb.isReadOnly()) {
 627             throw new ReadOnlyBufferException();
 628         }
 629         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), bitSize() / Byte.SIZE);
 630         VectorIntrinsics.store(DoubleScalableVector.class, double.class, LENGTH,
 631                                U.getObject(bb, BYTE_BUFFER_HB), ix + U.getLong(bb, BUFFER_ADDRESS),
 632                                this,
 633                                bb, ix,
 634                                (c, idx, v) -> {
 635                                    ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
 636                                    DoubleBuffer tb = bbc.asDoubleBuffer();
 637                                    v.forEach((i, e) -> tb.put(e));
 638                                });
 639     }
 640 
 641     @Override
 642     @ForceInline
 643     public void intoByteBuffer(ByteBuffer bb, int ix, Mask<Double, Shapes.SScalableBit> m) {
 644         // @@@ This can result in out of bounds errors for unset mask lanes
 645         DoubleScalableVector oldVal = SPECIES.fromByteBuffer(bb, ix);
 646         DoubleScalableVector newVal = oldVal.blend(this, m);
 647         newVal.intoByteBuffer(bb, ix);
 648     }
 649 
 650     //
 651 
 652     @Override
 653     public String toString() {
 654         return Arrays.toString(getElements());
 655     }
 656 
 657     @Override
 658     public boolean equals(Object o) {
 659         if (this == o) return true;
 660         if (o == null || this.getClass() != o.getClass()) return false;
 661 
 662         // @@@ Use equal op
 663         DoubleScalableVector that = (DoubleScalableVector) o;
 664         return Arrays.equals(this.getElements(), that.getElements());
 665     }
 666 
 667     @Override
 668     public int hashCode() {
 669         return Arrays.hashCode(vec);
 670     }
 671 
 672     // Binary test
 673 
 674     @Override
 675     DoubleScalableMask bTest(Vector<Double, Shapes.SScalableBit> o, FBinTest f) {
 676         double[] vec1 = getElements();
 677         double[] vec2 = ((DoubleScalableVector)o).getElements();
 678         boolean[] bits = new boolean[length()];
 679         for (int i = 0; i < length(); i++){
 680             bits[i] = f.apply(i, vec1[i], vec2[i]);
 681         }
 682         return new DoubleScalableMask(bits);
 683     }
 684 
 685     // Comparisons
 686 
 687     @Override
 688     @ForceInline
 689     public DoubleScalableMask equal(Vector<Double, Shapes.SScalableBit> o) {
 690         Objects.requireNonNull(o);
 691         DoubleScalableVector v = (DoubleScalableVector)o;
 692 
 693         return VectorIntrinsics.compare(
 694             BT_eq, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 695             this, v,
 696             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a == b));
 697     }
 698 
 699     @Override
 700     @ForceInline
 701     public DoubleScalableMask notEqual(Vector<Double, Shapes.SScalableBit> o) {
 702         Objects.requireNonNull(o);
 703         DoubleScalableVector v = (DoubleScalableVector)o;
 704 
 705         return VectorIntrinsics.compare(
 706             BT_ne, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 707             this, v,
 708             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a != b));
 709     }
 710 
 711     @Override
 712     @ForceInline
 713     public DoubleScalableMask lessThan(Vector<Double, Shapes.SScalableBit> o) {
 714         Objects.requireNonNull(o);
 715         DoubleScalableVector v = (DoubleScalableVector)o;
 716 
 717         return VectorIntrinsics.compare(
 718             BT_lt, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 719             this, v,
 720             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a < b));
 721     }
 722 
 723     @Override
 724     @ForceInline
 725     public DoubleScalableMask lessThanEq(Vector<Double, Shapes.SScalableBit> o) {
 726         Objects.requireNonNull(o);
 727         DoubleScalableVector v = (DoubleScalableVector)o;
 728 
 729         return VectorIntrinsics.compare(
 730             BT_le, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 731             this, v,
 732             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a <= b));
 733     }
 734 
 735     @Override
 736     @ForceInline
 737     public DoubleScalableMask greaterThan(Vector<Double, Shapes.SScalableBit> o) {
 738         Objects.requireNonNull(o);
 739         DoubleScalableVector v = (DoubleScalableVector)o;
 740 
 741         return (DoubleScalableMask) VectorIntrinsics.compare(
 742             BT_gt, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 743             this, v,
 744             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a > b));
 745     }
 746 
 747     @Override
 748     @ForceInline
 749     public DoubleScalableMask greaterThanEq(Vector<Double, Shapes.SScalableBit> o) {
 750         Objects.requireNonNull(o);
 751         DoubleScalableVector v = (DoubleScalableVector)o;
 752 
 753         return VectorIntrinsics.compare(
 754             BT_ge, DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 755             this, v,
 756             (v1, v2) -> v1.bTest(v2, (i, a, b) -> a >= b));
 757     }
 758 
 759     // Foreach
 760 
 761     @Override
 762     void forEach(FUnCon f) {
 763         double[] vec = getElements();
 764         for (int i = 0; i < length(); i++) {
 765             f.apply(i, vec[i]);
 766         }
 767     }
 768 
 769     @Override
 770     void forEach(Mask<Double, Shapes.SScalableBit> o, FUnCon f) {
 771         boolean[] mbits = ((DoubleScalableMask)o).getBits();
 772         forEach((i, a) -> {
 773             if (mbits[i]) { f.apply(i, a); }
 774         });
 775     }
 776 
 777     LongScalableVector toBits() {
 778         double[] vec = getElements();
 779         long[] res = new long[this.species().length()];
 780         for(int i = 0; i < this.species().length(); i++){
 781             res[i] = Double.doubleToLongBits(vec[i]);
 782         }
 783         return new LongScalableVector(res);
 784     }
 785 
 786 
 787     @Override
 788     public DoubleScalableVector rotateEL(int j) {
 789         double[] vec = getElements();
 790         double[] res = new double[length()];
 791         for (int i = 0; i < length(); i++){
 792             res[(j + i) % length()] = vec[i];
 793         }
 794         return new DoubleScalableVector(res);
 795     }
 796 
 797     @Override
 798     public DoubleScalableVector rotateER(int j) {
 799         double[] vec = getElements();
 800         double[] res = new double[length()];
 801         for (int i = 0; i < length(); i++){
 802             int z = i - j;
 803             if(j < 0) {
 804                 res[length() + z] = vec[i];
 805             } else {
 806                 res[z] = vec[i];
 807             }
 808         }
 809         return new DoubleScalableVector(res);
 810     }
 811 
 812     @Override
 813     public DoubleScalableVector shiftEL(int j) {
 814         double[] vec = getElements();
 815         double[] res = new double[length()];
 816         for (int i = 0; i < length() - j; i++) {
 817             res[i] = vec[i + j];
 818         }
 819         return new DoubleScalableVector(res);
 820     }
 821 
 822     @Override
 823     public DoubleScalableVector shiftER(int j) {
 824         double[] vec = getElements();
 825         double[] res = new double[length()];
 826         for (int i = 0; i < length() - j; i++){
 827             res[i + j] = vec[i];
 828         }
 829         return new DoubleScalableVector(res);
 830     }
 831 
 832     @Override
 833     @ForceInline
 834     public DoubleScalableVector rearrange(Vector<Double, Shapes.SScalableBit> v,
 835                                   Shuffle<Double, Shapes.SScalableBit> s, Mask<Double, Shapes.SScalableBit> m) {
 836         return this.rearrange(s).blend(v.rearrange(s), m);
 837     }
 838 
 839     @Override
 840     public DoubleScalableVector rearrange(Shuffle<Double, Shapes.SScalableBit> s) {
 841         return uOp((i, a) -> {
 842             double[] vec = this.getElements();
 843             int ei = s.getElement(i);
 844             return vec[ei];
 845         });
 846     }
 847 
 848     @Override
 849     @ForceInline
 850     public DoubleScalableVector blend(Vector<Double, Shapes.SScalableBit> o1, Mask<Double, Shapes.SScalableBit> o2) {
 851         Objects.requireNonNull(o1);
 852         Objects.requireNonNull(o2);
 853         DoubleScalableVector v = (DoubleScalableVector)o1;
 854         DoubleScalableMask   m = (DoubleScalableMask)o2;
 855 
 856         return VectorIntrinsics.blend(
 857             DoubleScalableVector.class, DoubleScalableMask.class, double.class, LENGTH,
 858             this, v, m,
 859             (v1, v2, m_) -> v1.bOp(v2, (i, a, b) -> m_.getElement(i) ? b : a));
 860     }
 861 
 862     // Accessors
 863 
 864     @Override
 865     public double get(int i) {
 866         if (i < 0 || i >= LENGTH) {
 867             throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + LENGTH);
 868         }
 869         long bits = (long) VectorIntrinsics.extract(
 870                                 DoubleScalableVector.class, double.class, LENGTH,
 871                                 this, i,
 872                                 (vec, ix) -> {
 873                                     double[] vecarr = vec.getElements();
 874                                     return (long)Double.doubleToLongBits(vecarr[ix]);
 875                                 });
 876         return Double.longBitsToDouble(bits);
 877     }
 878 
 879     @Override
 880     public DoubleScalableVector with(int i, double e) {
 881         if (i < 0 || i >= LENGTH) {
 882             throw new IllegalArgumentException("Index " + i + " must be zero or positive, and less than " + LENGTH);
 883         }
 884         return VectorIntrinsics.insert(
 885                                 DoubleScalableVector.class, double.class, LENGTH,
 886                                 this, i, (long)Double.doubleToLongBits(e),
 887                                 (v, ix, bits) -> {
 888                                     double[] res = v.getElements().clone();
 889                                     res[ix] = Double.longBitsToDouble((long)bits);
 890                                     return new DoubleScalableVector(res);
 891                                 });
 892     }
 893 
 894     // Mask
 895 
 896     static final class DoubleScalableMask extends AbstractMask<Double, Shapes.SScalableBit> {
 897         static final DoubleScalableMask TRUE_MASK = new DoubleScalableMask(true);
 898         static final DoubleScalableMask FALSE_MASK = new DoubleScalableMask(false);
 899 
 900         // FIXME: was temporarily put here to simplify rematerialization support in the JVM
 901         private final boolean[] bits; // Don't access directly, use getBits() instead.
 902 
 903         public DoubleScalableMask(boolean[] bits) {
 904             this(bits, 0);
 905         }
 906 
 907         public DoubleScalableMask(boolean[] bits, int offset) {
 908             boolean[] a = new boolean[species().length()];
 909             for (int i = 0; i < a.length; i++) {
 910                 a[i] = bits[offset + i];
 911             }
 912             this.bits = a;
 913         }
 914 
 915         public DoubleScalableMask(boolean val) {
 916             boolean[] bits = new boolean[species().length()];
 917             Arrays.fill(bits, val);
 918             this.bits = bits;
 919         }
 920 
 921         boolean[] getBits() {
 922             return VectorIntrinsics.maybeRebox(this).bits;
 923         }
 924 
 925         @Override
 926         DoubleScalableMask uOp(MUnOp f) {
 927             boolean[] res = new boolean[species().length()];
 928             boolean[] bits = getBits();
 929             for (int i = 0; i < species().length(); i++) {
 930                 res[i] = f.apply(i, bits[i]);
 931             }
 932             return new DoubleScalableMask(res);
 933         }
 934 
 935         @Override
 936         DoubleScalableMask bOp(Mask<Double, Shapes.SScalableBit> o, MBinOp f) {
 937             boolean[] res = new boolean[species().length()];
 938             boolean[] bits = getBits();
 939             boolean[] mbits = ((DoubleScalableMask)o).getBits();
 940             for (int i = 0; i < species().length(); i++) {
 941                 res[i] = f.apply(i, bits[i], mbits[i]);
 942             }
 943             return new DoubleScalableMask(res);
 944         }
 945 
 946         @Override
 947         public DoubleScalableSpecies species() {
 948             return SPECIES;
 949         }
 950 
 951         @Override
 952         public DoubleScalableVector toVector() {
 953             double[] res = new double[species().length()];
 954             boolean[] bits = getBits();
 955             for (int i = 0; i < species().length(); i++) {
 956                 // -1 will result in the most significant bit being set in
 957                 // addition to some or all other bits
 958                 res[i] = (double) (bits[i] ? -1 : 0);
 959             }
 960             return new DoubleScalableVector(res);
 961         }
 962 
 963         // Unary operations
 964 
 965         @Override
 966         @ForceInline
 967         public DoubleScalableMask not() {
 968             return (DoubleScalableMask) VectorIntrinsics.unaryOp(
 969                                              VECTOR_OP_NOT, DoubleScalableMask.class, long.class, LENGTH,
 970                                              this,
 971                                              (m1) -> m1.uOp((i, a) -> !a));
 972         }
 973 
 974         // Binary operations
 975 
 976         @Override
 977         @ForceInline
 978         public DoubleScalableMask and(Mask<Double,Shapes.SScalableBit> o) {
 979             Objects.requireNonNull(o);
 980             DoubleScalableMask m = (DoubleScalableMask)o;
 981             return VectorIntrinsics.binaryOp(VECTOR_OP_AND, DoubleScalableMask.class, long.class, LENGTH,
 982                                              this, m,
 983                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a & b));
 984         }
 985 
 986         @Override
 987         @ForceInline
 988         public DoubleScalableMask or(Mask<Double,Shapes.SScalableBit> o) {
 989             Objects.requireNonNull(o);
 990             DoubleScalableMask m = (DoubleScalableMask)o;
 991             return VectorIntrinsics.binaryOp(VECTOR_OP_OR, DoubleScalableMask.class, long.class, LENGTH,
 992                                              this, m,
 993                                              (m1, m2) -> m1.bOp(m2, (i, a, b) -> a | b));
 994         }
 995 
 996         // Reductions
 997 
 998         @Override
 999         @ForceInline
1000         public boolean anyTrue() {
1001             return VectorIntrinsics.test(COND_notZero, DoubleScalableMask.class, long.class, LENGTH,
1002                                          this, this,
1003                                          (m1, m2) -> super.anyTrue());
1004         }
1005 
1006         @Override
1007         @ForceInline
1008         public boolean allTrue() {
1009             return VectorIntrinsics.test(COND_carrySet, DoubleScalableMask.class, long.class, LENGTH,
1010                                          this, species().maskAllTrue(),
1011                                          (m1, m2) -> super.allTrue());
1012         }
1013     }
1014 
1015     // Shuffle
1016 
1017     static final class DoubleScalableShuffle extends AbstractShuffle<Double, Shapes.SScalableBit> {
1018         DoubleScalableShuffle(byte[] reorder) {
1019             super(reorder);
1020         }
1021 
1022         public DoubleScalableShuffle(int[] reorder) {
1023             super(reorder);
1024         }
1025 
1026         public DoubleScalableShuffle(int[] reorder, int i) {
1027             super(reorder, i);
1028         }
1029 
1030         public DoubleScalableShuffle(IntUnaryOperator f) {
1031             super(f);
1032         }
1033 
1034         @Override
1035         public DoubleScalableSpecies species() {
1036             return SPECIES;
1037         }
1038 
1039         @Override
1040         public DoubleScalableVector toVector() {
1041             double[] va = new double[SPECIES.length()];
1042             for (int i = 0; i < va.length; i++) {
1043               va[i] = (double) getElement(i);
1044             }
1045             return species().fromArray(va, 0);
1046         }
1047 
1048         @Override
1049         public DoubleScalableShuffle rearrange(Vector.Shuffle<Double, Shapes.SScalableBit> o) {
1050             DoubleScalableShuffle s = (DoubleScalableShuffle) o;
1051             byte[] r = new byte[reorder.length];
1052             for (int i = 0; i < reorder.length; i++) {
1053                 r[i] = reorder[s.reorder[i]];
1054             }
1055             return new DoubleScalableShuffle(r);
1056         }
1057     }
1058 
1059     // Species
1060 
1061     @Override
1062     public DoubleScalableSpecies species() {
1063         return SPECIES;
1064     }
1065 
1066     static final class DoubleScalableSpecies extends DoubleSpecies<Shapes.SScalableBit> {
1067         static final int BIT_SIZE = Shapes.S_Scalable_BIT.bitSize();
1068 
1069         static final int LENGTH = BIT_SIZE / Double.SIZE;
1070 
1071         @Override
1072         public String toString() {
1073            StringBuilder sb = new StringBuilder("Shape[");
1074            sb.append(bitSize()).append(" bits, ");
1075            sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
1076            sb.append(elementSize()).append(" bits");
1077            sb.append("]");
1078            return sb.toString();
1079         }
1080 
1081         @Override
1082         @ForceInline
1083         public int bitSize() {
1084             return BIT_SIZE;
1085         }
1086 
1087         @Override
1088         @ForceInline
1089         public int length() {
1090             return LENGTH;
1091         }
1092 
1093         @Override
1094         @ForceInline
1095         public Class<Double> elementType() {
1096             return double.class;
1097         }
1098 
1099         @Override
1100         @ForceInline
1101         public int elementSize() {
1102             return Double.SIZE;
1103         }
1104 
1105         @Override
1106         @ForceInline
1107         public Shapes.SScalableBit shape() {
1108             return Shapes.S_Scalable_BIT;
1109         }
1110 
1111         @Override
1112         DoubleScalableVector op(FOp f) {
1113             double[] res = new double[length()];
1114             for (int i = 0; i < length(); i++) {
1115                 res[i] = f.apply(i);
1116             }
1117             return new DoubleScalableVector(res);
1118         }
1119 
1120         @Override
1121         DoubleScalableVector op(Mask<Double, Shapes.SScalableBit> o, FOp f) {
1122             double[] res = new double[length()];
1123             boolean[] mbits = ((DoubleScalableMask)o).getBits();
1124             for (int i = 0; i < length(); i++) {
1125                 if (mbits[i]) {
1126                     res[i] = f.apply(i);
1127                 }
1128             }
1129             return new DoubleScalableVector(res);
1130         }
1131 
1132         // Factories
1133 
1134         @Override
1135         public DoubleScalableMask maskFromValues(boolean... bits) {
1136             return new DoubleScalableMask(bits);
1137         }
1138 
1139         @Override
1140         public DoubleScalableMask maskFromArray(boolean[] bits, int i) {
1141             return new DoubleScalableMask(bits, i);
1142         }
1143 
1144         @Override
1145         public DoubleScalableShuffle shuffle(IntUnaryOperator f) {
1146             return new DoubleScalableShuffle(f);
1147         }
1148 
1149         @Override
1150         public DoubleScalableShuffle shuffleIota() {
1151             return new DoubleScalableShuffle(AbstractShuffle.IDENTITY);
1152         }
1153 
1154         @Override
1155         public DoubleScalableShuffle shuffleFromValues(int... ixs) {
1156             return new DoubleScalableShuffle(ixs);
1157         }
1158 
1159         @Override
1160         public DoubleScalableShuffle shuffleFromArray(int[] ixs, int i) {
1161             return new DoubleScalableShuffle(ixs, i);
1162         }
1163 
1164         @Override
1165         @ForceInline
1166         public DoubleScalableVector zero() {
1167             return VectorIntrinsics.broadcastCoerced(DoubleScalableVector.class, double.class, LENGTH,
1168                                                      Double.doubleToLongBits(0.0f),
1169                                                      (z -> ZERO));
1170         }
1171 
1172         @Override
1173         @ForceInline
1174         public DoubleScalableVector broadcast(double e) {
1175             return VectorIntrinsics.broadcastCoerced(
1176                 DoubleScalableVector.class, double.class, LENGTH,
1177                 Double.doubleToLongBits(e),
1178                 ((long bits) -> SPECIES.op(i -> Double.longBitsToDouble((long)bits))));
1179         }
1180 
1181         @Override
1182         @ForceInline
1183         public DoubleScalableMask maskAllTrue() {
1184             return VectorIntrinsics.broadcastCoerced(DoubleScalableMask.class, long.class, LENGTH,
1185                                                      (long)-1,
1186                                                      (z -> DoubleScalableMask.TRUE_MASK));
1187         }
1188 
1189         @Override
1190         @ForceInline
1191         public DoubleScalableMask maskAllFalse() {
1192             return VectorIntrinsics.broadcastCoerced(DoubleScalableMask.class, long.class, LENGTH,
1193                                                      0,
1194                                                      (z -> DoubleScalableMask.FALSE_MASK));
1195         }
1196 
1197         @Override
1198         @ForceInline
1199         public DoubleScalableVector scalars(double... es) {
1200             Objects.requireNonNull(es);
1201             int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
1202             return VectorIntrinsics.load(DoubleScalableVector.class, double.class, LENGTH,
1203                                          es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
1204                                          es, ix,
1205                                          (c, idx) -> op(n -> c[idx + n]));
1206         }
1207 
1208         @Override
1209         @ForceInline
1210         public DoubleScalableVector fromArray(double[] a, int ix) {
1211             Objects.requireNonNull(a);
1212             ix = VectorIntrinsics.checkIndex(ix, a.length, LENGTH);
1213             return VectorIntrinsics.load(DoubleScalableVector.class, double.class, LENGTH,
1214                                          a, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
1215                                          a, ix,
1216                                          (c, idx) -> op(n -> c[idx + n]));
1217         }
1218 
1219         @Override
1220         @ForceInline
1221         public DoubleScalableVector fromArray(double[] a, int ax, Mask<Double, Shapes.SScalableBit> m) {
1222             // @@@ This can result in out of bounds errors for unset mask lanes
1223             return zero().blend(fromArray(a, ax), m);
1224         }
1225 
1226         @Override
1227         @ForceInline
1228         public DoubleScalableVector fromByteArray(byte[] a, int ix) {
1229             // @@@ Endianess
1230             Objects.requireNonNull(a);
1231             ix = VectorIntrinsics.checkIndex(ix, a.length, bitSize() / Byte.SIZE);
1232             return VectorIntrinsics.load(DoubleScalableVector.class, double.class, LENGTH,
1233                                          a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
1234                                          a, ix,
1235                                          (c, idx) -> {
1236                                              ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
1237                                              DoubleBuffer tb = bbc.asDoubleBuffer();
1238                                              return op(i -> tb.get());
1239                                          });
1240         }
1241 
1242         @Override
1243         @ForceInline
1244         public DoubleScalableVector fromByteArray(byte[] a, int ix, Mask<Double, Shapes.SScalableBit> m) {
1245             // @@@ This can result in out of bounds errors for unset mask lanes
1246             return zero().blend(fromByteArray(a, ix), m);
1247         }
1248 
1249         @Override
1250         @ForceInline
1251         public DoubleScalableVector fromByteBuffer(ByteBuffer bb, int ix) {
1252             // @@@ Endianess
1253             if (bb.order() != ByteOrder.nativeOrder()) {
1254                 throw new IllegalArgumentException();
1255             }
1256             ix = VectorIntrinsics.checkIndex(ix, bb.limit(), bitSize() / Byte.SIZE);
1257             return VectorIntrinsics.load(DoubleScalableVector.class, double.class, LENGTH,
1258                                          U.getObject(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
1259                                          bb, ix,
1260                                          (c, idx) -> {
1261                                              ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
1262                                              DoubleBuffer tb = bbc.asDoubleBuffer();
1263                                              return op(i -> tb.get());
1264                                          });
1265         }
1266 
1267         @Override
1268         @ForceInline
1269         public DoubleScalableVector fromByteBuffer(ByteBuffer bb, int ix, Mask<Double, Shapes.SScalableBit> m) {
1270             // @@@ This can result in out of bounds errors for unset mask lanes
1271             return zero().blend(fromByteBuffer(bb, ix), m);
1272         }
1273 
1274         @Override
1275         @ForceInline
1276         @SuppressWarnings("unchecked")
1277         public <F, T extends Shape> DoubleScalableVector cast(Vector<F, T> o) {
1278             if (o.length() != LENGTH)
1279                 throw new IllegalArgumentException("Vector length this species length differ");
1280 
1281             return VectorIntrinsics.cast(
1282                 o.getClass(),
1283                 o.elementType(), LENGTH,
1284                 double.class, LENGTH,
1285                 o, this,
1286                 (s, v) -> s.castDefault(v)
1287             );
1288         }
1289 
1290         @SuppressWarnings("unchecked")
1291         @ForceInline
1292         private <F, T extends Shape> DoubleScalableVector castDefault(Vector<F, T> v) {
1293             // Allocate array of required size
1294             int limit = length();
1295             double[] a = new double[limit];
1296 
1297             Class<?> vtype = v.species().elementType();
1298             if (vtype == byte.class) {
1299                 ByteVector<T> tv = (ByteVector<T>)v;
1300                 for (int i = 0; i < limit; i++) {
1301                     a[i] = (double) tv.get(i);
1302                 }
1303             } else if (vtype == short.class) {
1304                 ShortVector<T> tv = (ShortVector<T>)v;
1305                 for (int i = 0; i < limit; i++) {
1306                     a[i] = (double) tv.get(i);
1307                 }
1308             } else if (vtype == int.class) {
1309                 IntVector<T> tv = (IntVector<T>)v;
1310                 for (int i = 0; i < limit; i++) {
1311                     a[i] = (double) tv.get(i);
1312                 }
1313             } else if (vtype == long.class){
1314                 LongVector<T> tv = (LongVector<T>)v;
1315                 for (int i = 0; i < limit; i++) {
1316                     a[i] = (double) tv.get(i);
1317                 }
1318             } else if (vtype == float.class){
1319                 FloatVector<T> tv = (FloatVector<T>)v;
1320                 for (int i = 0; i < limit; i++) {
1321                     a[i] = (double) tv.get(i);
1322                 }
1323             } else if (vtype == double.class){
1324                 DoubleVector<T> tv = (DoubleVector<T>)v;
1325                 for (int i = 0; i < limit; i++) {
1326                     a[i] = (double) tv.get(i);
1327                 }
1328             } else {
1329                 throw new UnsupportedOperationException("Bad lane type for casting.");
1330             }
1331 
1332             return scalars(a);
1333         }
1334 
1335         @Override
1336         @ForceInline
1337         public <E, S extends Shape> DoubleScalableMask cast(Mask<E, S> m) {
1338             if (m.length() != LENGTH)
1339                 throw new IllegalArgumentException("Mask length this species length differ");
1340             return new DoubleScalableMask(m.toArray());
1341         }
1342 
1343         @Override
1344         @ForceInline
1345         public <E, S extends Shape> DoubleScalableShuffle cast(Shuffle<E, S> s) {
1346             if (s.length() != LENGTH)
1347                 throw new IllegalArgumentException("Shuffle length this species length differ");
1348             return new DoubleScalableShuffle(s.toArray());
1349         }
1350 
1351         @Override
1352         @ForceInline
1353         @SuppressWarnings("unchecked")
1354         public <F> DoubleScalableVector rebracket(Vector<F, Shapes.SScalableBit> o) {
1355             Objects.requireNonNull(o);
1356             if (o.elementType() == byte.class) {
1357                 ByteScalableVector so = (ByteScalableVector)o;
1358                 return VectorIntrinsics.reinterpret(
1359                     ByteScalableVector.class,
1360                     byte.class, so.length(),
1361                     double.class, LENGTH,
1362                     so, this,
1363                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1364                 );
1365             } else if (o.elementType() == short.class) {
1366                 ShortScalableVector so = (ShortScalableVector)o;
1367                 return VectorIntrinsics.reinterpret(
1368                     ShortScalableVector.class,
1369                     short.class, so.length(),
1370                     double.class, LENGTH,
1371                     so, this,
1372                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1373                 );
1374             } else if (o.elementType() == int.class) {
1375                 IntScalableVector so = (IntScalableVector)o;
1376                 return VectorIntrinsics.reinterpret(
1377                     IntScalableVector.class,
1378                     int.class, so.length(),
1379                     double.class, LENGTH,
1380                     so, this,
1381                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1382                 );
1383             } else if (o.elementType() == long.class) {
1384                 LongScalableVector so = (LongScalableVector)o;
1385                 return VectorIntrinsics.reinterpret(
1386                     LongScalableVector.class,
1387                     long.class, so.length(),
1388                     double.class, LENGTH,
1389                     so, this,
1390                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1391                 );
1392             } else if (o.elementType() == float.class) {
1393                 FloatScalableVector so = (FloatScalableVector)o;
1394                 return VectorIntrinsics.reinterpret(
1395                     FloatScalableVector.class,
1396                     float.class, so.length(),
1397                     double.class, LENGTH,
1398                     so, this,
1399                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1400                 );
1401             } else if (o.elementType() == double.class) {
1402                 DoubleScalableVector so = (DoubleScalableVector)o;
1403                 return VectorIntrinsics.reinterpret(
1404                     DoubleScalableVector.class,
1405                     double.class, so.length(),
1406                     double.class, LENGTH,
1407                     so, this,
1408                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1409                 );
1410             } else {
1411                 throw new InternalError("Unimplemented type");
1412             }
1413         }
1414 
1415         @Override
1416         @ForceInline
1417         @SuppressWarnings("unchecked")
1418         public <T extends Shape> DoubleScalableVector resize(Vector<Double, T> o) {
1419             Objects.requireNonNull(o);
1420             if (o.bitSize() == 64) {
1421                 Double64Vector so = (Double64Vector)o;
1422                 return VectorIntrinsics.reinterpret(
1423                     Double64Vector.class,
1424                     double.class, so.length(),
1425                     double.class, LENGTH,
1426                     so, this,
1427                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1428                 );
1429             } else if (o.bitSize() == 128) {
1430                 Double128Vector so = (Double128Vector)o;
1431                 return VectorIntrinsics.reinterpret(
1432                     Double128Vector.class,
1433                     double.class, so.length(),
1434                     double.class, LENGTH,
1435                     so, this,
1436                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1437                 );
1438             } else if (o.bitSize() == 256) {
1439                 Double256Vector so = (Double256Vector)o;
1440                 return VectorIntrinsics.reinterpret(
1441                     Double256Vector.class,
1442                     double.class, so.length(),
1443                     double.class, LENGTH,
1444                     so, this,
1445                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1446                 );
1447             } else if (o.bitSize() == 512) {
1448                 Double512Vector so = (Double512Vector)o;
1449                 return VectorIntrinsics.reinterpret(
1450                     Double512Vector.class,
1451                     double.class, so.length(),
1452                     double.class, LENGTH,
1453                     so, this,
1454                     (s, v) -> (DoubleScalableVector) s.reshape(v)
1455                 );
1456             } else if ((o.bitSize() <= 2048) && (o.bitSize() % 128 == 0)) {
1457                 throw new InternalError("Resize to scalable shape unimplemented.");
1458             } else {
1459                 throw new InternalError("Unimplemented size");
1460             }
1461         }
1462     }
1463 }