1 /* 2 * Copyright (c) 2017, 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 23 * questions. 24 */ 25 package jdk.incubator.vector; 26 27 import jdk.internal.misc.Unsafe; 28 import jdk.internal.vm.annotation.ForceInline; 29 30 import java.util.Objects; 31 32 /** 33 * A {@code VectorMask} represents an ordered immutable sequence of {@code boolean} 34 * values. A VectorMask can be used with a mask accepting vector operation to 35 * control the selection and operation of lane elements of input vectors. 36 * <p> 37 * The number of values in the sequence is referred to as the VectorMask 38 * {@link #length() length}. The length also corresponds to the number of 39 * VectorMask lanes. The lane element at lane index {@code N} (from {@code 0}, 40 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th 41 * value in the sequence. 42 * A VectorMask and Vector of the same element type and shape have the same number 43 * of lanes. 44 * <p> 45 * A lane is said to be <em>set</em> if the lane element is {@code true}, 46 * otherwise a lane is said to be <em>unset</em> if the lane element is 47 * {@code false}. 48 * <p> 49 * VectorMask declares a limited set of unary, binary and reductive mask 50 * operations. 51 * <ul> 52 * <li> 53 * A mask unary operation (1-ary) operates on one input mask to produce a 54 * result mask. 55 * For each lane of the input mask the 56 * lane element is operated on using the specified scalar unary operation and 57 * the boolean result is placed into the mask result at the same lane. 58 * The following pseudocode expresses the behaviour of this operation category: 59 * 60 * <pre>{@code 61 * VectorMask<E> a = ...; 62 * boolean[] ar = new boolean[a.length()]; 63 * for (int i = 0; i < a.length(); i++) { 64 * ar[i] = boolean_unary_op(a.isSet(i)); 65 * } 66 * VectorMask<E> r = VectorMask.fromArray(ar, 0); 67 * }</pre> 68 * 69 * <li> 70 * A mask binary operation (2-ary) operates on two input 71 * masks to produce a result mask. 72 * For each lane of the two input masks, 73 * a and b say, the corresponding lane elements from a and b are operated on 74 * using the specified scalar binary operation and the boolean result is placed 75 * into the mask result at the same lane. 76 * The following pseudocode expresses the behaviour of this operation category: 77 * 78 * <pre>{@code 79 * VectorMask<E> a = ...; 80 * VectorMask<E> b = ...; 81 * boolean[] ar = new boolean[a.length()]; 82 * for (int i = 0; i < a.length(); i++) { 83 * ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i)); 84 * } 85 * VectorMask<E> r = VectorMask.fromArray(ar, 0); 86 * }</pre> 87 * 88 * </ul> 89 * @param <E> the boxed element type of this mask 90 */ 91 public abstract class VectorMask<E> { 92 VectorMask() {} 93 94 /** 95 * Returns the species of this mask. 96 * 97 * @return the species of this mask 98 */ 99 public abstract VectorSpecies<E> species(); 100 101 /** 102 * Returns the number of mask lanes (the length). 103 * 104 * @return the number of mask lanes 105 */ 106 public int length() { return species().length(); } 107 108 /** 109 * Returns a mask where each lane is set or unset according to given 110 * {@code boolean} values 111 * <p> 112 * For each mask lane, where {@code N} is the mask lane index, 113 * if the given {@code boolean} value at index {@code N} is {@code true} 114 * then the mask lane at index {@code N} is set, otherwise it is unset. 115 * 116 * @param species mask species 117 * @param bits the given {@code boolean} values 118 * @return a mask where each lane is set or unset according to the given {@code boolean} value 119 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()} 120 */ 121 @ForceInline 122 public static <E> VectorMask<E> fromValues(VectorSpecies<E> species, boolean... bits) { 123 return fromArray(species, bits, 0); 124 } 125 126 /** 127 * Loads a mask from a {@code boolean} array starting at an offset. 128 * <p> 129 * For each mask lane, where {@code N} is the mask lane index, 130 * if the array element at index {@code ix + N} is {@code true} then the 131 * mask lane at index {@code N} is set, otherwise it is unset. 132 * 133 * @param species mask species 134 * @param bits the {@code boolean} array 135 * @param ix the offset into the array 136 * @return the mask loaded from a {@code boolean} array 137 * @throws IndexOutOfBoundsException if {@code ix < 0}, or 138 * {@code ix > bits.length - species.length()} 139 */ 140 @ForceInline 141 @SuppressWarnings("unchecked") 142 public static <E> VectorMask<E> fromArray(VectorSpecies<E> species, boolean[] bits, int ix) { 143 Objects.requireNonNull(bits); 144 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length()); 145 return VectorIntrinsics.load((Class<VectorMask<E>>) species.maskType(), species.elementType(), species.length(), 146 bits, (long) ix + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, 147 bits, ix, species, 148 (boolean[] c, int idx, VectorSpecies<E> s) -> ((AbstractSpecies<E>)s).opm(n -> c[idx + n])); 149 } 150 151 /** 152 * Returns a mask where all lanes are set. 153 * 154 * @param species mask species 155 * @return a mask where all lanes are set 156 */ 157 @ForceInline 158 @SuppressWarnings("unchecked") 159 public static <E> VectorMask<E> maskAllTrue(VectorSpecies<E> species) { 160 return VectorIntrinsics.broadcastCoerced((Class<VectorMask<E>>) species.maskType(), species.elementType(), species.length(), 161 -1, species, 162 ((z, s) -> AbstractMask.trueMask(s))); 163 } 164 165 /** 166 * Returns a mask where all lanes are unset. 167 * 168 * @param species mask species 169 * @return a mask where all lanes are unset 170 */ 171 @ForceInline 172 @SuppressWarnings("unchecked") 173 public static <E> VectorMask<E> maskAllFalse(VectorSpecies<E> species) { 174 return VectorIntrinsics.broadcastCoerced((Class<VectorMask<E>>) species.maskType(), species.elementType(), species.length(), 175 0, species, 176 ((z, s) -> AbstractMask.falseMask(s))); 177 } 178 179 /** 180 * Converts this mask to a mask of the given species shape of element type {@code F}. 181 * <p> 182 * For each mask lane, where {@code N} is the lane index, if the 183 * mask lane at index {@code N} is set, then the mask lane at index 184 * {@code N} of the resulting mask is set, otherwise that mask lane is 185 * not set. 186 * 187 * @param s the species of the desired mask 188 * @param <F> the boxed element type of the species 189 * @return a mask converted by shape and element type 190 * @throws IllegalArgumentException if this mask length and the species 191 * length differ 192 */ 193 public abstract <F> VectorMask<F> cast(VectorSpecies<F> s); 194 195 /** 196 * Returns the lane elements of this mask packed into a {@code long} 197 * value for at most the first 64 lane elements. 198 * <p> 199 * The lane elements are packed in the order of least significant bit 200 * to most significant bit. 201 * For each mask lane where {@code N} is the mask lane index, if the 202 * mask lane is set then the {@code N}'th bit is set to one in the 203 * resulting {@code long} value, otherwise the {@code N}'th bit is set 204 * to zero. 205 * 206 * @return the lane elements of this mask packed into a {@code long} 207 * value. 208 */ 209 public abstract long toLong(); 210 211 /** 212 * Returns an {@code boolean} array containing the lane elements of this 213 * mask. 214 * <p> 215 * This method behaves as if it {@link #intoArray(boolean[], int)} stores} 216 * this mask into an allocated array and returns that array as 217 * follows: 218 * <pre>{@code 219 * boolean[] a = new boolean[this.length()]; 220 * this.intoArray(a, 0); 221 * return a; 222 * }</pre> 223 * 224 * @return an array containing the the lane elements of this vector 225 */ 226 public abstract boolean[] toArray(); 227 228 /** 229 * Stores this mask into a {@code boolean} array starting at offset. 230 * <p> 231 * For each mask lane, where {@code N} is the mask lane index, 232 * the lane element at index {@code N} is stored into the array at index 233 * {@code i + N}. 234 * 235 * @param a the array 236 * @param i the offset into the array 237 * @throws IndexOutOfBoundsException if {@code i < 0}, or 238 * {@code i > a.length - this.length()} 239 */ 240 public abstract void intoArray(boolean[] a, int i); 241 242 /** 243 * Returns {@code true} if any of the mask lanes are set. 244 * 245 * @return {@code true} if any of the mask lanes are set, otherwise 246 * {@code false}. 247 */ 248 public abstract boolean anyTrue(); 249 250 /** 251 * Returns {@code true} if all of the mask lanes are set. 252 * 253 * @return {@code true} if all of the mask lanes are set, otherwise 254 * {@code false}. 255 */ 256 public abstract boolean allTrue(); 257 258 /** 259 * Returns the number of mask lanes that are set. 260 * 261 * @return the number of mask lanes that are set. 262 */ 263 public abstract int trueCount(); 264 265 /** 266 * Logically ands this mask with an input mask. 267 * <p> 268 * This is a mask binary operation where the logical and operation 269 * ({@code &&} is applied to lane elements. 270 * 271 * @param o the input mask 272 * @return the result of logically and'ing this mask with an input mask 273 */ 274 public abstract VectorMask<E> and(VectorMask<E> o); 275 276 /** 277 * Logically ors this mask with an input mask. 278 * <p> 279 * This is a mask binary operation where the logical or operation 280 * ({@code ||} is applied to lane elements. 281 * 282 * @param o the input mask 283 * @return the result of logically or'ing this mask with an input mask 284 */ 285 public abstract VectorMask<E> or(VectorMask<E> o); 286 287 /** 288 * Logically negates this mask. 289 * <p> 290 * This is a mask unary operation where the logical not operation 291 * ({@code !} is applied to lane elements. 292 * 293 * @return the result of logically negating this mask. 294 */ 295 public abstract VectorMask<E> not(); 296 297 /** 298 * Returns a vector representation of this mask. 299 * <p> 300 * For each mask lane, where {@code N} is the mask lane index, 301 * if the mask lane is set then an element value whose most significant 302 * bit is set is placed into the resulting vector at lane index 303 * {@code N}, otherwise the default element value is placed into the 304 * resulting vector at lane index {@code N}. 305 * 306 * @return a vector representation of this mask. 307 */ 308 public abstract Vector<E> toVector(); 309 310 /** 311 * Tests if the lane at index {@code i} is set 312 * @param i the lane index 313 * 314 * @return true if the lane at index {@code i} is set, otherwise false 315 */ 316 public abstract boolean getElement(int i); 317 318 /** 319 * Tests if the lane at index {@code i} is set 320 * @param i the lane index 321 * @return true if the lane at index {@code i} is set, otherwise false 322 * @see #getElement 323 */ 324 public boolean isSet(int i) { 325 return getElement(i); 326 } 327 }