1 /*
   2  * Copyright (c) 2017, 2021, 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 any
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.nio.ByteOrder;
  29 import java.nio.ReadOnlyBufferException;
  30 import java.util.Arrays;
  31 import java.util.Objects;
  32 import java.util.function.BinaryOperator;
  33 import java.util.function.Function;
  34 import java.util.function.UnaryOperator;
  35 
  36 import jdk.internal.misc.ScopedMemoryAccess;
  37 import jdk.internal.misc.Unsafe;
  38 import jdk.internal.vm.annotation.ForceInline;
  39 import jdk.internal.vm.vector.VectorSupport;
  40 
  41 import static jdk.internal.vm.vector.VectorSupport.*;
  42 import static jdk.incubator.vector.VectorIntrinsics.*;
  43 
  44 import static jdk.incubator.vector.VectorOperators.*;
  45 
  46 // -- This file was mechanically generated: Do not edit! -- //
  47 
  48 /**
  49  * A specialized {@link Vector} representing an ordered immutable sequence of
  50  * {@code double} values.
  51  */
  52 @SuppressWarnings("cast")  // warning: redundant cast
  53 public abstract class DoubleVector extends AbstractVector<Double> {
  54 
  55     DoubleVector(double[] vec) {
  56         super(vec);
  57     }
  58 
  59     static final int FORBID_OPCODE_KIND = VO_NOFP;
  60 
  61     @ForceInline
  62     static int opCode(Operator op) {
  63         return VectorOperators.opCode(op, VO_OPCODE_VALID, FORBID_OPCODE_KIND);
  64     }
  65     @ForceInline
  66     static int opCode(Operator op, int requireKind) {
  67         requireKind |= VO_OPCODE_VALID;
  68         return VectorOperators.opCode(op, requireKind, FORBID_OPCODE_KIND);
  69     }
  70     @ForceInline
  71     static boolean opKind(Operator op, int bit) {
  72         return VectorOperators.opKind(op, bit);
  73     }
  74 
  75     // Virtualized factories and operators,
  76     // coded with portable definitions.
  77     // These are all @ForceInline in case
  78     // they need to be used performantly.
  79     // The various shape-specific subclasses
  80     // also specialize them by wrapping
  81     // them in a call like this:
  82     //    return (Byte128Vector)
  83     //       super.bOp((Byte128Vector) o);
  84     // The purpose of that is to forcibly inline
  85     // the generic definition from this file
  86     // into a sharply type- and size-specific
  87     // wrapper in the subclass file, so that
  88     // the JIT can specialize the code.
  89     // The code is only inlined and expanded
  90     // if it gets hot.  Think of it as a cheap
  91     // and lazy version of C++ templates.
  92 
  93     // Virtualized getter
  94 
  95     /*package-private*/
  96     abstract double[] vec();
  97 
  98     // Virtualized constructors
  99 
 100     /**
 101      * Build a vector directly using my own constructor.
 102      * It is an error if the array is aliased elsewhere.
 103      */
 104     /*package-private*/
 105     abstract DoubleVector vectorFactory(double[] vec);
 106 
 107     /**
 108      * Build a mask directly using my species.
 109      * It is an error if the array is aliased elsewhere.
 110      */
 111     /*package-private*/
 112     @ForceInline
 113     final
 114     AbstractMask<Double> maskFactory(boolean[] bits) {
 115         return vspecies().maskFactory(bits);
 116     }
 117 
 118     // Constant loader (takes dummy as vector arg)
 119     interface FVOp {
 120         double apply(int i);
 121     }
 122 
 123     /*package-private*/
 124     @ForceInline
 125     final
 126     DoubleVector vOp(FVOp f) {
 127         double[] res = new double[length()];
 128         for (int i = 0; i < res.length; i++) {
 129             res[i] = f.apply(i);
 130         }
 131         return vectorFactory(res);
 132     }
 133 
 134     @ForceInline
 135     final
 136     DoubleVector vOp(VectorMask<Double> m, FVOp f) {
 137         double[] res = new double[length()];
 138         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 139         for (int i = 0; i < res.length; i++) {
 140             if (mbits[i]) {
 141                 res[i] = f.apply(i);
 142             }
 143         }
 144         return vectorFactory(res);
 145     }
 146 
 147     // Unary operator
 148 
 149     /*package-private*/
 150     interface FUnOp {
 151         double apply(int i, double a);
 152     }
 153 
 154     /*package-private*/
 155     abstract
 156     DoubleVector uOp(FUnOp f);
 157     @ForceInline
 158     final
 159     DoubleVector uOpTemplate(FUnOp f) {
 160         double[] vec = vec();
 161         double[] res = new double[length()];
 162         for (int i = 0; i < res.length; i++) {
 163             res[i] = f.apply(i, vec[i]);
 164         }
 165         return vectorFactory(res);
 166     }
 167 
 168     /*package-private*/
 169     abstract
 170     DoubleVector uOp(VectorMask<Double> m,
 171                              FUnOp f);
 172     @ForceInline
 173     final
 174     DoubleVector uOpTemplate(VectorMask<Double> m,
 175                                      FUnOp f) {
 176         double[] vec = vec();
 177         double[] res = new double[length()];
 178         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 179         for (int i = 0; i < res.length; i++) {
 180             res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i];
 181         }
 182         return vectorFactory(res);
 183     }
 184 
 185     // Binary operator
 186 
 187     /*package-private*/
 188     interface FBinOp {
 189         double apply(int i, double a, double b);
 190     }
 191 
 192     /*package-private*/
 193     abstract
 194     DoubleVector bOp(Vector<Double> o,
 195                              FBinOp f);
 196     @ForceInline
 197     final
 198     DoubleVector bOpTemplate(Vector<Double> o,
 199                                      FBinOp f) {
 200         double[] res = new double[length()];
 201         double[] vec1 = this.vec();
 202         double[] vec2 = ((DoubleVector)o).vec();
 203         for (int i = 0; i < res.length; i++) {
 204             res[i] = f.apply(i, vec1[i], vec2[i]);
 205         }
 206         return vectorFactory(res);
 207     }
 208 
 209     /*package-private*/
 210     abstract
 211     DoubleVector bOp(Vector<Double> o,
 212                              VectorMask<Double> m,
 213                              FBinOp f);
 214     @ForceInline
 215     final
 216     DoubleVector bOpTemplate(Vector<Double> o,
 217                                      VectorMask<Double> m,
 218                                      FBinOp f) {
 219         double[] res = new double[length()];
 220         double[] vec1 = this.vec();
 221         double[] vec2 = ((DoubleVector)o).vec();
 222         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 223         for (int i = 0; i < res.length; i++) {
 224             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i];
 225         }
 226         return vectorFactory(res);
 227     }
 228 
 229     // Ternary operator
 230 
 231     /*package-private*/
 232     interface FTriOp {
 233         double apply(int i, double a, double b, double c);
 234     }
 235 
 236     /*package-private*/
 237     abstract
 238     DoubleVector tOp(Vector<Double> o1,
 239                              Vector<Double> o2,
 240                              FTriOp f);
 241     @ForceInline
 242     final
 243     DoubleVector tOpTemplate(Vector<Double> o1,
 244                                      Vector<Double> o2,
 245                                      FTriOp f) {
 246         double[] res = new double[length()];
 247         double[] vec1 = this.vec();
 248         double[] vec2 = ((DoubleVector)o1).vec();
 249         double[] vec3 = ((DoubleVector)o2).vec();
 250         for (int i = 0; i < res.length; i++) {
 251             res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]);
 252         }
 253         return vectorFactory(res);
 254     }
 255 
 256     /*package-private*/
 257     abstract
 258     DoubleVector tOp(Vector<Double> o1,
 259                              Vector<Double> o2,
 260                              VectorMask<Double> m,
 261                              FTriOp f);
 262     @ForceInline
 263     final
 264     DoubleVector tOpTemplate(Vector<Double> o1,
 265                                      Vector<Double> o2,
 266                                      VectorMask<Double> m,
 267                                      FTriOp f) {
 268         double[] res = new double[length()];
 269         double[] vec1 = this.vec();
 270         double[] vec2 = ((DoubleVector)o1).vec();
 271         double[] vec3 = ((DoubleVector)o2).vec();
 272         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 273         for (int i = 0; i < res.length; i++) {
 274             res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i];
 275         }
 276         return vectorFactory(res);
 277     }
 278 
 279     // Reduction operator
 280 
 281     /*package-private*/
 282     abstract
 283     double rOp(double v, FBinOp f);
 284     @ForceInline
 285     final
 286     double rOpTemplate(double v, FBinOp f) {
 287         double[] vec = vec();
 288         for (int i = 0; i < vec.length; i++) {
 289             v = f.apply(i, v, vec[i]);
 290         }
 291         return v;
 292     }
 293 
 294     // Memory reference
 295 
 296     /*package-private*/
 297     interface FLdOp<M> {
 298         double apply(M memory, int offset, int i);
 299     }
 300 
 301     /*package-private*/
 302     @ForceInline
 303     final
 304     <M> DoubleVector ldOp(M memory, int offset,
 305                                   FLdOp<M> f) {
 306         //dummy; no vec = vec();
 307         double[] res = new double[length()];
 308         for (int i = 0; i < res.length; i++) {
 309             res[i] = f.apply(memory, offset, i);
 310         }
 311         return vectorFactory(res);
 312     }
 313 
 314     /*package-private*/
 315     @ForceInline
 316     final
 317     <M> DoubleVector ldOp(M memory, int offset,
 318                                   VectorMask<Double> m,
 319                                   FLdOp<M> f) {
 320         //double[] vec = vec();
 321         double[] res = new double[length()];
 322         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 323         for (int i = 0; i < res.length; i++) {
 324             if (mbits[i]) {
 325                 res[i] = f.apply(memory, offset, i);
 326             }
 327         }
 328         return vectorFactory(res);
 329     }
 330 
 331     interface FStOp<M> {
 332         void apply(M memory, int offset, int i, double a);
 333     }
 334 
 335     /*package-private*/
 336     @ForceInline
 337     final
 338     <M> void stOp(M memory, int offset,
 339                   FStOp<M> f) {
 340         double[] vec = vec();
 341         for (int i = 0; i < vec.length; i++) {
 342             f.apply(memory, offset, i, vec[i]);
 343         }
 344     }
 345 
 346     /*package-private*/
 347     @ForceInline
 348     final
 349     <M> void stOp(M memory, int offset,
 350                   VectorMask<Double> m,
 351                   FStOp<M> f) {
 352         double[] vec = vec();
 353         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
 354         for (int i = 0; i < vec.length; i++) {
 355             if (mbits[i]) {
 356                 f.apply(memory, offset, i, vec[i]);
 357             }
 358         }
 359     }
 360 
 361     // Binary test
 362 
 363     /*package-private*/
 364     interface FBinTest {
 365         boolean apply(int cond, int i, double a, double b);
 366     }
 367 
 368     /*package-private*/
 369     @ForceInline
 370     final
 371     AbstractMask<Double> bTest(int cond,
 372                                   Vector<Double> o,
 373                                   FBinTest f) {
 374         double[] vec1 = vec();
 375         double[] vec2 = ((DoubleVector)o).vec();
 376         boolean[] bits = new boolean[length()];
 377         for (int i = 0; i < length(); i++){
 378             bits[i] = f.apply(cond, i, vec1[i], vec2[i]);
 379         }
 380         return maskFactory(bits);
 381     }
 382 
 383 
 384     /*package-private*/
 385     @Override
 386     abstract DoubleSpecies vspecies();
 387 
 388     /*package-private*/
 389     @ForceInline
 390     static long toBits(double e) {
 391         return  Double.doubleToRawLongBits(e);
 392     }
 393 
 394     /*package-private*/
 395     @ForceInline
 396     static double fromBits(long bits) {
 397         return Double.longBitsToDouble((long)bits);
 398     }
 399 
 400     // Static factories (other than memory operations)
 401 
 402     // Note: A surprising behavior in javadoc
 403     // sometimes makes a lone /** {@inheritDoc} */
 404     // comment drop the method altogether,
 405     // apparently if the method mentions an
 406     // parameter or return type of Vector<Double>
 407     // instead of Vector<E> as originally specified.
 408     // Adding an empty HTML fragment appears to
 409     // nudge javadoc into providing the desired
 410     // inherited documentation.  We use the HTML
 411     // comment <!--workaround--> for this.
 412 
 413     /**
 414      * Returns a vector of the given species
 415      * where all lane elements are set to
 416      * zero, the default primitive value.
 417      *
 418      * @param species species of the desired zero vector
 419      * @return a zero vector
 420      */
 421     @ForceInline
 422     public static DoubleVector zero(VectorSpecies<Double> species) {
 423         DoubleSpecies vsp = (DoubleSpecies) species;
 424         return VectorSupport.broadcastCoerced(vsp.vectorType(), double.class, species.length(),
 425                         toBits(0.0f), vsp,
 426                         ((bits_, s_) -> s_.rvOp(i -> bits_)));
 427     }
 428 
 429     /**
 430      * Returns a vector of the same species as this one
 431      * where all lane elements are set to
 432      * the primitive value {@code e}.
 433      *
 434      * The contents of the current vector are discarded;
 435      * only the species is relevant to this operation.
 436      *
 437      * <p> This method returns the value of this expression:
 438      * {@code DoubleVector.broadcast(this.species(), e)}.
 439      *
 440      * @apiNote
 441      * Unlike the similar method named {@code broadcast()}
 442      * in the supertype {@code Vector}, this method does not
 443      * need to validate its argument, and cannot throw
 444      * {@code IllegalArgumentException}.  This method is
 445      * therefore preferable to the supertype method.
 446      *
 447      * @param e the value to broadcast
 448      * @return a vector where all lane elements are set to
 449      *         the primitive value {@code e}
 450      * @see #broadcast(VectorSpecies,long)
 451      * @see Vector#broadcast(long)
 452      * @see VectorSpecies#broadcast(long)
 453      */
 454     public abstract DoubleVector broadcast(double e);
 455 
 456     /**
 457      * Returns a vector of the given species
 458      * where all lane elements are set to
 459      * the primitive value {@code e}.
 460      *
 461      * @param species species of the desired vector
 462      * @param e the value to broadcast
 463      * @return a vector where all lane elements are set to
 464      *         the primitive value {@code e}
 465      * @see #broadcast(long)
 466      * @see Vector#broadcast(long)
 467      * @see VectorSpecies#broadcast(long)
 468      */
 469     @ForceInline
 470     public static DoubleVector broadcast(VectorSpecies<Double> species, double e) {
 471         DoubleSpecies vsp = (DoubleSpecies) species;
 472         return vsp.broadcast(e);
 473     }
 474 
 475     /*package-private*/
 476     @ForceInline
 477     final DoubleVector broadcastTemplate(double e) {
 478         DoubleSpecies vsp = vspecies();
 479         return vsp.broadcast(e);
 480     }
 481 
 482     /**
 483      * {@inheritDoc} <!--workaround-->
 484      * @apiNote
 485      * When working with vector subtypes like {@code DoubleVector},
 486      * {@linkplain #broadcast(double) the more strongly typed method}
 487      * is typically selected.  It can be explicitly selected
 488      * using a cast: {@code v.broadcast((double)e)}.
 489      * The two expressions will produce numerically identical results.
 490      */
 491     @Override
 492     public abstract DoubleVector broadcast(long e);
 493 
 494     /**
 495      * Returns a vector of the given species
 496      * where all lane elements are set to
 497      * the primitive value {@code e}.
 498      *
 499      * The {@code long} value must be accurately representable
 500      * by the {@code ETYPE} of the vector species, so that
 501      * {@code e==(long)(ETYPE)e}.
 502      *
 503      * @param species species of the desired vector
 504      * @param e the value to broadcast
 505      * @return a vector where all lane elements are set to
 506      *         the primitive value {@code e}
 507      * @throws IllegalArgumentException
 508      *         if the given {@code long} value cannot
 509      *         be represented by the vector's {@code ETYPE}
 510      * @see #broadcast(VectorSpecies,double)
 511      * @see VectorSpecies#checkValue(long)
 512      */
 513     @ForceInline
 514     public static DoubleVector broadcast(VectorSpecies<Double> species, long e) {
 515         DoubleSpecies vsp = (DoubleSpecies) species;
 516         return vsp.broadcast(e);
 517     }
 518 
 519     /*package-private*/
 520     @ForceInline
 521     final DoubleVector broadcastTemplate(long e) {
 522         return vspecies().broadcast(e);
 523     }
 524 
 525     // Unary lanewise support
 526 
 527     /**
 528      * {@inheritDoc} <!--workaround-->
 529      */
 530     public abstract
 531     DoubleVector lanewise(VectorOperators.Unary op);
 532 
 533     @ForceInline
 534     final
 535     DoubleVector lanewiseTemplate(VectorOperators.Unary op) {
 536         if (opKind(op, VO_SPECIAL)) {
 537             if (op == ZOMO) {
 538                 return blend(broadcast(-1), compare(NE, 0));
 539             }
 540         }
 541         int opc = opCode(op);
 542         return VectorSupport.unaryOp(
 543             opc, getClass(), double.class, length(),
 544             this,
 545             UN_IMPL.find(op, opc, (opc_) -> {
 546               switch (opc_) {
 547                 case VECTOR_OP_NEG: return v0 ->
 548                         v0.uOp((i, a) -> (double) -a);
 549                 case VECTOR_OP_ABS: return v0 ->
 550                         v0.uOp((i, a) -> (double) Math.abs(a));
 551                 case VECTOR_OP_SIN: return v0 ->
 552                         v0.uOp((i, a) -> (double) Math.sin(a));
 553                 case VECTOR_OP_COS: return v0 ->
 554                         v0.uOp((i, a) -> (double) Math.cos(a));
 555                 case VECTOR_OP_TAN: return v0 ->
 556                         v0.uOp((i, a) -> (double) Math.tan(a));
 557                 case VECTOR_OP_ASIN: return v0 ->
 558                         v0.uOp((i, a) -> (double) Math.asin(a));
 559                 case VECTOR_OP_ACOS: return v0 ->
 560                         v0.uOp((i, a) -> (double) Math.acos(a));
 561                 case VECTOR_OP_ATAN: return v0 ->
 562                         v0.uOp((i, a) -> (double) Math.atan(a));
 563                 case VECTOR_OP_EXP: return v0 ->
 564                         v0.uOp((i, a) -> (double) Math.exp(a));
 565                 case VECTOR_OP_LOG: return v0 ->
 566                         v0.uOp((i, a) -> (double) Math.log(a));
 567                 case VECTOR_OP_LOG10: return v0 ->
 568                         v0.uOp((i, a) -> (double) Math.log10(a));
 569                 case VECTOR_OP_SQRT: return v0 ->
 570                         v0.uOp((i, a) -> (double) Math.sqrt(a));
 571                 case VECTOR_OP_CBRT: return v0 ->
 572                         v0.uOp((i, a) -> (double) Math.cbrt(a));
 573                 case VECTOR_OP_SINH: return v0 ->
 574                         v0.uOp((i, a) -> (double) Math.sinh(a));
 575                 case VECTOR_OP_COSH: return v0 ->
 576                         v0.uOp((i, a) -> (double) Math.cosh(a));
 577                 case VECTOR_OP_TANH: return v0 ->
 578                         v0.uOp((i, a) -> (double) Math.tanh(a));
 579                 case VECTOR_OP_EXPM1: return v0 ->
 580                         v0.uOp((i, a) -> (double) Math.expm1(a));
 581                 case VECTOR_OP_LOG1P: return v0 ->
 582                         v0.uOp((i, a) -> (double) Math.log1p(a));
 583                 default: return null;
 584               }}));
 585     }
 586     private static final
 587     ImplCache<Unary,UnaryOperator<DoubleVector>> UN_IMPL
 588         = new ImplCache<>(Unary.class, DoubleVector.class);
 589 
 590     /**
 591      * {@inheritDoc} <!--workaround-->
 592      */
 593     @ForceInline
 594     public final
 595     DoubleVector lanewise(VectorOperators.Unary op,
 596                                   VectorMask<Double> m) {
 597         return blend(lanewise(op), m);
 598     }
 599 
 600     // Binary lanewise support
 601 
 602     /**
 603      * {@inheritDoc} <!--workaround-->
 604      * @see #lanewise(VectorOperators.Binary,double)
 605      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
 606      */
 607     @Override
 608     public abstract
 609     DoubleVector lanewise(VectorOperators.Binary op,
 610                                   Vector<Double> v);
 611     @ForceInline
 612     final
 613     DoubleVector lanewiseTemplate(VectorOperators.Binary op,
 614                                           Vector<Double> v) {
 615         DoubleVector that = (DoubleVector) v;
 616         that.check(this);
 617         if (opKind(op, VO_SPECIAL )) {
 618             if (op == FIRST_NONZERO) {
 619                 // FIXME: Support this in the JIT.
 620                 VectorMask<Long> thisNZ
 621                     = this.viewAsIntegralLanes().compare(NE, (long) 0);
 622                 that = that.blend((double) 0, thisNZ.cast(vspecies()));
 623                 op = OR_UNCHECKED;
 624                 // FIXME: Support OR_UNCHECKED on float/double also!
 625                 return this.viewAsIntegralLanes()
 626                     .lanewise(op, that.viewAsIntegralLanes())
 627                     .viewAsFloatingLanes();
 628             }
 629         }
 630         int opc = opCode(op);
 631         return VectorSupport.binaryOp(
 632             opc, getClass(), double.class, length(),
 633             this, that,
 634             BIN_IMPL.find(op, opc, (opc_) -> {
 635               switch (opc_) {
 636                 case VECTOR_OP_ADD: return (v0, v1) ->
 637                         v0.bOp(v1, (i, a, b) -> (double)(a + b));
 638                 case VECTOR_OP_SUB: return (v0, v1) ->
 639                         v0.bOp(v1, (i, a, b) -> (double)(a - b));
 640                 case VECTOR_OP_MUL: return (v0, v1) ->
 641                         v0.bOp(v1, (i, a, b) -> (double)(a * b));
 642                 case VECTOR_OP_DIV: return (v0, v1) ->
 643                         v0.bOp(v1, (i, a, b) -> (double)(a / b));
 644                 case VECTOR_OP_MAX: return (v0, v1) ->
 645                         v0.bOp(v1, (i, a, b) -> (double)Math.max(a, b));
 646                 case VECTOR_OP_MIN: return (v0, v1) ->
 647                         v0.bOp(v1, (i, a, b) -> (double)Math.min(a, b));
 648                 case VECTOR_OP_ATAN2: return (v0, v1) ->
 649                         v0.bOp(v1, (i, a, b) -> (double) Math.atan2(a, b));
 650                 case VECTOR_OP_POW: return (v0, v1) ->
 651                         v0.bOp(v1, (i, a, b) -> (double) Math.pow(a, b));
 652                 case VECTOR_OP_HYPOT: return (v0, v1) ->
 653                         v0.bOp(v1, (i, a, b) -> (double) Math.hypot(a, b));
 654                 default: return null;
 655                 }}));
 656     }
 657     private static final
 658     ImplCache<Binary,BinaryOperator<DoubleVector>> BIN_IMPL
 659         = new ImplCache<>(Binary.class, DoubleVector.class);
 660 
 661     /**
 662      * {@inheritDoc} <!--workaround-->
 663      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
 664      */
 665     @ForceInline
 666     public final
 667     DoubleVector lanewise(VectorOperators.Binary op,
 668                                   Vector<Double> v,
 669                                   VectorMask<Double> m) {
 670         return blend(lanewise(op, v), m);
 671     }
 672     // FIXME: Maybe all of the public final methods in this file (the
 673     // simple ones that just call lanewise) should be pushed down to
 674     // the X-VectorBits template.  They can't optimize properly at
 675     // this level, and must rely on inlining.  Does it work?
 676     // (If it works, of course keep the code here.)
 677 
 678     /**
 679      * Combines the lane values of this vector
 680      * with the value of a broadcast scalar.
 681      *
 682      * This is a lane-wise binary operation which applies
 683      * the selected operation to each lane.
 684      * The return value will be equal to this expression:
 685      * {@code this.lanewise(op, this.broadcast(e))}.
 686      *
 687      * @param op the operation used to process lane values
 688      * @param e the input scalar
 689      * @return the result of applying the operation lane-wise
 690      *         to the two input vectors
 691      * @throws UnsupportedOperationException if this vector does
 692      *         not support the requested operation
 693      * @see #lanewise(VectorOperators.Binary,Vector)
 694      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
 695      */
 696     @ForceInline
 697     public final
 698     DoubleVector lanewise(VectorOperators.Binary op,
 699                                   double e) {
 700         return lanewise(op, broadcast(e));
 701     }
 702 
 703     /**
 704      * Combines the lane values of this vector
 705      * with the value of a broadcast scalar,
 706      * with selection of lane elements controlled by a mask.
 707      *
 708      * This is a masked lane-wise binary operation which applies
 709      * the selected operation to each lane.
 710      * The return value will be equal to this expression:
 711      * {@code this.lanewise(op, this.broadcast(e), m)}.
 712      *
 713      * @param op the operation used to process lane values
 714      * @param e the input scalar
 715      * @param m the mask controlling lane selection
 716      * @return the result of applying the operation lane-wise
 717      *         to the input vector and the scalar
 718      * @throws UnsupportedOperationException if this vector does
 719      *         not support the requested operation
 720      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
 721      * @see #lanewise(VectorOperators.Binary,double)
 722      */
 723     @ForceInline
 724     public final
 725     DoubleVector lanewise(VectorOperators.Binary op,
 726                                   double e,
 727                                   VectorMask<Double> m) {
 728         return blend(lanewise(op, e), m);
 729     }
 730 
 731     /**
 732      * {@inheritDoc} <!--workaround-->
 733      * @apiNote
 734      * When working with vector subtypes like {@code DoubleVector},
 735      * {@linkplain #lanewise(VectorOperators.Binary,double)
 736      * the more strongly typed method}
 737      * is typically selected.  It can be explicitly selected
 738      * using a cast: {@code v.lanewise(op,(double)e)}.
 739      * The two expressions will produce numerically identical results.
 740      */
 741     @ForceInline
 742     public final
 743     DoubleVector lanewise(VectorOperators.Binary op,
 744                                   long e) {
 745         double e1 = (double) e;
 746         if ((long)e1 != e
 747             ) {
 748             vspecies().checkValue(e);  // for exception
 749         }
 750         return lanewise(op, e1);
 751     }
 752 
 753     /**
 754      * {@inheritDoc} <!--workaround-->
 755      * @apiNote
 756      * When working with vector subtypes like {@code DoubleVector},
 757      * {@linkplain #lanewise(VectorOperators.Binary,double,VectorMask)
 758      * the more strongly typed method}
 759      * is typically selected.  It can be explicitly selected
 760      * using a cast: {@code v.lanewise(op,(double)e,m)}.
 761      * The two expressions will produce numerically identical results.
 762      */
 763     @ForceInline
 764     public final
 765     DoubleVector lanewise(VectorOperators.Binary op,
 766                                   long e, VectorMask<Double> m) {
 767         return blend(lanewise(op, e), m);
 768     }
 769 
 770 
 771     // Ternary lanewise support
 772 
 773     // Ternary operators come in eight variations:
 774     //   lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2])
 775     //   lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2], mask)
 776 
 777     // It is annoying to support all of these variations of masking
 778     // and broadcast, but it would be more surprising not to continue
 779     // the obvious pattern started by unary and binary.
 780 
 781    /**
 782      * {@inheritDoc} <!--workaround-->
 783      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
 784      * @see #lanewise(VectorOperators.Ternary,Vector,double,VectorMask)
 785      * @see #lanewise(VectorOperators.Ternary,double,Vector,VectorMask)
 786      * @see #lanewise(VectorOperators.Ternary,double,double)
 787      * @see #lanewise(VectorOperators.Ternary,Vector,double)
 788      * @see #lanewise(VectorOperators.Ternary,double,Vector)
 789      */
 790     @Override
 791     public abstract
 792     DoubleVector lanewise(VectorOperators.Ternary op,
 793                                                   Vector<Double> v1,
 794                                                   Vector<Double> v2);
 795     @ForceInline
 796     final
 797     DoubleVector lanewiseTemplate(VectorOperators.Ternary op,
 798                                           Vector<Double> v1,
 799                                           Vector<Double> v2) {
 800         DoubleVector that = (DoubleVector) v1;
 801         DoubleVector tother = (DoubleVector) v2;
 802         // It's a word: https://www.dictionary.com/browse/tother
 803         // See also Chapter 11 of Dickens, Our Mutual Friend:
 804         // "Totherest Governor," replied Mr Riderhood...
 805         that.check(this);
 806         tother.check(this);
 807         int opc = opCode(op);
 808         return VectorSupport.ternaryOp(
 809             opc, getClass(), double.class, length(),
 810             this, that, tother,
 811             TERN_IMPL.find(op, opc, (opc_) -> {
 812               switch (opc_) {
 813                 case VECTOR_OP_FMA: return (v0, v1_, v2_) ->
 814                         v0.tOp(v1_, v2_, (i, a, b, c) -> Math.fma(a, b, c));
 815                 default: return null;
 816                 }}));
 817     }
 818     private static final
 819     ImplCache<Ternary,TernaryOperation<DoubleVector>> TERN_IMPL
 820         = new ImplCache<>(Ternary.class, DoubleVector.class);
 821 
 822     /**
 823      * {@inheritDoc} <!--workaround-->
 824      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
 825      * @see #lanewise(VectorOperators.Ternary,Vector,double,VectorMask)
 826      * @see #lanewise(VectorOperators.Ternary,double,Vector,VectorMask)
 827      */
 828     @ForceInline
 829     public final
 830     DoubleVector lanewise(VectorOperators.Ternary op,
 831                                   Vector<Double> v1,
 832                                   Vector<Double> v2,
 833                                   VectorMask<Double> m) {
 834         return blend(lanewise(op, v1, v2), m);
 835     }
 836 
 837     /**
 838      * Combines the lane values of this vector
 839      * with the values of two broadcast scalars.
 840      *
 841      * This is a lane-wise ternary operation which applies
 842      * the selected operation to each lane.
 843      * The return value will be equal to this expression:
 844      * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2))}.
 845      *
 846      * @param op the operation used to combine lane values
 847      * @param e1 the first input scalar
 848      * @param e2 the second input scalar
 849      * @return the result of applying the operation lane-wise
 850      *         to the input vector and the scalars
 851      * @throws UnsupportedOperationException if this vector does
 852      *         not support the requested operation
 853      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
 854      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
 855      */
 856     @ForceInline
 857     public final
 858     DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,e2)
 859                                   double e1,
 860                                   double e2) {
 861         return lanewise(op, broadcast(e1), broadcast(e2));
 862     }
 863 
 864     /**
 865      * Combines the lane values of this vector
 866      * with the values of two broadcast scalars,
 867      * with selection of lane elements controlled by a mask.
 868      *
 869      * This is a masked lane-wise ternary operation which applies
 870      * the selected operation to each lane.
 871      * The return value will be equal to this expression:
 872      * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2), m)}.
 873      *
 874      * @param op the operation used to combine lane values
 875      * @param e1 the first input scalar
 876      * @param e2 the second input scalar
 877      * @param m the mask controlling lane selection
 878      * @return the result of applying the operation lane-wise
 879      *         to the input vector and the scalars
 880      * @throws UnsupportedOperationException if this vector does
 881      *         not support the requested operation
 882      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
 883      * @see #lanewise(VectorOperators.Ternary,double,double)
 884      */
 885     @ForceInline
 886     public final
 887     DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,e2,m)
 888                                   double e1,
 889                                   double e2,
 890                                   VectorMask<Double> m) {
 891         return blend(lanewise(op, e1, e2), m);
 892     }
 893 
 894     /**
 895      * Combines the lane values of this vector
 896      * with the values of another vector and a broadcast scalar.
 897      *
 898      * This is a lane-wise ternary operation which applies
 899      * the selected operation to each lane.
 900      * The return value will be equal to this expression:
 901      * {@code this.lanewise(op, v1, this.broadcast(e2))}.
 902      *
 903      * @param op the operation used to combine lane values
 904      * @param v1 the other input vector
 905      * @param e2 the input scalar
 906      * @return the result of applying the operation lane-wise
 907      *         to the input vectors and the scalar
 908      * @throws UnsupportedOperationException if this vector does
 909      *         not support the requested operation
 910      * @see #lanewise(VectorOperators.Ternary,double,double)
 911      * @see #lanewise(VectorOperators.Ternary,Vector,double,VectorMask)
 912      */
 913     @ForceInline
 914     public final
 915     DoubleVector lanewise(VectorOperators.Ternary op, //(op,v1,e2)
 916                                   Vector<Double> v1,
 917                                   double e2) {
 918         return lanewise(op, v1, broadcast(e2));
 919     }
 920 
 921     /**
 922      * Combines the lane values of this vector
 923      * with the values of another vector and a broadcast scalar,
 924      * with selection of lane elements controlled by a mask.
 925      *
 926      * This is a masked lane-wise ternary operation which applies
 927      * the selected operation to each lane.
 928      * The return value will be equal to this expression:
 929      * {@code this.lanewise(op, v1, this.broadcast(e2), m)}.
 930      *
 931      * @param op the operation used to combine lane values
 932      * @param v1 the other input vector
 933      * @param e2 the input scalar
 934      * @param m the mask controlling lane selection
 935      * @return the result of applying the operation lane-wise
 936      *         to the input vectors and the scalar
 937      * @throws UnsupportedOperationException if this vector does
 938      *         not support the requested operation
 939      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
 940      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
 941      * @see #lanewise(VectorOperators.Ternary,Vector,double)
 942      */
 943     @ForceInline
 944     public final
 945     DoubleVector lanewise(VectorOperators.Ternary op, //(op,v1,e2,m)
 946                                   Vector<Double> v1,
 947                                   double e2,
 948                                   VectorMask<Double> m) {
 949         return blend(lanewise(op, v1, e2), m);
 950     }
 951 
 952     /**
 953      * Combines the lane values of this vector
 954      * with the values of another vector and a broadcast scalar.
 955      *
 956      * This is a lane-wise ternary operation which applies
 957      * the selected operation to each lane.
 958      * The return value will be equal to this expression:
 959      * {@code this.lanewise(op, this.broadcast(e1), v2)}.
 960      *
 961      * @param op the operation used to combine lane values
 962      * @param e1 the input scalar
 963      * @param v2 the other input vector
 964      * @return the result of applying the operation lane-wise
 965      *         to the input vectors and the scalar
 966      * @throws UnsupportedOperationException if this vector does
 967      *         not support the requested operation
 968      * @see #lanewise(VectorOperators.Ternary,Vector,Vector)
 969      * @see #lanewise(VectorOperators.Ternary,double,Vector,VectorMask)
 970      */
 971     @ForceInline
 972     public final
 973     DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,v2)
 974                                   double e1,
 975                                   Vector<Double> v2) {
 976         return lanewise(op, broadcast(e1), v2);
 977     }
 978 
 979     /**
 980      * Combines the lane values of this vector
 981      * with the values of another vector and a broadcast scalar,
 982      * with selection of lane elements controlled by a mask.
 983      *
 984      * This is a masked lane-wise ternary operation which applies
 985      * the selected operation to each lane.
 986      * The return value will be equal to this expression:
 987      * {@code this.lanewise(op, this.broadcast(e1), v2, m)}.
 988      *
 989      * @param op the operation used to combine lane values
 990      * @param e1 the input scalar
 991      * @param v2 the other input vector
 992      * @param m the mask controlling lane selection
 993      * @return the result of applying the operation lane-wise
 994      *         to the input vectors and the scalar
 995      * @throws UnsupportedOperationException if this vector does
 996      *         not support the requested operation
 997      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
 998      * @see #lanewise(VectorOperators.Ternary,double,Vector)
 999      */
1000     @ForceInline
1001     public final
1002     DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,v2,m)
1003                                   double e1,
1004                                   Vector<Double> v2,
1005                                   VectorMask<Double> m) {
1006         return blend(lanewise(op, e1, v2), m);
1007     }
1008 
1009     // (Thus endeth the Great and Mighty Ternary Ogdoad.)
1010     // https://en.wikipedia.org/wiki/Ogdoad
1011 
1012     /// FULL-SERVICE BINARY METHODS: ADD, SUB, MUL, DIV
1013     //
1014     // These include masked and non-masked versions.
1015     // This subclass adds broadcast (masked or not).
1016 
1017     /**
1018      * {@inheritDoc} <!--workaround-->
1019      * @see #add(double)
1020      */
1021     @Override
1022     @ForceInline
1023     public final DoubleVector add(Vector<Double> v) {
1024         return lanewise(ADD, v);
1025     }
1026 
1027     /**
1028      * Adds this vector to the broadcast of an input scalar.
1029      *
1030      * This is a lane-wise binary operation which applies
1031      * the primitive addition operation ({@code +}) to each lane.
1032      *
1033      * This method is also equivalent to the expression
1034      * {@link #lanewise(VectorOperators.Binary,double)
1035      *    lanewise}{@code (}{@link VectorOperators#ADD
1036      *    ADD}{@code , e)}.
1037      *
1038      * @param e the input scalar
1039      * @return the result of adding each lane of this vector to the scalar
1040      * @see #add(Vector)
1041      * @see #broadcast(double)
1042      * @see #add(double,VectorMask)
1043      * @see VectorOperators#ADD
1044      * @see #lanewise(VectorOperators.Binary,Vector)
1045      * @see #lanewise(VectorOperators.Binary,double)
1046      */
1047     @ForceInline
1048     public final
1049     DoubleVector add(double e) {
1050         return lanewise(ADD, e);
1051     }
1052 
1053     /**
1054      * {@inheritDoc} <!--workaround-->
1055      * @see #add(double,VectorMask)
1056      */
1057     @Override
1058     @ForceInline
1059     public final DoubleVector add(Vector<Double> v,
1060                                           VectorMask<Double> m) {
1061         return lanewise(ADD, v, m);
1062     }
1063 
1064     /**
1065      * Adds this vector to the broadcast of an input scalar,
1066      * selecting lane elements controlled by a mask.
1067      *
1068      * This is a masked lane-wise binary operation which applies
1069      * the primitive addition operation ({@code +}) to each lane.
1070      *
1071      * This method is also equivalent to the expression
1072      * {@link #lanewise(VectorOperators.Binary,double,VectorMask)
1073      *    lanewise}{@code (}{@link VectorOperators#ADD
1074      *    ADD}{@code , s, m)}.
1075      *
1076      * @param e the input scalar
1077      * @param m the mask controlling lane selection
1078      * @return the result of adding each lane of this vector to the scalar
1079      * @see #add(Vector,VectorMask)
1080      * @see #broadcast(double)
1081      * @see #add(double)
1082      * @see VectorOperators#ADD
1083      * @see #lanewise(VectorOperators.Binary,Vector)
1084      * @see #lanewise(VectorOperators.Binary,double)
1085      */
1086     @ForceInline
1087     public final DoubleVector add(double e,
1088                                           VectorMask<Double> m) {
1089         return lanewise(ADD, e, m);
1090     }
1091 
1092     /**
1093      * {@inheritDoc} <!--workaround-->
1094      * @see #sub(double)
1095      */
1096     @Override
1097     @ForceInline
1098     public final DoubleVector sub(Vector<Double> v) {
1099         return lanewise(SUB, v);
1100     }
1101 
1102     /**
1103      * Subtracts an input scalar from this vector.
1104      *
1105      * This is a masked lane-wise binary operation which applies
1106      * the primitive subtraction operation ({@code -}) to each lane.
1107      *
1108      * This method is also equivalent to the expression
1109      * {@link #lanewise(VectorOperators.Binary,double)
1110      *    lanewise}{@code (}{@link VectorOperators#SUB
1111      *    SUB}{@code , e)}.
1112      *
1113      * @param e the input scalar
1114      * @return the result of subtracting the scalar from each lane of this vector
1115      * @see #sub(Vector)
1116      * @see #broadcast(double)
1117      * @see #sub(double,VectorMask)
1118      * @see VectorOperators#SUB
1119      * @see #lanewise(VectorOperators.Binary,Vector)
1120      * @see #lanewise(VectorOperators.Binary,double)
1121      */
1122     @ForceInline
1123     public final DoubleVector sub(double e) {
1124         return lanewise(SUB, e);
1125     }
1126 
1127     /**
1128      * {@inheritDoc} <!--workaround-->
1129      * @see #sub(double,VectorMask)
1130      */
1131     @Override
1132     @ForceInline
1133     public final DoubleVector sub(Vector<Double> v,
1134                                           VectorMask<Double> m) {
1135         return lanewise(SUB, v, m);
1136     }
1137 
1138     /**
1139      * Subtracts an input scalar from this vector
1140      * under the control of a mask.
1141      *
1142      * This is a masked lane-wise binary operation which applies
1143      * the primitive subtraction operation ({@code -}) to each lane.
1144      *
1145      * This method is also equivalent to the expression
1146      * {@link #lanewise(VectorOperators.Binary,double,VectorMask)
1147      *    lanewise}{@code (}{@link VectorOperators#SUB
1148      *    SUB}{@code , s, m)}.
1149      *
1150      * @param e the input scalar
1151      * @param m the mask controlling lane selection
1152      * @return the result of subtracting the scalar from each lane of this vector
1153      * @see #sub(Vector,VectorMask)
1154      * @see #broadcast(double)
1155      * @see #sub(double)
1156      * @see VectorOperators#SUB
1157      * @see #lanewise(VectorOperators.Binary,Vector)
1158      * @see #lanewise(VectorOperators.Binary,double)
1159      */
1160     @ForceInline
1161     public final DoubleVector sub(double e,
1162                                           VectorMask<Double> m) {
1163         return lanewise(SUB, e, m);
1164     }
1165 
1166     /**
1167      * {@inheritDoc} <!--workaround-->
1168      * @see #mul(double)
1169      */
1170     @Override
1171     @ForceInline
1172     public final DoubleVector mul(Vector<Double> v) {
1173         return lanewise(MUL, v);
1174     }
1175 
1176     /**
1177      * Multiplies this vector by the broadcast of an input scalar.
1178      *
1179      * This is a lane-wise binary operation which applies
1180      * the primitive multiplication operation ({@code *}) to each lane.
1181      *
1182      * This method is also equivalent to the expression
1183      * {@link #lanewise(VectorOperators.Binary,double)
1184      *    lanewise}{@code (}{@link VectorOperators#MUL
1185      *    MUL}{@code , e)}.
1186      *
1187      * @param e the input scalar
1188      * @return the result of multiplying this vector by the given scalar
1189      * @see #mul(Vector)
1190      * @see #broadcast(double)
1191      * @see #mul(double,VectorMask)
1192      * @see VectorOperators#MUL
1193      * @see #lanewise(VectorOperators.Binary,Vector)
1194      * @see #lanewise(VectorOperators.Binary,double)
1195      */
1196     @ForceInline
1197     public final DoubleVector mul(double e) {
1198         return lanewise(MUL, e);
1199     }
1200 
1201     /**
1202      * {@inheritDoc} <!--workaround-->
1203      * @see #mul(double,VectorMask)
1204      */
1205     @Override
1206     @ForceInline
1207     public final DoubleVector mul(Vector<Double> v,
1208                                           VectorMask<Double> m) {
1209         return lanewise(MUL, v, m);
1210     }
1211 
1212     /**
1213      * Multiplies this vector by the broadcast of an input scalar,
1214      * selecting lane elements controlled by a mask.
1215      *
1216      * This is a masked lane-wise binary operation which applies
1217      * the primitive multiplication operation ({@code *}) to each lane.
1218      *
1219      * This method is also equivalent to the expression
1220      * {@link #lanewise(VectorOperators.Binary,double,VectorMask)
1221      *    lanewise}{@code (}{@link VectorOperators#MUL
1222      *    MUL}{@code , s, m)}.
1223      *
1224      * @param e the input scalar
1225      * @param m the mask controlling lane selection
1226      * @return the result of muling each lane of this vector to the scalar
1227      * @see #mul(Vector,VectorMask)
1228      * @see #broadcast(double)
1229      * @see #mul(double)
1230      * @see VectorOperators#MUL
1231      * @see #lanewise(VectorOperators.Binary,Vector)
1232      * @see #lanewise(VectorOperators.Binary,double)
1233      */
1234     @ForceInline
1235     public final DoubleVector mul(double e,
1236                                           VectorMask<Double> m) {
1237         return lanewise(MUL, e, m);
1238     }
1239 
1240     /**
1241      * {@inheritDoc} <!--workaround-->
1242      * @apiNote Because the underlying scalar operator is an IEEE
1243      * floating point number, division by zero in fact will
1244      * not throw an exception, but will yield a signed
1245      * infinity or NaN.
1246      */
1247     @Override
1248     @ForceInline
1249     public final DoubleVector div(Vector<Double> v) {
1250         return lanewise(DIV, v);
1251     }
1252 
1253     /**
1254      * Divides this vector by the broadcast of an input scalar.
1255      *
1256      * This is a lane-wise binary operation which applies
1257      * the primitive division operation ({@code /}) to each lane.
1258      *
1259      * This method is also equivalent to the expression
1260      * {@link #lanewise(VectorOperators.Binary,double)
1261      *    lanewise}{@code (}{@link VectorOperators#DIV
1262      *    DIV}{@code , e)}.
1263      *
1264      * @apiNote Because the underlying scalar operator is an IEEE
1265      * floating point number, division by zero in fact will
1266      * not throw an exception, but will yield a signed
1267      * infinity or NaN.
1268      *
1269      * @param e the input scalar
1270      * @return the result of dividing each lane of this vector by the scalar
1271      * @see #div(Vector)
1272      * @see #broadcast(double)
1273      * @see #div(double,VectorMask)
1274      * @see VectorOperators#DIV
1275      * @see #lanewise(VectorOperators.Binary,Vector)
1276      * @see #lanewise(VectorOperators.Binary,double)
1277      */
1278     @ForceInline
1279     public final DoubleVector div(double e) {
1280         return lanewise(DIV, e);
1281     }
1282 
1283     /**
1284      * {@inheritDoc} <!--workaround-->
1285      * @see #div(double,VectorMask)
1286      * @apiNote Because the underlying scalar operator is an IEEE
1287      * floating point number, division by zero in fact will
1288      * not throw an exception, but will yield a signed
1289      * infinity or NaN.
1290      */
1291     @Override
1292     @ForceInline
1293     public final DoubleVector div(Vector<Double> v,
1294                                           VectorMask<Double> m) {
1295         return lanewise(DIV, v, m);
1296     }
1297 
1298     /**
1299      * Divides this vector by the broadcast of an input scalar,
1300      * selecting lane elements controlled by a mask.
1301      *
1302      * This is a masked lane-wise binary operation which applies
1303      * the primitive division operation ({@code /}) to each lane.
1304      *
1305      * This method is also equivalent to the expression
1306      * {@link #lanewise(VectorOperators.Binary,double,VectorMask)
1307      *    lanewise}{@code (}{@link VectorOperators#DIV
1308      *    DIV}{@code , s, m)}.
1309      *
1310      * @apiNote Because the underlying scalar operator is an IEEE
1311      * floating point number, division by zero in fact will
1312      * not throw an exception, but will yield a signed
1313      * infinity or NaN.
1314      *
1315      * @param e the input scalar
1316      * @param m the mask controlling lane selection
1317      * @return the result of dividing each lane of this vector by the scalar
1318      * @see #div(Vector,VectorMask)
1319      * @see #broadcast(double)
1320      * @see #div(double)
1321      * @see VectorOperators#DIV
1322      * @see #lanewise(VectorOperators.Binary,Vector)
1323      * @see #lanewise(VectorOperators.Binary,double)
1324      */
1325     @ForceInline
1326     public final DoubleVector div(double e,
1327                                           VectorMask<Double> m) {
1328         return lanewise(DIV, e, m);
1329     }
1330 
1331     /// END OF FULL-SERVICE BINARY METHODS
1332 
1333     /// SECOND-TIER BINARY METHODS
1334     //
1335     // There are no masked versions.
1336 
1337     /**
1338      * {@inheritDoc} <!--workaround-->
1339      * @apiNote
1340      * For this method, floating point negative
1341      * zero {@code -0.0} is treated as a value distinct from, and less
1342      * than the default value (positive zero).
1343      */
1344     @Override
1345     @ForceInline
1346     public final DoubleVector min(Vector<Double> v) {
1347         return lanewise(MIN, v);
1348     }
1349 
1350     // FIXME:  "broadcast of an input scalar" is really wordy.  Reduce?
1351     /**
1352      * Computes the smaller of this vector and the broadcast of an input scalar.
1353      *
1354      * This is a lane-wise binary operation which applies the
1355      * operation {@code Math.min()} to each pair of
1356      * corresponding lane values.
1357      *
1358      * This method is also equivalent to the expression
1359      * {@link #lanewise(VectorOperators.Binary,double)
1360      *    lanewise}{@code (}{@link VectorOperators#MIN
1361      *    MIN}{@code , e)}.
1362      *
1363      * @param e the input scalar
1364      * @return the result of multiplying this vector by the given scalar
1365      * @see #min(Vector)
1366      * @see #broadcast(double)
1367      * @see VectorOperators#MIN
1368      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
1369      * @apiNote
1370      * For this method, floating point negative
1371      * zero {@code -0.0} is treated as a value distinct from, and less
1372      * than the default value (positive zero).
1373      */
1374     @ForceInline
1375     public final DoubleVector min(double e) {
1376         return lanewise(MIN, e);
1377     }
1378 
1379     /**
1380      * {@inheritDoc} <!--workaround-->
1381      * @apiNote
1382      * For this method, floating point negative
1383      * zero {@code -0.0} is treated as a value distinct from, and less
1384      * than the default value (positive zero).
1385      */
1386     @Override
1387     @ForceInline
1388     public final DoubleVector max(Vector<Double> v) {
1389         return lanewise(MAX, v);
1390     }
1391 
1392     /**
1393      * Computes the larger of this vector and the broadcast of an input scalar.
1394      *
1395      * This is a lane-wise binary operation which applies the
1396      * operation {@code Math.max()} to each pair of
1397      * corresponding lane values.
1398      *
1399      * This method is also equivalent to the expression
1400      * {@link #lanewise(VectorOperators.Binary,double)
1401      *    lanewise}{@code (}{@link VectorOperators#MAX
1402      *    MAX}{@code , e)}.
1403      *
1404      * @param e the input scalar
1405      * @return the result of multiplying this vector by the given scalar
1406      * @see #max(Vector)
1407      * @see #broadcast(double)
1408      * @see VectorOperators#MAX
1409      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
1410      * @apiNote
1411      * For this method, floating point negative
1412      * zero {@code -0.0} is treated as a value distinct from, and less
1413      * than the default value (positive zero).
1414      */
1415     @ForceInline
1416     public final DoubleVector max(double e) {
1417         return lanewise(MAX, e);
1418     }
1419 
1420 
1421     // common FP operator: pow
1422     /**
1423      * Raises this vector to the power of a second input vector.
1424      *
1425      * This is a lane-wise binary operation which applies an operation
1426      * conforming to the specification of
1427      * {@link Math#pow Math.pow(a,b)}
1428      * to each pair of corresponding lane values.
1429      *
1430      * This method is also equivalent to the expression
1431      * {@link #lanewise(VectorOperators.Binary,Vector)
1432      *    lanewise}{@code (}{@link VectorOperators#POW
1433      *    POW}{@code , b)}.
1434      *
1435      * <p>
1436      * This is not a full-service named operation like
1437      * {@link #add(Vector) add}.  A masked version of
1438      * this operation is not directly available
1439      * but may be obtained via the masked version of
1440      * {@code lanewise}.
1441      *
1442      * @param b a vector exponent by which to raise this vector
1443      * @return the {@code b}-th power of this vector
1444      * @see #pow(double)
1445      * @see VectorOperators#POW
1446      * @see #lanewise(VectorOperators.Binary,Vector,VectorMask)
1447      */
1448     @ForceInline
1449     public final DoubleVector pow(Vector<Double> b) {
1450         return lanewise(POW, b);
1451     }
1452 
1453     /**
1454      * Raises this vector to a scalar power.
1455      *
1456      * This is a lane-wise binary operation which applies an operation
1457      * conforming to the specification of
1458      * {@link Math#pow Math.pow(a,b)}
1459      * to each pair of corresponding lane values.
1460      *
1461      * This method is also equivalent to the expression
1462      * {@link #lanewise(VectorOperators.Binary,Vector)
1463      *    lanewise}{@code (}{@link VectorOperators#POW
1464      *    POW}{@code , b)}.
1465      *
1466      * @param b a scalar exponent by which to raise this vector
1467      * @return the {@code b}-th power of this vector
1468      * @see #pow(Vector)
1469      * @see VectorOperators#POW
1470      * @see #lanewise(VectorOperators.Binary,double,VectorMask)
1471      */
1472     @ForceInline
1473     public final DoubleVector pow(double b) {
1474         return lanewise(POW, b);
1475     }
1476 
1477     /// UNARY METHODS
1478 
1479     /**
1480      * {@inheritDoc} <!--workaround-->
1481      */
1482     @Override
1483     @ForceInline
1484     public final
1485     DoubleVector neg() {
1486         return lanewise(NEG);
1487     }
1488 
1489     /**
1490      * {@inheritDoc} <!--workaround-->
1491      */
1492     @Override
1493     @ForceInline
1494     public final
1495     DoubleVector abs() {
1496         return lanewise(ABS);
1497     }
1498 
1499 
1500     // sqrt
1501     /**
1502      * Computes the square root of this vector.
1503      *
1504      * This is a lane-wise unary operation which applies an operation
1505      * conforming to the specification of
1506      * {@link Math#sqrt Math.sqrt(a)}
1507      * to each lane value.
1508      *
1509      * This method is also equivalent to the expression
1510      * {@link #lanewise(VectorOperators.Unary)
1511      *    lanewise}{@code (}{@link VectorOperators#SQRT
1512      *    SQRT}{@code )}.
1513      *
1514      * @return the square root of this vector
1515      * @see VectorOperators#SQRT
1516      * @see #lanewise(VectorOperators.Unary,VectorMask)
1517      */
1518     @ForceInline
1519     public final DoubleVector sqrt() {
1520         return lanewise(SQRT);
1521     }
1522 
1523     /// COMPARISONS
1524 
1525     /**
1526      * {@inheritDoc} <!--workaround-->
1527      */
1528     @Override
1529     @ForceInline
1530     public final
1531     VectorMask<Double> eq(Vector<Double> v) {
1532         return compare(EQ, v);
1533     }
1534 
1535     /**
1536      * Tests if this vector is equal to an input scalar.
1537      *
1538      * This is a lane-wise binary test operation which applies
1539      * the primitive equals operation ({@code ==}) to each lane.
1540      * The result is the same as {@code compare(VectorOperators.Comparison.EQ, e)}.
1541      *
1542      * @param e the input scalar
1543      * @return the result mask of testing if this vector
1544      *         is equal to {@code e}
1545      * @see #compare(VectorOperators.Comparison,double)
1546      */
1547     @ForceInline
1548     public final
1549     VectorMask<Double> eq(double e) {
1550         return compare(EQ, e);
1551     }
1552 
1553     /**
1554      * {@inheritDoc} <!--workaround-->
1555      */
1556     @Override
1557     @ForceInline
1558     public final
1559     VectorMask<Double> lt(Vector<Double> v) {
1560         return compare(LT, v);
1561     }
1562 
1563     /**
1564      * Tests if this vector is less than an input scalar.
1565      *
1566      * This is a lane-wise binary test operation which applies
1567      * the primitive less than operation ({@code <}) to each lane.
1568      * The result is the same as {@code compare(VectorOperators.LT, e)}.
1569      *
1570      * @param e the input scalar
1571      * @return the mask result of testing if this vector
1572      *         is less than the input scalar
1573      * @see #compare(VectorOperators.Comparison,double)
1574      */
1575     @ForceInline
1576     public final
1577     VectorMask<Double> lt(double e) {
1578         return compare(LT, e);
1579     }
1580 
1581     /**
1582      * {@inheritDoc} <!--workaround-->
1583      */
1584     @Override
1585     public abstract
1586     VectorMask<Double> test(VectorOperators.Test op);
1587 
1588     /*package-private*/
1589     @ForceInline
1590     final
1591     <M extends VectorMask<Double>>
1592     M testTemplate(Class<M> maskType, Test op) {
1593         DoubleSpecies vsp = vspecies();
1594         if (opKind(op, VO_SPECIAL)) {
1595             LongVector bits = this.viewAsIntegralLanes();
1596             VectorMask<Long> m;
1597             if (op == IS_DEFAULT) {
1598                 m = bits.compare(EQ, (long) 0);
1599             } else if (op == IS_NEGATIVE) {
1600                 m = bits.compare(LT, (long) 0);
1601             }
1602             else if (op == IS_FINITE ||
1603                      op == IS_NAN ||
1604                      op == IS_INFINITE) {
1605                 // first kill the sign:
1606                 bits = bits.and(Long.MAX_VALUE);
1607                 // next find the bit pattern for infinity:
1608                 long infbits = (long) toBits(Double.POSITIVE_INFINITY);
1609                 // now compare:
1610                 if (op == IS_FINITE) {
1611                     m = bits.compare(LT, infbits);
1612                 } else if (op == IS_NAN) {
1613                     m = bits.compare(GT, infbits);
1614                 } else {
1615                     m = bits.compare(EQ, infbits);
1616                 }
1617             }
1618             else {
1619                 throw new AssertionError(op);
1620             }
1621             return maskType.cast(m.cast(this.vspecies()));
1622         }
1623         int opc = opCode(op);
1624         throw new AssertionError(op);
1625     }
1626 
1627     /**
1628      * {@inheritDoc} <!--workaround-->
1629      */
1630     @Override
1631     @ForceInline
1632     public final
1633     VectorMask<Double> test(VectorOperators.Test op,
1634                                   VectorMask<Double> m) {
1635         return test(op).and(m);
1636     }
1637 
1638     /**
1639      * {@inheritDoc} <!--workaround-->
1640      */
1641     @Override
1642     public abstract
1643     VectorMask<Double> compare(VectorOperators.Comparison op, Vector<Double> v);
1644 
1645     /*package-private*/
1646     @ForceInline
1647     final
1648     <M extends VectorMask<Double>>
1649     M compareTemplate(Class<M> maskType, Comparison op, Vector<Double> v) {
1650         Objects.requireNonNull(v);
1651         DoubleSpecies vsp = vspecies();
1652         DoubleVector that = (DoubleVector) v;
1653         that.check(this);
1654         int opc = opCode(op);
1655         return VectorSupport.compare(
1656             opc, getClass(), maskType, double.class, length(),
1657             this, that,
1658             (cond, v0, v1) -> {
1659                 AbstractMask<Double> m
1660                     = v0.bTest(cond, v1, (cond_, i, a, b)
1661                                -> compareWithOp(cond, a, b));
1662                 @SuppressWarnings("unchecked")
1663                 M m2 = (M) m;
1664                 return m2;
1665             });
1666     }
1667 
1668     @ForceInline
1669     private static boolean compareWithOp(int cond, double a, double b) {
1670         return switch (cond) {
1671             case BT_eq -> a == b;
1672             case BT_ne -> a != b;
1673             case BT_lt -> a < b;
1674             case BT_le -> a <= b;
1675             case BT_gt -> a > b;
1676             case BT_ge -> a >= b;
1677             default -> throw new AssertionError();
1678         };
1679     }
1680 
1681     /**
1682      * {@inheritDoc} <!--workaround-->
1683      */
1684     @Override
1685     @ForceInline
1686     public final
1687     VectorMask<Double> compare(VectorOperators.Comparison op,
1688                                   Vector<Double> v,
1689                                   VectorMask<Double> m) {
1690         return compare(op, v).and(m);
1691     }
1692 
1693     /**
1694      * Tests this vector by comparing it with an input scalar,
1695      * according to the given comparison operation.
1696      *
1697      * This is a lane-wise binary test operation which applies
1698      * the comparison operation to each lane.
1699      * <p>
1700      * The result is the same as
1701      * {@code compare(op, broadcast(species(), e))}.
1702      * That is, the scalar may be regarded as broadcast to
1703      * a vector of the same species, and then compared
1704      * against the original vector, using the selected
1705      * comparison operation.
1706      *
1707      * @param op the operation used to compare lane values
1708      * @param e the input scalar
1709      * @return the mask result of testing lane-wise if this vector
1710      *         compares to the input, according to the selected
1711      *         comparison operator
1712      * @see DoubleVector#compare(VectorOperators.Comparison,Vector)
1713      * @see #eq(double)
1714      * @see #lt(double)
1715      */
1716     public abstract
1717     VectorMask<Double> compare(Comparison op, double e);
1718 
1719     /*package-private*/
1720     @ForceInline
1721     final
1722     <M extends VectorMask<Double>>
1723     M compareTemplate(Class<M> maskType, Comparison op, double e) {
1724         return compareTemplate(maskType, op, broadcast(e));
1725     }
1726 
1727     /**
1728      * Tests this vector by comparing it with an input scalar,
1729      * according to the given comparison operation,
1730      * in lanes selected by a mask.
1731      *
1732      * This is a masked lane-wise binary test operation which applies
1733      * to each pair of corresponding lane values.
1734      *
1735      * The returned result is equal to the expression
1736      * {@code compare(op,s).and(m)}.
1737      *
1738      * @param op the operation used to compare lane values
1739      * @param e the input scalar
1740      * @param m the mask controlling lane selection
1741      * @return the mask result of testing lane-wise if this vector
1742      *         compares to the input, according to the selected
1743      *         comparison operator,
1744      *         and only in the lanes selected by the mask
1745      * @see DoubleVector#compare(VectorOperators.Comparison,Vector,VectorMask)
1746      */
1747     @ForceInline
1748     public final VectorMask<Double> compare(VectorOperators.Comparison op,
1749                                                double e,
1750                                                VectorMask<Double> m) {
1751         return compare(op, e).and(m);
1752     }
1753 
1754     /**
1755      * {@inheritDoc} <!--workaround-->
1756      */
1757     @Override
1758     public abstract
1759     VectorMask<Double> compare(Comparison op, long e);
1760 
1761     /*package-private*/
1762     @ForceInline
1763     final
1764     <M extends VectorMask<Double>>
1765     M compareTemplate(Class<M> maskType, Comparison op, long e) {
1766         return compareTemplate(maskType, op, broadcast(e));
1767     }
1768 
1769     /**
1770      * {@inheritDoc} <!--workaround-->
1771      */
1772     @Override
1773     @ForceInline
1774     public final
1775     VectorMask<Double> compare(Comparison op, long e, VectorMask<Double> m) {
1776         return compare(op, broadcast(e), m);
1777     }
1778 
1779 
1780 
1781     /**
1782      * {@inheritDoc} <!--workaround-->
1783      */
1784     @Override public abstract
1785     DoubleVector blend(Vector<Double> v, VectorMask<Double> m);
1786 
1787     /*package-private*/
1788     @ForceInline
1789     final
1790     <M extends VectorMask<Double>>
1791     DoubleVector
1792     blendTemplate(Class<M> maskType, DoubleVector v, M m) {
1793         v.check(this);
1794         return VectorSupport.blend(
1795             getClass(), maskType, double.class, length(),
1796             this, v, m,
1797             (v0, v1, m_) -> v0.bOp(v1, m_, (i, a, b) -> b));
1798     }
1799 
1800     /**
1801      * {@inheritDoc} <!--workaround-->
1802      */
1803     @Override public abstract DoubleVector addIndex(int scale);
1804 
1805     /*package-private*/
1806     @ForceInline
1807     final DoubleVector addIndexTemplate(int scale) {
1808         DoubleSpecies vsp = vspecies();
1809         // make sure VLENGTH*scale doesn't overflow:
1810         vsp.checkScale(scale);
1811         return VectorSupport.indexVector(
1812             getClass(), double.class, length(),
1813             this, scale, vsp,
1814             (v, scale_, s)
1815             -> {
1816                 // If the platform doesn't support an INDEX
1817                 // instruction directly, load IOTA from memory
1818                 // and multiply.
1819                 DoubleVector iota = s.iota();
1820                 double sc = (double) scale_;
1821                 return v.add(sc == 1 ? iota : iota.mul(sc));
1822             });
1823     }
1824 
1825     /**
1826      * Replaces selected lanes of this vector with
1827      * a scalar value
1828      * under the control of a mask.
1829      *
1830      * This is a masked lane-wise binary operation which
1831      * selects each lane value from one or the other input.
1832      *
1833      * The returned result is equal to the expression
1834      * {@code blend(broadcast(e),m)}.
1835      *
1836      * @param e the input scalar, containing the replacement lane value
1837      * @param m the mask controlling lane selection of the scalar
1838      * @return the result of blending the lane elements of this vector with
1839      *         the scalar value
1840      */
1841     @ForceInline
1842     public final DoubleVector blend(double e,
1843                                             VectorMask<Double> m) {
1844         return blend(broadcast(e), m);
1845     }
1846 
1847     /**
1848      * Replaces selected lanes of this vector with
1849      * a scalar value
1850      * under the control of a mask.
1851      *
1852      * This is a masked lane-wise binary operation which
1853      * selects each lane value from one or the other input.
1854      *
1855      * The returned result is equal to the expression
1856      * {@code blend(broadcast(e),m)}.
1857      *
1858      * @param e the input scalar, containing the replacement lane value
1859      * @param m the mask controlling lane selection of the scalar
1860      * @return the result of blending the lane elements of this vector with
1861      *         the scalar value
1862      */
1863     @ForceInline
1864     public final DoubleVector blend(long e,
1865                                             VectorMask<Double> m) {
1866         return blend(broadcast(e), m);
1867     }
1868 
1869     /**
1870      * {@inheritDoc} <!--workaround-->
1871      */
1872     @Override
1873     public abstract
1874     DoubleVector slice(int origin, Vector<Double> v1);
1875 
1876     /*package-private*/
1877     final
1878     @ForceInline
1879     DoubleVector sliceTemplate(int origin, Vector<Double> v1) {
1880         DoubleVector that = (DoubleVector) v1;
1881         that.check(this);
1882         Objects.checkIndex(origin, length() + 1);
1883         VectorShuffle<Double> iota = iotaShuffle();
1884         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.LT, (broadcast((double)(length() - origin))));
1885         iota = iotaShuffle(origin, 1, true);
1886         return that.rearrange(iota).blend(this.rearrange(iota), blendMask);
1887     }
1888 
1889     /**
1890      * {@inheritDoc} <!--workaround-->
1891      */
1892     @Override
1893     @ForceInline
1894     public final
1895     DoubleVector slice(int origin,
1896                                Vector<Double> w,
1897                                VectorMask<Double> m) {
1898         return broadcast(0).blend(slice(origin, w), m);
1899     }
1900 
1901     /**
1902      * {@inheritDoc} <!--workaround-->
1903      */
1904     @Override
1905     public abstract
1906     DoubleVector slice(int origin);
1907 
1908     /*package-private*/
1909     final
1910     @ForceInline
1911     DoubleVector sliceTemplate(int origin) {
1912         Objects.checkIndex(origin, length() + 1);
1913         VectorShuffle<Double> iota = iotaShuffle();
1914         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.LT, (broadcast((double)(length() - origin))));
1915         iota = iotaShuffle(origin, 1, true);
1916         return vspecies().zero().blend(this.rearrange(iota), blendMask);
1917     }
1918 
1919     /**
1920      * {@inheritDoc} <!--workaround-->
1921      */
1922     @Override
1923     public abstract
1924     DoubleVector unslice(int origin, Vector<Double> w, int part);
1925 
1926     /*package-private*/
1927     final
1928     @ForceInline
1929     DoubleVector
1930     unsliceTemplate(int origin, Vector<Double> w, int part) {
1931         DoubleVector that = (DoubleVector) w;
1932         that.check(this);
1933         Objects.checkIndex(origin, length() + 1);
1934         VectorShuffle<Double> iota = iotaShuffle();
1935         VectorMask<Double> blendMask = iota.toVector().compare((part == 0) ? VectorOperators.GE : VectorOperators.LT,
1936                                                                   (broadcast((double)(origin))));
1937         iota = iotaShuffle(-origin, 1, true);
1938         return that.blend(this.rearrange(iota), blendMask);
1939     }
1940 
1941     /*package-private*/
1942     final
1943     @ForceInline
1944     <M extends VectorMask<Double>>
1945     DoubleVector
1946     unsliceTemplate(Class<M> maskType, int origin, Vector<Double> w, int part, M m) {
1947         DoubleVector that = (DoubleVector) w;
1948         that.check(this);
1949         DoubleVector slice = that.sliceTemplate(origin, that);
1950         slice = slice.blendTemplate(maskType, this, m);
1951         return slice.unsliceTemplate(origin, w, part);
1952     }
1953 
1954     /**
1955      * {@inheritDoc} <!--workaround-->
1956      */
1957     @Override
1958     public abstract
1959     DoubleVector unslice(int origin, Vector<Double> w, int part, VectorMask<Double> m);
1960 
1961     /**
1962      * {@inheritDoc} <!--workaround-->
1963      */
1964     @Override
1965     public abstract
1966     DoubleVector unslice(int origin);
1967 
1968     /*package-private*/
1969     final
1970     @ForceInline
1971     DoubleVector
1972     unsliceTemplate(int origin) {
1973         Objects.checkIndex(origin, length() + 1);
1974         VectorShuffle<Double> iota = iotaShuffle();
1975         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.GE,
1976                                                                   (broadcast((double)(origin))));
1977         iota = iotaShuffle(-origin, 1, true);
1978         return vspecies().zero().blend(this.rearrange(iota), blendMask);
1979     }
1980 
1981     private ArrayIndexOutOfBoundsException
1982     wrongPartForSlice(int part) {
1983         String msg = String.format("bad part number %d for slice operation",
1984                                    part);
1985         return new ArrayIndexOutOfBoundsException(msg);
1986     }
1987 
1988     /**
1989      * {@inheritDoc} <!--workaround-->
1990      */
1991     @Override
1992     public abstract
1993     DoubleVector rearrange(VectorShuffle<Double> m);
1994 
1995     /*package-private*/
1996     @ForceInline
1997     final
1998     <S extends VectorShuffle<Double>>
1999     DoubleVector rearrangeTemplate(Class<S> shuffletype, S shuffle) {
2000         shuffle.checkIndexes();
2001         return VectorSupport.rearrangeOp(
2002             getClass(), shuffletype, double.class, length(),
2003             this, shuffle,
2004             (v1, s_) -> v1.uOp((i, a) -> {
2005                 int ei = s_.laneSource(i);
2006                 return v1.lane(ei);
2007             }));
2008     }
2009 
2010     /**
2011      * {@inheritDoc} <!--workaround-->
2012      */
2013     @Override
2014     public abstract
2015     DoubleVector rearrange(VectorShuffle<Double> s,
2016                                    VectorMask<Double> m);
2017 
2018     /*package-private*/
2019     @ForceInline
2020     final
2021     <S extends VectorShuffle<Double>>
2022     DoubleVector rearrangeTemplate(Class<S> shuffletype,
2023                                            S shuffle,
2024                                            VectorMask<Double> m) {
2025         DoubleVector unmasked =
2026             VectorSupport.rearrangeOp(
2027                 getClass(), shuffletype, double.class, length(),
2028                 this, shuffle,
2029                 (v1, s_) -> v1.uOp((i, a) -> {
2030                     int ei = s_.laneSource(i);
2031                     return ei < 0 ? 0 : v1.lane(ei);
2032                 }));
2033         VectorMask<Double> valid = shuffle.laneIsValid();
2034         if (m.andNot(valid).anyTrue()) {
2035             shuffle.checkIndexes();
2036             throw new AssertionError();
2037         }
2038         return broadcast((double)0).blend(unmasked, m);
2039     }
2040 
2041     /**
2042      * {@inheritDoc} <!--workaround-->
2043      */
2044     @Override
2045     public abstract
2046     DoubleVector rearrange(VectorShuffle<Double> s,
2047                                    Vector<Double> v);
2048 
2049     /*package-private*/
2050     @ForceInline
2051     final
2052     <S extends VectorShuffle<Double>>
2053     DoubleVector rearrangeTemplate(Class<S> shuffletype,
2054                                            S shuffle,
2055                                            DoubleVector v) {
2056         VectorMask<Double> valid = shuffle.laneIsValid();
2057         @SuppressWarnings("unchecked")
2058         S ws = (S) shuffle.wrapIndexes();
2059         DoubleVector r0 =
2060             VectorSupport.rearrangeOp(
2061                 getClass(), shuffletype, double.class, length(),
2062                 this, ws,
2063                 (v0, s_) -> v0.uOp((i, a) -> {
2064                     int ei = s_.laneSource(i);
2065                     return v0.lane(ei);
2066                 }));
2067         DoubleVector r1 =
2068             VectorSupport.rearrangeOp(
2069                 getClass(), shuffletype, double.class, length(),
2070                 v, ws,
2071                 (v1, s_) -> v1.uOp((i, a) -> {
2072                     int ei = s_.laneSource(i);
2073                     return v1.lane(ei);
2074                 }));
2075         return r1.blend(r0, valid);
2076     }
2077 
2078     @ForceInline
2079     private final
2080     VectorShuffle<Double> toShuffle0(DoubleSpecies dsp) {
2081         double[] a = toArray();
2082         int[] sa = new int[a.length];
2083         for (int i = 0; i < a.length; i++) {
2084             sa[i] = (int) a[i];
2085         }
2086         return VectorShuffle.fromArray(dsp, sa, 0);
2087     }
2088 
2089     /*package-private*/
2090     @ForceInline
2091     final
2092     VectorShuffle<Double> toShuffleTemplate(Class<?> shuffleType) {
2093         DoubleSpecies vsp = vspecies();
2094         return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST,
2095                                      getClass(), double.class, length(),
2096                                      shuffleType, byte.class, length(),
2097                                      this, vsp,
2098                                      DoubleVector::toShuffle0);
2099     }
2100 
2101     /**
2102      * {@inheritDoc} <!--workaround-->
2103      */
2104     @Override
2105     public abstract
2106     DoubleVector selectFrom(Vector<Double> v);
2107 
2108     /*package-private*/
2109     @ForceInline
2110     final DoubleVector selectFromTemplate(DoubleVector v) {
2111         return v.rearrange(this.toShuffle());
2112     }
2113 
2114     /**
2115      * {@inheritDoc} <!--workaround-->
2116      */
2117     @Override
2118     public abstract
2119     DoubleVector selectFrom(Vector<Double> s, VectorMask<Double> m);
2120 
2121     /*package-private*/
2122     @ForceInline
2123     final DoubleVector selectFromTemplate(DoubleVector v,
2124                                                   AbstractMask<Double> m) {
2125         return v.rearrange(this.toShuffle(), m);
2126     }
2127 
2128     /// Ternary operations
2129 
2130 
2131     /**
2132      * Multiplies this vector by a second input vector, and sums
2133      * the result with a third.
2134      *
2135      * Extended precision is used for the intermediate result,
2136      * avoiding possible loss of precision from rounding once
2137      * for each of the two operations.
2138      * The result is numerically close to {@code this.mul(b).add(c)},
2139      * and is typically closer to the true mathematical result.
2140      *
2141      * This is a lane-wise ternary operation which applies an operation
2142      * conforming to the specification of
2143      * {@link Math#fma(double,double,double) Math.fma(a,b,c)}
2144      * to each lane.
2145      *
2146      * This method is also equivalent to the expression
2147      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2148      *    lanewise}{@code (}{@link VectorOperators#FMA
2149      *    FMA}{@code , b, c)}.
2150      *
2151      * @param b the second input vector, supplying multiplier values
2152      * @param c the third input vector, supplying addend values
2153      * @return the product of this vector and the second input vector
2154      *         summed with the third input vector, using extended precision
2155      *         for the intermediate result
2156      * @see #fma(double,double)
2157      * @see VectorOperators#FMA
2158      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
2159      */
2160     @ForceInline
2161     public final
2162     DoubleVector fma(Vector<Double> b, Vector<Double> c) {
2163         return lanewise(FMA, b, c);
2164     }
2165 
2166     /**
2167      * Multiplies this vector by a scalar multiplier, and sums
2168      * the result with a scalar addend.
2169      *
2170      * Extended precision is used for the intermediate result,
2171      * avoiding possible loss of precision from rounding once
2172      * for each of the two operations.
2173      * The result is numerically close to {@code this.mul(b).add(c)},
2174      * and is typically closer to the true mathematical result.
2175      *
2176      * This is a lane-wise ternary operation which applies an operation
2177      * conforming to the specification of
2178      * {@link Math#fma(double,double,double) Math.fma(a,b,c)}
2179      * to each lane.
2180      *
2181      * This method is also equivalent to the expression
2182      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2183      *    lanewise}{@code (}{@link VectorOperators#FMA
2184      *    FMA}{@code , b, c)}.
2185      *
2186      * @param b the scalar multiplier
2187      * @param c the scalar addend
2188      * @return the product of this vector and the scalar multiplier
2189      *         summed with scalar addend, using extended precision
2190      *         for the intermediate result
2191      * @see #fma(Vector,Vector)
2192      * @see VectorOperators#FMA
2193      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
2194      */
2195     @ForceInline
2196     public final
2197     DoubleVector fma(double b, double c) {
2198         return lanewise(FMA, b, c);
2199     }
2200 
2201     // Don't bother with (Vector,double) and (double,Vector) overloadings.
2202 
2203     // Type specific horizontal reductions
2204 
2205     /**
2206      * Returns a value accumulated from all the lanes of this vector.
2207      *
2208      * This is an associative cross-lane reduction operation which
2209      * applies the specified operation to all the lane elements.
2210      * <p>
2211      * A few reduction operations do not support arbitrary reordering
2212      * of their operands, yet are included here because of their
2213      * usefulness.
2214      * <ul>
2215      * <li>
2216      * In the case of {@code FIRST_NONZERO}, the reduction returns
2217      * the value from the lowest-numbered non-zero lane.
2218      * (As with {@code MAX} and {@code MIN}, floating point negative
2219      * zero {@code -0.0} is treated as a value distinct from
2220      * the default value, positive zero. So a first-nonzero lane reduction
2221      * might return {@code -0.0} even in the presence of non-zero
2222      * lane values.)
2223      * <li>
2224      * In the case of {@code ADD} and {@code MUL}, the
2225      * precise result will reflect the choice of an arbitrary order
2226      * of operations, which may even vary over time.
2227      * For further details see the section
2228      * <a href="VectorOperators.html#fp_assoc">Operations on floating point vectors</a>.
2229      * <li>
2230      * All other reduction operations are fully commutative and
2231      * associative.  The implementation can choose any order of
2232      * processing, yet it will always produce the same result.
2233      * </ul>
2234      *
2235      * @param op the operation used to combine lane values
2236      * @return the accumulated result
2237      * @throws UnsupportedOperationException if this vector does
2238      *         not support the requested operation
2239      * @see #reduceLanes(VectorOperators.Associative,VectorMask)
2240      * @see #add(Vector)
2241      * @see #mul(Vector)
2242      * @see #min(Vector)
2243      * @see #max(Vector)
2244      * @see VectorOperators#FIRST_NONZERO
2245      */
2246     public abstract double reduceLanes(VectorOperators.Associative op);
2247 
2248     /**
2249      * Returns a value accumulated from selected lanes of this vector,
2250      * controlled by a mask.
2251      *
2252      * This is an associative cross-lane reduction operation which
2253      * applies the specified operation to the selected lane elements.
2254      * <p>
2255      * If no elements are selected, an operation-specific identity
2256      * value is returned.
2257      * <ul>
2258      * <li>
2259      * If the operation is
2260      *  {@code ADD}
2261      * or {@code FIRST_NONZERO},
2262      * then the identity value is positive zero, the default {@code double} value.
2263      * <li>
2264      * If the operation is {@code MUL},
2265      * then the identity value is one.
2266      * <li>
2267      * If the operation is {@code MAX},
2268      * then the identity value is {@code Double.NEGATIVE_INFINITY}.
2269      * <li>
2270      * If the operation is {@code MIN},
2271      * then the identity value is {@code Double.POSITIVE_INFINITY}.
2272      * </ul>
2273      * <p>
2274      * A few reduction operations do not support arbitrary reordering
2275      * of their operands, yet are included here because of their
2276      * usefulness.
2277      * <ul>
2278      * <li>
2279      * In the case of {@code FIRST_NONZERO}, the reduction returns
2280      * the value from the lowest-numbered non-zero lane.
2281      * (As with {@code MAX} and {@code MIN}, floating point negative
2282      * zero {@code -0.0} is treated as a value distinct from
2283      * the default value, positive zero. So a first-nonzero lane reduction
2284      * might return {@code -0.0} even in the presence of non-zero
2285      * lane values.)
2286      * <li>
2287      * In the case of {@code ADD} and {@code MUL}, the
2288      * precise result will reflect the choice of an arbitrary order
2289      * of operations, which may even vary over time.
2290      * For further details see the section
2291      * <a href="VectorOperators.html#fp_assoc">Operations on floating point vectors</a>.
2292      * <li>
2293      * All other reduction operations are fully commutative and
2294      * associative.  The implementation can choose any order of
2295      * processing, yet it will always produce the same result.
2296      * </ul>
2297      *
2298      * @param op the operation used to combine lane values
2299      * @param m the mask controlling lane selection
2300      * @return the reduced result accumulated from the selected lane values
2301      * @throws UnsupportedOperationException if this vector does
2302      *         not support the requested operation
2303      * @see #reduceLanes(VectorOperators.Associative)
2304      */
2305     public abstract double reduceLanes(VectorOperators.Associative op,
2306                                        VectorMask<Double> m);
2307 
2308     /*package-private*/
2309     @ForceInline
2310     final
2311     double reduceLanesTemplate(VectorOperators.Associative op,
2312                                VectorMask<Double> m) {
2313         DoubleVector v = reduceIdentityVector(op).blend(this, m);
2314         return v.reduceLanesTemplate(op);
2315     }
2316 
2317     /*package-private*/
2318     @ForceInline
2319     final
2320     double reduceLanesTemplate(VectorOperators.Associative op) {
2321         if (op == FIRST_NONZERO) {
2322             // FIXME:  The JIT should handle this, and other scan ops alos.
2323             VectorMask<Long> thisNZ
2324                 = this.viewAsIntegralLanes().compare(NE, (long) 0);
2325             return this.lane(thisNZ.firstTrue());
2326         }
2327         int opc = opCode(op);
2328         return fromBits(VectorSupport.reductionCoerced(
2329             opc, getClass(), double.class, length(),
2330             this,
2331             REDUCE_IMPL.find(op, opc, (opc_) -> {
2332               switch (opc_) {
2333               case VECTOR_OP_ADD: return v ->
2334                       toBits(v.rOp((double)0, (i, a, b) -> (double)(a + b)));
2335               case VECTOR_OP_MUL: return v ->
2336                       toBits(v.rOp((double)1, (i, a, b) -> (double)(a * b)));
2337               case VECTOR_OP_MIN: return v ->
2338                       toBits(v.rOp(MAX_OR_INF, (i, a, b) -> (double) Math.min(a, b)));
2339               case VECTOR_OP_MAX: return v ->
2340                       toBits(v.rOp(MIN_OR_INF, (i, a, b) -> (double) Math.max(a, b)));
2341               default: return null;
2342               }})));
2343     }
2344     private static final
2345     ImplCache<Associative,Function<DoubleVector,Long>> REDUCE_IMPL
2346         = new ImplCache<>(Associative.class, DoubleVector.class);
2347 
2348     private
2349     @ForceInline
2350     DoubleVector reduceIdentityVector(VectorOperators.Associative op) {
2351         int opc = opCode(op);
2352         UnaryOperator<DoubleVector> fn
2353             = REDUCE_ID_IMPL.find(op, opc, (opc_) -> {
2354                 switch (opc_) {
2355                 case VECTOR_OP_ADD:
2356                     return v -> v.broadcast(0);
2357                 case VECTOR_OP_MUL:
2358                     return v -> v.broadcast(1);
2359                 case VECTOR_OP_MIN:
2360                     return v -> v.broadcast(MAX_OR_INF);
2361                 case VECTOR_OP_MAX:
2362                     return v -> v.broadcast(MIN_OR_INF);
2363                 default: return null;
2364                 }
2365             });
2366         return fn.apply(this);
2367     }
2368     private static final
2369     ImplCache<Associative,UnaryOperator<DoubleVector>> REDUCE_ID_IMPL
2370         = new ImplCache<>(Associative.class, DoubleVector.class);
2371 
2372     private static final double MIN_OR_INF = Double.NEGATIVE_INFINITY;
2373     private static final double MAX_OR_INF = Double.POSITIVE_INFINITY;
2374 
2375     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op);
2376     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op,
2377                                                      VectorMask<Double> m);
2378 
2379     // Type specific accessors
2380 
2381     /**
2382      * Gets the lane element at lane index {@code i}
2383      *
2384      * @param i the lane index
2385      * @return the lane element at lane index {@code i}
2386      * @throws IllegalArgumentException if the index is is out of range
2387      * ({@code < 0 || >= length()})
2388      */
2389     public abstract double lane(int i);
2390 
2391     /**
2392      * Replaces the lane element of this vector at lane index {@code i} with
2393      * value {@code e}.
2394      *
2395      * This is a cross-lane operation and behaves as if it returns the result
2396      * of blending this vector with an input vector that is the result of
2397      * broadcasting {@code e} and a mask that has only one lane set at lane
2398      * index {@code i}.
2399      *
2400      * @param i the lane index of the lane element to be replaced
2401      * @param e the value to be placed
2402      * @return the result of replacing the lane element of this vector at lane
2403      * index {@code i} with value {@code e}.
2404      * @throws IllegalArgumentException if the index is is out of range
2405      * ({@code < 0 || >= length()})
2406      */
2407     public abstract DoubleVector withLane(int i, double e);
2408 
2409     // Memory load operations
2410 
2411     /**
2412      * Returns an array of type {@code double[]}
2413      * containing all the lane values.
2414      * The array length is the same as the vector length.
2415      * The array elements are stored in lane order.
2416      * <p>
2417      * This method behaves as if it stores
2418      * this vector into an allocated array
2419      * (using {@link #intoArray(double[], int) intoArray})
2420      * and returns the array as follows:
2421      * <pre>{@code
2422      *   double[] a = new double[this.length()];
2423      *   this.intoArray(a, 0);
2424      *   return a;
2425      * }</pre>
2426      *
2427      * @return an array containing the lane values of this vector
2428      */
2429     @ForceInline
2430     @Override
2431     public final double[] toArray() {
2432         double[] a = new double[vspecies().laneCount()];
2433         intoArray(a, 0);
2434         return a;
2435     }
2436 
2437     /** {@inheritDoc} <!--workaround-->
2438      */
2439     @ForceInline
2440     @Override
2441     public final int[] toIntArray() {
2442         double[] a = toArray();
2443         int[] res = new int[a.length];
2444         for (int i = 0; i < a.length; i++) {
2445             double e = a[i];
2446             res[i] = (int) DoubleSpecies.toIntegralChecked(e, true);
2447         }
2448         return res;
2449     }
2450 
2451     /** {@inheritDoc} <!--workaround-->
2452      */
2453     @ForceInline
2454     @Override
2455     public final long[] toLongArray() {
2456         double[] a = toArray();
2457         long[] res = new long[a.length];
2458         for (int i = 0; i < a.length; i++) {
2459             double e = a[i];
2460             res[i] = DoubleSpecies.toIntegralChecked(e, false);
2461         }
2462         return res;
2463     }
2464 
2465     /** {@inheritDoc} <!--workaround-->
2466      * @implNote
2467      * This is an alias for {@link #toArray()}
2468      * When this method is used on used on vectors
2469      * of type {@code DoubleVector},
2470      * there will be no loss of precision.
2471      */
2472     @ForceInline
2473     @Override
2474     public final double[] toDoubleArray() {
2475         return toArray();
2476     }
2477 
2478     /**
2479      * Loads a vector from a byte array starting at an offset.
2480      * Bytes are composed into primitive lane elements according
2481      * to the specified byte order.
2482      * The vector is arranged into lanes according to
2483      * <a href="Vector.html#lane-order">memory ordering</a>.
2484      * <p>
2485      * This method behaves as if it returns the result of calling
2486      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2487      * fromByteBuffer()} as follows:
2488      * <pre>{@code
2489      * var bb = ByteBuffer.wrap(a);
2490      * var m = species.maskAll(true);
2491      * return fromByteBuffer(species, bb, offset, bo, m);
2492      * }</pre>
2493      *
2494      * @param species species of desired vector
2495      * @param a the byte array
2496      * @param offset the offset into the array
2497      * @param bo the intended byte order
2498      * @return a vector loaded from a byte array
2499      * @throws IndexOutOfBoundsException
2500      *         if {@code offset+N*ESIZE < 0}
2501      *         or {@code offset+(N+1)*ESIZE > a.length}
2502      *         for any lane {@code N} in the vector
2503      */
2504     @ForceInline
2505     public static
2506     DoubleVector fromByteArray(VectorSpecies<Double> species,
2507                                        byte[] a, int offset,
2508                                        ByteOrder bo) {
2509         offset = checkFromIndexSize(offset, species.vectorByteSize(), a.length);
2510         DoubleSpecies vsp = (DoubleSpecies) species;
2511         return vsp.dummyVector().fromByteArray0(a, offset).maybeSwap(bo);
2512     }
2513 
2514     /**
2515      * Loads a vector from a byte array starting at an offset
2516      * and using a mask.
2517      * Lanes where the mask is unset are filled with the default
2518      * value of {@code double} (positive zero).
2519      * Bytes are composed into primitive lane elements according
2520      * to the specified byte order.
2521      * The vector is arranged into lanes according to
2522      * <a href="Vector.html#lane-order">memory ordering</a>.
2523      * <p>
2524      * This method behaves as if it returns the result of calling
2525      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2526      * fromByteBuffer()} as follows:
2527      * <pre>{@code
2528      * var bb = ByteBuffer.wrap(a);
2529      * return fromByteBuffer(species, bb, offset, bo, m);
2530      * }</pre>
2531      *
2532      * @param species species of desired vector
2533      * @param a the byte array
2534      * @param offset the offset into the array
2535      * @param bo the intended byte order
2536      * @param m the mask controlling lane selection
2537      * @return a vector loaded from a byte array
2538      * @throws IndexOutOfBoundsException
2539      *         if {@code offset+N*ESIZE < 0}
2540      *         or {@code offset+(N+1)*ESIZE > a.length}
2541      *         for any lane {@code N} in the vector
2542      *         where the mask is set
2543      */
2544     @ForceInline
2545     public static
2546     DoubleVector fromByteArray(VectorSpecies<Double> species,
2547                                        byte[] a, int offset,
2548                                        ByteOrder bo,
2549                                        VectorMask<Double> m) {
2550         DoubleSpecies vsp = (DoubleSpecies) species;
2551         if (offset >= 0 && offset <= (a.length - species.vectorByteSize())) {
2552             DoubleVector zero = vsp.zero();
2553             DoubleVector v = zero.fromByteArray0(a, offset);
2554             return zero.blend(v.maybeSwap(bo), m);
2555         }
2556 
2557         // FIXME: optimize
2558         checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
2559         ByteBuffer wb = wrapper(a, bo);
2560         return vsp.ldOp(wb, offset, (AbstractMask<Double>)m,
2561                    (wb_, o, i)  -> wb_.getDouble(o + i * 8));
2562     }
2563 
2564     /**
2565      * Loads a vector from an array of type {@code double[]}
2566      * starting at an offset.
2567      * For each vector lane, where {@code N} is the vector lane index, the
2568      * array element at index {@code offset + N} is placed into the
2569      * resulting vector at lane index {@code N}.
2570      *
2571      * @param species species of desired vector
2572      * @param a the array
2573      * @param offset the offset into the array
2574      * @return the vector loaded from an array
2575      * @throws IndexOutOfBoundsException
2576      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2577      *         for any lane {@code N} in the vector
2578      */
2579     @ForceInline
2580     public static
2581     DoubleVector fromArray(VectorSpecies<Double> species,
2582                                    double[] a, int offset) {
2583         offset = checkFromIndexSize(offset, species.length(), a.length);
2584         DoubleSpecies vsp = (DoubleSpecies) species;
2585         return vsp.dummyVector().fromArray0(a, offset);
2586     }
2587 
2588     /**
2589      * Loads a vector from an array of type {@code double[]}
2590      * starting at an offset and using a mask.
2591      * Lanes where the mask is unset are filled with the default
2592      * value of {@code double} (positive zero).
2593      * For each vector lane, where {@code N} is the vector lane index,
2594      * if the mask lane at index {@code N} is set then the array element at
2595      * index {@code offset + N} is placed into the resulting vector at lane index
2596      * {@code N}, otherwise the default element value is placed into the
2597      * resulting vector at lane index {@code N}.
2598      *
2599      * @param species species of desired vector
2600      * @param a the array
2601      * @param offset the offset into the array
2602      * @param m the mask controlling lane selection
2603      * @return the vector loaded from an array
2604      * @throws IndexOutOfBoundsException
2605      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2606      *         for any lane {@code N} in the vector
2607      *         where the mask is set
2608      */
2609     @ForceInline
2610     public static
2611     DoubleVector fromArray(VectorSpecies<Double> species,
2612                                    double[] a, int offset,
2613                                    VectorMask<Double> m) {
2614         DoubleSpecies vsp = (DoubleSpecies) species;
2615         if (offset >= 0 && offset <= (a.length - species.length())) {
2616             DoubleVector zero = vsp.zero();
2617             return zero.blend(zero.fromArray0(a, offset), m);
2618         }
2619 
2620         // FIXME: optimize
2621         checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
2622         return vsp.vOp(m, i -> a[offset + i]);
2623     }
2624 
2625     /**
2626      * Gathers a new vector composed of elements from an array of type
2627      * {@code double[]},
2628      * using indexes obtained by adding a fixed {@code offset} to a
2629      * series of secondary offsets from an <em>index map</em>.
2630      * The index map is a contiguous sequence of {@code VLENGTH}
2631      * elements in a second array of {@code int}s, starting at a given
2632      * {@code mapOffset}.
2633      * <p>
2634      * For each vector lane, where {@code N} is the vector lane index,
2635      * the lane is loaded from the array
2636      * element {@code a[f(N)]}, where {@code f(N)} is the
2637      * index mapping expression
2638      * {@code offset + indexMap[mapOffset + N]]}.
2639      *
2640      * @param species species of desired vector
2641      * @param a the array
2642      * @param offset the offset into the array, may be negative if relative
2643      * indexes in the index map compensate to produce a value within the
2644      * array bounds
2645      * @param indexMap the index map
2646      * @param mapOffset the offset into the index map
2647      * @return the vector loaded from the indexed elements of the array
2648      * @throws IndexOutOfBoundsException
2649      *         if {@code mapOffset+N < 0}
2650      *         or if {@code mapOffset+N >= indexMap.length},
2651      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2652      *         is an invalid index into {@code a},
2653      *         for any lane {@code N} in the vector
2654      * @see DoubleVector#toIntArray()
2655      */
2656     @ForceInline
2657     public static
2658     DoubleVector fromArray(VectorSpecies<Double> species,
2659                                    double[] a, int offset,
2660                                    int[] indexMap, int mapOffset) {
2661         DoubleSpecies vsp = (DoubleSpecies) species;
2662         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
2663         Objects.requireNonNull(a);
2664         Objects.requireNonNull(indexMap);
2665         Class<? extends DoubleVector> vectorType = vsp.vectorType();
2666 
2667         if (vsp.laneCount() == 1) {
2668           return DoubleVector.fromArray(vsp, a, offset + indexMap[mapOffset]);
2669         }
2670 
2671         // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k]
2672         IntVector vix;
2673         if (isp.laneCount() != vsp.laneCount()) {
2674             // For DoubleMaxVector,  if vector length is non-power-of-two or
2675             // 2048 bits, indexShape of Double species is S_MAX_BIT.
2676             // Assume that vector length is 2048, then the lane count of Double
2677             // vector is 32. When converting Double species to int species,
2678             // indexShape is still S_MAX_BIT, but the lane count of int vector
2679             // is 64. So when loading index vector (IntVector), only lower half
2680             // of index data is needed.
2681             vix = IntVector
2682                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
2683                 .add(offset);
2684         } else {
2685             vix = IntVector
2686                 .fromArray(isp, indexMap, mapOffset)
2687                 .add(offset);
2688         }
2689 
2690         vix = VectorIntrinsics.checkIndex(vix, a.length);
2691 
2692         return VectorSupport.loadWithMap(
2693             vectorType, double.class, vsp.laneCount(),
2694             IntVector.species(vsp.indexShape()).vectorType(),
2695             a, ARRAY_BASE, vix,
2696             a, offset, indexMap, mapOffset, vsp,
2697             (double[] c, int idx, int[] iMap, int idy, DoubleSpecies s) ->
2698             s.vOp(n -> c[idx + iMap[idy+n]]));
2699         }
2700 
2701     /**
2702      * Gathers a new vector composed of elements from an array of type
2703      * {@code double[]},
2704      * under the control of a mask, and
2705      * using indexes obtained by adding a fixed {@code offset} to a
2706      * series of secondary offsets from an <em>index map</em>.
2707      * The index map is a contiguous sequence of {@code VLENGTH}
2708      * elements in a second array of {@code int}s, starting at a given
2709      * {@code mapOffset}.
2710      * <p>
2711      * For each vector lane, where {@code N} is the vector lane index,
2712      * if the lane is set in the mask,
2713      * the lane is loaded from the array
2714      * element {@code a[f(N)]}, where {@code f(N)} is the
2715      * index mapping expression
2716      * {@code offset + indexMap[mapOffset + N]]}.
2717      * Unset lanes in the resulting vector are set to zero.
2718      *
2719      * @param species species of desired vector
2720      * @param a the array
2721      * @param offset the offset into the array, may be negative if relative
2722      * indexes in the index map compensate to produce a value within the
2723      * array bounds
2724      * @param indexMap the index map
2725      * @param mapOffset the offset into the index map
2726      * @param m the mask controlling lane selection
2727      * @return the vector loaded from the indexed elements of the array
2728      * @throws IndexOutOfBoundsException
2729      *         if {@code mapOffset+N < 0}
2730      *         or if {@code mapOffset+N >= indexMap.length},
2731      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2732      *         is an invalid index into {@code a},
2733      *         for any lane {@code N} in the vector
2734      *         where the mask is set
2735      * @see DoubleVector#toIntArray()
2736      */
2737     @ForceInline
2738     public static
2739     DoubleVector fromArray(VectorSpecies<Double> species,
2740                                    double[] a, int offset,
2741                                    int[] indexMap, int mapOffset,
2742                                    VectorMask<Double> m) {
2743         if (m.allTrue()) {
2744             return fromArray(species, a, offset, indexMap, mapOffset);
2745         }
2746         else {
2747             // FIXME: Cannot vectorize yet, if there's a mask.
2748             DoubleSpecies vsp = (DoubleSpecies) species;
2749             return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]);
2750         }
2751     }
2752 
2753 
2754 
2755     /**
2756      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2757      * starting at an offset into the byte buffer.
2758      * Bytes are composed into primitive lane elements according
2759      * to the specified byte order.
2760      * The vector is arranged into lanes according to
2761      * <a href="Vector.html#lane-order">memory ordering</a>.
2762      * <p>
2763      * This method behaves as if it returns the result of calling
2764      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2765      * fromByteBuffer()} as follows:
2766      * <pre>{@code
2767      * var m = species.maskAll(true);
2768      * return fromByteBuffer(species, bb, offset, bo, m);
2769      * }</pre>
2770      *
2771      * @param species species of desired vector
2772      * @param bb the byte buffer
2773      * @param offset the offset into the byte buffer
2774      * @param bo the intended byte order
2775      * @return a vector loaded from a byte buffer
2776      * @throws IndexOutOfBoundsException
2777      *         if {@code offset+N*8 < 0}
2778      *         or {@code offset+N*8 >= bb.limit()}
2779      *         for any lane {@code N} in the vector
2780      */
2781     @ForceInline
2782     public static
2783     DoubleVector fromByteBuffer(VectorSpecies<Double> species,
2784                                         ByteBuffer bb, int offset,
2785                                         ByteOrder bo) {
2786         offset = checkFromIndexSize(offset, species.vectorByteSize(), bb.limit());
2787         DoubleSpecies vsp = (DoubleSpecies) species;
2788         return vsp.dummyVector().fromByteBuffer0(bb, offset).maybeSwap(bo);
2789     }
2790 
2791     /**
2792      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2793      * starting at an offset into the byte buffer
2794      * and using a mask.
2795      * Lanes where the mask is unset are filled with the default
2796      * value of {@code double} (positive zero).
2797      * Bytes are composed into primitive lane elements according
2798      * to the specified byte order.
2799      * The vector is arranged into lanes according to
2800      * <a href="Vector.html#lane-order">memory ordering</a>.
2801      * <p>
2802      * The following pseudocode illustrates the behavior:
2803      * <pre>{@code
2804      * DoubleBuffer eb = bb.duplicate()
2805      *     .position(offset)
2806      *     .order(bo).asDoubleBuffer();
2807      * double[] ar = new double[species.length()];
2808      * for (int n = 0; n < ar.length; n++) {
2809      *     if (m.laneIsSet(n)) {
2810      *         ar[n] = eb.get(n);
2811      *     }
2812      * }
2813      * DoubleVector r = DoubleVector.fromArray(species, ar, 0);
2814      * }</pre>
2815      * @implNote
2816      * This operation is likely to be more efficient if
2817      * the specified byte order is the same as
2818      * {@linkplain ByteOrder#nativeOrder()
2819      * the platform native order},
2820      * since this method will not need to reorder
2821      * the bytes of lane values.
2822      *
2823      * @param species species of desired vector
2824      * @param bb the byte buffer
2825      * @param offset the offset into the byte buffer
2826      * @param bo the intended byte order
2827      * @param m the mask controlling lane selection
2828      * @return a vector loaded from a byte buffer
2829      * @throws IndexOutOfBoundsException
2830      *         if {@code offset+N*8 < 0}
2831      *         or {@code offset+N*8 >= bb.limit()}
2832      *         for any lane {@code N} in the vector
2833      *         where the mask is set
2834      */
2835     @ForceInline
2836     public static
2837     DoubleVector fromByteBuffer(VectorSpecies<Double> species,
2838                                         ByteBuffer bb, int offset,
2839                                         ByteOrder bo,
2840                                         VectorMask<Double> m) {
2841         DoubleSpecies vsp = (DoubleSpecies) species;
2842         if (offset >= 0 && offset <= (bb.limit() - species.vectorByteSize())) {
2843             DoubleVector zero = vsp.zero();
2844             DoubleVector v = zero.fromByteBuffer0(bb, offset);
2845             return zero.blend(v.maybeSwap(bo), m);
2846         }
2847 
2848         // FIXME: optimize
2849         checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
2850         ByteBuffer wb = wrapper(bb, bo);
2851         return vsp.ldOp(wb, offset, (AbstractMask<Double>)m,
2852                    (wb_, o, i)  -> wb_.getDouble(o + i * 8));
2853     }
2854 
2855     // Memory store operations
2856 
2857     /**
2858      * Stores this vector into an array of type {@code double[]}
2859      * starting at an offset.
2860      * <p>
2861      * For each vector lane, where {@code N} is the vector lane index,
2862      * the lane element at index {@code N} is stored into the array
2863      * element {@code a[offset+N]}.
2864      *
2865      * @param a the array, of type {@code double[]}
2866      * @param offset the offset into the array
2867      * @throws IndexOutOfBoundsException
2868      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2869      *         for any lane {@code N} in the vector
2870      */
2871     @ForceInline
2872     public final
2873     void intoArray(double[] a, int offset) {
2874         offset = checkFromIndexSize(offset, length(), a.length);
2875         DoubleSpecies vsp = vspecies();
2876         VectorSupport.store(
2877             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
2878             a, arrayAddress(a, offset),
2879             this,
2880             a, offset,
2881             (arr, off, v)
2882             -> v.stOp(arr, off,
2883                       (arr_, off_, i, e) -> arr_[off_ + i] = e));
2884     }
2885 
2886     /**
2887      * Stores this vector into an array of type {@code double[]}
2888      * starting at offset and using a mask.
2889      * <p>
2890      * For each vector lane, where {@code N} is the vector lane index,
2891      * the lane element at index {@code N} is stored into the array
2892      * element {@code a[offset+N]}.
2893      * If the mask lane at {@code N} is unset then the corresponding
2894      * array element {@code a[offset+N]} is left unchanged.
2895      * <p>
2896      * Array range checking is done for lanes where the mask is set.
2897      * Lanes where the mask is unset are not stored and do not need
2898      * to correspond to legitimate elements of {@code a}.
2899      * That is, unset lanes may correspond to array indexes less than
2900      * zero or beyond the end of the array.
2901      *
2902      * @param a the array, of type {@code double[]}
2903      * @param offset the offset into the array
2904      * @param m the mask controlling lane storage
2905      * @throws IndexOutOfBoundsException
2906      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2907      *         for any lane {@code N} in the vector
2908      *         where the mask is set
2909      */
2910     @ForceInline
2911     public final
2912     void intoArray(double[] a, int offset,
2913                    VectorMask<Double> m) {
2914         if (m.allTrue()) {
2915             intoArray(a, offset);
2916         } else {
2917             // FIXME: optimize
2918             DoubleSpecies vsp = vspecies();
2919             checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
2920             stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = v);
2921         }
2922     }
2923 
2924     /**
2925      * Scatters this vector into an array of type {@code double[]}
2926      * using indexes obtained by adding a fixed {@code offset} to a
2927      * series of secondary offsets from an <em>index map</em>.
2928      * The index map is a contiguous sequence of {@code VLENGTH}
2929      * elements in a second array of {@code int}s, starting at a given
2930      * {@code mapOffset}.
2931      * <p>
2932      * For each vector lane, where {@code N} is the vector lane index,
2933      * the lane element at index {@code N} is stored into the array
2934      * element {@code a[f(N)]}, where {@code f(N)} is the
2935      * index mapping expression
2936      * {@code offset + indexMap[mapOffset + N]]}.
2937      *
2938      * @param a the array
2939      * @param offset an offset to combine with the index map offsets
2940      * @param indexMap the index map
2941      * @param mapOffset the offset into the index map
2942      * @throws IndexOutOfBoundsException
2943      *         if {@code mapOffset+N < 0}
2944      *         or if {@code mapOffset+N >= indexMap.length},
2945      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2946      *         is an invalid index into {@code a},
2947      *         for any lane {@code N} in the vector
2948      * @see DoubleVector#toIntArray()
2949      */
2950     @ForceInline
2951     public final
2952     void intoArray(double[] a, int offset,
2953                    int[] indexMap, int mapOffset) {
2954         DoubleSpecies vsp = vspecies();
2955         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
2956         if (vsp.laneCount() == 1) {
2957             intoArray(a, offset + indexMap[mapOffset]);
2958             return;
2959         }
2960 
2961         // Index vector: vix[0:n] = i -> offset + indexMap[mo + i]
2962         IntVector vix;
2963         if (isp.laneCount() != vsp.laneCount()) {
2964             // For DoubleMaxVector,  if vector length  is 2048 bits, indexShape
2965             // of Double species is S_MAX_BIT. and the lane count of Double
2966             // vector is 32. When converting Double species to int species,
2967             // indexShape is still S_MAX_BIT, but the lane count of int vector
2968             // is 64. So when loading index vector (IntVector), only lower half
2969             // of index data is needed.
2970             vix = IntVector
2971                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
2972                 .add(offset);
2973         } else {
2974             vix = IntVector
2975                 .fromArray(isp, indexMap, mapOffset)
2976                 .add(offset);
2977         }
2978 
2979 
2980         vix = VectorIntrinsics.checkIndex(vix, a.length);
2981 
2982         VectorSupport.storeWithMap(
2983             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
2984             isp.vectorType(),
2985             a, arrayAddress(a, 0), vix,
2986             this,
2987             a, offset, indexMap, mapOffset,
2988             (arr, off, v, map, mo)
2989             -> v.stOp(arr, off,
2990                       (arr_, off_, i, e) -> {
2991                           int j = map[mo + i];
2992                           arr[off + j] = e;
2993                       }));
2994     }
2995 
2996     /**
2997      * Scatters this vector into an array of type {@code double[]},
2998      * under the control of a mask, and
2999      * using indexes obtained by adding a fixed {@code offset} to a
3000      * series of secondary offsets from an <em>index map</em>.
3001      * The index map is a contiguous sequence of {@code VLENGTH}
3002      * elements in a second array of {@code int}s, starting at a given
3003      * {@code mapOffset}.
3004      * <p>
3005      * For each vector lane, where {@code N} is the vector lane index,
3006      * if the mask lane at index {@code N} is set then
3007      * the lane element at index {@code N} is stored into the array
3008      * element {@code a[f(N)]}, where {@code f(N)} is the
3009      * index mapping expression
3010      * {@code offset + indexMap[mapOffset + N]]}.
3011      *
3012      * @param a the array
3013      * @param offset an offset to combine with the index map offsets
3014      * @param indexMap the index map
3015      * @param mapOffset the offset into the index map
3016      * @param m the mask
3017      * @throws IndexOutOfBoundsException
3018      *         if {@code mapOffset+N < 0}
3019      *         or if {@code mapOffset+N >= indexMap.length},
3020      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
3021      *         is an invalid index into {@code a},
3022      *         for any lane {@code N} in the vector
3023      *         where the mask is set
3024      * @see DoubleVector#toIntArray()
3025      */
3026     @ForceInline
3027     public final
3028     void intoArray(double[] a, int offset,
3029                    int[] indexMap, int mapOffset,
3030                    VectorMask<Double> m) {
3031         if (m.allTrue()) {
3032             intoArray(a, offset, indexMap, mapOffset);
3033         }
3034         else {
3035             // FIXME: Cannot vectorize yet, if there's a mask.
3036             stOp(a, offset, m,
3037                  (arr, off, i, e) -> {
3038                      int j = indexMap[mapOffset + i];
3039                      arr[off + j] = e;
3040                  });
3041         }
3042     }
3043 
3044 
3045 
3046     /**
3047      * {@inheritDoc} <!--workaround-->
3048      */
3049     @Override
3050     @ForceInline
3051     public final
3052     void intoByteArray(byte[] a, int offset,
3053                        ByteOrder bo) {
3054         offset = checkFromIndexSize(offset, byteSize(), a.length);
3055         maybeSwap(bo).intoByteArray0(a, offset);
3056     }
3057 
3058     /**
3059      * {@inheritDoc} <!--workaround-->
3060      */
3061     @Override
3062     @ForceInline
3063     public final
3064     void intoByteArray(byte[] a, int offset,
3065                        ByteOrder bo,
3066                        VectorMask<Double> m) {
3067         if (m.allTrue()) {
3068             intoByteArray(a, offset, bo);
3069         } else {
3070             // FIXME: optimize
3071             DoubleSpecies vsp = vspecies();
3072             checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
3073             ByteBuffer wb = wrapper(a, bo);
3074             this.stOp(wb, offset, m,
3075                     (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
3076         }
3077     }
3078 
3079     /**
3080      * {@inheritDoc} <!--workaround-->
3081      */
3082     @Override
3083     @ForceInline
3084     public final
3085     void intoByteBuffer(ByteBuffer bb, int offset,
3086                         ByteOrder bo) {
3087         if (bb.isReadOnly()) {
3088             throw new ReadOnlyBufferException();
3089         }
3090         offset = checkFromIndexSize(offset, byteSize(), bb.limit());
3091         maybeSwap(bo).intoByteBuffer0(bb, offset);
3092     }
3093 
3094     /**
3095      * {@inheritDoc} <!--workaround-->
3096      */
3097     @Override
3098     @ForceInline
3099     public final
3100     void intoByteBuffer(ByteBuffer bb, int offset,
3101                         ByteOrder bo,
3102                         VectorMask<Double> m) {
3103         if (m.allTrue()) {
3104             intoByteBuffer(bb, offset, bo);
3105         } else {
3106             // FIXME: optimize
3107             if (bb.isReadOnly()) {
3108                 throw new ReadOnlyBufferException();
3109             }
3110             DoubleSpecies vsp = vspecies();
3111             checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
3112             ByteBuffer wb = wrapper(bb, bo);
3113             this.stOp(wb, offset, m,
3114                     (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
3115         }
3116     }
3117 
3118     // ================================================
3119 
3120     // Low-level memory operations.
3121     //
3122     // Note that all of these operations *must* inline into a context
3123     // where the exact species of the involved vector is a
3124     // compile-time constant.  Otherwise, the intrinsic generation
3125     // will fail and performance will suffer.
3126     //
3127     // In many cases this is achieved by re-deriving a version of the
3128     // method in each concrete subclass (per species).  The re-derived
3129     // method simply calls one of these generic methods, with exact
3130     // parameters for the controlling metadata, which is either a
3131     // typed vector or constant species instance.
3132 
3133     // Unchecked loading operations in native byte order.
3134     // Caller is responsible for applying index checks, masking, and
3135     // byte swapping.
3136 
3137     /*package-private*/
3138     abstract
3139     DoubleVector fromArray0(double[] a, int offset);
3140     @ForceInline
3141     final
3142     DoubleVector fromArray0Template(double[] a, int offset) {
3143         DoubleSpecies vsp = vspecies();
3144         return VectorSupport.load(
3145             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3146             a, arrayAddress(a, offset),
3147             a, offset, vsp,
3148             (arr, off, s) -> s.ldOp(arr, off,
3149                                     (arr_, off_, i) -> arr_[off_ + i]));
3150     }
3151 
3152 
3153 
3154     @Override
3155     abstract
3156     DoubleVector fromByteArray0(byte[] a, int offset);
3157     @ForceInline
3158     final
3159     DoubleVector fromByteArray0Template(byte[] a, int offset) {
3160         DoubleSpecies vsp = vspecies();
3161         return VectorSupport.load(
3162             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3163             a, byteArrayAddress(a, offset),
3164             a, offset, vsp,
3165             (arr, off, s) -> {
3166                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3167                 return s.ldOp(wb, off,
3168                         (wb_, o, i) -> wb_.getDouble(o + i * 8));
3169             });
3170     }
3171 
3172     abstract
3173     DoubleVector fromByteBuffer0(ByteBuffer bb, int offset);
3174     @ForceInline
3175     final
3176     DoubleVector fromByteBuffer0Template(ByteBuffer bb, int offset) {
3177         DoubleSpecies vsp = vspecies();
3178         return ScopedMemoryAccess.loadFromByteBuffer(
3179                 vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3180                 bb, offset, vsp,
3181                 (buf, off, s) -> {
3182                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3183                     return s.ldOp(wb, off,
3184                             (wb_, o, i) -> wb_.getDouble(o + i * 8));
3185                 });
3186     }
3187 
3188     // Unchecked storing operations in native byte order.
3189     // Caller is responsible for applying index checks, masking, and
3190     // byte swapping.
3191 
3192     abstract
3193     void intoArray0(double[] a, int offset);
3194     @ForceInline
3195     final
3196     void intoArray0Template(double[] a, int offset) {
3197         DoubleSpecies vsp = vspecies();
3198         VectorSupport.store(
3199             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3200             a, arrayAddress(a, offset),
3201             this, a, offset,
3202             (arr, off, v)
3203             -> v.stOp(arr, off,
3204                       (arr_, off_, i, e) -> arr_[off_+i] = e));
3205     }
3206 
3207     abstract
3208     void intoByteArray0(byte[] a, int offset);
3209     @ForceInline
3210     final
3211     void intoByteArray0Template(byte[] a, int offset) {
3212         DoubleSpecies vsp = vspecies();
3213         VectorSupport.store(
3214             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3215             a, byteArrayAddress(a, offset),
3216             this, a, offset,
3217             (arr, off, v) -> {
3218                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3219                 v.stOp(wb, off,
3220                         (tb_, o, i, e) -> tb_.putDouble(o + i * 8, e));
3221             });
3222     }
3223 
3224     @ForceInline
3225     final
3226     void intoByteBuffer0(ByteBuffer bb, int offset) {
3227         DoubleSpecies vsp = vspecies();
3228         ScopedMemoryAccess.storeIntoByteBuffer(
3229                 vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3230                 this, bb, offset,
3231                 (buf, off, v) -> {
3232                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3233                     v.stOp(wb, off,
3234                             (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
3235                 });
3236     }
3237 
3238     // End of low-level memory operations.
3239 
3240     private static
3241     void checkMaskFromIndexSize(int offset,
3242                                 DoubleSpecies vsp,
3243                                 VectorMask<Double> m,
3244                                 int scale,
3245                                 int limit) {
3246         ((AbstractMask<Double>)m)
3247             .checkIndexByLane(offset, limit, vsp.iota(), scale);
3248     }
3249 
3250     @ForceInline
3251     private void conditionalStoreNYI(int offset,
3252                                      DoubleSpecies vsp,
3253                                      VectorMask<Double> m,
3254                                      int scale,
3255                                      int limit) {
3256         if (offset < 0 || offset + vsp.laneCount() * scale > limit) {
3257             String msg =
3258                 String.format("unimplemented: store @%d in [0..%d), %s in %s",
3259                               offset, limit, m, vsp);
3260             throw new AssertionError(msg);
3261         }
3262     }
3263 
3264     /*package-private*/
3265     @Override
3266     @ForceInline
3267     final
3268     DoubleVector maybeSwap(ByteOrder bo) {
3269         if (bo != NATIVE_ENDIAN) {
3270             return this.reinterpretAsBytes()
3271                 .rearrange(swapBytesShuffle())
3272                 .reinterpretAsDoubles();
3273         }
3274         return this;
3275     }
3276 
3277     static final int ARRAY_SHIFT =
3278         31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
3279     static final long ARRAY_BASE =
3280         Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
3281 
3282     @ForceInline
3283     static long arrayAddress(double[] a, int index) {
3284         return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
3285     }
3286 
3287 
3288 
3289     @ForceInline
3290     static long byteArrayAddress(byte[] a, int index) {
3291         return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
3292     }
3293 
3294     // ================================================
3295 
3296     /// Reinterpreting view methods:
3297     //   lanewise reinterpret: viewAsXVector()
3298     //   keep shape, redraw lanes: reinterpretAsEs()
3299 
3300     /**
3301      * {@inheritDoc} <!--workaround-->
3302      */
3303     @ForceInline
3304     @Override
3305     public final ByteVector reinterpretAsBytes() {
3306          // Going to ByteVector, pay close attention to byte order.
3307          assert(REGISTER_ENDIAN == ByteOrder.LITTLE_ENDIAN);
3308          return asByteVectorRaw();
3309          //return asByteVectorRaw().rearrange(swapBytesShuffle());
3310     }
3311 
3312     /**
3313      * {@inheritDoc} <!--workaround-->
3314      */
3315     @ForceInline
3316     @Override
3317     public final LongVector viewAsIntegralLanes() {
3318         LaneType ilt = LaneType.DOUBLE.asIntegral();
3319         return (LongVector) asVectorRaw(ilt);
3320     }
3321 
3322     /**
3323      * {@inheritDoc} <!--workaround-->
3324      */
3325     @ForceInline
3326     @Override
3327     public final
3328     DoubleVector
3329     viewAsFloatingLanes() {
3330         return this;
3331     }
3332 
3333     // ================================================
3334 
3335     /// Object methods: toString, equals, hashCode
3336     //
3337     // Object methods are defined as if via Arrays.toString, etc.,
3338     // is applied to the array of elements.  Two equal vectors
3339     // are required to have equal species and equal lane values.
3340 
3341     /**
3342      * Returns a string representation of this vector, of the form
3343      * {@code "[0,1,2...]"}, reporting the lane values of this vector,
3344      * in lane order.
3345      *
3346      * The string is produced as if by a call to {@link
3347      * java.util.Arrays#toString(double[]) Arrays.toString()},
3348      * as appropriate to the {@code double} array returned by
3349      * {@link #toArray this.toArray()}.
3350      *
3351      * @return a string of the form {@code "[0,1,2...]"}
3352      * reporting the lane values of this vector
3353      */
3354     @Override
3355     @ForceInline
3356     public final
3357     String toString() {
3358         // now that toArray is strongly typed, we can define this
3359         return Arrays.toString(toArray());
3360     }
3361 
3362     /**
3363      * {@inheritDoc} <!--workaround-->
3364      */
3365     @Override
3366     @ForceInline
3367     public final
3368     boolean equals(Object obj) {
3369         if (obj instanceof Vector) {
3370             Vector<?> that = (Vector<?>) obj;
3371             if (this.species().equals(that.species())) {
3372                 return this.eq(that.check(this.species())).allTrue();
3373             }
3374         }
3375         return false;
3376     }
3377 
3378     /**
3379      * {@inheritDoc} <!--workaround-->
3380      */
3381     @Override
3382     @ForceInline
3383     public final
3384     int hashCode() {
3385         // now that toArray is strongly typed, we can define this
3386         return Objects.hash(species(), Arrays.hashCode(toArray()));
3387     }
3388 
3389     // ================================================
3390 
3391     // Species
3392 
3393     /**
3394      * Class representing {@link DoubleVector}'s of the same {@link VectorShape VectorShape}.
3395      */
3396     /*package-private*/
3397     static final class DoubleSpecies extends AbstractSpecies<Double> {
3398         private DoubleSpecies(VectorShape shape,
3399                 Class<? extends DoubleVector> vectorType,
3400                 Class<? extends AbstractMask<Double>> maskType,
3401                 Function<Object, DoubleVector> vectorFactory) {
3402             super(shape, LaneType.of(double.class),
3403                   vectorType, maskType,
3404                   vectorFactory);
3405             assert(this.elementSize() == Double.SIZE);
3406         }
3407 
3408         // Specializing overrides:
3409 
3410         @Override
3411         @ForceInline
3412         public final Class<Double> elementType() {
3413             return double.class;
3414         }
3415 
3416         @Override
3417         @ForceInline
3418         final Class<Double> genericElementType() {
3419             return Double.class;
3420         }
3421 
3422         @SuppressWarnings("unchecked")
3423         @Override
3424         @ForceInline
3425         public final Class<? extends DoubleVector> vectorType() {
3426             return (Class<? extends DoubleVector>) vectorType;
3427         }
3428 
3429         @Override
3430         @ForceInline
3431         public final long checkValue(long e) {
3432             longToElementBits(e);  // only for exception
3433             return e;
3434         }
3435 
3436         /*package-private*/
3437         @Override
3438         @ForceInline
3439         final DoubleVector broadcastBits(long bits) {
3440             return (DoubleVector)
3441                 VectorSupport.broadcastCoerced(
3442                     vectorType, double.class, laneCount,
3443                     bits, this,
3444                     (bits_, s_) -> s_.rvOp(i -> bits_));
3445         }
3446 
3447         /*package-private*/
3448         @ForceInline
3449         final DoubleVector broadcast(double e) {
3450             return broadcastBits(toBits(e));
3451         }
3452 
3453         @Override
3454         @ForceInline
3455         public final DoubleVector broadcast(long e) {
3456             return broadcastBits(longToElementBits(e));
3457         }
3458 
3459         /*package-private*/
3460         final @Override
3461         @ForceInline
3462         long longToElementBits(long value) {
3463             // Do the conversion, and then test it for failure.
3464             double e = (double) value;
3465             if ((long) e != value) {
3466                 throw badElementBits(value, e);
3467             }
3468             return toBits(e);
3469         }
3470 
3471         /*package-private*/
3472         @ForceInline
3473         static long toIntegralChecked(double e, boolean convertToInt) {
3474             long value = convertToInt ? (int) e : (long) e;
3475             if ((double) value != e) {
3476                 throw badArrayBits(e, convertToInt, value);
3477             }
3478             return value;
3479         }
3480 
3481         /* this non-public one is for internal conversions */
3482         @Override
3483         @ForceInline
3484         final DoubleVector fromIntValues(int[] values) {
3485             VectorIntrinsics.requireLength(values.length, laneCount);
3486             double[] va = new double[laneCount()];
3487             for (int i = 0; i < va.length; i++) {
3488                 int lv = values[i];
3489                 double v = (double) lv;
3490                 va[i] = v;
3491                 if ((int)v != lv) {
3492                     throw badElementBits(lv, v);
3493                 }
3494             }
3495             return dummyVector().fromArray0(va, 0);
3496         }
3497 
3498         // Virtual constructors
3499 
3500         @ForceInline
3501         @Override final
3502         public DoubleVector fromArray(Object a, int offset) {
3503             // User entry point:  Be careful with inputs.
3504             return DoubleVector
3505                 .fromArray(this, (double[]) a, offset);
3506         }
3507 
3508         @ForceInline
3509         @Override final
3510         DoubleVector dummyVector() {
3511             return (DoubleVector) super.dummyVector();
3512         }
3513 
3514         /*package-private*/
3515         final @Override
3516         @ForceInline
3517         DoubleVector rvOp(RVOp f) {
3518             double[] res = new double[laneCount()];
3519             for (int i = 0; i < res.length; i++) {
3520                 long bits = (long) f.apply(i);
3521                 res[i] = fromBits(bits);
3522             }
3523             return dummyVector().vectorFactory(res);
3524         }
3525 
3526         DoubleVector vOp(FVOp f) {
3527             double[] res = new double[laneCount()];
3528             for (int i = 0; i < res.length; i++) {
3529                 res[i] = f.apply(i);
3530             }
3531             return dummyVector().vectorFactory(res);
3532         }
3533 
3534         DoubleVector vOp(VectorMask<Double> m, FVOp f) {
3535             double[] res = new double[laneCount()];
3536             boolean[] mbits = ((AbstractMask<Double>)m).getBits();
3537             for (int i = 0; i < res.length; i++) {
3538                 if (mbits[i]) {
3539                     res[i] = f.apply(i);
3540                 }
3541             }
3542             return dummyVector().vectorFactory(res);
3543         }
3544 
3545         /*package-private*/
3546         @ForceInline
3547         <M> DoubleVector ldOp(M memory, int offset,
3548                                       FLdOp<M> f) {
3549             return dummyVector().ldOp(memory, offset, f);
3550         }
3551 
3552         /*package-private*/
3553         @ForceInline
3554         <M> DoubleVector ldOp(M memory, int offset,
3555                                       AbstractMask<Double> m,
3556                                       FLdOp<M> f) {
3557             return dummyVector().ldOp(memory, offset, m, f);
3558         }
3559 
3560         /*package-private*/
3561         @ForceInline
3562         <M> void stOp(M memory, int offset, FStOp<M> f) {
3563             dummyVector().stOp(memory, offset, f);
3564         }
3565 
3566         /*package-private*/
3567         @ForceInline
3568         <M> void stOp(M memory, int offset,
3569                       AbstractMask<Double> m,
3570                       FStOp<M> f) {
3571             dummyVector().stOp(memory, offset, m, f);
3572         }
3573 
3574         // N.B. Make sure these constant vectors and
3575         // masks load up correctly into registers.
3576         //
3577         // Also, see if we can avoid all that switching.
3578         // Could we cache both vectors and both masks in
3579         // this species object?
3580 
3581         // Zero and iota vector access
3582         @Override
3583         @ForceInline
3584         public final DoubleVector zero() {
3585             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3586                 return DoubleMaxVector.ZERO;
3587             switch (vectorBitSize()) {
3588                 case 64: return Double64Vector.ZERO;
3589                 case 128: return Double128Vector.ZERO;
3590                 case 256: return Double256Vector.ZERO;
3591                 case 512: return Double512Vector.ZERO;
3592             }
3593             throw new AssertionError();
3594         }
3595 
3596         @Override
3597         @ForceInline
3598         public final DoubleVector iota() {
3599             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3600                 return DoubleMaxVector.IOTA;
3601             switch (vectorBitSize()) {
3602                 case 64: return Double64Vector.IOTA;
3603                 case 128: return Double128Vector.IOTA;
3604                 case 256: return Double256Vector.IOTA;
3605                 case 512: return Double512Vector.IOTA;
3606             }
3607             throw new AssertionError();
3608         }
3609 
3610         // Mask access
3611         @Override
3612         @ForceInline
3613         public final VectorMask<Double> maskAll(boolean bit) {
3614             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3615                 return DoubleMaxVector.DoubleMaxMask.maskAll(bit);
3616             switch (vectorBitSize()) {
3617                 case 64: return Double64Vector.Double64Mask.maskAll(bit);
3618                 case 128: return Double128Vector.Double128Mask.maskAll(bit);
3619                 case 256: return Double256Vector.Double256Mask.maskAll(bit);
3620                 case 512: return Double512Vector.Double512Mask.maskAll(bit);
3621             }
3622             throw new AssertionError();
3623         }
3624     }
3625 
3626     /**
3627      * Finds a species for an element type of {@code double} and shape.
3628      *
3629      * @param s the shape
3630      * @return a species for an element type of {@code double} and shape
3631      * @throws IllegalArgumentException if no such species exists for the shape
3632      */
3633     static DoubleSpecies species(VectorShape s) {
3634         Objects.requireNonNull(s);
3635         switch (s) {
3636             case S_64_BIT: return (DoubleSpecies) SPECIES_64;
3637             case S_128_BIT: return (DoubleSpecies) SPECIES_128;
3638             case S_256_BIT: return (DoubleSpecies) SPECIES_256;
3639             case S_512_BIT: return (DoubleSpecies) SPECIES_512;
3640             case S_Max_BIT: return (DoubleSpecies) SPECIES_MAX;
3641             default: throw new IllegalArgumentException("Bad shape: " + s);
3642         }
3643     }
3644 
3645     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_64_BIT VectorShape.S_64_BIT}. */
3646     public static final VectorSpecies<Double> SPECIES_64
3647         = new DoubleSpecies(VectorShape.S_64_BIT,
3648                             Double64Vector.class,
3649                             Double64Vector.Double64Mask.class,
3650                             Double64Vector::new);
3651 
3652     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_128_BIT VectorShape.S_128_BIT}. */
3653     public static final VectorSpecies<Double> SPECIES_128
3654         = new DoubleSpecies(VectorShape.S_128_BIT,
3655                             Double128Vector.class,
3656                             Double128Vector.Double128Mask.class,
3657                             Double128Vector::new);
3658 
3659     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_256_BIT VectorShape.S_256_BIT}. */
3660     public static final VectorSpecies<Double> SPECIES_256
3661         = new DoubleSpecies(VectorShape.S_256_BIT,
3662                             Double256Vector.class,
3663                             Double256Vector.Double256Mask.class,
3664                             Double256Vector::new);
3665 
3666     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_512_BIT VectorShape.S_512_BIT}. */
3667     public static final VectorSpecies<Double> SPECIES_512
3668         = new DoubleSpecies(VectorShape.S_512_BIT,
3669                             Double512Vector.class,
3670                             Double512Vector.Double512Mask.class,
3671                             Double512Vector::new);
3672 
3673     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_Max_BIT VectorShape.S_Max_BIT}. */
3674     public static final VectorSpecies<Double> SPECIES_MAX
3675         = new DoubleSpecies(VectorShape.S_Max_BIT,
3676                             DoubleMaxVector.class,
3677                             DoubleMaxVector.DoubleMaxMask.class,
3678                             DoubleMaxVector::new);
3679 
3680     /**
3681      * Preferred species for {@link DoubleVector}s.
3682      * A preferred species is a species of maximal bit-size for the platform.
3683      */
3684     public static final VectorSpecies<Double> SPECIES_PREFERRED
3685         = (DoubleSpecies) VectorSpecies.ofPreferred(double.class);
3686 }