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