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