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