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