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