--- /dev/null 2019-04-11 15:42:46.000000000 -0700 +++ new/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Mask.java 2019-04-11 15:42:44.277923300 -0700 @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have + * questions. + */ +package jdk.incubator.vector; + +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.ForceInline; + +import java.util.Objects; + +/** + * A {@code Mask} represents an ordered immutable sequence of {@code boolean} + * values. A Mask can be used with a mask accepting vector operation to + * control the selection and operation of lane elements of input vectors. + *

+ * 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. + *

+ * @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 mask lane index, + * if the array element at index {@code ix + 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 {@code boolean} array + * @param ix the offset into the array + * @return the mask loaded from a {@code boolean} array + * @throws IndexOutOfBoundsException if {@code ix < 0}, or + * {@code ix > bits.length - species.length()} + */ + @ForceInline + @SuppressWarnings("unchecked") + public static Mask fromArray(Species species, boolean[] bits, int ix) { + Objects.requireNonNull(bits); + ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length()); + return VectorIntrinsics.load((Class>) species.maskType(), species.elementType(), species.length(), + bits, (long) ix + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, + bits, ix, species, + (boolean[] c, int idx, Species s) -> s.opm(n -> c[idx + n])); + } + + /** + * Returns a mask where all lanes are set. + * + * @param species mask species + * @return a mask where all lanes are set + */ + @ForceInline + @SuppressWarnings("unchecked") + public static Mask maskAllTrue(Species species) { + return VectorIntrinsics.broadcastCoerced((Class>) species.maskType(), species.elementType(), species.length(), + -1, species, + ((z, s) -> AbstractMask.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 maskAllFalse(Species species) { + return VectorIntrinsics.broadcastCoerced((Class>) species.maskType(), species.elementType(), species.length(), + 0, species, + ((z, s) -> AbstractMask.falseMask(s))); + } + + /** + * Converts this mask to a mask of the given species shape of element type {@code F}. + *

+ * 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); + } +}