< prev index next >

src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java

Print this page
rev 55589 : Species-phase2
rev 55590 : added missing javadocs, changed jtreg test
rev 55591 : XxxSpecies made package private
rev 55592 : Capitalized Species names

@@ -27,10 +27,11 @@
 import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
 import java.nio.ByteOrder;
 import java.util.Objects;
 import java.util.function.IntUnaryOperator;
+import java.util.function.Function;
 import java.util.concurrent.ThreadLocalRandom;
 
 import jdk.internal.misc.Unsafe;
 import jdk.internal.vm.annotation.ForceInline;
 import static jdk.incubator.vector.VectorIntrinsics.*;

@@ -108,23 +109,25 @@
      * @param species species of desired vector
      * @return a zero vector of given species
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector zero(FloatSpecies species) {
-        return species.zero();
+    public static FloatVector zero(Species<Float> species) {
+        return VectorIntrinsics.broadcastCoerced((Class<FloatVector>) species.boxType(), float.class, species.length(),
+                                                 Float.floatToIntBits(0.0f), species,
+                                                 ((bits, s) -> ((FloatSpecies)s).op(i -> Float.intBitsToFloat((int)bits))));
     }
 
     /**
      * Loads a vector from a byte array starting at an offset.
      * <p>
      * Bytes are composed into primitive lane elements according to the
      * native byte order of the underlying platform
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Float>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
      * }</pre>
      *
      * @param species species of desired vector

@@ -134,11 +137,11 @@
      * @throws IndexOutOfBoundsException if {@code i < 0} or
      * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromByteArray(FloatSpecies species, byte[] a, int ix) {
+    public static FloatVector fromByteArray(Species<Float> species, byte[] a, int ix) {
         Objects.requireNonNull(a);
         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
         return VectorIntrinsics.load((Class<FloatVector>) species.boxType(), float.class, species.length(),
                                      a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
                                      a, ix, species,

@@ -156,11 +159,11 @@
      * Bytes are composed into primitive lane elements according to the
      * native byte order of the underlying platform.
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Float>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
      * }</pre>
      *
      * @param species species of desired vector

@@ -175,11 +178,11 @@
      * for any vector lane index {@code N} where the mask at lane {@code N}
      * is set
      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static FloatVector fromByteArray(FloatSpecies species, byte[] a, int ix, Mask<Float> m) {
+    public static FloatVector fromByteArray(Species<Float> species, byte[] a, int ix, Mask<Float> m) {
         return zero(species).blend(fromByteArray(species, a, ix), m);
     }
 
     /**
      * Loads a vector from an array starting at offset.

@@ -195,11 +198,11 @@
      * @throws IndexOutOfBoundsException if {@code i < 0}, or
      * {@code i > a.length - this.length()}
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i){
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i){
         Objects.requireNonNull(a);
         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
         return VectorIntrinsics.load((Class<FloatVector>) species.boxType(), float.class, species.length(),
                                      a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_FLOAT_BASE_OFFSET,
                                      a, i, species,

@@ -224,11 +227,11 @@
      * @throws IndexOutOfBoundsException if {@code i < 0}, or
      * for any vector lane index {@code N} where the mask at lane {@code N}
      * is set {@code i > a.length - N}
      */
     @ForceInline
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, Mask<Float> m) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, Mask<Float> m) {
         return zero(species).blend(fromArray(species, a, i), m);
     }
 
     /**
      * Loads a vector from an array using indexes obtained from an index

@@ -251,24 +254,25 @@
      * or for any vector lane index {@code N} the result of
      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, int[] indexMap, int j) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, int[] indexMap, int j) {
         Objects.requireNonNull(a);
         Objects.requireNonNull(indexMap);
 
 
-        // Index vector: vix[0:n] = k -> i + indexMap[j + i]
-        IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
+        // Index vector: vix[0:n] = k -> i + indexMap[j + k]
+        IntVector vix = IntVector.fromArray(IntVector.species(species.indexShape()), indexMap, j).add(i);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
         return VectorIntrinsics.loadWithMap((Class<FloatVector>) species.boxType(), float.class, species.length(),
-                                            species.indexSpecies().vectorType(), a, Unsafe.ARRAY_FLOAT_BASE_OFFSET, vix,
+                                            IntVector.species(species.indexShape()).boxType(), a, Unsafe.ARRAY_FLOAT_BASE_OFFSET, vix,
                                             a, i, indexMap, j, species,
-                                           (c, idx, iMap, idy, s) -> ((FloatSpecies)s).op(n -> c[idx + iMap[idy+n]]));
+                                            (float[] c, int idx, int[] iMap, int idy, Species<Float> s) ->
+                                                ((FloatSpecies)s).op(n -> c[idx + iMap[idy+n]]));
         }
 
     /**
      * Loads a vector from an array using indexes obtained from an index
      * map and using a mask.

@@ -293,11 +297,11 @@
      * {@code N} is set the result of {@code i + indexMap[j + N]} is
      * {@code < 0} or {@code >= a.length}
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, Mask<Float> m, int[] indexMap, int j) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, Mask<Float> m, int[] indexMap, int j) {
         // @@@ This can result in out of bounds errors for unset mask lanes
         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
     }
 
 

@@ -308,11 +312,11 @@
      * Bytes are composed into primitive lane elements according to the
      * native byte order of the underlying platform.
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask)} method} as follows:
+     * {@link #fromByteBuffer(Species<Float>, ByteBuffer, int, Mask)} method} as follows:
      * <pre>{@code
      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
      * }</pre>
      *
      * @param species species of desired vector

@@ -325,11 +329,11 @@
      * {@code this.length() * this.elementSize() / Byte.SIZE} bytes
      * remaining in the byte buffer from the given offset
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromByteBuffer(FloatSpecies species, ByteBuffer bb, int ix) {
+    public static FloatVector fromByteBuffer(Species<Float> species, ByteBuffer bb, int ix) {
         if (bb.order() != ByteOrder.nativeOrder()) {
             throw new IllegalArgumentException();
         }
         ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE);
         return VectorIntrinsics.load((Class<FloatVector>) species.boxType(), float.class, species.length(),

@@ -377,15 +381,89 @@
      * for any vector lane index {@code N} where the mask at lane {@code N}
      * is set
      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static FloatVector fromByteBuffer(FloatSpecies species, ByteBuffer bb, int ix, Mask<Float> m) {
+    public static FloatVector fromByteBuffer(Species<Float> species, ByteBuffer bb, int ix, Mask<Float> m) {
         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
     }
 
     /**
+     * Returns a vector where all lane elements are set to the primitive
+     * value {@code e}.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector of vector where all lane elements are set to
+     * the primitive value {@code e}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static FloatVector broadcast(Species<Float> s, float e) {
+        return VectorIntrinsics.broadcastCoerced(
+            (Class<FloatVector>) s.boxType(), float.class, s.length(),
+            Float.floatToIntBits(e), s,
+            ((bits, sp) -> ((FloatSpecies)sp).op(i -> Float.intBitsToFloat((int)bits))));
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a given
+     * primitive value.
+     * <p>
+     * For each vector lane, where {@code N} is the vector lane index, the
+     * the primitive value at index {@code N} is placed into the resulting
+     * vector at lane index {@code N}.
+     *
+     * @param s species of the desired vector
+     * @param es the given primitive values
+     * @return a vector where each lane element is set to a given primitive
+     * value
+     * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static FloatVector scalars(Species<Float> s, float... es) {
+        Objects.requireNonNull(es);
+        int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
+        return VectorIntrinsics.load((Class<FloatVector>) s.boxType(), float.class, s.length(),
+                                     es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
+                                     es, ix, s,
+                                     (c, idx, sp) -> ((FloatSpecies)sp).op(n -> c[idx + n]));
+    }
+
+    /**
+     * Returns a vector where the first lane element is set to the primtive
+     * value {@code e}, all other lane elements are set to the default
+     * value.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector where the first lane element is set to the primitive
+     * value {@code e}
+     */
+    @ForceInline
+    public static final FloatVector single(Species<Float> s, float e) {
+        return zero(s).with(0, e);
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a randomly
+     * generated primitive value.
+     *
+     * The semantics are equivalent to calling
+     * {@link ThreadLocalRandom#nextFloat()}
+     *
+     * @param s species of the desired vector
+     * @return a vector where each lane elements is set to a randomly
+     * generated primitive value
+     */
+    public static FloatVector random(Species<Float> s) {
+        ThreadLocalRandom r = ThreadLocalRandom.current();
+        return ((FloatSpecies)s).op(i -> r.nextFloat());
+    }
+
+    /**
      * Returns a mask where each lane is set or unset according to given
      * {@code boolean} values
      * <p>
      * For each mask lane, where {@code N} is the mask lane index,
      * if the given {@code boolean} value at index {@code N} is {@code true}

@@ -395,11 +473,11 @@
      * @param bits the given {@code boolean} values
      * @return a mask where each lane is set or unset according to the given {@code boolean} value
      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
      */
     @ForceInline
-    public static Mask<Float> maskFromValues(FloatSpecies species, boolean... bits) {
+    public static Mask<Float> maskFromValues(Species<Float> species, boolean... bits) {
         if (species.boxType() == FloatMaxVector.class)
             return new FloatMaxVector.FloatMaxMask(bits);
         switch (species.bitSize()) {
             case 64: return new Float64Vector.Float64Mask(bits);
             case 128: return new Float128Vector.Float128Mask(bits);

@@ -408,11 +486,11 @@
             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
         }
     }
 
     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
-    static Mask<Float> trueMask(FloatSpecies species) {
+    static Mask<Float> trueMask(Species<Float> species) {
         if (species.boxType() == FloatMaxVector.class)
             return FloatMaxVector.FloatMaxMask.TRUE_MASK;
         switch (species.bitSize()) {
             case 64: return Float64Vector.Float64Mask.TRUE_MASK;
             case 128: return Float128Vector.Float128Mask.TRUE_MASK;

@@ -420,11 +498,11 @@
             case 512: return Float512Vector.Float512Mask.TRUE_MASK;
             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
         }
     }
 
-    static Mask<Float> falseMask(FloatSpecies species) {
+    static Mask<Float> falseMask(Species<Float> species) {
         if (species.boxType() == FloatMaxVector.class)
             return FloatMaxVector.FloatMaxMask.FALSE_MASK;
         switch (species.bitSize()) {
             case 64: return Float64Vector.Float64Mask.FALSE_MASK;
             case 128: return Float128Vector.Float128Mask.FALSE_MASK;

@@ -448,11 +526,11 @@
      * @throws IndexOutOfBoundsException if {@code ix < 0}, or
      * {@code ix > bits.length - species.length()}
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Float> maskFromArray(FloatSpecies species, boolean[] bits, int ix) {
+    public static Mask<Float> maskFromArray(Species<Float> species, boolean[] bits, int ix) {
         Objects.requireNonNull(bits);
         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
         return VectorIntrinsics.load((Class<Mask<Float>>) species.maskType(), int.class, species.length(),
                                      bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
                                      bits, ix, species,

@@ -465,28 +543,28 @@
      * @param species mask species
      * @return a mask where all lanes are set
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Float> maskAllTrue(FloatSpecies species) {
+    public static Mask<Float> maskAllTrue(Species<Float> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Float>>) species.maskType(), int.class, species.length(),
                                                  (int)-1,  species,
-                                                 ((z, s) -> trueMask((FloatSpecies)s)));
+                                                 ((z, s) -> trueMask(s)));
     }
 
     /**
      * Returns a mask where all lanes are unset.
      *
      * @param species mask species
      * @return a mask where all lanes are unset
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Float> maskAllFalse(FloatSpecies species) {
+    public static Mask<Float> maskAllFalse(Species<Float> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Float>>) species.maskType(), int.class, species.length(),
                                                  0, species, 
-                                                 ((z, s) -> falseMask((FloatSpecies)s)));
+                                                 ((z, s) -> falseMask(s)));
     }
 
     /**
      * Returns a shuffle of mapped indexes where each lane element is
      * the result of applying a mapping function to the corresponding lane

@@ -510,11 +588,11 @@
      * @param species shuffle species
      * @param f the lane index mapping function
      * @return a shuffle of mapped indexes
      */
     @ForceInline
-    public static Shuffle<Float> shuffle(FloatSpecies species, IntUnaryOperator f) {
+    public static Shuffle<Float> shuffle(Species<Float> species, IntUnaryOperator f) {
         if (species.boxType() == FloatMaxVector.class)
             return new FloatMaxVector.FloatMaxShuffle(f);
         switch (species.bitSize()) {
             case 64: return new Float64Vector.Float64Shuffle(f);
             case 128: return new Float128Vector.Float128Shuffle(f);

@@ -536,11 +614,11 @@
      *
      * @param species shuffle species
      * @return a shuffle of lane indexes
      */
     @ForceInline
-    public static Shuffle<Float> shuffleIota(FloatSpecies species) {
+    public static Shuffle<Float> shuffleIota(Species<Float> species) {
         if (species.boxType() == FloatMaxVector.class)
             return new FloatMaxVector.FloatMaxShuffle(AbstractShuffle.IDENTITY);
         switch (species.bitSize()) {
             case 64: return new Float64Vector.Float64Shuffle(AbstractShuffle.IDENTITY);
             case 128: return new Float128Vector.Float128Shuffle(AbstractShuffle.IDENTITY);

@@ -565,11 +643,11 @@
      * {@code int} value
      * @throws IndexOutOfBoundsException if the number of int values is
      * {@code < species.length()}
      */
     @ForceInline
-    public static Shuffle<Float> shuffleFromValues(FloatSpecies species, int... ixs) {
+    public static Shuffle<Float> shuffleFromValues(Species<Float> species, int... ixs) {
         if (species.boxType() == FloatMaxVector.class)
             return new FloatMaxVector.FloatMaxShuffle(ixs);
         switch (species.bitSize()) {
             case 64: return new Float64Vector.Float64Shuffle(ixs);
             case 128: return new Float128Vector.Float128Shuffle(ixs);

@@ -593,11 +671,11 @@
      * @return a shuffle loaded from the {@code int} array
      * @throws IndexOutOfBoundsException if {@code i < 0}, or
      * {@code i > a.length - species.length()}
      */
     @ForceInline
-    public static Shuffle<Float> shuffleFromArray(FloatSpecies species, int[] ixs, int i) {
+    public static Shuffle<Float> shuffleFromArray(Species<Float> species, int[] ixs, int i) {
         if (species.boxType() == FloatMaxVector.class)
             return new FloatMaxVector.FloatMaxShuffle(ixs, i);
         switch (species.bitSize()) {
             case 64: return new Float64Vector.Float64Shuffle(ixs, i);
             case 128: return new Float128Vector.Float128Shuffle(ixs, i);

@@ -605,11 +683,10 @@
             case 512: return new Float512Vector.Float512Shuffle(ixs, i);
             default: throw new IllegalArgumentException(Integer.toString(species.bitSize()));
         }
     }
 
-
     // Ops
 
     @Override
     public abstract FloatVector add(Vector<Float> v);
 

@@ -2017,91 +2094,63 @@
      */
     public abstract void intoArray(float[] a, int i, Mask<Float> m, int[] indexMap, int j);
     // Species
 
     @Override
-    public abstract FloatSpecies species();
+    public abstract Species<Float> species();
 
     /**
      * Class representing {@link FloatVector}'s of the same {@link Vector.Shape Shape}.
      */
-    public static abstract class FloatSpecies extends Vector.Species<Float> {
+    static final class FloatSpecies extends Vector.AbstractSpecies<Float> {
+        final Function<float[], FloatVector> vectorFactory;
+        final Function<boolean[], Vector.Mask<Float>> maskFactory;
+
+        private FloatSpecies(Vector.Shape shape,
+                          Class<?> boxType,
+                          Class<?> maskType,
+                          Function<float[], FloatVector> vectorFactory,
+                          Function<boolean[], Vector.Mask<Float>> maskFactory) {
+            super(shape, float.class, Float.SIZE, boxType, maskType);
+            this.vectorFactory = vectorFactory;
+            this.maskFactory = maskFactory;
+        }
+
         interface FOp {
             float apply(int i);
         }
 
-        abstract FloatVector op(FOp f);
-
-        abstract FloatVector op(Mask<Float> m, FOp f);
-
         interface FOpm {
             boolean apply(int i);
         }
 
-        abstract Mask<Float> opm(FOpm f);
-
-        abstract IntVector.IntSpecies indexSpecies();
-
-
-        // Factories
-
-        @Override
-        public abstract FloatVector zero();
-
-        /**
-         * Returns a vector where all lane elements are set to the primitive
-         * value {@code e}.
-         *
-         * @param e the value
-         * @return a vector of vector where all lane elements are set to
-         * the primitive value {@code e}
-         */
-        public abstract FloatVector broadcast(float e);
-
-        /**
-         * Returns a vector where the first lane element is set to the primtive
-         * value {@code e}, all other lane elements are set to the default
-         * value.
-         *
-         * @param e the value
-         * @return a vector where the first lane element is set to the primitive
-         * value {@code e}
-         */
-        @ForceInline
-        public final FloatVector single(float e) {
-            return zero().with(0, e);
+        FloatVector op(FOp f) {
+            float[] res = new float[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = f.apply(i);
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a randomly
-         * generated primitive value.
-         *
-         * The semantics are equivalent to calling
-         * {@code ThreadLocalRandom#nextFloat}.
-         *
-         * @return a vector where each lane elements is set to a randomly
-         * generated primitive value
-         */
-        public FloatVector random() {
-            ThreadLocalRandom r = ThreadLocalRandom.current();
-            return op(i -> r.nextFloat());
+        FloatVector op(Vector.Mask<Float> o, FOp f) {
+            float[] res = new float[length()];
+            boolean[] mbits = ((AbstractMask<Float>)o).getBits();
+            for (int i = 0; i < length(); i++) {
+                if (mbits[i]) {
+                    res[i] = f.apply(i);
+                }
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a given
-         * primitive value.
-         * <p>
-         * For each vector lane, where {@code N} is the vector lane index, the
-         * the primitive value at index {@code N} is placed into the resulting
-         * vector at lane index {@code N}.
-         *
-         * @param es the given primitive values
-         * @return a vector where each lane element is set to a given primitive
-         * value
-         * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
-         */
-        public abstract FloatVector scalars(float... es);
+        Vector.Mask<Float> opm(IntVector.IntSpecies.FOpm f) {
+            boolean[] res = new boolean[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = (boolean)f.apply(i);
+            }
+            return maskFactory.apply(res);
+        }
     }
 
     /**
      * Finds the preferred species for an element type of {@code float}.
      * <p>

@@ -2110,30 +2159,54 @@
      * types will have the same shape, and therefore vectors, masks, and
      * shuffles created from such species will be shape compatible.
      *
      * @return the preferred species for an element type of {@code float}
      */
-    @SuppressWarnings("unchecked")
-    public static FloatSpecies preferredSpecies() {
+    private static FloatSpecies preferredSpecies() {
         return (FloatSpecies) Species.ofPreferred(float.class);
     }
 
     /**
      * Finds a species for an element type of {@code float} and shape.
      *
      * @param s the shape
      * @return a species for an element type of {@code float} and shape
      * @throws IllegalArgumentException if no such species exists for the shape
      */
-    @SuppressWarnings("unchecked")
-    public static FloatSpecies species(Vector.Shape s) {
+    static FloatSpecies species(Vector.Shape s) {
         Objects.requireNonNull(s);
         switch (s) {
-            case S_64_BIT: return Float64Vector.SPECIES;
-            case S_128_BIT: return Float128Vector.SPECIES;
-            case S_256_BIT: return Float256Vector.SPECIES;
-            case S_512_BIT: return Float512Vector.SPECIES;
-            case S_Max_BIT: return FloatMaxVector.SPECIES;
+            case S_64_BIT: return (FloatSpecies) SPECIES_64;
+            case S_128_BIT: return (FloatSpecies) SPECIES_128;
+            case S_256_BIT: return (FloatSpecies) SPECIES_256;
+            case S_512_BIT: return (FloatSpecies) SPECIES_512;
+            case S_Max_BIT: return (FloatSpecies) SPECIES_MAX;
             default: throw new IllegalArgumentException("Bad shape: " + s);
         }
     }
+
+    /** Species representing {@link FloatVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
+    public static final Species<Float> SPECIES_64 = new FloatSpecies(Shape.S_64_BIT, Float64Vector.class, Float64Vector.Float64Mask.class,
+                                                                     Float64Vector::new, Float64Vector.Float64Mask::new);
+
+    /** Species representing {@link FloatVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
+    public static final Species<Float> SPECIES_128 = new FloatSpecies(Shape.S_128_BIT, Float128Vector.class, Float128Vector.Float128Mask.class,
+                                                                      Float128Vector::new, Float128Vector.Float128Mask::new);
+
+    /** Species representing {@link FloatVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
+    public static final Species<Float> SPECIES_256 = new FloatSpecies(Shape.S_256_BIT, Float256Vector.class, Float256Vector.Float256Mask.class,
+                                                                      Float256Vector::new, Float256Vector.Float256Mask::new);
+
+    /** Species representing {@link FloatVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
+    public static final Species<Float> SPECIES_512 = new FloatSpecies(Shape.S_512_BIT, Float512Vector.class, Float512Vector.Float512Mask.class,
+                                                                      Float512Vector::new, Float512Vector.Float512Mask::new);
+
+    /** Species representing {@link FloatVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
+    public static final Species<Float> SPECIES_MAX = new FloatSpecies(Shape.S_Max_BIT, FloatMaxVector.class, FloatMaxVector.FloatMaxMask.class,
+                                                                      FloatMaxVector::new, FloatMaxVector.FloatMaxMask::new);
+
+    /**
+     * Preferred species for {@link FloatVector}s.
+     * A preferred species is a species of maximal bit size for the platform.
+     */
+    public static final Species<Float> SPECIES_PREFERRED = (Species<Float>) preferredSpecies();
 }
< prev index next >