1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have
  23  * questions.
  24  */
  25 package jdk.incubator.vector;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.nio.DoubleBuffer;
  29 import java.nio.ByteOrder;
  30 import java.util.Objects;
  31 import java.util.function.IntUnaryOperator;
  32 import java.util.concurrent.ThreadLocalRandom;
  33 
  34 import jdk.internal.misc.Unsafe;
  35 import jdk.internal.vm.annotation.ForceInline;
  36 import static jdk.incubator.vector.VectorIntrinsics.*;
  37 
  38 
  39 /**
  40  * A specialized {@link Vector} representing an ordered immutable sequence of
  41  * {@code double} values.
  42  */
  43 @SuppressWarnings("cast")
  44 public abstract class DoubleVector extends Vector<Double> {
  45 
  46     DoubleVector() {}
  47 
  48     private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
  49 
  50     // Unary operator
  51 
  52     interface FUnOp {
  53         double apply(int i, double a);
  54     }
  55 
  56     abstract DoubleVector uOp(FUnOp f);
  57 
  58     abstract DoubleVector uOp(Mask<Double> m, FUnOp f);
  59 
  60     // Binary operator
  61 
  62     interface FBinOp {
  63         double apply(int i, double a, double b);
  64     }
  65 
  66     abstract DoubleVector bOp(Vector<Double> v, FBinOp f);
  67 
  68     abstract DoubleVector bOp(Vector<Double> v, Mask<Double> m, FBinOp f);
  69 
  70     // Trinary operator
  71 
  72     interface FTriOp {
  73         double apply(int i, double a, double b, double c);
  74     }
  75 
  76     abstract DoubleVector tOp(Vector<Double> v1, Vector<Double> v2, FTriOp f);
  77 
  78     abstract DoubleVector tOp(Vector<Double> v1, Vector<Double> v2, Mask<Double> m, FTriOp f);
  79 
  80     // Reduction operator
  81 
  82     abstract double rOp(double v, FBinOp f);
  83 
  84     // Binary test
  85 
  86     interface FBinTest {
  87         boolean apply(int i, double a, double b);
  88     }
  89 
  90     abstract Mask<Double> bTest(Vector<Double> v, FBinTest f);
  91 
  92     // Foreach
  93 
  94     interface FUnCon {
  95         void apply(int i, double a);
  96     }
  97 
  98     abstract void forEach(FUnCon f);
  99 
 100     abstract void forEach(Mask<Double> m, FUnCon f);
 101 
 102     // Static factories
 103 
 104     /**
 105      * Returns a vector where all lane elements are set to the default
 106      * primitive value.
 107      *
 108      * @param species species of desired vector
 109      * @return a zero vector of given species
 110      */
 111     @ForceInline
 112     @SuppressWarnings("unchecked")
 113     public static DoubleVector zero(DoubleSpecies species) {
 114         return species.zero();
 115     }
 116 
 117     /**
 118      * Loads a vector from a byte array starting at an offset.
 119      * <p>
 120      * Bytes are composed into primitive lane elements according to the
 121      * native byte order of the underlying platform
 122      * <p>
 123      * This method behaves as if it returns the result of calling the
 124      * byte buffer, offset, and mask accepting
 125      * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask) method} as follows:
 126      * <pre>{@code
 127      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
 128      * }</pre>
 129      *
 130      * @param species species of desired vector
 131      * @param a the byte array
 132      * @param ix the offset into the array
 133      * @return a vector loaded from a byte array
 134      * @throws IndexOutOfBoundsException if {@code i < 0} or
 135      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 136      */
 137     @ForceInline
 138     @SuppressWarnings("unchecked")
 139     public static DoubleVector fromByteArray(DoubleSpecies species, byte[] a, int ix) {
 140         Objects.requireNonNull(a);
 141         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
 142         return VectorIntrinsics.load((Class<DoubleVector>) species.boxType(), double.class, species.length(),
 143                                      a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 144                                      a, ix, species,
 145                                      (c, idx, s) -> {
 146                                          ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder());
 147                                          DoubleBuffer tb = bbc.asDoubleBuffer();
 148                                          return ((DoubleSpecies)s).op(i -> tb.get());
 149                                      });
 150     }
 151 
 152     /**
 153      * Loads a vector from a byte array starting at an offset and using a
 154      * mask.
 155      * <p>
 156      * Bytes are composed into primitive lane elements according to the
 157      * native byte order of the underlying platform.
 158      * <p>
 159      * This method behaves as if it returns the result of calling the
 160      * byte buffer, offset, and mask accepting
 161      * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask) method} as follows:
 162      * <pre>{@code
 163      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
 164      * }</pre>
 165      *
 166      * @param species species of desired vector
 167      * @param a the byte array
 168      * @param ix the offset into the array
 169      * @param m the mask
 170      * @return a vector loaded from a byte array
 171      * @throws IndexOutOfBoundsException if {@code i < 0} or
 172      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
 173      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 174      * or {@code > a.length},
 175      * for any vector lane index {@code N} where the mask at lane {@code N}
 176      * is set
 177      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
 178      */
 179     @ForceInline
 180     public static DoubleVector fromByteArray(DoubleSpecies species, byte[] a, int ix, Mask<Double> m) {
 181         return zero(species).blend(fromByteArray(species, a, ix), m);
 182     }
 183 
 184     /**
 185      * Loads a vector from an array starting at offset.
 186      * <p>
 187      * For each vector lane, where {@code N} is the vector lane index, the
 188      * array element at index {@code i + N} is placed into the
 189      * resulting vector at lane index {@code N}.
 190      *
 191      * @param species species of desired vector
 192      * @param a the array
 193      * @param i the offset into the array
 194      * @return the vector loaded from an array
 195      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 196      * {@code i > a.length - this.length()}
 197      */
 198     @ForceInline
 199     @SuppressWarnings("unchecked")
 200     public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i){
 201         Objects.requireNonNull(a);
 202         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
 203         return VectorIntrinsics.load((Class<DoubleVector>) species.boxType(), double.class, species.length(),
 204                                      a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
 205                                      a, i, species,
 206                                      (c, idx, s) -> ((DoubleSpecies)s).op(n -> c[idx + n]));
 207     }
 208 
 209 
 210     /**
 211      * Loads a vector from an array starting at offset and using a mask.
 212      * <p>
 213      * For each vector lane, where {@code N} is the vector lane index,
 214      * if the mask lane at index {@code N} is set then the array element at
 215      * index {@code i + N} is placed into the resulting vector at lane index
 216      * {@code N}, otherwise the default element value is placed into the
 217      * resulting vector at lane index {@code N}.
 218      *
 219      * @param species species of desired vector
 220      * @param a the array
 221      * @param i the offset into the array
 222      * @param m the mask
 223      * @return the vector loaded from an array
 224      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 225      * for any vector lane index {@code N} where the mask at lane {@code N}
 226      * is set {@code i > a.length - N}
 227      */
 228     @ForceInline
 229     public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, Mask<Double> m) {
 230         return zero(species).blend(fromArray(species, a, i), m);
 231     }
 232 
 233     /**
 234      * Loads a vector from an array using indexes obtained from an index
 235      * map.
 236      * <p>
 237      * For each vector lane, where {@code N} is the vector lane index, the
 238      * array element at index {@code i + indexMap[j + N]} is placed into the
 239      * resulting vector at lane index {@code N}.
 240      *
 241      * @param species species of desired vector
 242      * @param a the array
 243      * @param i the offset into the array, may be negative if relative
 244      * indexes in the index map compensate to produce a value within the
 245      * array bounds
 246      * @param indexMap the index map
 247      * @param j the offset into the index map
 248      * @return the vector loaded from an array
 249      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 250      * {@code j > indexMap.length - this.length()},
 251      * or for any vector lane index {@code N} the result of
 252      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
 253      */
 254     @ForceInline
 255     @SuppressWarnings("unchecked")
 256     public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, int[] indexMap, int j) {
 257         Objects.requireNonNull(a);
 258         Objects.requireNonNull(indexMap);
 259 
 260         if (species.length() == 1) {
 261           return DoubleVector.fromArray(species, a, i + indexMap[j]);
 262         }
 263 
 264         // Index vector: vix[0:n] = k -> i + indexMap[j + i]
 265         IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
 266 
 267         vix = VectorIntrinsics.checkIndex(vix, a.length);
 268 
 269         return VectorIntrinsics.loadWithMap((Class<DoubleVector>) species.boxType(), double.class, species.length(),
 270                                             species.indexSpecies().vectorType(), a, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, vix,
 271                                             a, i, indexMap, j, species,
 272                                            (c, idx, iMap, idy, s) -> ((DoubleSpecies)s).op(n -> c[idx + iMap[idy+n]]));
 273         }
 274 
 275     /**
 276      * Loads a vector from an array using indexes obtained from an index
 277      * map and using a mask.
 278      * <p>
 279      * For each vector lane, where {@code N} is the vector lane index,
 280      * if the mask lane at index {@code N} is set then the array element at
 281      * index {@code i + indexMap[j + N]} is placed into the resulting vector
 282      * at lane index {@code N}.
 283      *
 284      * @param species species of desired vector
 285      * @param a the array
 286      * @param i the offset into the array, may be negative if relative
 287      * indexes in the index map compensate to produce a value within the
 288      * array bounds
 289      * @param m the mask
 290      * @param indexMap the index map
 291      * @param j the offset into the index map
 292      * @return the vector loaded from an array
 293      * @throws IndexOutOfBoundsException if {@code j < 0}, or
 294      * {@code j > indexMap.length - this.length()},
 295      * or for any vector lane index {@code N} where the mask at lane
 296      * {@code N} is set the result of {@code i + indexMap[j + N]} is
 297      * {@code < 0} or {@code >= a.length}
 298      */
 299     @ForceInline
 300     @SuppressWarnings("unchecked")
 301     public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, Mask<Double> m, int[] indexMap, int j) {
 302         // @@@ This can result in out of bounds errors for unset mask lanes
 303         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
 304     }
 305 
 306 
 307     /**
 308      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 309      * offset into the byte buffer.
 310      * <p>
 311      * Bytes are composed into primitive lane elements according to the
 312      * native byte order of the underlying platform.
 313      * <p>
 314      * This method behaves as if it returns the result of calling the
 315      * byte buffer, offset, and mask accepting
 316      * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask)} method} as follows:
 317      * <pre>{@code
 318      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
 319      * }</pre>
 320      *
 321      * @param species species of desired vector
 322      * @param bb the byte buffer
 323      * @param ix the offset into the byte buffer
 324      * @return a vector loaded from a byte buffer
 325      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 326      * or {@code > b.limit()},
 327      * or if there are fewer than
 328      * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
 329      * remaining in the byte buffer from the given offset
 330      */
 331     @ForceInline
 332     @SuppressWarnings("unchecked")
 333     public static DoubleVector fromByteBuffer(DoubleSpecies species, ByteBuffer bb, int ix) {
 334         if (bb.order() != ByteOrder.nativeOrder()) {
 335             throw new IllegalArgumentException();
 336         }
 337         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
 338         return VectorIntrinsics.load((Class<DoubleVector>) species.boxType(), double.class, species.length(),
 339                                      U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix,
 340                                      bb, ix, species,
 341                                      (c, idx, s) -> {
 342                                          ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder());
 343                                          DoubleBuffer tb = bbc.asDoubleBuffer();
 344                                          return ((DoubleSpecies)s).op(i -> tb.get());
 345                                      });
 346     }
 347 
 348     /**
 349      * Loads a vector from a {@link ByteBuffer byte buffer} starting at an
 350      * offset into the byte buffer and using a mask.
 351      * <p>
 352      * This method behaves as if the byte buffer is viewed as a primitive
 353      * {@link java.nio.Buffer buffer} for the primitive element type,
 354      * according to the native byte order of the underlying platform, and
 355      * the returned vector is loaded with a mask from a primitive array
 356      * obtained from the primitive buffer.
 357      * The following pseudocode expresses the behaviour, where
 358      * {@coce EBuffer} is the primitive buffer type, {@code e} is the
 359      * primitive element type, and {@code ESpecies<S>} is the primitive
 360      * species for {@code e}:
 361      * <pre>{@code
 362      * EBuffer eb = b.duplicate().
 363      *     order(ByteOrder.nativeOrder()).position(i).
 364      *     asEBuffer();
 365      * e[] es = new e[this.length()];
 366      * for (int n = 0; n < t.length; n++) {
 367      *     if (m.isSet(n))
 368      *         es[n] = eb.get(n);
 369      * }
 370      * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m);
 371      * }</pre>
 372      *
 373      * @param species species of desired vector
 374      * @param bb the byte buffer
 375      * @param ix the offset into the byte buffer
 376      * @param m the mask
 377      * @return a vector loaded from a byte buffer
 378      * @throws IndexOutOfBoundsException if the offset is {@code < 0},
 379      * or {@code > b.limit()},
 380      * for any vector lane index {@code N} where the mask at lane {@code N}
 381      * is set
 382      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
 383      */
 384     @ForceInline
 385     public static DoubleVector fromByteBuffer(DoubleSpecies species, ByteBuffer bb, int ix, Mask<Double> m) {
 386         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
 387     }
 388 
 389     /**
 390      * Returns a mask where each lane is set or unset according to given
 391      * {@code boolean} values
 392      * <p>
 393      * For each mask lane, where {@code N} is the mask lane index,
 394      * if the given {@code boolean} value at index {@code N} is {@code true}
 395      * then the mask lane at index {@code N} is set, otherwise it is unset.
 396      *
 397      * @param species mask species
 398      * @param bits the given {@code boolean} values
 399      * @return a mask where each lane is set or unset according to the given {@code boolean} value
 400      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
 401      */
 402     @ForceInline
 403     public static Mask<Double> maskFromValues(DoubleSpecies species, boolean... bits) {
 404         if (species.boxType() == DoubleMaxVector.class)
 405             return new DoubleMaxVector.DoubleMaxMask(bits);
 406         switch (species.bitSize()) {
 407             case 64: return new Double64Vector.Double64Mask(bits);
 408             case 128: return new Double128Vector.Double128Mask(bits);
 409             case 256: return new Double256Vector.Double256Mask(bits);
 410             case 512: return new Double512Vector.Double512Mask(bits);
 411             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 412         }
 413     }
 414 
 415     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
 416     static Mask<Double> trueMask(DoubleSpecies species) {
 417         if (species.boxType() == DoubleMaxVector.class)
 418             return DoubleMaxVector.DoubleMaxMask.TRUE_MASK;
 419         switch (species.bitSize()) {
 420             case 64: return Double64Vector.Double64Mask.TRUE_MASK;
 421             case 128: return Double128Vector.Double128Mask.TRUE_MASK;
 422             case 256: return Double256Vector.Double256Mask.TRUE_MASK;
 423             case 512: return Double512Vector.Double512Mask.TRUE_MASK;
 424             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 425         }
 426     }
 427 
 428     static Mask<Double> falseMask(DoubleSpecies species) {
 429         if (species.boxType() == DoubleMaxVector.class)
 430             return DoubleMaxVector.DoubleMaxMask.FALSE_MASK;
 431         switch (species.bitSize()) {
 432             case 64: return Double64Vector.Double64Mask.FALSE_MASK;
 433             case 128: return Double128Vector.Double128Mask.FALSE_MASK;
 434             case 256: return Double256Vector.Double256Mask.FALSE_MASK;
 435             case 512: return Double512Vector.Double512Mask.FALSE_MASK;
 436             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 437         }
 438     }
 439 
 440     /**
 441      * Loads a mask from a {@code boolean} array starting at an offset.
 442      * <p>
 443      * For each mask lane, where {@code N} is the mask lane index,
 444      * if the array element at index {@code i + N} is {@code true} then the
 445      * mask lane at index {@code N} is set, otherwise it is unset.
 446      *
 447      * @param species mask species
 448      * @param bits the {@code boolean} array
 449      * @param ix the offset into the array
 450      * @return the mask loaded from a {@code boolean} array
 451      * @throws IndexOutOfBoundsException if {@code ix < 0}, or
 452      * {@code ix > bits.length - species.length()}
 453      */
 454     @ForceInline
 455     @SuppressWarnings("unchecked")
 456     public static Mask<Double> maskFromArray(DoubleSpecies species, boolean[] bits, int ix) {
 457         Objects.requireNonNull(bits);
 458         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
 459         return VectorIntrinsics.load((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
 460                                      bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
 461                                      bits, ix, species,
 462                                      (c, idx, s) -> (Mask<Double>) ((DoubleSpecies)s).opm(n -> c[idx + n]));
 463     }
 464 
 465     /**
 466      * Returns a mask where all lanes are a set.
 467      *
 468      * @param species mask species
 469      * @return a mask where all lanes are a set
 470      */
 471     @ForceInline
 472     @SuppressWarnings("unchecked")
 473     public static Mask<Double> maskAllTrue(DoubleSpecies species) {
 474         return VectorIntrinsics.broadcastCoerced((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
 475                                                  (long)-1,  species,
 476                                                  ((z, s) -> trueMask((DoubleSpecies)s)));
 477     }
 478 
 479     /**
 480      * Returns a mask where all lanes are a unset.
 481      *
 482      * @param species mask species
 483      * @return a mask where all lanes are a unset
 484      */
 485     @ForceInline
 486     @SuppressWarnings("unchecked")
 487     public static Mask<Double> maskAllFalse(DoubleSpecies species) {
 488         return VectorIntrinsics.broadcastCoerced((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
 489                                                  0, species, 
 490                                                  ((z, s) -> falseMask((DoubleSpecies)s)));
 491     }
 492 
 493     /**
 494      * Returns a shuffle of mapped indexes where each lane element is
 495      * the result of applying a mapping function to the corresponding lane
 496      * index.
 497      * <p>
 498      * Care should be taken to ensure Shuffle values produced from this
 499      * method are consumed as constants to ensure optimal generation of
 500      * code.  For example, values held in static final fields or values
 501      * held in loop constant local variables.
 502      * <p>
 503      * This method behaves as if a shuffle is created from an array of
 504      * mapped indexes as follows:
 505      * <pre>{@code
 506      *   int[] a = new int[species.length()];
 507      *   for (int i = 0; i < a.length; i++) {
 508      *       a[i] = f.applyAsInt(i);
 509      *   }
 510      *   return this.shuffleFromValues(a);
 511      * }</pre>
 512      *
 513      * @param species shuffle species
 514      * @param f the lane index mapping function
 515      * @return a shuffle of mapped indexes
 516      */
 517     @ForceInline
 518     public static Shuffle<Double> shuffle(DoubleSpecies species, IntUnaryOperator f) {
 519         if (species.boxType() == DoubleMaxVector.class)
 520             return new DoubleMaxVector.DoubleMaxShuffle(f);
 521         switch (species.bitSize()) {
 522             case 64: return new Double64Vector.Double64Shuffle(f);
 523             case 128: return new Double128Vector.Double128Shuffle(f);
 524             case 256: return new Double256Vector.Double256Shuffle(f);
 525             case 512: return new Double512Vector.Double512Shuffle(f);
 526             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 527         }
 528     }
 529 
 530     /**
 531      * Returns a shuffle where each lane element is the value of its
 532      * corresponding lane index.
 533      * <p>
 534      * This method behaves as if a shuffle is created from an identity
 535      * index mapping function as follows:
 536      * <pre>{@code
 537      *   return this.shuffle(i -> i);
 538      * }</pre>
 539      *
 540      * @param species shuffle species
 541      * @return a shuffle of lane indexes
 542      */
 543     @ForceInline
 544     public static Shuffle<Double> shuffleIota(DoubleSpecies species) {
 545         if (species.boxType() == DoubleMaxVector.class)
 546             return new DoubleMaxVector.DoubleMaxShuffle(AbstractShuffle.IDENTITY);
 547         switch (species.bitSize()) {
 548             case 64: return new Double64Vector.Double64Shuffle(AbstractShuffle.IDENTITY);
 549             case 128: return new Double128Vector.Double128Shuffle(AbstractShuffle.IDENTITY);
 550             case 256: return new Double256Vector.Double256Shuffle(AbstractShuffle.IDENTITY);
 551             case 512: return new Double512Vector.Double512Shuffle(AbstractShuffle.IDENTITY);
 552             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 553         }
 554     }
 555 
 556     /**
 557      * Returns a shuffle where each lane element is set to a given
 558      * {@code int} value logically AND'ed by the species length minus one.
 559      * <p>
 560      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 561      * the {@code int} value at index {@code N} logically AND'ed by
 562      * {@code species.length() - 1} is placed into the resulting shuffle at
 563      * lane index {@code N}.
 564      *
 565      * @param species shuffle species
 566      * @param ixs the given {@code int} values
 567      * @return a shuffle where each lane element is set to a given
 568      * {@code int} value
 569      * @throws IndexOutOfBoundsException if the number of int values is
 570      * {@code < species.length()}
 571      */
 572     @ForceInline
 573     public static Shuffle<Double> shuffleFromValues(DoubleSpecies species, int... ixs) {
 574         if (species.boxType() == DoubleMaxVector.class)
 575             return new DoubleMaxVector.DoubleMaxShuffle(ixs);
 576         switch (species.bitSize()) {
 577             case 64: return new Double64Vector.Double64Shuffle(ixs);
 578             case 128: return new Double128Vector.Double128Shuffle(ixs);
 579             case 256: return new Double256Vector.Double256Shuffle(ixs);
 580             case 512: return new Double512Vector.Double512Shuffle(ixs);
 581             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 582         }
 583     }
 584 
 585     /**
 586      * Loads a shuffle from an {@code int} array starting at an offset.
 587      * <p>
 588      * For each shuffle lane, where {@code N} is the shuffle lane index, the
 589      * array element at index {@code i + N} logically AND'ed by
 590      * {@code species.length() - 1} is placed into the resulting shuffle at lane
 591      * index {@code N}.
 592      *
 593      * @param species shuffle species
 594      * @param ixs the {@code int} array
 595      * @param i the offset into the array
 596      * @return a shuffle loaded from the {@code int} array
 597      * @throws IndexOutOfBoundsException if {@code i < 0}, or
 598      * {@code i > a.length - species.length()}
 599      */
 600     @ForceInline
 601     public static Shuffle<Double> shuffleFromArray(DoubleSpecies species, int[] ixs, int i) {
 602         if (species.boxType() == DoubleMaxVector.class)
 603             return new DoubleMaxVector.DoubleMaxShuffle(ixs, i);
 604         switch (species.bitSize()) {
 605             case 64: return new Double64Vector.Double64Shuffle(ixs, i);
 606             case 128: return new Double128Vector.Double128Shuffle(ixs, i);
 607             case 256: return new Double256Vector.Double256Shuffle(ixs, i);
 608             case 512: return new Double512Vector.Double512Shuffle(ixs, i);
 609             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
 610         }
 611     }
 612 
 613 
 614     // Ops
 615 
 616     @Override
 617     public abstract DoubleVector add(Vector<Double> v);
 618 
 619     /**
 620      * Adds this vector to the broadcast of an input scalar.
 621      * <p>
 622      * This is a vector binary operation where the primitive addition operation
 623      * ({@code +}) is applied to lane elements.
 624      *
 625      * @param s the input scalar
 626      * @return the result of adding this vector to the broadcast of an input
 627      * scalar
 628      */
 629     public abstract DoubleVector add(double s);
 630 
 631     @Override
 632     public abstract DoubleVector add(Vector<Double> v, Mask<Double> m);
 633 
 634     /**
 635      * Adds this vector to broadcast of an input scalar,
 636      * selecting lane elements controlled by a mask.
 637      * <p>
 638      * This is a vector binary operation where the primitive addition operation
 639      * ({@code +}) is applied to lane elements.
 640      *
 641      * @param s the input scalar
 642      * @param m the mask controlling lane selection
 643      * @return the result of adding this vector to the broadcast of an input
 644      * scalar
 645      */
 646     public abstract DoubleVector add(double s, Mask<Double> m);
 647 
 648     @Override
 649     public abstract DoubleVector sub(Vector<Double> v);
 650 
 651     /**
 652      * Subtracts the broadcast of an input scalar from this vector.
 653      * <p>
 654      * This is a vector binary operation where the primitive subtraction
 655      * operation ({@code -}) is applied to lane elements.
 656      *
 657      * @param s the input scalar
 658      * @return the result of subtracting the broadcast of an input
 659      * scalar from this vector
 660      */
 661     public abstract DoubleVector sub(double s);
 662 
 663     @Override
 664     public abstract DoubleVector sub(Vector<Double> v, Mask<Double> m);
 665 
 666     /**
 667      * Subtracts the broadcast of an input scalar from this vector, selecting
 668      * lane elements controlled by a mask.
 669      * <p>
 670      * This is a vector binary operation where the primitive subtraction
 671      * operation ({@code -}) is applied to lane elements.
 672      *
 673      * @param s the input scalar
 674      * @param m the mask controlling lane selection
 675      * @return the result of subtracting the broadcast of an input
 676      * scalar from this vector
 677      */
 678     public abstract DoubleVector sub(double s, Mask<Double> m);
 679 
 680     @Override
 681     public abstract DoubleVector mul(Vector<Double> v);
 682 
 683     /**
 684      * Multiplies this vector with the broadcast of an input scalar.
 685      * <p>
 686      * This is a vector binary operation where the primitive multiplication
 687      * operation ({@code *}) is applied to lane elements.
 688      *
 689      * @param s the input scalar
 690      * @return the result of multiplying this vector with the broadcast of an
 691      * input scalar
 692      */
 693     public abstract DoubleVector mul(double s);
 694 
 695     @Override
 696     public abstract DoubleVector mul(Vector<Double> v, Mask<Double> m);
 697 
 698     /**
 699      * Multiplies this vector with the broadcast of an input scalar, selecting
 700      * lane elements controlled by a mask.
 701      * <p>
 702      * This is a vector binary operation where the primitive multiplication
 703      * operation ({@code *}) is applied to lane elements.
 704      *
 705      * @param s the input scalar
 706      * @param m the mask controlling lane selection
 707      * @return the result of multiplying this vector with the broadcast of an
 708      * input scalar
 709      */
 710     public abstract DoubleVector mul(double s, Mask<Double> m);
 711 
 712     @Override
 713     public abstract DoubleVector neg();
 714 
 715     @Override
 716     public abstract DoubleVector neg(Mask<Double> m);
 717 
 718     @Override
 719     public abstract DoubleVector abs();
 720 
 721     @Override
 722     public abstract DoubleVector abs(Mask<Double> m);
 723 
 724     @Override
 725     public abstract DoubleVector min(Vector<Double> v);
 726 
 727     @Override
 728     public abstract DoubleVector min(Vector<Double> v, Mask<Double> m);
 729 
 730     /**
 731      * Returns the minimum of this vector and the broadcast of an input scalar.
 732      * <p>
 733      * This is a vector binary operation where the operation
 734      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements.
 735      *
 736      * @param s the input scalar
 737      * @return the minimum of this vector and the broadcast of an input scalar
 738      */
 739     public abstract DoubleVector min(double s);
 740 
 741     @Override
 742     public abstract DoubleVector max(Vector<Double> v);
 743 
 744     @Override
 745     public abstract DoubleVector max(Vector<Double> v, Mask<Double> m);
 746 
 747     /**
 748      * Returns the maximum of this vector and the broadcast of an input scalar.
 749      * <p>
 750      * This is a vector binary operation where the operation
 751      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements.
 752      *
 753      * @param s the input scalar
 754      * @return the maximum of this vector and the broadcast of an input scalar
 755      */
 756     public abstract DoubleVector max(double s);
 757 
 758     @Override
 759     public abstract Mask<Double> equal(Vector<Double> v);
 760 
 761     /**
 762      * Tests if this vector is equal to the broadcast of an input scalar.
 763      * <p>
 764      * This is a vector binary test operation where the primitive equals
 765      * operation ({@code ==}) is applied to lane elements.
 766      *
 767      * @param s the input scalar
 768      * @return the result mask of testing if this vector is equal to the
 769      * broadcast of an input scalar
 770      */
 771     public abstract Mask<Double> equal(double s);
 772 
 773     @Override
 774     public abstract Mask<Double> notEqual(Vector<Double> v);
 775 
 776     /**
 777      * Tests if this vector is not equal to the broadcast of an input scalar.
 778      * <p>
 779      * This is a vector binary test operation where the primitive not equals
 780      * operation ({@code !=}) is applied to lane elements.
 781      *
 782      * @param s the input scalar
 783      * @return the result mask of testing if this vector is not equal to the
 784      * broadcast of an input scalar
 785      */
 786     public abstract Mask<Double> notEqual(double s);
 787 
 788     @Override
 789     public abstract Mask<Double> lessThan(Vector<Double> v);
 790 
 791     /**
 792      * Tests if this vector is less than the broadcast of an input scalar.
 793      * <p>
 794      * This is a vector binary test operation where the primitive less than
 795      * operation ({@code <}) is applied to lane elements.
 796      *
 797      * @param s the input scalar
 798      * @return the mask result of testing if this vector is less than the
 799      * broadcast of an input scalar
 800      */
 801     public abstract Mask<Double> lessThan(double s);
 802 
 803     @Override
 804     public abstract Mask<Double> lessThanEq(Vector<Double> v);
 805 
 806     /**
 807      * Tests if this vector is less or equal to the broadcast of an input scalar.
 808      * <p>
 809      * This is a vector binary test operation where the primitive less than
 810      * or equal to operation ({@code <=}) is applied to lane elements.
 811      *
 812      * @param s the input scalar
 813      * @return the mask result of testing if this vector is less than or equal
 814      * to the broadcast of an input scalar
 815      */
 816     public abstract Mask<Double> lessThanEq(double s);
 817 
 818     @Override
 819     public abstract Mask<Double> greaterThan(Vector<Double> v);
 820 
 821     /**
 822      * Tests if this vector is greater than the broadcast of an input scalar.
 823      * <p>
 824      * This is a vector binary test operation where the primitive greater than
 825      * operation ({@code >}) is applied to lane elements.
 826      *
 827      * @param s the input scalar
 828      * @return the mask result of testing if this vector is greater than the
 829      * broadcast of an input scalar
 830      */
 831     public abstract Mask<Double> greaterThan(double s);
 832 
 833     @Override
 834     public abstract Mask<Double> greaterThanEq(Vector<Double> v);
 835 
 836     /**
 837      * Tests if this vector is greater than or equal to the broadcast of an
 838      * input scalar.
 839      * <p>
 840      * This is a vector binary test operation where the primitive greater than
 841      * or equal to operation ({@code >=}) is applied to lane elements.
 842      *
 843      * @param s the input scalar
 844      * @return the mask result of testing if this vector is greater than or
 845      * equal to the broadcast of an input scalar
 846      */
 847     public abstract Mask<Double> greaterThanEq(double s);
 848 
 849     @Override
 850     public abstract DoubleVector blend(Vector<Double> v, Mask<Double> m);
 851 
 852     /**
 853      * Blends the lane elements of this vector with those of the broadcast of an
 854      * input scalar, selecting lanes controlled by a mask.
 855      * <p>
 856      * For each lane of the mask, at lane index {@code N}, if the mask lane
 857      * is set then the lane element at {@code N} from the input vector is
 858      * selected and placed into the resulting vector at {@code N},
 859      * otherwise the the lane element at {@code N} from this input vector is
 860      * selected and placed into the resulting vector at {@code N}.
 861      *
 862      * @param s the input scalar
 863      * @param m the mask controlling lane selection
 864      * @return the result of blending the lane elements of this vector with
 865      * those of the broadcast of an input scalar
 866      */
 867     public abstract DoubleVector blend(double s, Mask<Double> m);
 868 
 869     @Override
 870     public abstract DoubleVector rearrange(Vector<Double> v,
 871                                                       Shuffle<Double> s, Mask<Double> m);
 872 
 873     @Override
 874     public abstract DoubleVector rearrange(Shuffle<Double> m);
 875 
 876     @Override
 877     public abstract DoubleVector reshape(Species<Double> s);
 878 
 879     @Override
 880     public abstract DoubleVector rotateEL(int i);
 881 
 882     @Override
 883     public abstract DoubleVector rotateER(int i);
 884 
 885     @Override
 886     public abstract DoubleVector shiftEL(int i);
 887 
 888     @Override
 889     public abstract DoubleVector shiftER(int i);
 890 
 891     /**
 892      * Divides this vector by an input vector.
 893      * <p>
 894      * This is a vector binary operation where the primitive division
 895      * operation ({@code /}) is applied to lane elements.
 896      *
 897      * @param v the input vector
 898      * @return the result of dividing this vector by the input vector
 899      */
 900     public abstract DoubleVector div(Vector<Double> v);
 901 
 902     /**
 903      * Divides this vector by the broadcast of an input scalar.
 904      * <p>
 905      * This is a vector binary operation where the primitive division
 906      * operation ({@code /}) is applied to lane elements.
 907      *
 908      * @param s the input scalar
 909      * @return the result of dividing this vector by the broadcast of an input
 910      * scalar
 911      */
 912     public abstract DoubleVector div(double s);
 913 
 914     /**
 915      * Divides this vector by an input vector, selecting lane elements
 916      * controlled by a mask.
 917      * <p>
 918      * This is a vector binary operation where the primitive division
 919      * operation ({@code /}) is applied to lane elements.
 920      *
 921      * @param v the input vector
 922      * @param m the mask controlling lane selection
 923      * @return the result of dividing this vector by the input vector
 924      */
 925     public abstract DoubleVector div(Vector<Double> v, Mask<Double> m);
 926 
 927     /**
 928      * Divides this vector by the broadcast of an input scalar, selecting lane
 929      * elements controlled by a mask.
 930      * <p>
 931      * This is a vector binary operation where the primitive division
 932      * operation ({@code /}) is applied to lane elements.
 933      *
 934      * @param s the input scalar
 935      * @param m the mask controlling lane selection
 936      * @return the result of dividing this vector by the broadcast of an input
 937      * scalar
 938      */
 939     public abstract DoubleVector div(double s, Mask<Double> m);
 940 
 941     /**
 942      * Calculates the square root of this vector.
 943      * <p>
 944      * This is a vector unary operation where the {@link Math#sqrt} operation
 945      * is applied to lane elements.
 946      *
 947      * @return the square root of this vector
 948      */
 949     public abstract DoubleVector sqrt();
 950 
 951     /**
 952      * Calculates the square root of this vector, selecting lane elements
 953      * controlled by a mask.
 954      * <p>
 955      * This is a vector unary operation where the {@link Math#sqrt} operation
 956      * is applied to lane elements.
 957      *
 958      * @param m the mask controlling lane selection
 959      * @return the square root of this vector
 960      */
 961     public DoubleVector sqrt(Mask<Double> m) {
 962         return uOp(m, (i, a) -> (double) Math.sqrt((double) a));
 963     }
 964 
 965     /**
 966      * Calculates the trigonometric tangent of this vector.
 967      * <p>
 968      * This is a vector unary operation with same semantic definition as
 969      * {@link Math#tan} operation applied to lane elements.
 970      * The implementation is not required to return same
 971      * results as {@link Math#tan}, but adheres to rounding, monotonicity,
 972      * and special case semantics as defined in the {@link Math#tan}
 973      * specifications. The computed result will be within 1 ulp of the
 974      * exact result.
 975      *
 976      * @return the tangent of this vector
 977      */
 978     public DoubleVector tan() {
 979         return uOp((i, a) -> (double) Math.tan((double) a));
 980     }
 981 
 982     /**
 983      * Calculates the trigonometric tangent of this vector, selecting lane
 984      * elements controlled by a mask.
 985      * <p>
 986      * Semantics for rounding, monotonicity, and special cases are
 987      * described in {@link DoubleVector#tan}
 988      *
 989      * @param m the mask controlling lane selection
 990      * @return the tangent of this vector
 991      */
 992     public DoubleVector tan(Mask<Double> m) {
 993         return uOp(m, (i, a) -> (double) Math.tan((double) a));
 994     }
 995 
 996     /**
 997      * Calculates the hyperbolic tangent of this vector.
 998      * <p>
 999      * This is a vector unary operation with same semantic definition as
1000      * {@link Math#tanh} operation applied to lane elements.
1001      * The implementation is not required to return same
1002      * results as {@link Math#tanh}, but adheres to rounding, monotonicity,
1003      * and special case semantics as defined in the {@link Math#tanh}
1004      * specifications. The computed result will be within 2.5 ulps of the
1005      * exact result.
1006      *
1007      * @return the hyperbolic tangent of this vector
1008      */
1009     public DoubleVector tanh() {
1010         return uOp((i, a) -> (double) Math.tanh((double) a));
1011     }
1012 
1013     /**
1014      * Calculates the hyperbolic tangent of this vector, selecting lane elements
1015      * controlled by a mask.
1016      * <p>
1017      * Semantics for rounding, monotonicity, and special cases are
1018      * described in {@link DoubleVector#tanh}
1019      *
1020      * @param m the mask controlling lane selection
1021      * @return the hyperbolic tangent of this vector
1022      */
1023     public DoubleVector tanh(Mask<Double> m) {
1024         return uOp(m, (i, a) -> (double) Math.tanh((double) a));
1025     }
1026 
1027     /**
1028      * Calculates the trigonometric sine of this vector.
1029      * <p>
1030      * This is a vector unary operation with same semantic definition as
1031      * {@link Math#sin} operation applied to lane elements.
1032      * The implementation is not required to return same
1033      * results as {@link Math#sin}, but adheres to rounding, monotonicity,
1034      * and special case semantics as defined in the {@link Math#sin}
1035      * specifications. The computed result will be within 1 ulp of the
1036      * exact result.
1037      *
1038      * @return the sine of this vector
1039      */
1040     public DoubleVector sin() {
1041         return uOp((i, a) -> (double) Math.sin((double) a));
1042     }
1043 
1044     /**
1045      * Calculates the trigonometric sine of this vector, selecting lane elements
1046      * controlled by a mask.
1047      * <p>
1048      * Semantics for rounding, monotonicity, and special cases are
1049      * described in {@link DoubleVector#sin}
1050      *
1051      * @param m the mask controlling lane selection
1052      * @return the sine of this vector
1053      */
1054     public DoubleVector sin(Mask<Double> m) {
1055         return uOp(m, (i, a) -> (double) Math.sin((double) a));
1056     }
1057 
1058     /**
1059      * Calculates the hyperbolic sine of this vector.
1060      * <p>
1061      * This is a vector unary operation with same semantic definition as
1062      * {@link Math#sinh} operation applied to lane elements.
1063      * The implementation is not required to return same
1064      * results as  {@link Math#sinh}, but adheres to rounding, monotonicity,
1065      * and special case semantics as defined in the {@link Math#sinh}
1066      * specifications. The computed result will be within 2.5 ulps of the
1067      * exact result.
1068      *
1069      * @return the hyperbolic sine of this vector
1070      */
1071     public DoubleVector sinh() {
1072         return uOp((i, a) -> (double) Math.sinh((double) a));
1073     }
1074 
1075     /**
1076      * Calculates the hyperbolic sine of this vector, selecting lane elements
1077      * controlled by a mask.
1078      * <p>
1079      * Semantics for rounding, monotonicity, and special cases are
1080      * described in {@link DoubleVector#sinh}
1081      *
1082      * @param m the mask controlling lane selection
1083      * @return the hyperbolic sine of this vector
1084      */
1085     public DoubleVector sinh(Mask<Double> m) {
1086         return uOp(m, (i, a) -> (double) Math.sinh((double) a));
1087     }
1088 
1089     /**
1090      * Calculates the trigonometric cosine of this vector.
1091      * <p>
1092      * This is a vector unary operation with same semantic definition as
1093      * {@link Math#cos} operation applied to lane elements.
1094      * The implementation is not required to return same
1095      * results as {@link Math#cos}, but adheres to rounding, monotonicity,
1096      * and special case semantics as defined in the {@link Math#cos}
1097      * specifications. The computed result will be within 1 ulp of the
1098      * exact result.
1099      *
1100      * @return the cosine of this vector
1101      */
1102     public DoubleVector cos() {
1103         return uOp((i, a) -> (double) Math.cos((double) a));
1104     }
1105 
1106     /**
1107      * Calculates the trigonometric cosine of this vector, selecting lane
1108      * elements controlled by a mask.
1109      * <p>
1110      * Semantics for rounding, monotonicity, and special cases are
1111      * described in {@link DoubleVector#cos}
1112      *
1113      * @param m the mask controlling lane selection
1114      * @return the cosine of this vector
1115      */
1116     public DoubleVector cos(Mask<Double> m) {
1117         return uOp(m, (i, a) -> (double) Math.cos((double) a));
1118     }
1119 
1120     /**
1121      * Calculates the hyperbolic cosine of this vector.
1122      * <p>
1123      * This is a vector unary operation with same semantic definition as
1124      * {@link Math#cosh} operation applied to lane elements.
1125      * The implementation is not required to return same
1126      * results as {@link Math#cosh}, but adheres to rounding, monotonicity,
1127      * and special case semantics as defined in the {@link Math#cosh}
1128      * specifications. The computed result will be within 2.5 ulps of the
1129      * exact result.
1130      *
1131      * @return the hyperbolic cosine of this vector
1132      */
1133     public DoubleVector cosh() {
1134         return uOp((i, a) -> (double) Math.cosh((double) a));
1135     }
1136 
1137     /**
1138      * Calculates the hyperbolic cosine of this vector, selecting lane elements
1139      * controlled by a mask.
1140      * <p>
1141      * Semantics for rounding, monotonicity, and special cases are
1142      * described in {@link DoubleVector#cosh}
1143      *
1144      * @param m the mask controlling lane selection
1145      * @return the hyperbolic cosine of this vector
1146      */
1147     public DoubleVector cosh(Mask<Double> m) {
1148         return uOp(m, (i, a) -> (double) Math.cosh((double) a));
1149     }
1150 
1151     /**
1152      * Calculates the arc sine of this vector.
1153      * <p>
1154      * This is a vector unary operation with same semantic definition as
1155      * {@link Math#asin} operation applied to lane elements.
1156      * The implementation is not required to return same
1157      * results as {@link Math#asin}, but adheres to rounding, monotonicity,
1158      * and special case semantics as defined in the {@link Math#asin}
1159      * specifications. The computed result will be within 1 ulp of the
1160      * exact result.
1161      *
1162      * @return the arc sine of this vector
1163      */
1164     public DoubleVector asin() {
1165         return uOp((i, a) -> (double) Math.asin((double) a));
1166     }
1167 
1168     /**
1169      * Calculates the arc sine of this vector, selecting lane elements
1170      * controlled by a mask.
1171      * <p>
1172      * Semantics for rounding, monotonicity, and special cases are
1173      * described in {@link DoubleVector#asin}
1174      *
1175      * @param m the mask controlling lane selection
1176      * @return the arc sine of this vector
1177      */
1178     public DoubleVector asin(Mask<Double> m) {
1179         return uOp(m, (i, a) -> (double) Math.asin((double) a));
1180     }
1181 
1182     /**
1183      * Calculates the arc cosine of this vector.
1184      * <p>
1185      * This is a vector unary operation with same semantic definition as
1186      * {@link Math#acos} operation applied to lane elements.
1187      * The implementation is not required to return same
1188      * results as {@link Math#acos}, but adheres to rounding, monotonicity,
1189      * and special case semantics as defined in the {@link Math#acos}
1190      * specifications. The computed result will be within 1 ulp of the
1191      * exact result.
1192      *
1193      * @return the arc cosine of this vector
1194      */
1195     public DoubleVector acos() {
1196         return uOp((i, a) -> (double) Math.acos((double) a));
1197     }
1198 
1199     /**
1200      * Calculates the arc cosine of this vector, selecting lane elements
1201      * controlled by a mask.
1202      * <p>
1203      * Semantics for rounding, monotonicity, and special cases are
1204      * described in {@link DoubleVector#acos}
1205      *
1206      * @param m the mask controlling lane selection
1207      * @return the arc cosine of this vector
1208      */
1209     public DoubleVector acos(Mask<Double> m) {
1210         return uOp(m, (i, a) -> (double) Math.acos((double) a));
1211     }
1212 
1213     /**
1214      * Calculates the arc tangent of this vector.
1215      * <p>
1216      * This is a vector unary operation with same semantic definition as
1217      * {@link Math#atan} operation applied to lane elements.
1218      * The implementation is not required to return same
1219      * results as {@link Math#atan}, but adheres to rounding, monotonicity,
1220      * and special case semantics as defined in the {@link Math#atan}
1221      * specifications. The computed result will be within 1 ulp of the
1222      * exact result.
1223      *
1224      * @return the arc tangent of this vector
1225      */
1226     public DoubleVector atan() {
1227         return uOp((i, a) -> (double) Math.atan((double) a));
1228     }
1229 
1230     /**
1231      * Calculates the arc tangent of this vector, selecting lane elements
1232      * controlled by a mask.
1233      * <p>
1234      * Semantics for rounding, monotonicity, and special cases are
1235      * described in {@link DoubleVector#atan}
1236      *
1237      * @param m the mask controlling lane selection
1238      * @return the arc tangent of this vector
1239      */
1240     public DoubleVector atan(Mask<Double> m) {
1241         return uOp(m, (i, a) -> (double) Math.atan((double) a));
1242     }
1243 
1244     /**
1245      * Calculates the arc tangent of this vector divided by an input vector.
1246      * <p>
1247      * This is a vector binary operation with same semantic definition as
1248      * {@link Math#atan2} operation applied to lane elements.
1249      * The implementation is not required to return same
1250      * results as {@link Math#atan2}, but adheres to rounding, monotonicity,
1251      * and special case semantics as defined in the {@link Math#atan2}
1252      * specifications. The computed result will be within 2 ulps of the
1253      * exact result.
1254      *
1255      * @param v the input vector
1256      * @return the arc tangent of this vector divided by the input vector
1257      */
1258     public DoubleVector atan2(Vector<Double> v) {
1259         return bOp(v, (i, a, b) -> (double) Math.atan2((double) a, (double) b));
1260     }
1261 
1262     /**
1263      * Calculates the arc tangent of this vector divided by the broadcast of an
1264      * an input scalar.
1265      * <p>
1266      * This is a vector binary operation with same semantic definition as
1267      * {@link Math#atan2} operation applied to lane elements.
1268      * The implementation is not required to return same
1269      * results as {@link Math#atan2}, but adheres to rounding, monotonicity,
1270      * and special case semantics as defined in the {@link Math#atan2}
1271      * specifications. The computed result will be within 1 ulp of the
1272      * exact result.
1273      *
1274      * @param s the input scalar
1275      * @return the arc tangent of this vector over the input vector
1276      */
1277     public abstract DoubleVector atan2(double s);
1278 
1279     /**
1280      * Calculates the arc tangent of this vector divided by an input vector,
1281      * selecting lane elements controlled by a mask.
1282      * <p>
1283      * Semantics for rounding, monotonicity, and special cases are
1284      * described in {@link DoubleVector#atan2}
1285      *
1286      * @param v the input vector
1287      * @param m the mask controlling lane selection
1288      * @return the arc tangent of this vector divided by the input vector
1289      */
1290     public DoubleVector atan2(Vector<Double> v, Mask<Double> m) {
1291         return bOp(v, m, (i, a, b) -> (double) Math.atan2((double) a, (double) b));
1292     }
1293 
1294     /**
1295      * Calculates the arc tangent of this vector divided by the broadcast of an
1296      * an input scalar, selecting lane elements controlled by a mask.
1297      * <p>
1298      * Semantics for rounding, monotonicity, and special cases are
1299      * described in {@link DoubleVector#atan2}
1300      *
1301      * @param s the input scalar
1302      * @param m the mask controlling lane selection
1303      * @return the arc tangent of this vector over the input vector
1304      */
1305     public abstract DoubleVector atan2(double s, Mask<Double> m);
1306 
1307     /**
1308      * Calculates the cube root of this vector.
1309      * <p>
1310      * This is a vector unary operation with same semantic definition as
1311      * {@link Math#cbrt} operation applied to lane elements.
1312      * The implementation is not required to return same
1313      * results as {@link Math#cbrt}, but adheres to rounding, monotonicity,
1314      * and special case semantics as defined in the {@link Math#cbrt}
1315      * specifications. The computed result will be within 1 ulp of the
1316      * exact result.
1317      *
1318      * @return the cube root of this vector
1319      */
1320     public DoubleVector cbrt() {
1321         return uOp((i, a) -> (double) Math.cbrt((double) a));
1322     }
1323 
1324     /**
1325      * Calculates the cube root of this vector, selecting lane elements
1326      * controlled by a mask.
1327      * <p>
1328      * Semantics for rounding, monotonicity, and special cases are
1329      * described in {@link DoubleVector#cbrt}
1330      *
1331      * @param m the mask controlling lane selection
1332      * @return the cube root of this vector
1333      */
1334     public DoubleVector cbrt(Mask<Double> m) {
1335         return uOp(m, (i, a) -> (double) Math.cbrt((double) a));
1336     }
1337 
1338     /**
1339      * Calculates the natural logarithm of this vector.
1340      * <p>
1341      * This is a vector unary operation with same semantic definition as
1342      * {@link Math#log} operation applied to lane elements.
1343      * The implementation is not required to return same
1344      * results as {@link Math#log}, but adheres to rounding, monotonicity,
1345      * and special case semantics as defined in the {@link Math#log}
1346      * specifications. The computed result will be within 1 ulp of the
1347      * exact result.
1348      *
1349      * @return the natural logarithm of this vector
1350      */
1351     public DoubleVector log() {
1352         return uOp((i, a) -> (double) Math.log((double) a));
1353     }
1354 
1355     /**
1356      * Calculates the natural logarithm of this vector, selecting lane elements
1357      * controlled by a mask.
1358      * <p>
1359      * Semantics for rounding, monotonicity, and special cases are
1360      * described in {@link DoubleVector#log}
1361      *
1362      * @param m the mask controlling lane selection
1363      * @return the natural logarithm of this vector
1364      */
1365     public DoubleVector log(Mask<Double> m) {
1366         return uOp(m, (i, a) -> (double) Math.log((double) a));
1367     }
1368 
1369     /**
1370      * Calculates the base 10 logarithm of this vector.
1371      * <p>
1372      * This is a vector unary operation with same semantic definition as
1373      * {@link Math#log10} operation applied to lane elements.
1374      * The implementation is not required to return same
1375      * results as {@link Math#log10}, but adheres to rounding, monotonicity,
1376      * and special case semantics as defined in the {@link Math#log10}
1377      * specifications. The computed result will be within 1 ulp of the
1378      * exact result.
1379      *
1380      * @return the base 10 logarithm of this vector
1381      */
1382     public DoubleVector log10() {
1383         return uOp((i, a) -> (double) Math.log10((double) a));
1384     }
1385 
1386     /**
1387      * Calculates the base 10 logarithm of this vector, selecting lane elements
1388      * controlled by a mask.
1389      * <p>
1390      * Semantics for rounding, monotonicity, and special cases are
1391      * described in {@link DoubleVector#log10}
1392      *
1393      * @param m the mask controlling lane selection
1394      * @return the base 10 logarithm of this vector
1395      */
1396     public DoubleVector log10(Mask<Double> m) {
1397         return uOp(m, (i, a) -> (double) Math.log10((double) a));
1398     }
1399 
1400     /**
1401      * Calculates the natural logarithm of the sum of this vector and the
1402      * broadcast of {@code 1}.
1403      * <p>
1404      * This is a vector unary operation with same semantic definition as
1405      * {@link Math#log1p} operation applied to lane elements.
1406      * The implementation is not required to return same
1407      * results as  {@link Math#log1p}, but adheres to rounding, monotonicity,
1408      * and special case semantics as defined in the {@link Math#log1p}
1409      * specifications. The computed result will be within 1 ulp of the
1410      * exact result.
1411      *
1412      * @return the natural logarithm of the sum of this vector and the broadcast
1413      * of {@code 1}
1414      */
1415     public DoubleVector log1p() {
1416         return uOp((i, a) -> (double) Math.log1p((double) a));
1417     }
1418 
1419     /**
1420      * Calculates the natural logarithm of the sum of this vector and the
1421      * broadcast of {@code 1}, selecting lane elements controlled by a mask.
1422      * <p>
1423      * Semantics for rounding, monotonicity, and special cases are
1424      * described in {@link DoubleVector#log1p}
1425      *
1426      * @param m the mask controlling lane selection
1427      * @return the natural logarithm of the sum of this vector and the broadcast
1428      * of {@code 1}
1429      */
1430     public DoubleVector log1p(Mask<Double> m) {
1431         return uOp(m, (i, a) -> (double) Math.log1p((double) a));
1432     }
1433 
1434     /**
1435      * Calculates this vector raised to the power of an input vector.
1436      * <p>
1437      * This is a vector binary operation with same semantic definition as
1438      * {@link Math#pow} operation applied to lane elements.
1439      * The implementation is not required to return same
1440      * results as {@link Math#pow}, but adheres to rounding, monotonicity,
1441      * and special case semantics as defined in the {@link Math#pow}
1442      * specifications. The computed result will be within 1 ulp of the
1443      * exact result.
1444      *
1445      * @param v the input vector
1446      * @return this vector raised to the power of an input vector
1447      */
1448     public DoubleVector pow(Vector<Double> v) {
1449         return bOp(v, (i, a, b) -> (double) Math.pow((double) a, (double) b));
1450     }
1451 
1452     /**
1453      * Calculates this vector raised to the power of the broadcast of an input
1454      * scalar.
1455      * <p>
1456      * This is a vector binary operation with same semantic definition as
1457      * {@link Math#pow} operation applied to lane elements.
1458      * The implementation is not required to return same
1459      * results as {@link Math#pow}, but adheres to rounding, monotonicity,
1460      * and special case semantics as defined in the {@link Math#pow}
1461      * specifications. The computed result will be within 1 ulp of the
1462      * exact result.
1463      *
1464      * @param s the input scalar
1465      * @return this vector raised to the power of the broadcast of an input
1466      * scalar.
1467      */
1468     public abstract DoubleVector pow(double s);
1469 
1470     /**
1471      * Calculates this vector raised to the power of an input vector, selecting
1472      * lane elements controlled by a mask.
1473      * <p>
1474      * Semantics for rounding, monotonicity, and special cases are
1475      * described in {@link DoubleVector#pow}
1476      *
1477      * @param v the input vector
1478      * @param m the mask controlling lane selection
1479      * @return this vector raised to the power of an input vector
1480      */
1481     public DoubleVector pow(Vector<Double> v, Mask<Double> m) {
1482         return bOp(v, m, (i, a, b) -> (double) Math.pow((double) a, (double) b));
1483     }
1484 
1485     /**
1486      * Calculates this vector raised to the power of the broadcast of an input
1487      * scalar, selecting lane elements controlled by a mask.
1488      * <p>
1489      * Semantics for rounding, monotonicity, and special cases are
1490      * described in {@link DoubleVector#pow}
1491      *
1492      * @param s the input scalar
1493      * @param m the mask controlling lane selection
1494      * @return this vector raised to the power of the broadcast of an input
1495      * scalar.
1496      */
1497     public abstract DoubleVector pow(double s, Mask<Double> m);
1498 
1499     /**
1500      * Calculates the broadcast of Euler's number {@code e} raised to the power
1501      * of this vector.
1502      * <p>
1503      * This is a vector unary operation with same semantic definition as
1504      * {@link Math#exp} operation applied to lane elements.
1505      * The implementation is not required to return same
1506      * results as {@link Math#exp}, but adheres to rounding, monotonicity,
1507      * and special case semantics as defined in the {@link Math#exp}
1508      * specifications. The computed result will be within 1 ulp of the
1509      * exact result.
1510      *
1511      * @return the broadcast of Euler's number {@code e} raised to the power of
1512      * this vector
1513      */
1514     public DoubleVector exp() {
1515         return uOp((i, a) -> (double) Math.exp((double) a));
1516     }
1517 
1518     /**
1519      * Calculates the broadcast of Euler's number {@code e} raised to the power
1520      * of this vector, selecting lane elements controlled by a mask.
1521      * <p>
1522      * Semantics for rounding, monotonicity, and special cases are
1523      * described in {@link DoubleVector#exp}
1524      *
1525      * @param m the mask controlling lane selection
1526      * @return the broadcast of Euler's number {@code e} raised to the power of
1527      * this vector
1528      */
1529     public DoubleVector exp(Mask<Double> m) {
1530         return uOp(m, (i, a) -> (double) Math.exp((double) a));
1531     }
1532 
1533     /**
1534      * Calculates the broadcast of Euler's number {@code e} raised to the power
1535      * of this vector minus the broadcast of {@code -1}.
1536      * More specifically as if the following (ignoring any differences in
1537      * numerical accuracy):
1538      * <pre>{@code
1539      *   this.exp().sub(this.species().broadcast(1))
1540      * }</pre>
1541      * <p>
1542      * This is a vector unary operation with same semantic definition as
1543      * {@link Math#expm1} operation applied to lane elements.
1544      * The implementation is not required to return same
1545      * results as {@link Math#expm1}, but adheres to rounding, monotonicity,
1546      * and special case semantics as defined in the {@link Math#expm1}
1547      * specifications. The computed result will be within 1 ulp of the
1548      * exact result.
1549      *
1550      * @return the broadcast of Euler's number {@code e} raised to the power of
1551      * this vector minus the broadcast of {@code -1}
1552      */
1553     public DoubleVector expm1() {
1554         return uOp((i, a) -> (double) Math.expm1((double) a));
1555     }
1556 
1557     /**
1558      * Calculates the broadcast of Euler's number {@code e} raised to the power
1559      * of this vector minus the broadcast of {@code -1}, selecting lane elements
1560      * controlled by a mask
1561      * More specifically as if the following (ignoring any differences in
1562      * numerical accuracy):
1563      * <pre>{@code
1564      *   this.exp(m).sub(this.species().broadcast(1), m)
1565      * }</pre>
1566      * <p>
1567      * Semantics for rounding, monotonicity, and special cases are
1568      * described in {@link DoubleVector#expm1}
1569      *
1570      * @param m the mask controlling lane selection
1571      * @return the broadcast of Euler's number {@code e} raised to the power of
1572      * this vector minus the broadcast of {@code -1}
1573      */
1574     public DoubleVector expm1(Mask<Double> m) {
1575         return uOp(m, (i, a) -> (double) Math.expm1((double) a));
1576     }
1577 
1578     /**
1579      * Calculates the product of this vector and a first input vector summed
1580      * with a second input vector.
1581      * More specifically as if the following (ignoring any differences in
1582      * numerical accuracy):
1583      * <pre>{@code
1584      *   this.mul(v1).add(v2)
1585      * }</pre>
1586      * <p>
1587      * This is a vector ternary operation where the {@link Math#fma} operation
1588      * is applied to lane elements.
1589      *
1590      * @param v1 the first input vector
1591      * @param v2 the second input vector
1592      * @return the product of this vector and the first input vector summed with
1593      * the second input vector
1594      */
1595     public abstract DoubleVector fma(Vector<Double> v1, Vector<Double> v2);
1596 
1597     /**
1598      * Calculates the product of this vector and the broadcast of a first input
1599      * scalar summed with the broadcast of a second input scalar.
1600      * More specifically as if the following:
1601      * <pre>{@code
1602      *   this.fma(this.species().broadcast(s1), this.species().broadcast(s2))
1603      * }</pre>
1604      * <p>
1605      * This is a vector ternary operation where the {@link Math#fma} operation
1606      * is applied to lane elements.
1607      *
1608      * @param s1 the first input scalar
1609      * @param s2 the second input scalar
1610      * @return the product of this vector and the broadcast of a first input
1611      * scalar summed with the broadcast of a second input scalar
1612      */
1613     public abstract DoubleVector fma(double s1, double s2);
1614 
1615     /**
1616      * Calculates the product of this vector and a first input vector summed
1617      * with a second input vector, selecting lane elements controlled by a mask.
1618      * More specifically as if the following (ignoring any differences in
1619      * numerical accuracy):
1620      * <pre>{@code
1621      *   this.mul(v1, m).add(v2, m)
1622      * }</pre>
1623      * <p>
1624      * This is a vector ternary operation where the {@link Math#fma} operation
1625      * is applied to lane elements.
1626      *
1627      * @param v1 the first input vector
1628      * @param v2 the second input vector
1629      * @param m the mask controlling lane selection
1630      * @return the product of this vector and the first input vector summed with
1631      * the second input vector
1632      */
1633     public DoubleVector fma(Vector<Double> v1, Vector<Double> v2, Mask<Double> m) {
1634         return tOp(v1, v2, m, (i, a, b, c) -> Math.fma(a, b, c));
1635     }
1636 
1637     /**
1638      * Calculates the product of this vector and the broadcast of a first input
1639      * scalar summed with the broadcast of a second input scalar, selecting lane
1640      * elements controlled by a mask
1641      * More specifically as if the following:
1642      * <pre>{@code
1643      *   this.fma(this.species().broadcast(s1), this.species().broadcast(s2), m)
1644      * }</pre>
1645      * <p>
1646      * This is a vector ternary operation where the {@link Math#fma} operation
1647      * is applied to lane elements.
1648      *
1649      * @param s1 the first input scalar
1650      * @param s2 the second input scalar
1651      * @param m the mask controlling lane selection
1652      * @return the product of this vector and the broadcast of a first input
1653      * scalar summed with the broadcast of a second input scalar
1654      */
1655     public abstract DoubleVector fma(double s1, double s2, Mask<Double> m);
1656 
1657     /**
1658      * Calculates square root of the sum of the squares of this vector and an
1659      * input vector.
1660      * More specifically as if the following (ignoring any differences in
1661      * numerical accuracy):
1662      * <pre>{@code
1663      *   this.mul(this).add(v.mul(v)).sqrt()
1664      * }</pre>
1665      * <p>
1666      * This is a vector binary operation with same semantic definition as
1667      * {@link Math#hypot} operation applied to lane elements.
1668      * The implementation is not required to return same
1669      * results as {@link Math#hypot}, but adheres to rounding, monotonicity,
1670      * and special case semantics as defined in the {@link Math#hypot}
1671      * specifications. The computed result will be within 1 ulp of the
1672      * exact result.
1673      *
1674      * @param v the input vector
1675      * @return square root of the sum of the squares of this vector and an input
1676      * vector
1677      */
1678     public DoubleVector hypot(Vector<Double> v) {
1679         return bOp(v, (i, a, b) -> (double) Math.hypot((double) a, (double) b));
1680     }
1681 
1682     /**
1683      * Calculates square root of the sum of the squares of this vector and the
1684      * broadcast of an input scalar.
1685      * More specifically as if the following (ignoring any differences in
1686      * numerical accuracy):
1687      * <pre>{@code
1688      *   this.mul(this).add(this.species().broadcast(v * v)).sqrt()
1689      * }</pre>
1690      * <p>
1691      * This is a vector binary operation with same semantic definition as
1692      * {@link Math#hypot} operation applied to lane elements.
1693      * The implementation is not required to return same
1694      * results as {@link Math#hypot}, but adheres to rounding, monotonicity,
1695      * and special case semantics as defined in the {@link Math#hypot}
1696      * specifications. The computed result will be within 1 ulp of the
1697      * exact result.
1698      *
1699      * @param s the input scalar
1700      * @return square root of the sum of the squares of this vector and the
1701      * broadcast of an input scalar
1702      */
1703     public abstract DoubleVector hypot(double s);
1704 
1705     /**
1706      * Calculates square root of the sum of the squares of this vector and an
1707      * input vector, selecting lane elements controlled by a mask.
1708      * More specifically as if the following (ignoring any differences in
1709      * numerical accuracy):
1710      * <pre>{@code
1711      *   this.mul(this, m).add(v.mul(v), m).sqrt(m)
1712      * }</pre>
1713      * <p>
1714      * Semantics for rounding, monotonicity, and special cases are
1715      * described in {@link DoubleVector#hypot}
1716      *
1717      * @param v the input vector
1718      * @param m the mask controlling lane selection
1719      * @return square root of the sum of the squares of this vector and an input
1720      * vector
1721      */
1722     public DoubleVector hypot(Vector<Double> v, Mask<Double> m) {
1723         return bOp(v, m, (i, a, b) -> (double) Math.hypot((double) a, (double) b));
1724     }
1725 
1726     /**
1727      * Calculates square root of the sum of the squares of this vector and the
1728      * broadcast of an input scalar, selecting lane elements controlled by a
1729      * mask.
1730      * More specifically as if the following (ignoring any differences in
1731      * numerical accuracy):
1732      * <pre>{@code
1733      *   this.mul(this, m).add(this.species().broadcast(v * v), m).sqrt(m)
1734      * }</pre>
1735      * <p>
1736      * Semantics for rounding, monotonicity, and special cases are
1737      * described in {@link DoubleVector#hypot}
1738      *
1739      * @param s the input scalar
1740      * @param m the mask controlling lane selection
1741      * @return square root of the sum of the squares of this vector and the
1742      * broadcast of an input scalar
1743      */
1744     public abstract DoubleVector hypot(double s, Mask<Double> m);
1745 
1746 
1747     @Override
1748     public abstract void intoByteArray(byte[] a, int ix);
1749 
1750     @Override
1751     public abstract void intoByteArray(byte[] a, int ix, Mask<Double> m);
1752 
1753     @Override
1754     public abstract void intoByteBuffer(ByteBuffer bb, int ix);
1755 
1756     @Override
1757     public abstract void intoByteBuffer(ByteBuffer bb, int ix, Mask<Double> m);
1758 
1759 
1760     // Type specific horizontal reductions
1761     /**
1762      * Adds all lane elements of this vector.
1763      * <p>
1764      * This is a vector reduction operation where the addition
1765      * operation ({@code +}) is applied to lane elements,
1766      * and the identity value is {@code 0.0}.
1767      *
1768      * <p>The value of a floating-point sum is a function both of the input values as well
1769      * as the order of addition operations. The order of addition operations of this method
1770      * is intentionally not defined to allow for JVM to generate optimal machine
1771      * code for the underlying platform at runtime. If the platform supports a vector
1772      * instruction to add all values in the vector, or if there is some other efficient machine
1773      * code sequence, then the JVM has the option of generating this machine code. Otherwise,
1774      * the default implementation of adding vectors sequentially from left to right is used.
1775      * For this reason, the output of this method may vary for the same input values.
1776      *
1777      * @return the addition of all the lane elements of this vector
1778      */
1779     public abstract double addAll();
1780 
1781     /**
1782      * Adds all lane elements of this vector, selecting lane elements
1783      * controlled by a mask.
1784      * <p>
1785      * This is a vector reduction operation where the addition
1786      * operation ({@code +}) is applied to lane elements,
1787      * and the identity value is {@code 0.0}.
1788      *
1789      * <p>The value of a floating-point sum is a function both of the input values as well
1790      * as the order of addition operations. The order of addition operations of this method
1791      * is intentionally not defined to allow for JVM to generate optimal machine
1792      * code for the underlying platform at runtime. If the platform supports a vector
1793      * instruction to add all values in the vector, or if there is some other efficient machine
1794      * code sequence, then the JVM has the option of generating this machine code. Otherwise,
1795      * the default implementation of adding vectors sequentially from left to right is used.
1796      * For this reason, the output of this method may vary on the same input values.
1797      *
1798      * @param m the mask controlling lane selection
1799      * @return the addition of the selected lane elements of this vector
1800      */
1801     public abstract double addAll(Mask<Double> m);
1802 
1803     /**
1804      * Multiplies all lane elements of this vector.
1805      * <p>
1806      * This is a vector reduction operation where the
1807      * multiplication operation ({@code *}) is applied to lane elements,
1808      * and the identity value is {@code 1.0}.
1809      *
1810      * <p>The order of multiplication operations of this method
1811      * is intentionally not defined to allow for JVM to generate optimal machine
1812      * code for the underlying platform at runtime. If the platform supports a vector
1813      * instruction to multiply all values in the vector, or if there is some other efficient machine
1814      * code sequence, then the JVM has the option of generating this machine code. Otherwise,
1815      * the default implementation of multiplying vectors sequentially from left to right is used.
1816      * For this reason, the output of this method may vary on the same input values.
1817      *
1818      * @return the multiplication of all the lane elements of this vector
1819      */
1820     public abstract double mulAll();
1821 
1822     /**
1823      * Multiplies all lane elements of this vector, selecting lane elements
1824      * controlled by a mask.
1825      * <p>
1826      * This is a vector reduction operation where the
1827      * multiplication operation ({@code *}) is applied to lane elements,
1828      * and the identity value is {@code 1.0}.
1829      *
1830      * <p>The order of multiplication operations of this method
1831      * is intentionally not defined to allow for JVM to generate optimal machine
1832      * code for the underlying platform at runtime. If the platform supports a vector
1833      * instruction to multiply all values in the vector, or if there is some other efficient machine
1834      * code sequence, then the JVM has the option of generating this machine code. Otherwise,
1835      * the default implementation of multiplying vectors sequentially from left to right is used.
1836      * For this reason, the output of this method may vary on the same input values.
1837      *
1838      * @param m the mask controlling lane selection
1839      * @return the multiplication of all the lane elements of this vector
1840      */
1841     public abstract double mulAll(Mask<Double> m);
1842 
1843     /**
1844      * Returns the minimum lane element of this vector.
1845      * <p>
1846      * This is an associative vector reduction operation where the operation
1847      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements,
1848      * and the identity value is
1849      * {@link Double#POSITIVE_INFINITY}.
1850      *
1851      * @return the minimum lane element of this vector
1852      */
1853     public abstract double minAll();
1854 
1855     /**
1856      * Returns the minimum lane element of this vector, selecting lane elements
1857      * controlled by a mask.
1858      * <p>
1859      * This is an associative vector reduction operation where the operation
1860      * {@code (a, b) -> Math.min(a, b)} is applied to lane elements,
1861      * and the identity value is
1862      * {@link Double#POSITIVE_INFINITY}.
1863      *
1864      * @param m the mask controlling lane selection
1865      * @return the minimum lane element of this vector
1866      */
1867     public abstract double minAll(Mask<Double> m);
1868 
1869     /**
1870      * Returns the maximum lane element of this vector.
1871      * <p>
1872      * This is an associative vector reduction operation where the operation
1873      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements,
1874      * and the identity value is
1875      * {@link Double#NEGATIVE_INFINITY}.
1876      *
1877      * @return the maximum lane element of this vector
1878      */
1879     public abstract double maxAll();
1880 
1881     /**
1882      * Returns the maximum lane element of this vector, selecting lane elements
1883      * controlled by a mask.
1884      * <p>
1885      * This is an associative vector reduction operation where the operation
1886      * {@code (a, b) -> Math.max(a, b)} is applied to lane elements,
1887      * and the identity value is
1888      * {@link Double#NEGATIVE_INFINITY}.
1889      *
1890      * @param m the mask controlling lane selection
1891      * @return the maximum lane element of this vector
1892      */
1893     public abstract double maxAll(Mask<Double> m);
1894 
1895 
1896     // Type specific accessors
1897 
1898     /**
1899      * Gets the lane element at lane index {@code i}
1900      *
1901      * @param i the lane index
1902      * @return the lane element at lane index {@code i}
1903      * @throws IllegalArgumentException if the index is is out of range
1904      * ({@code < 0 || >= length()})
1905      */
1906     public abstract double get(int i);
1907 
1908     /**
1909      * Replaces the lane element of this vector at lane index {@code i} with
1910      * value {@code e}.
1911      * <p>
1912      * This is a cross-lane operation and behaves as if it returns the result
1913      * of blending this vector with an input vector that is the result of
1914      * broadcasting {@code e} and a mask that has only one lane set at lane
1915      * index {@code i}.
1916      *
1917      * @param i the lane index of the lane element to be replaced
1918      * @param e the value to be placed
1919      * @return the result of replacing the lane element of this vector at lane
1920      * index {@code i} with value {@code e}.
1921      * @throws IllegalArgumentException if the index is is out of range
1922      * ({@code < 0 || >= length()})
1923      */
1924     public abstract DoubleVector with(int i, double e);
1925 
1926     // Type specific extractors
1927 
1928     /**
1929      * Returns an array containing the lane elements of this vector.
1930      * <p>
1931      * This method behaves as if it {@link #intoArray(double[], int)} stores}
1932      * this vector into an allocated array and returns the array as follows:
1933      * <pre>{@code
1934      *   double[] a = new double[this.length()];
1935      *   this.intoArray(a, 0);
1936      *   return a;
1937      * }</pre>
1938      *
1939      * @return an array containing the the lane elements of this vector
1940      */
1941     @ForceInline
1942     public final double[] toArray() {
1943         double[] a = new double[species().length()];
1944         intoArray(a, 0);
1945         return a;
1946     }
1947 
1948     /**
1949      * Stores this vector into an array starting at offset.
1950      * <p>
1951      * For each vector lane, where {@code N} is the vector lane index,
1952      * the lane element at index {@code N} is stored into the array at index
1953      * {@code i + N}.
1954      *
1955      * @param a the array
1956      * @param i the offset into the array
1957      * @throws IndexOutOfBoundsException if {@code i < 0}, or
1958      * {@code i > a.length - this.length()}
1959      */
1960     public abstract void intoArray(double[] a, int i);
1961 
1962     /**
1963      * Stores this vector into an array starting at offset and using a mask.
1964      * <p>
1965      * For each vector lane, where {@code N} is the vector lane index,
1966      * if the mask lane at index {@code N} is set then the lane element at
1967      * index {@code N} is stored into the array index {@code i + N}.
1968      *
1969      * @param a the array
1970      * @param i the offset into the array
1971      * @param m the mask
1972      * @throws IndexOutOfBoundsException if {@code i < 0}, or
1973      * for any vector lane index {@code N} where the mask at lane {@code N}
1974      * is set {@code i >= a.length - N}
1975      */
1976     public abstract void intoArray(double[] a, int i, Mask<Double> m);
1977 
1978     /**
1979      * Stores this vector into an array using indexes obtained from an index
1980      * map.
1981      * <p>
1982      * For each vector lane, where {@code N} is the vector lane index, the
1983      * lane element at index {@code N} is stored into the array at index
1984      * {@code i + indexMap[j + N]}.
1985      *
1986      * @param a the array
1987      * @param i the offset into the array, may be negative if relative
1988      * indexes in the index map compensate to produce a value within the
1989      * array bounds
1990      * @param indexMap the index map
1991      * @param j the offset into the index map
1992      * @throws IndexOutOfBoundsException if {@code j < 0}, or
1993      * {@code j > indexMap.length - this.length()},
1994      * or for any vector lane index {@code N} the result of
1995      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
1996      */
1997     public abstract void intoArray(double[] a, int i, int[] indexMap, int j);
1998 
1999     /**
2000      * Stores this vector into an array using indexes obtained from an index
2001      * map and using a mask.
2002      * <p>
2003      * For each vector lane, where {@code N} is the vector lane index,
2004      * if the mask lane at index {@code N} is set then the lane element at
2005      * index {@code N} is stored into the array at index
2006      * {@code i + indexMap[j + N]}.
2007      *
2008      * @param a the array
2009      * @param i the offset into the array, may be negative if relative
2010      * indexes in the index map compensate to produce a value within the
2011      * array bounds
2012      * @param m the mask
2013      * @param indexMap the index map
2014      * @param j the offset into the index map
2015      * @throws IndexOutOfBoundsException if {@code j < 0}, or
2016      * {@code j > indexMap.length - this.length()},
2017      * or for any vector lane index {@code N} where the mask at lane
2018      * {@code N} is set the result of {@code i + indexMap[j + N]} is
2019      * {@code < 0} or {@code >= a.length}
2020      */
2021     public abstract void intoArray(double[] a, int i, Mask<Double> m, int[] indexMap, int j);
2022     // Species
2023 
2024     @Override
2025     public abstract DoubleSpecies species();
2026 
2027     /**
2028      * A specialized factory for creating {@link DoubleVector} value of the same
2029      * shape, and a {@link Mask} and {@link Shuffle} values of the same shape
2030      * and {@code int} element type.
2031      */
2032     public static abstract class DoubleSpecies extends Vector.Species<Double> {
2033         interface FOp {
2034             double apply(int i);
2035         }
2036 
2037         abstract DoubleVector op(FOp f);
2038 
2039         abstract DoubleVector op(Mask<Double> m, FOp f);
2040 
2041         interface FOpm {
2042             boolean apply(int i);
2043         }
2044 
2045         abstract Mask<Double> opm(FOpm f);
2046 
2047         abstract IntVector.IntSpecies indexSpecies();
2048 
2049 
2050         // Factories
2051 
2052         @Override
2053         public abstract DoubleVector zero();
2054 
2055         /**
2056          * Returns a vector where all lane elements are set to the primitive
2057          * value {@code e}.
2058          *
2059          * @param e the value
2060          * @return a vector of vector where all lane elements are set to
2061          * the primitive value {@code e}
2062          */
2063         public abstract DoubleVector broadcast(double e);
2064 
2065         /**
2066          * Returns a vector where the first lane element is set to the primtive
2067          * value {@code e}, all other lane elements are set to the default
2068          * value.
2069          *
2070          * @param e the value
2071          * @return a vector where the first lane element is set to the primitive
2072          * value {@code e}
2073          */
2074         @ForceInline
2075         public final DoubleVector single(double e) {
2076             return zero().with(0, e);
2077         }
2078 
2079         /**
2080          * Returns a vector where each lane element is set to a randomly
2081          * generated primitive value.
2082          *
2083          * The semantics are equivalent to calling
2084          * {@code ThreadLocalRandom#nextDouble}.
2085          *
2086          * @return a vector where each lane elements is set to a randomly
2087          * generated primitive value
2088          */
2089         public DoubleVector random() {
2090             ThreadLocalRandom r = ThreadLocalRandom.current();
2091             return op(i -> r.nextDouble());
2092         }
2093 
2094         /**
2095          * Returns a vector where each lane element is set to a given
2096          * primitive value.
2097          * <p>
2098          * For each vector lane, where {@code N} is the vector lane index, the
2099          * the primitive value at index {@code N} is placed into the resulting
2100          * vector at lane index {@code N}.
2101          *
2102          * @param es the given primitive values
2103          * @return a vector where each lane element is set to a given primitive
2104          * value
2105          * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
2106          */
2107         public abstract DoubleVector scalars(double... es);
2108     }
2109 
2110     /**
2111      * Finds the preferred species for an element type of {@code double}.
2112      * <p>
2113      * A preferred species is a species chosen by the platform that has a
2114      * shape of maximal bit size.  A preferred species for different element
2115      * types will have the same shape, and therefore vectors, masks, and
2116      * shuffles created from such species will be shape compatible.
2117      *
2118      * @return the preferred species for an element type of {@code double}
2119      */
2120     @SuppressWarnings("unchecked")
2121     public static DoubleSpecies preferredSpecies() {
2122         return (DoubleSpecies) Species.ofPreferred(double.class);
2123     }
2124 
2125     /**
2126      * Finds a species for an element type of {@code double} and shape.
2127      *
2128      * @param s the shape
2129      * @return a species for an element type of {@code double} and shape
2130      * @throws IllegalArgumentException if no such species exists for the shape
2131      */
2132     @SuppressWarnings("unchecked")
2133     public static DoubleSpecies species(Vector.Shape s) {
2134         Objects.requireNonNull(s);
2135         switch (s) {
2136             case S_64_BIT: return Double64Vector.SPECIES;
2137             case S_128_BIT: return Double128Vector.SPECIES;
2138             case S_256_BIT: return Double256Vector.SPECIES;
2139             case S_512_BIT: return Double512Vector.SPECIES;
2140             case S_Max_BIT: return DoubleMaxVector.SPECIES;
2141             default: throw new IllegalArgumentException("Bad shape: " + s);
2142         }
2143     }
2144 }