+ * The number of values in the sequence is referred to as the Mask + * {@link #length() length}. The length also corresponds to the number of + * Mask lanes. The lane element at lane index {@code N} (from {@code 0}, + * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th + * value in the sequence. + * A Mask and Vector of the same element type and shape have the same number + * of lanes. + *

+ * A lane is said to be set if the lane element is {@code true}, + * otherwise a lane is said to be unset if the lane element is + * {@code false}. + *

+ * Mask declares a limited set of unary, binary and reductive mask + * operations. + *

+ *
• + * A mask unary operation (1-ary) operates on one input mask to produce a + * result mask. + * For each lane of the input mask the + * lane element is operated on using the specified scalar unary operation and + * the boolean result is placed into the mask result at the same lane. + * The following pseudocode expresses the behaviour of this operation category: + * + *
```{@code
+ * Mask a = ...;
+ * boolean[] ar = new boolean[a.length()];
+ * for (int i = 0; i < a.length(); i++) {
+ *     ar[i] = boolean_unary_op(a.isSet(i));
+ * }
+ * }```
+ * + *
• + * A mask binary operation (2-ary) operates on two input + * masks to produce a result mask. + * For each lane of the two input masks, + * a and b say, the corresponding lane elements from a and b are operated on + * using the specified scalar binary operation and the boolean result is placed + * into the mask result at the same lane. + * The following pseudocode expresses the behaviour of this operation category: + * + *
```{@code
+ * Mask a = ...;
+ * Mask b = ...;
+ * boolean[] ar = new boolean[a.length()];
+ * for (int i = 0; i < a.length(); i++) {
+ *     ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i));
+ * }
+ * }```
+ * + *
+ * @param the boxed element type of this mask + */ +public abstract class Mask { + Mask() {} + + /** + * Returns the species of this mask. + * + * @return the species of this mask + */ + public abstract Species species(); + + /** + * Returns the number of mask lanes (the length). + * + * @return the number of mask lanes + */ + public int length() { return species().length(); } + + /** + * Returns a mask where each lane is set or unset according to given + * {@code boolean} values + *

+ * 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} + * then the mask lane at index {@code N} is set, otherwise it is unset. + * + * @param species mask species + * @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 fromValues(Species species, boolean... bits) { + return fromArray(species, bits, 0); + } + + /** + * Loads a mask from a {@code boolean} array starting at an offset. + *

+ * For each mask lane, where {@code N} is the lane index, if the + * mask lane at index {@code N} is set, then the mask lane at index + * {@code N} of the resulting mask is set, otherwise that mask lane is + * not set. + * + * @param s the species of the desired mask + * @param the boxed element type of the species + * @return a mask converted by shape and element type + * @throws IllegalArgumentException if this mask length and the species + * length differ + */ + public abstract Mask cast(Species s); + + /** + * Returns the lane elements of this mask packed into a {@code long} + * value for at most the first 64 lane elements. + *

+ * The lane elements are packed in the order of least significant bit + * to most significant bit. + * For each mask lane where {@code N} is the mask lane index, if the + * mask lane is set then the {@code N}'th bit is set to one in the + * resulting {@code long} value, otherwise the {@code N}'th bit is set + * to zero. + * + * @return the lane elements of this mask packed into a {@code long} + * value. + */ + public abstract long toLong(); + + /** + * Returns an {@code boolean} array containing the lane elements of this + * mask. + *

+ * This method behaves as if it {@link #intoArray(boolean[], int)} stores} + * this mask into an allocated array and returns that array as + * follows: + *

```{@code
+     * boolean[] a = new boolean[this.length()];
+     * this.intoArray(a, 0);
+     * return a;
+     * }```
+ * + * @return an array containing the the lane elements of this vector + */ + public abstract boolean[] toArray(); + + /** + * Stores this mask into a {@code boolean} array starting at offset. + *

+ * For each mask lane, where {@code N} is the mask lane index, + * the lane element at index {@code N} is stored into the array at index + * {@code i + N}. + * + * @param a the array + * @param i the offset into the array + * @throws IndexOutOfBoundsException if {@code i < 0}, or + * {@code i > a.length - this.length()} + */ + public abstract void intoArray(boolean[] a, int i); + + /** + * Returns {@code true} if any of the mask lanes are set. + * + * @return {@code true} if any of the mask lanes are set, otherwise + * {@code false}. + */ + public abstract boolean anyTrue(); + + /** + * Returns {@code true} if all of the mask lanes are set. + * + * @return {@code true} if all of the mask lanes are set, otherwise + * {@code false}. + */ + public abstract boolean allTrue(); + + /** + * Returns the number of mask lanes that are set. + * + * @return the number of mask lanes that are set. + */ + public abstract int trueCount(); + + /** + * Logically ands this mask with an input mask. + *

+ * This is a mask binary operation where the logical and operation + * ({@code &&} is applied to lane elements. + * + * @param o the input mask + * @return the result of logically and'ing this mask with an input mask + */ + public abstract Mask and(Mask o); + + /** + * Logically ors this mask with an input mask. + *

+ * This is a mask binary operation where the logical or operation + * ({@code ||} is applied to lane elements. + * + * @param o the input mask + * @return the result of logically or'ing this mask with an input mask + */ + public abstract Mask or(Mask o); + + /** + * Logically negates this mask. + *

+ * This is a mask unary operation where the logical not operation + * ({@code !} is applied to lane elements. + * + * @return the result of logically negating this mask. + */ + public abstract Mask not(); + + /** + * Returns a vector representation of this mask. + *

+ * For each mask lane, where {@code N} is the mask lane index, + * if the mask lane is set then an element value whose most significant + * bit is set is placed into the resulting vector at lane index + * {@code N}, otherwise the default element value is placed into the + * resulting vector at lane index {@code N}. + * + * @return a vector representation of this mask. + */ + public abstract Vector toVector(); + + /** + * Tests if the lane at index {@code i} is set + * @param i the lane index + * + * @return true if the lane at index {@code i} is set, otherwise false + */ + public abstract boolean getElement(int i); + + /** + * Tests if the lane at index {@code i} is set + * @param i the lane index + * @return true if the lane at index {@code i} is set, otherwise false + * @see #getElement + */ + public boolean isSet(int i) { + return getElement(i); + } +}