1 /*
   2  * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.nio.ByteOrder;
  29 import java.nio.ReadOnlyBufferException;
  30 import java.util.Arrays;
  31 import java.util.Objects;
  32 import java.util.function.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.broadcastCoerced(vsp.vectorType(), double.class, species.length(),
 448                         toBits(0.0f), 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(this.vspecies()));
1719         }
1720         int opc = opCode(op);
1721         throw new AssertionError(op);
1722     }
1723 
1724     /**
1725      * {@inheritDoc} <!--workaround-->
1726      */
1727     @Override
1728     @ForceInline
1729     public final
1730     VectorMask<Double> test(VectorOperators.Test op,
1731                                   VectorMask<Double> m) {
1732         return test(op).and(m);
1733     }
1734 
1735     /**
1736      * {@inheritDoc} <!--workaround-->
1737      */
1738     @Override
1739     public abstract
1740     VectorMask<Double> compare(VectorOperators.Comparison op, Vector<Double> v);
1741 
1742     /*package-private*/
1743     @ForceInline
1744     final
1745     <M extends VectorMask<Double>>
1746     M compareTemplate(Class<M> maskType, Comparison op, Vector<Double> v) {
1747         DoubleVector that = (DoubleVector) v;
1748         that.check(this);
1749         int opc = opCode(op);
1750         return VectorSupport.compare(
1751             opc, getClass(), maskType, double.class, length(),
1752             this, that, null,
1753             (cond, v0, v1, m1) -> {
1754                 AbstractMask<Double> m
1755                     = v0.bTest(cond, v1, (cond_, i, a, b)
1756                                -> compareWithOp(cond, a, b));
1757                 @SuppressWarnings("unchecked")
1758                 M m2 = (M) m;
1759                 return m2;
1760             });
1761     }
1762 
1763     /*package-private*/
1764     @ForceInline
1765     final
1766     <M extends VectorMask<Double>>
1767     M compareTemplate(Class<M> maskType, Comparison op, Vector<Double> v, M m) {
1768         DoubleVector that = (DoubleVector) v;
1769         that.check(this);
1770         m.check(maskType, this);
1771         int opc = opCode(op);
1772         return VectorSupport.compare(
1773             opc, getClass(), maskType, double.class, length(),
1774             this, that, m,
1775             (cond, v0, v1, m1) -> {
1776                 AbstractMask<Double> cmpM
1777                     = v0.bTest(cond, v1, (cond_, i, a, b)
1778                                -> compareWithOp(cond, a, b));
1779                 @SuppressWarnings("unchecked")
1780                 M m2 = (M) cmpM.and(m1);
1781                 return m2;
1782             });
1783     }
1784 
1785     @ForceInline
1786     private static boolean compareWithOp(int cond, double a, double b) {
1787         return switch (cond) {
1788             case BT_eq -> a == b;
1789             case BT_ne -> a != b;
1790             case BT_lt -> a < b;
1791             case BT_le -> a <= b;
1792             case BT_gt -> a > b;
1793             case BT_ge -> a >= b;
1794             default -> throw new AssertionError();
1795         };
1796     }
1797 
1798     /**
1799      * Tests this vector by comparing it with an input scalar,
1800      * according to the given comparison operation.
1801      *
1802      * This is a lane-wise binary test operation which applies
1803      * the comparison operation to each lane.
1804      * <p>
1805      * The result is the same as
1806      * {@code compare(op, broadcast(species(), e))}.
1807      * That is, the scalar may be regarded as broadcast to
1808      * a vector of the same species, and then compared
1809      * against the original vector, using the selected
1810      * comparison operation.
1811      *
1812      * @param op the operation used to compare lane values
1813      * @param e the input scalar
1814      * @return the mask result of testing lane-wise if this vector
1815      *         compares to the input, according to the selected
1816      *         comparison operator
1817      * @see DoubleVector#compare(VectorOperators.Comparison,Vector)
1818      * @see #eq(double)
1819      * @see #lt(double)
1820      */
1821     public abstract
1822     VectorMask<Double> compare(Comparison op, double e);
1823 
1824     /*package-private*/
1825     @ForceInline
1826     final
1827     <M extends VectorMask<Double>>
1828     M compareTemplate(Class<M> maskType, Comparison op, double e) {
1829         return compareTemplate(maskType, op, broadcast(e));
1830     }
1831 
1832     /**
1833      * Tests this vector by comparing it with an input scalar,
1834      * according to the given comparison operation,
1835      * in lanes selected by a mask.
1836      *
1837      * This is a masked lane-wise binary test operation which applies
1838      * to each pair of corresponding lane values.
1839      *
1840      * The returned result is equal to the expression
1841      * {@code compare(op,s).and(m)}.
1842      *
1843      * @param op the operation used to compare lane values
1844      * @param e the input scalar
1845      * @param m the mask controlling lane selection
1846      * @return the mask result of testing lane-wise if this vector
1847      *         compares to the input, according to the selected
1848      *         comparison operator,
1849      *         and only in the lanes selected by the mask
1850      * @see DoubleVector#compare(VectorOperators.Comparison,Vector,VectorMask)
1851      */
1852     @ForceInline
1853     public final VectorMask<Double> compare(VectorOperators.Comparison op,
1854                                                double e,
1855                                                VectorMask<Double> m) {
1856         return compare(op, broadcast(e), m);
1857     }
1858 
1859     /**
1860      * {@inheritDoc} <!--workaround-->
1861      */
1862     @Override
1863     public abstract
1864     VectorMask<Double> compare(Comparison op, long e);
1865 
1866     /*package-private*/
1867     @ForceInline
1868     final
1869     <M extends VectorMask<Double>>
1870     M compareTemplate(Class<M> maskType, Comparison op, long e) {
1871         return compareTemplate(maskType, op, broadcast(e));
1872     }
1873 
1874     /**
1875      * {@inheritDoc} <!--workaround-->
1876      */
1877     @Override
1878     @ForceInline
1879     public final
1880     VectorMask<Double> compare(Comparison op, long e, VectorMask<Double> m) {
1881         return compare(op, broadcast(e), m);
1882     }
1883 
1884 
1885 
1886     /**
1887      * {@inheritDoc} <!--workaround-->
1888      */
1889     @Override public abstract
1890     DoubleVector blend(Vector<Double> v, VectorMask<Double> m);
1891 
1892     /*package-private*/
1893     @ForceInline
1894     final
1895     <M extends VectorMask<Double>>
1896     DoubleVector
1897     blendTemplate(Class<M> maskType, DoubleVector v, M m) {
1898         v.check(this);
1899         return VectorSupport.blend(
1900             getClass(), maskType, double.class, length(),
1901             this, v, m,
1902             (v0, v1, m_) -> v0.bOp(v1, m_, (i, a, b) -> b));
1903     }
1904 
1905     /**
1906      * {@inheritDoc} <!--workaround-->
1907      */
1908     @Override public abstract DoubleVector addIndex(int scale);
1909 
1910     /*package-private*/
1911     @ForceInline
1912     final DoubleVector addIndexTemplate(int scale) {
1913         DoubleSpecies vsp = vspecies();
1914         // make sure VLENGTH*scale doesn't overflow:
1915         vsp.checkScale(scale);
1916         return VectorSupport.indexVector(
1917             getClass(), double.class, length(),
1918             this, scale, vsp,
1919             (v, scale_, s)
1920             -> {
1921                 // If the platform doesn't support an INDEX
1922                 // instruction directly, load IOTA from memory
1923                 // and multiply.
1924                 DoubleVector iota = s.iota();
1925                 double sc = (double) scale_;
1926                 return v.add(sc == 1 ? iota : iota.mul(sc));
1927             });
1928     }
1929 
1930     /**
1931      * Replaces selected lanes of this vector with
1932      * a scalar value
1933      * under the control of a mask.
1934      *
1935      * This is a masked lane-wise binary operation which
1936      * selects each lane value from one or the other input.
1937      *
1938      * The returned result is equal to the expression
1939      * {@code blend(broadcast(e),m)}.
1940      *
1941      * @param e the input scalar, containing the replacement lane value
1942      * @param m the mask controlling lane selection of the scalar
1943      * @return the result of blending the lane elements of this vector with
1944      *         the scalar value
1945      */
1946     @ForceInline
1947     public final DoubleVector blend(double e,
1948                                             VectorMask<Double> m) {
1949         return blend(broadcast(e), m);
1950     }
1951 
1952     /**
1953      * Replaces selected lanes of this vector with
1954      * a scalar value
1955      * under the control of a mask.
1956      *
1957      * This is a masked lane-wise binary operation which
1958      * selects each lane value from one or the other input.
1959      *
1960      * The returned result is equal to the expression
1961      * {@code blend(broadcast(e),m)}.
1962      *
1963      * @param e the input scalar, containing the replacement lane value
1964      * @param m the mask controlling lane selection of the scalar
1965      * @return the result of blending the lane elements of this vector with
1966      *         the scalar value
1967      */
1968     @ForceInline
1969     public final DoubleVector blend(long e,
1970                                             VectorMask<Double> m) {
1971         return blend(broadcast(e), m);
1972     }
1973 
1974     /**
1975      * {@inheritDoc} <!--workaround-->
1976      */
1977     @Override
1978     public abstract
1979     DoubleVector slice(int origin, Vector<Double> v1);
1980 
1981     /*package-private*/
1982     final
1983     @ForceInline
1984     DoubleVector sliceTemplate(int origin, Vector<Double> v1) {
1985         DoubleVector that = (DoubleVector) v1;
1986         that.check(this);
1987         Objects.checkIndex(origin, length() + 1);
1988         VectorShuffle<Double> iota = iotaShuffle();
1989         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.LT, (broadcast((double)(length() - origin))));
1990         iota = iotaShuffle(origin, 1, true);
1991         return that.rearrange(iota).blend(this.rearrange(iota), blendMask);
1992     }
1993 
1994     /**
1995      * {@inheritDoc} <!--workaround-->
1996      */
1997     @Override
1998     @ForceInline
1999     public final
2000     DoubleVector slice(int origin,
2001                                Vector<Double> w,
2002                                VectorMask<Double> m) {
2003         return broadcast(0).blend(slice(origin, w), m);
2004     }
2005 
2006     /**
2007      * {@inheritDoc} <!--workaround-->
2008      */
2009     @Override
2010     public abstract
2011     DoubleVector slice(int origin);
2012 
2013     /*package-private*/
2014     final
2015     @ForceInline
2016     DoubleVector sliceTemplate(int origin) {
2017         Objects.checkIndex(origin, length() + 1);
2018         VectorShuffle<Double> iota = iotaShuffle();
2019         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.LT, (broadcast((double)(length() - origin))));
2020         iota = iotaShuffle(origin, 1, true);
2021         return vspecies().zero().blend(this.rearrange(iota), blendMask);
2022     }
2023 
2024     /**
2025      * {@inheritDoc} <!--workaround-->
2026      */
2027     @Override
2028     public abstract
2029     DoubleVector unslice(int origin, Vector<Double> w, int part);
2030 
2031     /*package-private*/
2032     final
2033     @ForceInline
2034     DoubleVector
2035     unsliceTemplate(int origin, Vector<Double> w, int part) {
2036         DoubleVector that = (DoubleVector) w;
2037         that.check(this);
2038         Objects.checkIndex(origin, length() + 1);
2039         VectorShuffle<Double> iota = iotaShuffle();
2040         VectorMask<Double> blendMask = iota.toVector().compare((part == 0) ? VectorOperators.GE : VectorOperators.LT,
2041                                                                   (broadcast((double)(origin))));
2042         iota = iotaShuffle(-origin, 1, true);
2043         return that.blend(this.rearrange(iota), blendMask);
2044     }
2045 
2046     /*package-private*/
2047     final
2048     @ForceInline
2049     <M extends VectorMask<Double>>
2050     DoubleVector
2051     unsliceTemplate(Class<M> maskType, int origin, Vector<Double> w, int part, M m) {
2052         DoubleVector that = (DoubleVector) w;
2053         that.check(this);
2054         DoubleVector slice = that.sliceTemplate(origin, that);
2055         slice = slice.blendTemplate(maskType, this, m);
2056         return slice.unsliceTemplate(origin, w, part);
2057     }
2058 
2059     /**
2060      * {@inheritDoc} <!--workaround-->
2061      */
2062     @Override
2063     public abstract
2064     DoubleVector unslice(int origin, Vector<Double> w, int part, VectorMask<Double> m);
2065 
2066     /**
2067      * {@inheritDoc} <!--workaround-->
2068      */
2069     @Override
2070     public abstract
2071     DoubleVector unslice(int origin);
2072 
2073     /*package-private*/
2074     final
2075     @ForceInline
2076     DoubleVector
2077     unsliceTemplate(int origin) {
2078         Objects.checkIndex(origin, length() + 1);
2079         VectorShuffle<Double> iota = iotaShuffle();
2080         VectorMask<Double> blendMask = iota.toVector().compare(VectorOperators.GE,
2081                                                                   (broadcast((double)(origin))));
2082         iota = iotaShuffle(-origin, 1, true);
2083         return vspecies().zero().blend(this.rearrange(iota), blendMask);
2084     }
2085 
2086     private ArrayIndexOutOfBoundsException
2087     wrongPartForSlice(int part) {
2088         String msg = String.format("bad part number %d for slice operation",
2089                                    part);
2090         return new ArrayIndexOutOfBoundsException(msg);
2091     }
2092 
2093     /**
2094      * {@inheritDoc} <!--workaround-->
2095      */
2096     @Override
2097     public abstract
2098     DoubleVector rearrange(VectorShuffle<Double> m);
2099 
2100     /*package-private*/
2101     @ForceInline
2102     final
2103     <S extends VectorShuffle<Double>>
2104     DoubleVector rearrangeTemplate(Class<S> shuffletype, S shuffle) {
2105         shuffle.checkIndexes();
2106         return VectorSupport.rearrangeOp(
2107             getClass(), shuffletype, null, double.class, length(),
2108             this, shuffle, null,
2109             (v1, s_, m_) -> v1.uOp((i, a) -> {
2110                 int ei = s_.laneSource(i);
2111                 return v1.lane(ei);
2112             }));
2113     }
2114 
2115     /**
2116      * {@inheritDoc} <!--workaround-->
2117      */
2118     @Override
2119     public abstract
2120     DoubleVector rearrange(VectorShuffle<Double> s,
2121                                    VectorMask<Double> m);
2122 
2123     /*package-private*/
2124     @ForceInline
2125     final
2126     <S extends VectorShuffle<Double>, M extends VectorMask<Double>>
2127     DoubleVector rearrangeTemplate(Class<S> shuffletype,
2128                                            Class<M> masktype,
2129                                            S shuffle,
2130                                            M m) {
2131 
2132         m.check(masktype, this);
2133         VectorMask<Double> valid = shuffle.laneIsValid();
2134         if (m.andNot(valid).anyTrue()) {
2135             shuffle.checkIndexes();
2136             throw new AssertionError();
2137         }
2138         return VectorSupport.rearrangeOp(
2139                    getClass(), shuffletype, masktype, double.class, length(),
2140                    this, shuffle, m,
2141                    (v1, s_, m_) -> v1.uOp((i, a) -> {
2142                         int ei = s_.laneSource(i);
2143                         return ei < 0  || !m_.laneIsSet(i) ? 0 : v1.lane(ei);
2144                    }));
2145     }
2146 
2147     /**
2148      * {@inheritDoc} <!--workaround-->
2149      */
2150     @Override
2151     public abstract
2152     DoubleVector rearrange(VectorShuffle<Double> s,
2153                                    Vector<Double> v);
2154 
2155     /*package-private*/
2156     @ForceInline
2157     final
2158     <S extends VectorShuffle<Double>>
2159     DoubleVector rearrangeTemplate(Class<S> shuffletype,
2160                                            S shuffle,
2161                                            DoubleVector v) {
2162         VectorMask<Double> valid = shuffle.laneIsValid();
2163         @SuppressWarnings("unchecked")
2164         S ws = (S) shuffle.wrapIndexes();
2165         DoubleVector r0 =
2166             VectorSupport.rearrangeOp(
2167                 getClass(), shuffletype, null, double.class, length(),
2168                 this, ws, null,
2169                 (v0, s_, m_) -> v0.uOp((i, a) -> {
2170                     int ei = s_.laneSource(i);
2171                     return v0.lane(ei);
2172                 }));
2173         DoubleVector r1 =
2174             VectorSupport.rearrangeOp(
2175                 getClass(), shuffletype, null, double.class, length(),
2176                 v, ws, null,
2177                 (v1, s_, m_) -> v1.uOp((i, a) -> {
2178                     int ei = s_.laneSource(i);
2179                     return v1.lane(ei);
2180                 }));
2181         return r1.blend(r0, valid);
2182     }
2183 
2184     @ForceInline
2185     private final
2186     VectorShuffle<Double> toShuffle0(DoubleSpecies dsp) {
2187         double[] a = toArray();
2188         int[] sa = new int[a.length];
2189         for (int i = 0; i < a.length; i++) {
2190             sa[i] = (int) a[i];
2191         }
2192         return VectorShuffle.fromArray(dsp, sa, 0);
2193     }
2194 
2195     /*package-private*/
2196     @ForceInline
2197     final
2198     VectorShuffle<Double> toShuffleTemplate(Class<?> shuffleType) {
2199         DoubleSpecies vsp = vspecies();
2200         return VectorSupport.convert(VectorSupport.VECTOR_OP_CAST,
2201                                      getClass(), double.class, length(),
2202                                      shuffleType, byte.class, length(),
2203                                      this, vsp,
2204                                      DoubleVector::toShuffle0);
2205     }
2206 
2207     /**
2208      * {@inheritDoc} <!--workaround-->
2209      */
2210     @Override
2211     public abstract
2212     DoubleVector selectFrom(Vector<Double> v);
2213 
2214     /*package-private*/
2215     @ForceInline
2216     final DoubleVector selectFromTemplate(DoubleVector v) {
2217         return v.rearrange(this.toShuffle());
2218     }
2219 
2220     /**
2221      * {@inheritDoc} <!--workaround-->
2222      */
2223     @Override
2224     public abstract
2225     DoubleVector selectFrom(Vector<Double> s, VectorMask<Double> m);
2226 
2227     /*package-private*/
2228     @ForceInline
2229     final DoubleVector selectFromTemplate(DoubleVector v,
2230                                                   AbstractMask<Double> m) {
2231         return v.rearrange(this.toShuffle(), m);
2232     }
2233 
2234     /// Ternary operations
2235 
2236 
2237     /**
2238      * Multiplies this vector by a second input vector, and sums
2239      * the result with a third.
2240      *
2241      * Extended precision is used for the intermediate result,
2242      * avoiding possible loss of precision from rounding once
2243      * for each of the two operations.
2244      * The result is numerically close to {@code this.mul(b).add(c)},
2245      * and is typically closer to the true mathematical result.
2246      *
2247      * This is a lane-wise ternary operation which applies an operation
2248      * conforming to the specification of
2249      * {@link Math#fma(double,double,double) Math.fma(a,b,c)}
2250      * to each lane.
2251      *
2252      * This method is also equivalent to the expression
2253      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2254      *    lanewise}{@code (}{@link VectorOperators#FMA
2255      *    FMA}{@code , b, c)}.
2256      *
2257      * @param b the second input vector, supplying multiplier values
2258      * @param c the third input vector, supplying addend values
2259      * @return the product of this vector and the second input vector
2260      *         summed with the third input vector, using extended precision
2261      *         for the intermediate result
2262      * @see #fma(double,double)
2263      * @see VectorOperators#FMA
2264      * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask)
2265      */
2266     @ForceInline
2267     public final
2268     DoubleVector fma(Vector<Double> b, Vector<Double> c) {
2269         return lanewise(FMA, b, c);
2270     }
2271 
2272     /**
2273      * Multiplies this vector by a scalar multiplier, and sums
2274      * the result with a scalar addend.
2275      *
2276      * Extended precision is used for the intermediate result,
2277      * avoiding possible loss of precision from rounding once
2278      * for each of the two operations.
2279      * The result is numerically close to {@code this.mul(b).add(c)},
2280      * and is typically closer to the true mathematical result.
2281      *
2282      * This is a lane-wise ternary operation which applies an operation
2283      * conforming to the specification of
2284      * {@link Math#fma(double,double,double) Math.fma(a,b,c)}
2285      * to each lane.
2286      *
2287      * This method is also equivalent to the expression
2288      * {@link #lanewise(VectorOperators.Ternary,Vector,Vector)
2289      *    lanewise}{@code (}{@link VectorOperators#FMA
2290      *    FMA}{@code , b, c)}.
2291      *
2292      * @param b the scalar multiplier
2293      * @param c the scalar addend
2294      * @return the product of this vector and the scalar multiplier
2295      *         summed with scalar addend, using extended precision
2296      *         for the intermediate result
2297      * @see #fma(Vector,Vector)
2298      * @see VectorOperators#FMA
2299      * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
2300      */
2301     @ForceInline
2302     public final
2303     DoubleVector fma(double b, double c) {
2304         return lanewise(FMA, b, c);
2305     }
2306 
2307     // Don't bother with (Vector,double) and (double,Vector) overloadings.
2308 
2309     // Type specific horizontal reductions
2310 
2311     /**
2312      * Returns a value accumulated from all the lanes of this vector.
2313      *
2314      * This is an associative cross-lane reduction operation which
2315      * applies the specified operation to all the lane elements.
2316      * <p>
2317      * A few reduction operations do not support arbitrary reordering
2318      * of their operands, yet are included here because of their
2319      * usefulness.
2320      * <ul>
2321      * <li>
2322      * In the case of {@code FIRST_NONZERO}, the reduction returns
2323      * the value from the lowest-numbered non-zero lane.
2324      * (As with {@code MAX} and {@code MIN}, floating point negative
2325      * zero {@code -0.0} is treated as a value distinct from
2326      * the default value, positive zero. So a first-nonzero lane reduction
2327      * might return {@code -0.0} even in the presence of non-zero
2328      * lane values.)
2329      * <li>
2330      * In the case of {@code ADD} and {@code MUL}, the
2331      * precise result will reflect the choice of an arbitrary order
2332      * of operations, which may even vary over time.
2333      * For further details see the section
2334      * <a href="VectorOperators.html#fp_assoc">Operations on floating point vectors</a>.
2335      * <li>
2336      * All other reduction operations are fully commutative and
2337      * associative.  The implementation can choose any order of
2338      * processing, yet it will always produce the same result.
2339      * </ul>
2340      *
2341      * @param op the operation used to combine lane values
2342      * @return the accumulated result
2343      * @throws UnsupportedOperationException if this vector does
2344      *         not support the requested operation
2345      * @see #reduceLanes(VectorOperators.Associative,VectorMask)
2346      * @see #add(Vector)
2347      * @see #mul(Vector)
2348      * @see #min(Vector)
2349      * @see #max(Vector)
2350      * @see VectorOperators#FIRST_NONZERO
2351      */
2352     public abstract double reduceLanes(VectorOperators.Associative op);
2353 
2354     /**
2355      * Returns a value accumulated from selected lanes of this vector,
2356      * controlled by a mask.
2357      *
2358      * This is an associative cross-lane reduction operation which
2359      * applies the specified operation to the selected lane elements.
2360      * <p>
2361      * If no elements are selected, an operation-specific identity
2362      * value is returned.
2363      * <ul>
2364      * <li>
2365      * If the operation is
2366      *  {@code ADD}
2367      * or {@code FIRST_NONZERO},
2368      * then the identity value is positive zero, the default {@code double} value.
2369      * <li>
2370      * If the operation is {@code MUL},
2371      * then the identity value is one.
2372      * <li>
2373      * If the operation is {@code MAX},
2374      * then the identity value is {@code Double.NEGATIVE_INFINITY}.
2375      * <li>
2376      * If the operation is {@code MIN},
2377      * then the identity value is {@code Double.POSITIVE_INFINITY}.
2378      * </ul>
2379      * <p>
2380      * A few reduction operations do not support arbitrary reordering
2381      * of their operands, yet are included here because of their
2382      * usefulness.
2383      * <ul>
2384      * <li>
2385      * In the case of {@code FIRST_NONZERO}, the reduction returns
2386      * the value from the lowest-numbered non-zero lane.
2387      * (As with {@code MAX} and {@code MIN}, floating point negative
2388      * zero {@code -0.0} is treated as a value distinct from
2389      * the default value, positive zero. So a first-nonzero lane reduction
2390      * might return {@code -0.0} even in the presence of non-zero
2391      * lane values.)
2392      * <li>
2393      * In the case of {@code ADD} and {@code MUL}, the
2394      * precise result will reflect the choice of an arbitrary order
2395      * of operations, which may even vary over time.
2396      * For further details see the section
2397      * <a href="VectorOperators.html#fp_assoc">Operations on floating point vectors</a>.
2398      * <li>
2399      * All other reduction operations are fully commutative and
2400      * associative.  The implementation can choose any order of
2401      * processing, yet it will always produce the same result.
2402      * </ul>
2403      *
2404      * @param op the operation used to combine lane values
2405      * @param m the mask controlling lane selection
2406      * @return the reduced result accumulated from the selected lane values
2407      * @throws UnsupportedOperationException if this vector does
2408      *         not support the requested operation
2409      * @see #reduceLanes(VectorOperators.Associative)
2410      */
2411     public abstract double reduceLanes(VectorOperators.Associative op,
2412                                        VectorMask<Double> m);
2413 
2414     /*package-private*/
2415     @ForceInline
2416     final
2417     double reduceLanesTemplate(VectorOperators.Associative op,
2418                                Class<? extends VectorMask<Double>> maskClass,
2419                                VectorMask<Double> m) {
2420         m.check(maskClass, this);
2421         if (op == FIRST_NONZERO) {
2422             DoubleVector v = reduceIdentityVector(op).blend(this, m);
2423             return v.reduceLanesTemplate(op);
2424         }
2425         int opc = opCode(op);
2426         return fromBits(VectorSupport.reductionCoerced(
2427             opc, getClass(), maskClass, double.class, length(),
2428             this, m,
2429             REDUCE_IMPL.find(op, opc, DoubleVector::reductionOperations)));
2430     }
2431 
2432     /*package-private*/
2433     @ForceInline
2434     final
2435     double reduceLanesTemplate(VectorOperators.Associative op) {
2436         if (op == FIRST_NONZERO) {
2437             // FIXME:  The JIT should handle this, and other scan ops alos.
2438             VectorMask<Long> thisNZ
2439                 = this.viewAsIntegralLanes().compare(NE, (long) 0);
2440             return this.lane(thisNZ.firstTrue());
2441         }
2442         int opc = opCode(op);
2443         return fromBits(VectorSupport.reductionCoerced(
2444             opc, getClass(), null, double.class, length(),
2445             this, null,
2446             REDUCE_IMPL.find(op, opc, DoubleVector::reductionOperations)));
2447     }
2448 
2449     private static final
2450     ImplCache<Associative, ReductionOperation<DoubleVector, VectorMask<Double>>>
2451         REDUCE_IMPL = new ImplCache<>(Associative.class, DoubleVector.class);
2452 
2453     private static ReductionOperation<DoubleVector, VectorMask<Double>> reductionOperations(int opc_) {
2454         switch (opc_) {
2455             case VECTOR_OP_ADD: return (v, m) ->
2456                     toBits(v.rOp((double)0, m, (i, a, b) -> (double)(a + b)));
2457             case VECTOR_OP_MUL: return (v, m) ->
2458                     toBits(v.rOp((double)1, m, (i, a, b) -> (double)(a * b)));
2459             case VECTOR_OP_MIN: return (v, m) ->
2460                     toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (double) Math.min(a, b)));
2461             case VECTOR_OP_MAX: return (v, m) ->
2462                     toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (double) Math.max(a, b)));
2463             default: return null;
2464         }
2465     }
2466 
2467     private
2468     @ForceInline
2469     DoubleVector reduceIdentityVector(VectorOperators.Associative op) {
2470         int opc = opCode(op);
2471         UnaryOperator<DoubleVector> fn
2472             = REDUCE_ID_IMPL.find(op, opc, (opc_) -> {
2473                 switch (opc_) {
2474                 case VECTOR_OP_ADD:
2475                     return v -> v.broadcast(0);
2476                 case VECTOR_OP_MUL:
2477                     return v -> v.broadcast(1);
2478                 case VECTOR_OP_MIN:
2479                     return v -> v.broadcast(MAX_OR_INF);
2480                 case VECTOR_OP_MAX:
2481                     return v -> v.broadcast(MIN_OR_INF);
2482                 default: return null;
2483                 }
2484             });
2485         return fn.apply(this);
2486     }
2487     private static final
2488     ImplCache<Associative,UnaryOperator<DoubleVector>> REDUCE_ID_IMPL
2489         = new ImplCache<>(Associative.class, DoubleVector.class);
2490 
2491     private static final double MIN_OR_INF = Double.NEGATIVE_INFINITY;
2492     private static final double MAX_OR_INF = Double.POSITIVE_INFINITY;
2493 
2494     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op);
2495     public @Override abstract long reduceLanesToLong(VectorOperators.Associative op,
2496                                                      VectorMask<Double> m);
2497 
2498     // Type specific accessors
2499 
2500     /**
2501      * Gets the lane element at lane index {@code i}
2502      *
2503      * @param i the lane index
2504      * @return the lane element at lane index {@code i}
2505      * @throws IllegalArgumentException if the index is is out of range
2506      * ({@code < 0 || >= length()})
2507      */
2508     public abstract double lane(int i);
2509 
2510     /**
2511      * Replaces the lane element of this vector at lane index {@code i} with
2512      * value {@code e}.
2513      *
2514      * This is a cross-lane operation and behaves as if it returns the result
2515      * of blending this vector with an input vector that is the result of
2516      * broadcasting {@code e} and a mask that has only one lane set at lane
2517      * index {@code i}.
2518      *
2519      * @param i the lane index of the lane element to be replaced
2520      * @param e the value to be placed
2521      * @return the result of replacing the lane element of this vector at lane
2522      * index {@code i} with value {@code e}.
2523      * @throws IllegalArgumentException if the index is is out of range
2524      * ({@code < 0 || >= length()})
2525      */
2526     public abstract DoubleVector withLane(int i, double e);
2527 
2528     // Memory load operations
2529 
2530     /**
2531      * Returns an array of type {@code double[]}
2532      * containing all the lane values.
2533      * The array length is the same as the vector length.
2534      * The array elements are stored in lane order.
2535      * <p>
2536      * This method behaves as if it stores
2537      * this vector into an allocated array
2538      * (using {@link #intoArray(double[], int) intoArray})
2539      * and returns the array as follows:
2540      * <pre>{@code
2541      *   double[] a = new double[this.length()];
2542      *   this.intoArray(a, 0);
2543      *   return a;
2544      * }</pre>
2545      *
2546      * @return an array containing the lane values of this vector
2547      */
2548     @ForceInline
2549     @Override
2550     public final double[] toArray() {
2551         double[] a = new double[vspecies().laneCount()];
2552         intoArray(a, 0);
2553         return a;
2554     }
2555 
2556     /** {@inheritDoc} <!--workaround-->
2557      */
2558     @ForceInline
2559     @Override
2560     public final int[] toIntArray() {
2561         double[] a = toArray();
2562         int[] res = new int[a.length];
2563         for (int i = 0; i < a.length; i++) {
2564             double e = a[i];
2565             res[i] = (int) DoubleSpecies.toIntegralChecked(e, true);
2566         }
2567         return res;
2568     }
2569 
2570     /** {@inheritDoc} <!--workaround-->
2571      */
2572     @ForceInline
2573     @Override
2574     public final long[] toLongArray() {
2575         double[] a = toArray();
2576         long[] res = new long[a.length];
2577         for (int i = 0; i < a.length; i++) {
2578             double e = a[i];
2579             res[i] = DoubleSpecies.toIntegralChecked(e, false);
2580         }
2581         return res;
2582     }
2583 
2584     /** {@inheritDoc} <!--workaround-->
2585      * @implNote
2586      * This is an alias for {@link #toArray()}
2587      * When this method is used on used on vectors
2588      * of type {@code DoubleVector},
2589      * there will be no loss of precision.
2590      */
2591     @ForceInline
2592     @Override
2593     public final double[] toDoubleArray() {
2594         return toArray();
2595     }
2596 
2597     /**
2598      * Loads a vector from a byte array starting at an offset.
2599      * Bytes are composed into primitive lane elements according
2600      * to the specified byte order.
2601      * The vector is arranged into lanes according to
2602      * <a href="Vector.html#lane-order">memory ordering</a>.
2603      * <p>
2604      * This method behaves as if it returns the result of calling
2605      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2606      * fromByteBuffer()} as follows:
2607      * <pre>{@code
2608      * var bb = ByteBuffer.wrap(a);
2609      * var m = species.maskAll(true);
2610      * return fromByteBuffer(species, bb, offset, bo, m);
2611      * }</pre>
2612      *
2613      * @param species species of desired vector
2614      * @param a the byte array
2615      * @param offset the offset into the array
2616      * @param bo the intended byte order
2617      * @return a vector loaded from a byte array
2618      * @throws IndexOutOfBoundsException
2619      *         if {@code offset+N*ESIZE < 0}
2620      *         or {@code offset+(N+1)*ESIZE > a.length}
2621      *         for any lane {@code N} in the vector
2622      */
2623     @ForceInline
2624     public static
2625     DoubleVector fromByteArray(VectorSpecies<Double> species,
2626                                        byte[] a, int offset,
2627                                        ByteOrder bo) {
2628         offset = checkFromIndexSize(offset, species.vectorByteSize(), a.length);
2629         DoubleSpecies vsp = (DoubleSpecies) species;
2630         return vsp.dummyVector().fromByteArray0(a, offset).maybeSwap(bo);
2631     }
2632 
2633     /**
2634      * Loads a vector from a byte array starting at an offset
2635      * and using a mask.
2636      * Lanes where the mask is unset are filled with the default
2637      * value of {@code double} (positive zero).
2638      * Bytes are composed into primitive lane elements according
2639      * to the specified byte order.
2640      * The vector is arranged into lanes according to
2641      * <a href="Vector.html#lane-order">memory ordering</a>.
2642      * <p>
2643      * This method behaves as if it returns the result of calling
2644      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2645      * fromByteBuffer()} as follows:
2646      * <pre>{@code
2647      * var bb = ByteBuffer.wrap(a);
2648      * return fromByteBuffer(species, bb, offset, bo, m);
2649      * }</pre>
2650      *
2651      * @param species species of desired vector
2652      * @param a the byte array
2653      * @param offset the offset into the array
2654      * @param bo the intended byte order
2655      * @param m the mask controlling lane selection
2656      * @return a vector loaded from a byte array
2657      * @throws IndexOutOfBoundsException
2658      *         if {@code offset+N*ESIZE < 0}
2659      *         or {@code offset+(N+1)*ESIZE > a.length}
2660      *         for any lane {@code N} in the vector
2661      *         where the mask is set
2662      */
2663     @ForceInline
2664     public static
2665     DoubleVector fromByteArray(VectorSpecies<Double> species,
2666                                        byte[] a, int offset,
2667                                        ByteOrder bo,
2668                                        VectorMask<Double> m) {
2669         DoubleSpecies vsp = (DoubleSpecies) species;
2670         if (offset >= 0 && offset <= (a.length - species.vectorByteSize())) {
2671             return vsp.dummyVector().fromByteArray0(a, offset, m).maybeSwap(bo);
2672         }
2673 
2674         // FIXME: optimize
2675         checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
2676         ByteBuffer wb = wrapper(a, bo);
2677         return vsp.ldOp(wb, offset, (AbstractMask<Double>)m,
2678                    (wb_, o, i)  -> wb_.getDouble(o + i * 8));
2679     }
2680 
2681     /**
2682      * Loads a vector from an array of type {@code double[]}
2683      * starting at an offset.
2684      * For each vector lane, where {@code N} is the vector lane index, the
2685      * array element at index {@code offset + N} is placed into the
2686      * resulting vector at lane index {@code N}.
2687      *
2688      * @param species species of desired vector
2689      * @param a the array
2690      * @param offset the offset into the array
2691      * @return the vector loaded from an array
2692      * @throws IndexOutOfBoundsException
2693      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2694      *         for any lane {@code N} in the vector
2695      */
2696     @ForceInline
2697     public static
2698     DoubleVector fromArray(VectorSpecies<Double> species,
2699                                    double[] a, int offset) {
2700         offset = checkFromIndexSize(offset, species.length(), a.length);
2701         DoubleSpecies vsp = (DoubleSpecies) species;
2702         return vsp.dummyVector().fromArray0(a, offset);
2703     }
2704 
2705     /**
2706      * Loads a vector from an array of type {@code double[]}
2707      * starting at an offset and using a mask.
2708      * Lanes where the mask is unset are filled with the default
2709      * value of {@code double} (positive zero).
2710      * For each vector lane, where {@code N} is the vector lane index,
2711      * if the mask lane at index {@code N} is set then the array element at
2712      * index {@code offset + N} is placed into the resulting vector at lane index
2713      * {@code N}, otherwise the default element value is placed into the
2714      * resulting vector at lane index {@code N}.
2715      *
2716      * @param species species of desired vector
2717      * @param a the array
2718      * @param offset the offset into the array
2719      * @param m the mask controlling lane selection
2720      * @return the vector loaded from an array
2721      * @throws IndexOutOfBoundsException
2722      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2723      *         for any lane {@code N} in the vector
2724      *         where the mask is set
2725      */
2726     @ForceInline
2727     public static
2728     DoubleVector fromArray(VectorSpecies<Double> species,
2729                                    double[] a, int offset,
2730                                    VectorMask<Double> m) {
2731         DoubleSpecies vsp = (DoubleSpecies) species;
2732         if (offset >= 0 && offset <= (a.length - species.length())) {
2733             return vsp.dummyVector().fromArray0(a, offset, m);
2734         }
2735 
2736         // FIXME: optimize
2737         checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
2738         return vsp.vOp(m, i -> a[offset + i]);
2739     }
2740 
2741     /**
2742      * Gathers a new vector composed of elements from an array of type
2743      * {@code double[]},
2744      * using indexes obtained by adding a fixed {@code offset} to a
2745      * series of secondary offsets from an <em>index map</em>.
2746      * The index map is a contiguous sequence of {@code VLENGTH}
2747      * elements in a second array of {@code int}s, starting at a given
2748      * {@code mapOffset}.
2749      * <p>
2750      * For each vector lane, where {@code N} is the vector lane index,
2751      * the lane is loaded from the array
2752      * element {@code a[f(N)]}, where {@code f(N)} is the
2753      * index mapping expression
2754      * {@code offset + indexMap[mapOffset + N]]}.
2755      *
2756      * @param species species of desired vector
2757      * @param a the array
2758      * @param offset the offset into the array, may be negative if relative
2759      * indexes in the index map compensate to produce a value within the
2760      * array bounds
2761      * @param indexMap the index map
2762      * @param mapOffset the offset into the index map
2763      * @return the vector loaded from the indexed elements of the array
2764      * @throws IndexOutOfBoundsException
2765      *         if {@code mapOffset+N < 0}
2766      *         or if {@code mapOffset+N >= indexMap.length},
2767      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2768      *         is an invalid index into {@code a},
2769      *         for any lane {@code N} in the vector
2770      * @see DoubleVector#toIntArray()
2771      */
2772     @ForceInline
2773     public static
2774     DoubleVector fromArray(VectorSpecies<Double> species,
2775                                    double[] a, int offset,
2776                                    int[] indexMap, int mapOffset) {
2777         DoubleSpecies vsp = (DoubleSpecies) species;
2778         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
2779         Objects.requireNonNull(a);
2780         Objects.requireNonNull(indexMap);
2781         Class<? extends DoubleVector> vectorType = vsp.vectorType();
2782 
2783         if (vsp.laneCount() == 1) {
2784           return DoubleVector.fromArray(vsp, a, offset + indexMap[mapOffset]);
2785         }
2786 
2787         // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k]
2788         IntVector vix;
2789         if (isp.laneCount() != vsp.laneCount()) {
2790             // For DoubleMaxVector,  if vector length is non-power-of-two or
2791             // 2048 bits, indexShape of Double species is S_MAX_BIT.
2792             // Assume that vector length is 2048, then the lane count of Double
2793             // vector is 32. When converting Double species to int species,
2794             // indexShape is still S_MAX_BIT, but the lane count of int vector
2795             // is 64. So when loading index vector (IntVector), only lower half
2796             // of index data is needed.
2797             vix = IntVector
2798                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
2799                 .add(offset);
2800         } else {
2801             vix = IntVector
2802                 .fromArray(isp, indexMap, mapOffset)
2803                 .add(offset);
2804         }
2805 
2806         vix = VectorIntrinsics.checkIndex(vix, a.length);
2807 
2808         return VectorSupport.loadWithMap(
2809             vectorType, null, double.class, vsp.laneCount(),
2810             isp.vectorType(),
2811             a, ARRAY_BASE, vix, null,
2812             a, offset, indexMap, mapOffset, vsp,
2813             (c, idx, iMap, idy, s, vm) ->
2814             s.vOp(n -> c[idx + iMap[idy+n]]));
2815     }
2816 
2817     /**
2818      * Gathers a new vector composed of elements from an array of type
2819      * {@code double[]},
2820      * under the control of a mask, and
2821      * using indexes obtained by adding a fixed {@code offset} to a
2822      * series of secondary offsets from an <em>index map</em>.
2823      * The index map is a contiguous sequence of {@code VLENGTH}
2824      * elements in a second array of {@code int}s, starting at a given
2825      * {@code mapOffset}.
2826      * <p>
2827      * For each vector lane, where {@code N} is the vector lane index,
2828      * if the lane is set in the mask,
2829      * the lane is loaded from the array
2830      * element {@code a[f(N)]}, where {@code f(N)} is the
2831      * index mapping expression
2832      * {@code offset + indexMap[mapOffset + N]]}.
2833      * Unset lanes in the resulting vector are set to zero.
2834      *
2835      * @param species species of desired vector
2836      * @param a the array
2837      * @param offset the offset into the array, may be negative if relative
2838      * indexes in the index map compensate to produce a value within the
2839      * array bounds
2840      * @param indexMap the index map
2841      * @param mapOffset the offset into the index map
2842      * @param m the mask controlling lane selection
2843      * @return the vector loaded from the indexed elements of the array
2844      * @throws IndexOutOfBoundsException
2845      *         if {@code mapOffset+N < 0}
2846      *         or if {@code mapOffset+N >= indexMap.length},
2847      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
2848      *         is an invalid index into {@code a},
2849      *         for any lane {@code N} in the vector
2850      *         where the mask is set
2851      * @see DoubleVector#toIntArray()
2852      */
2853     @ForceInline
2854     public static
2855     DoubleVector fromArray(VectorSpecies<Double> species,
2856                                    double[] a, int offset,
2857                                    int[] indexMap, int mapOffset,
2858                                    VectorMask<Double> m) {
2859         if (m.allTrue()) {
2860             return fromArray(species, a, offset, indexMap, mapOffset);
2861         }
2862         else {
2863             DoubleSpecies vsp = (DoubleSpecies) species;
2864             return vsp.dummyVector().fromArray0(a, offset, indexMap, mapOffset, m);
2865         }
2866     }
2867 
2868 
2869 
2870     /**
2871      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2872      * starting at an offset into the byte buffer.
2873      * Bytes are composed into primitive lane elements according
2874      * to the specified byte order.
2875      * The vector is arranged into lanes according to
2876      * <a href="Vector.html#lane-order">memory ordering</a>.
2877      * <p>
2878      * This method behaves as if it returns the result of calling
2879      * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask)
2880      * fromByteBuffer()} as follows:
2881      * <pre>{@code
2882      * var m = species.maskAll(true);
2883      * return fromByteBuffer(species, bb, offset, bo, m);
2884      * }</pre>
2885      *
2886      * @param species species of desired vector
2887      * @param bb the byte buffer
2888      * @param offset the offset into the byte buffer
2889      * @param bo the intended byte order
2890      * @return a vector loaded from a byte buffer
2891      * @throws IndexOutOfBoundsException
2892      *         if {@code offset+N*8 < 0}
2893      *         or {@code offset+N*8 >= bb.limit()}
2894      *         for any lane {@code N} in the vector
2895      */
2896     @ForceInline
2897     public static
2898     DoubleVector fromByteBuffer(VectorSpecies<Double> species,
2899                                         ByteBuffer bb, int offset,
2900                                         ByteOrder bo) {
2901         offset = checkFromIndexSize(offset, species.vectorByteSize(), bb.limit());
2902         DoubleSpecies vsp = (DoubleSpecies) species;
2903         return vsp.dummyVector().fromByteBuffer0(bb, offset).maybeSwap(bo);
2904     }
2905 
2906     /**
2907      * Loads a vector from a {@linkplain ByteBuffer byte buffer}
2908      * starting at an offset into the byte buffer
2909      * and using a mask.
2910      * Lanes where the mask is unset are filled with the default
2911      * value of {@code double} (positive zero).
2912      * Bytes are composed into primitive lane elements according
2913      * to the specified byte order.
2914      * The vector is arranged into lanes according to
2915      * <a href="Vector.html#lane-order">memory ordering</a>.
2916      * <p>
2917      * The following pseudocode illustrates the behavior:
2918      * <pre>{@code
2919      * DoubleBuffer eb = bb.duplicate()
2920      *     .position(offset)
2921      *     .order(bo).asDoubleBuffer();
2922      * double[] ar = new double[species.length()];
2923      * for (int n = 0; n < ar.length; n++) {
2924      *     if (m.laneIsSet(n)) {
2925      *         ar[n] = eb.get(n);
2926      *     }
2927      * }
2928      * DoubleVector r = DoubleVector.fromArray(species, ar, 0);
2929      * }</pre>
2930      * @implNote
2931      * This operation is likely to be more efficient if
2932      * the specified byte order is the same as
2933      * {@linkplain ByteOrder#nativeOrder()
2934      * the platform native order},
2935      * since this method will not need to reorder
2936      * the bytes of lane values.
2937      *
2938      * @param species species of desired vector
2939      * @param bb the byte buffer
2940      * @param offset the offset into the byte buffer
2941      * @param bo the intended byte order
2942      * @param m the mask controlling lane selection
2943      * @return a vector loaded from a byte buffer
2944      * @throws IndexOutOfBoundsException
2945      *         if {@code offset+N*8 < 0}
2946      *         or {@code offset+N*8 >= bb.limit()}
2947      *         for any lane {@code N} in the vector
2948      *         where the mask is set
2949      */
2950     @ForceInline
2951     public static
2952     DoubleVector fromByteBuffer(VectorSpecies<Double> species,
2953                                         ByteBuffer bb, int offset,
2954                                         ByteOrder bo,
2955                                         VectorMask<Double> m) {
2956         DoubleSpecies vsp = (DoubleSpecies) species;
2957         if (offset >= 0 && offset <= (bb.limit() - species.vectorByteSize())) {
2958             return vsp.dummyVector().fromByteBuffer0(bb, offset, m).maybeSwap(bo);
2959         }
2960 
2961         // FIXME: optimize
2962         checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
2963         ByteBuffer wb = wrapper(bb, bo);
2964         return vsp.ldOp(wb, offset, (AbstractMask<Double>)m,
2965                    (wb_, o, i)  -> wb_.getDouble(o + i * 8));
2966     }
2967 
2968     // Memory store operations
2969 
2970     /**
2971      * Stores this vector into an array of type {@code double[]}
2972      * starting at an offset.
2973      * <p>
2974      * For each vector lane, where {@code N} is the vector lane index,
2975      * the lane element at index {@code N} is stored into the array
2976      * element {@code a[offset+N]}.
2977      *
2978      * @param a the array, of type {@code double[]}
2979      * @param offset the offset into the array
2980      * @throws IndexOutOfBoundsException
2981      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
2982      *         for any lane {@code N} in the vector
2983      */
2984     @ForceInline
2985     public final
2986     void intoArray(double[] a, int offset) {
2987         offset = checkFromIndexSize(offset, length(), a.length);
2988         DoubleSpecies vsp = vspecies();
2989         VectorSupport.store(
2990             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
2991             a, arrayAddress(a, offset),
2992             this,
2993             a, offset,
2994             (arr, off, v)
2995             -> v.stOp(arr, off,
2996                       (arr_, off_, i, e) -> arr_[off_ + i] = e));
2997     }
2998 
2999     /**
3000      * Stores this vector into an array of type {@code double[]}
3001      * starting at offset and using a mask.
3002      * <p>
3003      * For each vector lane, where {@code N} is the vector lane index,
3004      * the lane element at index {@code N} is stored into the array
3005      * element {@code a[offset+N]}.
3006      * If the mask lane at {@code N} is unset then the corresponding
3007      * array element {@code a[offset+N]} is left unchanged.
3008      * <p>
3009      * Array range checking is done for lanes where the mask is set.
3010      * Lanes where the mask is unset are not stored and do not need
3011      * to correspond to legitimate elements of {@code a}.
3012      * That is, unset lanes may correspond to array indexes less than
3013      * zero or beyond the end of the array.
3014      *
3015      * @param a the array, of type {@code double[]}
3016      * @param offset the offset into the array
3017      * @param m the mask controlling lane storage
3018      * @throws IndexOutOfBoundsException
3019      *         if {@code offset+N < 0} or {@code offset+N >= a.length}
3020      *         for any lane {@code N} in the vector
3021      *         where the mask is set
3022      */
3023     @ForceInline
3024     public final
3025     void intoArray(double[] a, int offset,
3026                    VectorMask<Double> m) {
3027         if (m.allTrue()) {
3028             intoArray(a, offset);
3029         } else {
3030             DoubleSpecies vsp = vspecies();
3031             checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
3032             intoArray0(a, offset, m);
3033         }
3034     }
3035 
3036     /**
3037      * Scatters this vector into an array of type {@code double[]}
3038      * using indexes obtained by adding a fixed {@code offset} to a
3039      * series of secondary offsets from an <em>index map</em>.
3040      * The index map is a contiguous sequence of {@code VLENGTH}
3041      * elements in a second array of {@code int}s, starting at a given
3042      * {@code mapOffset}.
3043      * <p>
3044      * For each vector lane, where {@code N} is the vector lane index,
3045      * the lane element at index {@code N} is stored into the array
3046      * element {@code a[f(N)]}, where {@code f(N)} is the
3047      * index mapping expression
3048      * {@code offset + indexMap[mapOffset + N]]}.
3049      *
3050      * @param a the array
3051      * @param offset an offset to combine with the index map offsets
3052      * @param indexMap the index map
3053      * @param mapOffset the offset into the index map
3054      * @throws IndexOutOfBoundsException
3055      *         if {@code mapOffset+N < 0}
3056      *         or if {@code mapOffset+N >= indexMap.length},
3057      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
3058      *         is an invalid index into {@code a},
3059      *         for any lane {@code N} in the vector
3060      * @see DoubleVector#toIntArray()
3061      */
3062     @ForceInline
3063     public final
3064     void intoArray(double[] a, int offset,
3065                    int[] indexMap, int mapOffset) {
3066         DoubleSpecies vsp = vspecies();
3067         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
3068         if (vsp.laneCount() == 1) {
3069             intoArray(a, offset + indexMap[mapOffset]);
3070             return;
3071         }
3072 
3073         // Index vector: vix[0:n] = i -> offset + indexMap[mo + i]
3074         IntVector vix;
3075         if (isp.laneCount() != vsp.laneCount()) {
3076             // For DoubleMaxVector,  if vector length  is 2048 bits, indexShape
3077             // of Double species is S_MAX_BIT. and the lane count of Double
3078             // vector is 32. When converting Double species to int species,
3079             // indexShape is still S_MAX_BIT, but the lane count of int vector
3080             // is 64. So when loading index vector (IntVector), only lower half
3081             // of index data is needed.
3082             vix = IntVector
3083                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
3084                 .add(offset);
3085         } else {
3086             vix = IntVector
3087                 .fromArray(isp, indexMap, mapOffset)
3088                 .add(offset);
3089         }
3090 
3091 
3092         vix = VectorIntrinsics.checkIndex(vix, a.length);
3093 
3094         VectorSupport.storeWithMap(
3095             vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(),
3096             isp.vectorType(),
3097             a, arrayAddress(a, 0), vix,
3098             this, null,
3099             a, offset, indexMap, mapOffset,
3100             (arr, off, v, map, mo, vm)
3101             -> v.stOp(arr, off,
3102                       (arr_, off_, i, e) -> {
3103                           int j = map[mo + i];
3104                           arr[off + j] = e;
3105                       }));
3106     }
3107 
3108     /**
3109      * Scatters this vector into an array of type {@code double[]},
3110      * under the control of a mask, and
3111      * using indexes obtained by adding a fixed {@code offset} to a
3112      * series of secondary offsets from an <em>index map</em>.
3113      * The index map is a contiguous sequence of {@code VLENGTH}
3114      * elements in a second array of {@code int}s, starting at a given
3115      * {@code mapOffset}.
3116      * <p>
3117      * For each vector lane, where {@code N} is the vector lane index,
3118      * if the mask lane at index {@code N} is set then
3119      * the lane element at index {@code N} is stored into the array
3120      * element {@code a[f(N)]}, where {@code f(N)} is the
3121      * index mapping expression
3122      * {@code offset + indexMap[mapOffset + N]]}.
3123      *
3124      * @param a the array
3125      * @param offset an offset to combine with the index map offsets
3126      * @param indexMap the index map
3127      * @param mapOffset the offset into the index map
3128      * @param m the mask
3129      * @throws IndexOutOfBoundsException
3130      *         if {@code mapOffset+N < 0}
3131      *         or if {@code mapOffset+N >= indexMap.length},
3132      *         or if {@code f(N)=offset+indexMap[mapOffset+N]}
3133      *         is an invalid index into {@code a},
3134      *         for any lane {@code N} in the vector
3135      *         where the mask is set
3136      * @see DoubleVector#toIntArray()
3137      */
3138     @ForceInline
3139     public final
3140     void intoArray(double[] a, int offset,
3141                    int[] indexMap, int mapOffset,
3142                    VectorMask<Double> m) {
3143         if (m.allTrue()) {
3144             intoArray(a, offset, indexMap, mapOffset);
3145         }
3146         else {
3147             intoArray0(a, offset, indexMap, mapOffset, m);
3148         }
3149     }
3150 
3151 
3152 
3153     /**
3154      * {@inheritDoc} <!--workaround-->
3155      */
3156     @Override
3157     @ForceInline
3158     public final
3159     void intoByteArray(byte[] a, int offset,
3160                        ByteOrder bo) {
3161         offset = checkFromIndexSize(offset, byteSize(), a.length);
3162         maybeSwap(bo).intoByteArray0(a, offset);
3163     }
3164 
3165     /**
3166      * {@inheritDoc} <!--workaround-->
3167      */
3168     @Override
3169     @ForceInline
3170     public final
3171     void intoByteArray(byte[] a, int offset,
3172                        ByteOrder bo,
3173                        VectorMask<Double> m) {
3174         if (m.allTrue()) {
3175             intoByteArray(a, offset, bo);
3176         } else {
3177             DoubleSpecies vsp = vspecies();
3178             checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
3179             maybeSwap(bo).intoByteArray0(a, offset, m);
3180         }
3181     }
3182 
3183     /**
3184      * {@inheritDoc} <!--workaround-->
3185      */
3186     @Override
3187     @ForceInline
3188     public final
3189     void intoByteBuffer(ByteBuffer bb, int offset,
3190                         ByteOrder bo) {
3191         if (ScopedMemoryAccess.isReadOnly(bb)) {
3192             throw new ReadOnlyBufferException();
3193         }
3194         offset = checkFromIndexSize(offset, byteSize(), bb.limit());
3195         maybeSwap(bo).intoByteBuffer0(bb, offset);
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                         VectorMask<Double> m) {
3207         if (m.allTrue()) {
3208             intoByteBuffer(bb, offset, bo);
3209         } else {
3210             if (bb.isReadOnly()) {
3211                 throw new ReadOnlyBufferException();
3212             }
3213             DoubleSpecies vsp = vspecies();
3214             checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
3215             maybeSwap(bo).intoByteBuffer0(bb, offset, m);
3216         }
3217     }
3218 
3219     // ================================================
3220 
3221     // Low-level memory operations.
3222     //
3223     // Note that all of these operations *must* inline into a context
3224     // where the exact species of the involved vector is a
3225     // compile-time constant.  Otherwise, the intrinsic generation
3226     // will fail and performance will suffer.
3227     //
3228     // In many cases this is achieved by re-deriving a version of the
3229     // method in each concrete subclass (per species).  The re-derived
3230     // method simply calls one of these generic methods, with exact
3231     // parameters for the controlling metadata, which is either a
3232     // typed vector or constant species instance.
3233 
3234     // Unchecked loading operations in native byte order.
3235     // Caller is responsible for applying index checks, masking, and
3236     // byte swapping.
3237 
3238     /*package-private*/
3239     abstract
3240     DoubleVector fromArray0(double[] a, int offset);
3241     @ForceInline
3242     final
3243     DoubleVector fromArray0Template(double[] a, int offset) {
3244         DoubleSpecies vsp = vspecies();
3245         return VectorSupport.load(
3246             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3247             a, arrayAddress(a, offset),
3248             a, offset, vsp,
3249             (arr, off, s) -> s.ldOp(arr, off,
3250                                     (arr_, off_, i) -> arr_[off_ + i]));
3251     }
3252 
3253     /*package-private*/
3254     abstract
3255     DoubleVector fromArray0(double[] a, int offset, VectorMask<Double> m);
3256     @ForceInline
3257     final
3258     <M extends VectorMask<Double>>
3259     DoubleVector fromArray0Template(Class<M> maskClass, double[] a, int offset, M m) {
3260         m.check(species());
3261         DoubleSpecies vsp = vspecies();
3262         return VectorSupport.loadMasked(
3263             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3264             a, arrayAddress(a, offset), m,
3265             a, offset, vsp,
3266             (arr, off, s, vm) -> s.ldOp(arr, off, vm,
3267                                         (arr_, off_, i) -> arr_[off_ + i]));
3268     }
3269 
3270     /*package-private*/
3271     abstract
3272     DoubleVector fromArray0(double[] a, int offset,
3273                                     int[] indexMap, int mapOffset,
3274                                     VectorMask<Double> m);
3275     @ForceInline
3276     final
3277     <M extends VectorMask<Double>>
3278     DoubleVector fromArray0Template(Class<M> maskClass, double[] a, int offset,
3279                                             int[] indexMap, int mapOffset, M m) {
3280         DoubleSpecies vsp = vspecies();
3281         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
3282         Objects.requireNonNull(a);
3283         Objects.requireNonNull(indexMap);
3284         m.check(vsp);
3285         Class<? extends DoubleVector> vectorType = vsp.vectorType();
3286 
3287         if (vsp.laneCount() == 1) {
3288           return DoubleVector.fromArray(vsp, a, offset + indexMap[mapOffset], m);
3289         }
3290 
3291         // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k]
3292         IntVector vix;
3293         if (isp.laneCount() != vsp.laneCount()) {
3294             // For DoubleMaxVector,  if vector length is non-power-of-two or
3295             // 2048 bits, indexShape of Double species is S_MAX_BIT.
3296             // Assume that vector length is 2048, then the lane count of Double
3297             // vector is 32. When converting Double species to int species,
3298             // indexShape is still S_MAX_BIT, but the lane count of int vector
3299             // is 64. So when loading index vector (IntVector), only lower half
3300             // of index data is needed.
3301             vix = IntVector
3302                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
3303                 .add(offset);
3304         } else {
3305             vix = IntVector
3306                 .fromArray(isp, indexMap, mapOffset)
3307                 .add(offset);
3308         }
3309 
3310         // FIXME: Check index under mask controlling.
3311         vix = VectorIntrinsics.checkIndex(vix, a.length);
3312 
3313         return VectorSupport.loadWithMap(
3314             vectorType, maskClass, double.class, vsp.laneCount(),
3315             isp.vectorType(),
3316             a, ARRAY_BASE, vix, m,
3317             a, offset, indexMap, mapOffset, vsp,
3318             (c, idx, iMap, idy, s, vm) ->
3319             s.vOp(vm, n -> c[idx + iMap[idy+n]]));
3320     }
3321 
3322 
3323 
3324     @Override
3325     abstract
3326     DoubleVector fromByteArray0(byte[] a, int offset);
3327     @ForceInline
3328     final
3329     DoubleVector fromByteArray0Template(byte[] a, int offset) {
3330         DoubleSpecies vsp = vspecies();
3331         return VectorSupport.load(
3332             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3333             a, byteArrayAddress(a, offset),
3334             a, offset, vsp,
3335             (arr, off, s) -> {
3336                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3337                 return s.ldOp(wb, off,
3338                         (wb_, o, i) -> wb_.getDouble(o + i * 8));
3339             });
3340     }
3341 
3342     abstract
3343     DoubleVector fromByteArray0(byte[] a, int offset, VectorMask<Double> m);
3344     @ForceInline
3345     final
3346     <M extends VectorMask<Double>>
3347     DoubleVector fromByteArray0Template(Class<M> maskClass, byte[] a, int offset, M m) {
3348         DoubleSpecies vsp = vspecies();
3349         m.check(vsp);
3350         return VectorSupport.loadMasked(
3351             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3352             a, byteArrayAddress(a, offset), m,
3353             a, offset, vsp,
3354             (arr, off, s, vm) -> {
3355                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3356                 return s.ldOp(wb, off, vm,
3357                         (wb_, o, i) -> wb_.getDouble(o + i * 8));
3358             });
3359     }
3360 
3361     abstract
3362     DoubleVector fromByteBuffer0(ByteBuffer bb, int offset);
3363     @ForceInline
3364     final
3365     DoubleVector fromByteBuffer0Template(ByteBuffer bb, int offset) {
3366         DoubleSpecies vsp = vspecies();
3367         return ScopedMemoryAccess.loadFromByteBuffer(
3368                 vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3369                 bb, offset, vsp,
3370                 (buf, off, s) -> {
3371                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3372                     return s.ldOp(wb, off,
3373                             (wb_, o, i) -> wb_.getDouble(o + i * 8));
3374                 });
3375     }
3376 
3377     abstract
3378     DoubleVector fromByteBuffer0(ByteBuffer bb, int offset, VectorMask<Double> m);
3379     @ForceInline
3380     final
3381     <M extends VectorMask<Double>>
3382     DoubleVector fromByteBuffer0Template(Class<M> maskClass, ByteBuffer bb, int offset, M m) {
3383         DoubleSpecies vsp = vspecies();
3384         m.check(vsp);
3385         return ScopedMemoryAccess.loadFromByteBufferMasked(
3386                 vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3387                 bb, offset, m, vsp,
3388                 (buf, off, s, vm) -> {
3389                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3390                     return s.ldOp(wb, off, vm,
3391                             (wb_, o, i) -> wb_.getDouble(o + i * 8));
3392                 });
3393     }
3394 
3395     // Unchecked storing operations in native byte order.
3396     // Caller is responsible for applying index checks, masking, and
3397     // byte swapping.
3398 
3399     abstract
3400     void intoArray0(double[] a, int offset);
3401     @ForceInline
3402     final
3403     void intoArray0Template(double[] a, int offset) {
3404         DoubleSpecies vsp = vspecies();
3405         VectorSupport.store(
3406             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3407             a, arrayAddress(a, offset),
3408             this, a, offset,
3409             (arr, off, v)
3410             -> v.stOp(arr, off,
3411                       (arr_, off_, i, e) -> arr_[off_+i] = e));
3412     }
3413 
3414     abstract
3415     void intoArray0(double[] a, int offset, VectorMask<Double> m);
3416     @ForceInline
3417     final
3418     <M extends VectorMask<Double>>
3419     void intoArray0Template(Class<M> maskClass, double[] a, int offset, M m) {
3420         m.check(species());
3421         DoubleSpecies vsp = vspecies();
3422         VectorSupport.storeMasked(
3423             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3424             a, arrayAddress(a, offset),
3425             this, m, a, offset,
3426             (arr, off, v, vm)
3427             -> v.stOp(arr, off, vm,
3428                       (arr_, off_, i, e) -> arr_[off_ + i] = e));
3429     }
3430 
3431     abstract
3432     void intoArray0(double[] a, int offset,
3433                     int[] indexMap, int mapOffset,
3434                     VectorMask<Double> m);
3435     @ForceInline
3436     final
3437     <M extends VectorMask<Double>>
3438     void intoArray0Template(Class<M> maskClass, double[] a, int offset,
3439                             int[] indexMap, int mapOffset, M m) {
3440         m.check(species());
3441         DoubleSpecies vsp = vspecies();
3442         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
3443         if (vsp.laneCount() == 1) {
3444             intoArray(a, offset + indexMap[mapOffset], m);
3445             return;
3446         }
3447 
3448         // Index vector: vix[0:n] = i -> offset + indexMap[mo + i]
3449         IntVector vix;
3450         if (isp.laneCount() != vsp.laneCount()) {
3451             // For DoubleMaxVector,  if vector length  is 2048 bits, indexShape
3452             // of Double species is S_MAX_BIT. and the lane count of Double
3453             // vector is 32. When converting Double species to int species,
3454             // indexShape is still S_MAX_BIT, but the lane count of int vector
3455             // is 64. So when loading index vector (IntVector), only lower half
3456             // of index data is needed.
3457             vix = IntVector
3458                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
3459                 .add(offset);
3460         } else {
3461             vix = IntVector
3462                 .fromArray(isp, indexMap, mapOffset)
3463                 .add(offset);
3464         }
3465 
3466 
3467         // FIXME: Check index under mask controlling.
3468         vix = VectorIntrinsics.checkIndex(vix, a.length);
3469 
3470         VectorSupport.storeWithMap(
3471             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3472             isp.vectorType(),
3473             a, arrayAddress(a, 0), vix,
3474             this, m,
3475             a, offset, indexMap, mapOffset,
3476             (arr, off, v, map, mo, vm)
3477             -> v.stOp(arr, off, vm,
3478                       (arr_, off_, i, e) -> {
3479                           int j = map[mo + i];
3480                           arr[off + j] = e;
3481                       }));
3482     }
3483 
3484 
3485     abstract
3486     void intoByteArray0(byte[] a, int offset);
3487     @ForceInline
3488     final
3489     void intoByteArray0Template(byte[] a, int offset) {
3490         DoubleSpecies vsp = vspecies();
3491         VectorSupport.store(
3492             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3493             a, byteArrayAddress(a, offset),
3494             this, a, offset,
3495             (arr, off, v) -> {
3496                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3497                 v.stOp(wb, off,
3498                         (tb_, o, i, e) -> tb_.putDouble(o + i * 8, e));
3499             });
3500     }
3501 
3502     abstract
3503     void intoByteArray0(byte[] a, int offset, VectorMask<Double> m);
3504     @ForceInline
3505     final
3506     <M extends VectorMask<Double>>
3507     void intoByteArray0Template(Class<M> maskClass, byte[] a, int offset, M m) {
3508         DoubleSpecies vsp = vspecies();
3509         m.check(vsp);
3510         VectorSupport.storeMasked(
3511             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3512             a, byteArrayAddress(a, offset),
3513             this, m, a, offset,
3514             (arr, off, v, vm) -> {
3515                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
3516                 v.stOp(wb, off, vm,
3517                         (tb_, o, i, e) -> tb_.putDouble(o + i * 8, e));
3518             });
3519     }
3520 
3521     @ForceInline
3522     final
3523     void intoByteBuffer0(ByteBuffer bb, int offset) {
3524         DoubleSpecies vsp = vspecies();
3525         ScopedMemoryAccess.storeIntoByteBuffer(
3526                 vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
3527                 this, bb, offset,
3528                 (buf, off, v) -> {
3529                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3530                     v.stOp(wb, off,
3531                             (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
3532                 });
3533     }
3534 
3535     abstract
3536     void intoByteBuffer0(ByteBuffer bb, int offset, VectorMask<Double> m);
3537     @ForceInline
3538     final
3539     <M extends VectorMask<Double>>
3540     void intoByteBuffer0Template(Class<M> maskClass, ByteBuffer bb, int offset, M m) {
3541         DoubleSpecies vsp = vspecies();
3542         m.check(vsp);
3543         ScopedMemoryAccess.storeIntoByteBufferMasked(
3544                 vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
3545                 this, m, bb, offset,
3546                 (buf, off, v, vm) -> {
3547                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
3548                     v.stOp(wb, off, vm,
3549                             (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
3550                 });
3551     }
3552 
3553 
3554     // End of low-level memory operations.
3555 
3556     private static
3557     void checkMaskFromIndexSize(int offset,
3558                                 DoubleSpecies vsp,
3559                                 VectorMask<Double> m,
3560                                 int scale,
3561                                 int limit) {
3562         ((AbstractMask<Double>)m)
3563             .checkIndexByLane(offset, limit, vsp.iota(), scale);
3564     }
3565 
3566     @ForceInline
3567     private void conditionalStoreNYI(int offset,
3568                                      DoubleSpecies vsp,
3569                                      VectorMask<Double> m,
3570                                      int scale,
3571                                      int limit) {
3572         if (offset < 0 || offset + vsp.laneCount() * scale > limit) {
3573             String msg =
3574                 String.format("unimplemented: store @%d in [0..%d), %s in %s",
3575                               offset, limit, m, vsp);
3576             throw new AssertionError(msg);
3577         }
3578     }
3579 
3580     /*package-private*/
3581     @Override
3582     @ForceInline
3583     final
3584     DoubleVector maybeSwap(ByteOrder bo) {
3585         if (bo != NATIVE_ENDIAN) {
3586             return this.reinterpretAsBytes()
3587                 .rearrange(swapBytesShuffle())
3588                 .reinterpretAsDoubles();
3589         }
3590         return this;
3591     }
3592 
3593     static final int ARRAY_SHIFT =
3594         31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
3595     static final long ARRAY_BASE =
3596         Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
3597 
3598     @ForceInline
3599     static long arrayAddress(double[] a, int index) {
3600         return ARRAY_BASE + (((long)index) << ARRAY_SHIFT);
3601     }
3602 
3603 
3604 
3605     @ForceInline
3606     static long byteArrayAddress(byte[] a, int index) {
3607         return Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
3608     }
3609 
3610     // ================================================
3611 
3612     /// Reinterpreting view methods:
3613     //   lanewise reinterpret: viewAsXVector()
3614     //   keep shape, redraw lanes: reinterpretAsEs()
3615 
3616     /**
3617      * {@inheritDoc} <!--workaround-->
3618      */
3619     @ForceInline
3620     @Override
3621     public final ByteVector reinterpretAsBytes() {
3622          // Going to ByteVector, pay close attention to byte order.
3623          assert(REGISTER_ENDIAN == ByteOrder.LITTLE_ENDIAN);
3624          return asByteVectorRaw();
3625          //return asByteVectorRaw().rearrange(swapBytesShuffle());
3626     }
3627 
3628     /**
3629      * {@inheritDoc} <!--workaround-->
3630      */
3631     @ForceInline
3632     @Override
3633     public final LongVector viewAsIntegralLanes() {
3634         LaneType ilt = LaneType.DOUBLE.asIntegral();
3635         return (LongVector) asVectorRaw(ilt);
3636     }
3637 
3638     /**
3639      * {@inheritDoc} <!--workaround-->
3640      */
3641     @ForceInline
3642     @Override
3643     public final
3644     DoubleVector
3645     viewAsFloatingLanes() {
3646         return this;
3647     }
3648 
3649     // ================================================
3650 
3651     /// Object methods: toString, equals, hashCode
3652     //
3653     // Object methods are defined as if via Arrays.toString, etc.,
3654     // is applied to the array of elements.  Two equal vectors
3655     // are required to have equal species and equal lane values.
3656 
3657     /**
3658      * Returns a string representation of this vector, of the form
3659      * {@code "[0,1,2...]"}, reporting the lane values of this vector,
3660      * in lane order.
3661      *
3662      * The string is produced as if by a call to {@link
3663      * java.util.Arrays#toString(double[]) Arrays.toString()},
3664      * as appropriate to the {@code double} array returned by
3665      * {@link #toArray this.toArray()}.
3666      *
3667      * @return a string of the form {@code "[0,1,2...]"}
3668      * reporting the lane values of this vector
3669      */
3670     @Override
3671     @ForceInline
3672     public final
3673     String toString() {
3674         // now that toArray is strongly typed, we can define this
3675         return Arrays.toString(toArray());
3676     }
3677 
3678     /**
3679      * {@inheritDoc} <!--workaround-->
3680      */
3681     @Override
3682     @ForceInline
3683     public final
3684     boolean equals(Object obj) {
3685         if (obj instanceof Vector) {
3686             Vector<?> that = (Vector<?>) obj;
3687             if (this.species().equals(that.species())) {
3688                 return this.eq(that.check(this.species())).allTrue();
3689             }
3690         }
3691         return false;
3692     }
3693 
3694     /**
3695      * {@inheritDoc} <!--workaround-->
3696      */
3697     @Override
3698     @ForceInline
3699     public final
3700     int hashCode() {
3701         // now that toArray is strongly typed, we can define this
3702         return Objects.hash(species(), Arrays.hashCode(toArray()));
3703     }
3704 
3705     // ================================================
3706 
3707     // Species
3708 
3709     /**
3710      * Class representing {@link DoubleVector}'s of the same {@link VectorShape VectorShape}.
3711      */
3712     /*package-private*/
3713     static final class DoubleSpecies extends AbstractSpecies<Double> {
3714         private DoubleSpecies(VectorShape shape,
3715                 Class<? extends DoubleVector> vectorType,
3716                 Class<? extends AbstractMask<Double>> maskType,
3717                 Function<Object, DoubleVector> vectorFactory) {
3718             super(shape, LaneType.of(double.class),
3719                   vectorType, maskType,
3720                   vectorFactory);
3721             assert(this.elementSize() == Double.SIZE);
3722         }
3723 
3724         // Specializing overrides:
3725 
3726         @Override
3727         @ForceInline
3728         public final Class<Double> elementType() {
3729             return double.class;
3730         }
3731 
3732         @Override
3733         @ForceInline
3734         final Class<Double> genericElementType() {
3735             return Double.class;
3736         }
3737 
3738         @SuppressWarnings("unchecked")
3739         @Override
3740         @ForceInline
3741         public final Class<? extends DoubleVector> vectorType() {
3742             return (Class<? extends DoubleVector>) vectorType;
3743         }
3744 
3745         @Override
3746         @ForceInline
3747         public final long checkValue(long e) {
3748             longToElementBits(e);  // only for exception
3749             return e;
3750         }
3751 
3752         /*package-private*/
3753         @Override
3754         @ForceInline
3755         final DoubleVector broadcastBits(long bits) {
3756             return (DoubleVector)
3757                 VectorSupport.broadcastCoerced(
3758                     vectorType, double.class, laneCount,
3759                     bits, this,
3760                     (bits_, s_) -> s_.rvOp(i -> bits_));
3761         }
3762 
3763         /*package-private*/
3764         @ForceInline
3765         final DoubleVector broadcast(double e) {
3766             return broadcastBits(toBits(e));
3767         }
3768 
3769         @Override
3770         @ForceInline
3771         public final DoubleVector broadcast(long e) {
3772             return broadcastBits(longToElementBits(e));
3773         }
3774 
3775         /*package-private*/
3776         final @Override
3777         @ForceInline
3778         long longToElementBits(long value) {
3779             // Do the conversion, and then test it for failure.
3780             double e = (double) value;
3781             if ((long) e != value) {
3782                 throw badElementBits(value, e);
3783             }
3784             return toBits(e);
3785         }
3786 
3787         /*package-private*/
3788         @ForceInline
3789         static long toIntegralChecked(double e, boolean convertToInt) {
3790             long value = convertToInt ? (int) e : (long) e;
3791             if ((double) value != e) {
3792                 throw badArrayBits(e, convertToInt, value);
3793             }
3794             return value;
3795         }
3796 
3797         /* this non-public one is for internal conversions */
3798         @Override
3799         @ForceInline
3800         final DoubleVector fromIntValues(int[] values) {
3801             VectorIntrinsics.requireLength(values.length, laneCount);
3802             double[] va = new double[laneCount()];
3803             for (int i = 0; i < va.length; i++) {
3804                 int lv = values[i];
3805                 double v = (double) lv;
3806                 va[i] = v;
3807                 if ((int)v != lv) {
3808                     throw badElementBits(lv, v);
3809                 }
3810             }
3811             return dummyVector().fromArray0(va, 0);
3812         }
3813 
3814         // Virtual constructors
3815 
3816         @ForceInline
3817         @Override final
3818         public DoubleVector fromArray(Object a, int offset) {
3819             // User entry point:  Be careful with inputs.
3820             return DoubleVector
3821                 .fromArray(this, (double[]) a, offset);
3822         }
3823 
3824         @ForceInline
3825         @Override final
3826         DoubleVector dummyVector() {
3827             return (DoubleVector) super.dummyVector();
3828         }
3829 
3830         /*package-private*/
3831         final @Override
3832         @ForceInline
3833         DoubleVector rvOp(RVOp f) {
3834             double[] res = new double[laneCount()];
3835             for (int i = 0; i < res.length; i++) {
3836                 long bits = (long) f.apply(i);
3837                 res[i] = fromBits(bits);
3838             }
3839             return dummyVector().vectorFactory(res);
3840         }
3841 
3842         DoubleVector vOp(FVOp f) {
3843             double[] res = new double[laneCount()];
3844             for (int i = 0; i < res.length; i++) {
3845                 res[i] = f.apply(i);
3846             }
3847             return dummyVector().vectorFactory(res);
3848         }
3849 
3850         DoubleVector vOp(VectorMask<Double> m, FVOp f) {
3851             double[] res = new double[laneCount()];
3852             boolean[] mbits = ((AbstractMask<Double>)m).getBits();
3853             for (int i = 0; i < res.length; i++) {
3854                 if (mbits[i]) {
3855                     res[i] = f.apply(i);
3856                 }
3857             }
3858             return dummyVector().vectorFactory(res);
3859         }
3860 
3861         /*package-private*/
3862         @ForceInline
3863         <M> DoubleVector ldOp(M memory, int offset,
3864                                       FLdOp<M> f) {
3865             return dummyVector().ldOp(memory, offset, f);
3866         }
3867 
3868         /*package-private*/
3869         @ForceInline
3870         <M> DoubleVector ldOp(M memory, int offset,
3871                                       VectorMask<Double> m,
3872                                       FLdOp<M> f) {
3873             return dummyVector().ldOp(memory, offset, m, f);
3874         }
3875 
3876         /*package-private*/
3877         @ForceInline
3878         <M> void stOp(M memory, int offset, FStOp<M> f) {
3879             dummyVector().stOp(memory, offset, f);
3880         }
3881 
3882         /*package-private*/
3883         @ForceInline
3884         <M> void stOp(M memory, int offset,
3885                       AbstractMask<Double> m,
3886                       FStOp<M> f) {
3887             dummyVector().stOp(memory, offset, m, f);
3888         }
3889 
3890         // N.B. Make sure these constant vectors and
3891         // masks load up correctly into registers.
3892         //
3893         // Also, see if we can avoid all that switching.
3894         // Could we cache both vectors and both masks in
3895         // this species object?
3896 
3897         // Zero and iota vector access
3898         @Override
3899         @ForceInline
3900         public final DoubleVector zero() {
3901             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3902                 return DoubleMaxVector.ZERO;
3903             switch (vectorBitSize()) {
3904                 case 64: return Double64Vector.ZERO;
3905                 case 128: return Double128Vector.ZERO;
3906                 case 256: return Double256Vector.ZERO;
3907                 case 512: return Double512Vector.ZERO;
3908             }
3909             throw new AssertionError();
3910         }
3911 
3912         @Override
3913         @ForceInline
3914         public final DoubleVector iota() {
3915             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3916                 return DoubleMaxVector.IOTA;
3917             switch (vectorBitSize()) {
3918                 case 64: return Double64Vector.IOTA;
3919                 case 128: return Double128Vector.IOTA;
3920                 case 256: return Double256Vector.IOTA;
3921                 case 512: return Double512Vector.IOTA;
3922             }
3923             throw new AssertionError();
3924         }
3925 
3926         // Mask access
3927         @Override
3928         @ForceInline
3929         public final VectorMask<Double> maskAll(boolean bit) {
3930             if ((Class<?>) vectorType() == DoubleMaxVector.class)
3931                 return DoubleMaxVector.DoubleMaxMask.maskAll(bit);
3932             switch (vectorBitSize()) {
3933                 case 64: return Double64Vector.Double64Mask.maskAll(bit);
3934                 case 128: return Double128Vector.Double128Mask.maskAll(bit);
3935                 case 256: return Double256Vector.Double256Mask.maskAll(bit);
3936                 case 512: return Double512Vector.Double512Mask.maskAll(bit);
3937             }
3938             throw new AssertionError();
3939         }
3940     }
3941 
3942     /**
3943      * Finds a species for an element type of {@code double} and shape.
3944      *
3945      * @param s the shape
3946      * @return a species for an element type of {@code double} and shape
3947      * @throws IllegalArgumentException if no such species exists for the shape
3948      */
3949     static DoubleSpecies species(VectorShape s) {
3950         Objects.requireNonNull(s);
3951         switch (s) {
3952             case S_64_BIT: return (DoubleSpecies) SPECIES_64;
3953             case S_128_BIT: return (DoubleSpecies) SPECIES_128;
3954             case S_256_BIT: return (DoubleSpecies) SPECIES_256;
3955             case S_512_BIT: return (DoubleSpecies) SPECIES_512;
3956             case S_Max_BIT: return (DoubleSpecies) SPECIES_MAX;
3957             default: throw new IllegalArgumentException("Bad shape: " + s);
3958         }
3959     }
3960 
3961     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_64_BIT VectorShape.S_64_BIT}. */
3962     public static final VectorSpecies<Double> SPECIES_64
3963         = new DoubleSpecies(VectorShape.S_64_BIT,
3964                             Double64Vector.class,
3965                             Double64Vector.Double64Mask.class,
3966                             Double64Vector::new);
3967 
3968     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_128_BIT VectorShape.S_128_BIT}. */
3969     public static final VectorSpecies<Double> SPECIES_128
3970         = new DoubleSpecies(VectorShape.S_128_BIT,
3971                             Double128Vector.class,
3972                             Double128Vector.Double128Mask.class,
3973                             Double128Vector::new);
3974 
3975     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_256_BIT VectorShape.S_256_BIT}. */
3976     public static final VectorSpecies<Double> SPECIES_256
3977         = new DoubleSpecies(VectorShape.S_256_BIT,
3978                             Double256Vector.class,
3979                             Double256Vector.Double256Mask.class,
3980                             Double256Vector::new);
3981 
3982     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_512_BIT VectorShape.S_512_BIT}. */
3983     public static final VectorSpecies<Double> SPECIES_512
3984         = new DoubleSpecies(VectorShape.S_512_BIT,
3985                             Double512Vector.class,
3986                             Double512Vector.Double512Mask.class,
3987                             Double512Vector::new);
3988 
3989     /** Species representing {@link DoubleVector}s of {@link VectorShape#S_Max_BIT VectorShape.S_Max_BIT}. */
3990     public static final VectorSpecies<Double> SPECIES_MAX
3991         = new DoubleSpecies(VectorShape.S_Max_BIT,
3992                             DoubleMaxVector.class,
3993                             DoubleMaxVector.DoubleMaxMask.class,
3994                             DoubleMaxVector::new);
3995 
3996     /**
3997      * Preferred species for {@link DoubleVector}s.
3998      * A preferred species is a species of maximal bit-size for the platform.
3999      */
4000     public static final VectorSpecies<Double> SPECIES_PREFERRED
4001         = (DoubleSpecies) VectorSpecies.ofPreferred(double.class);
4002 }