/* * 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 VectorMask} represents an ordered immutable sequence of {@code boolean} * values. Some vector operations accept masks to * control the selection and operation of lane elements of input vectors. *

* The number of values in the sequence is referred to as the VectorMask * {@link #length() length}. The length also corresponds to the number of * VectorMask 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 VectorMask 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}. *

* VectorMask declares a limited set of unary, binary and reduction operations. *

* @param the boxed element type of this mask */ public abstract class VectorMask { VectorMask() {} /** * Returns the species of this mask. * * @return the species of this mask */ public abstract VectorSpecies 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 VectorMask fromValues(VectorSpecies 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 offset the offset into the array * @return the mask loaded from a {@code boolean} array * @throws IndexOutOfBoundsException if {@code offset < 0}, or * {@code offset > bits.length - species.length()} */ @ForceInline @SuppressWarnings("unchecked") public static VectorMask fromArray(VectorSpecies species, boolean[] bits, int offset) { Objects.requireNonNull(bits); offset = VectorIntrinsics.checkIndex(offset, bits.length, species.length()); return VectorIntrinsics.load((Class>) species.maskType(), species.elementType(), species.length(), bits, (long) offset + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, bits, offset, species, (boolean[] c, int idx, VectorSpecies s) -> ((AbstractSpecies)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 VectorMask maskAllTrue(VectorSpecies 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 VectorMask maskAllFalse(VectorSpecies 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 VectorMask cast(VectorSpecies 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 offset the offset into the array * @throws IndexOutOfBoundsException if {@code offset < 0}, or * {@code offset > a.length - this.length()} */ public abstract void intoArray(boolean[] a, int offset); /** * 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 lane-wise binary operation which applies the logical and operation * ({@code &&}) to each lane. * * @param o the input mask * @return the result of logically and'ing this mask with an input mask */ public abstract VectorMask and(VectorMask o); /** * Logically ors this mask with an input mask. *

* This is a lane-wise binary operation which applies the logical or operation * ({@code ||}) to each lane. * * @param o the input mask * @return the result of logically or'ing this mask with an input mask */ public abstract VectorMask or(VectorMask o); /** * Logically negates this mask. *

* This is a lane-wise unary operation which applies the logical not operation * ({@code !}) to each lane. * * @return the result of logically negating this mask. */ public abstract VectorMask 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 lane(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 #lane */ public boolean isSet(int i) { return lane(i); } }