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 java.nio.ByteBuffer; 28 import java.nio.ByteOrder; 29 import java.util.Objects; 30 import java.util.function.IntUnaryOperator; 31 import java.util.function.Function; 32 import java.util.concurrent.ThreadLocalRandom; 33 34 import jdk.internal.misc.Unsafe; 35 import jdk.internal.vm.annotation.ForceInline; 36 import static jdk.incubator.vector.VectorIntrinsics.*; 37 38 39 /** 40 * A specialized {@link Vector} representing an ordered immutable sequence of 41 * {@code byte} values. 42 */ 43 @SuppressWarnings("cast") 44 public abstract class ByteVector extends Vector<Byte> { 45 46 ByteVector() {} 47 48 private static final int ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_BYTE_INDEX_SCALE); 49 50 // Unary operator 51 52 interface FUnOp { 53 byte apply(int i, byte a); 54 } 55 56 abstract ByteVector uOp(FUnOp f); 57 58 abstract ByteVector uOp(Mask<Byte> m, FUnOp f); 59 60 // Binary operator 61 62 interface FBinOp { 63 byte apply(int i, byte a, byte b); 64 } 65 66 abstract ByteVector bOp(Vector<Byte> v, FBinOp f); 67 68 abstract ByteVector bOp(Vector<Byte> v, Mask<Byte> m, FBinOp f); 69 70 // Trinary operator 71 72 interface FTriOp { 73 byte apply(int i, byte a, byte b, byte c); 74 } 75 76 abstract ByteVector tOp(Vector<Byte> v1, Vector<Byte> v2, FTriOp f); 77 78 abstract ByteVector tOp(Vector<Byte> v1, Vector<Byte> v2, Mask<Byte> m, FTriOp f); 79 80 // Reduction operator 81 82 abstract byte rOp(byte v, FBinOp f); 83 84 // Binary test 85 86 interface FBinTest { 87 boolean apply(int i, byte a, byte b); 88 } 89 90 abstract Mask<Byte> bTest(Vector<Byte> v, FBinTest f); 91 92 // Foreach 93 94 interface FUnCon { 95 void apply(int i, byte a); 96 } 97 98 abstract void forEach(FUnCon f); 99 100 abstract void forEach(Mask<Byte> m, FUnCon f); 101 102 // Static factories 103 104 /** 105 * Returns a vector where all lane elements are set to the default 106 * primitive value. 107 * 108 * @param species species of desired vector 109 * @return a zero vector of given species 110 */ 111 @ForceInline 112 @SuppressWarnings("unchecked") 113 public static ByteVector zero(Species<Byte> species) { 114 return VectorIntrinsics.broadcastCoerced((Class<ByteVector>) species.boxType(), byte.class, species.length(), 115 0, species, 116 ((bits, s) -> ((ByteSpecies)s).op(i -> (byte)bits))); 117 } 118 119 /** 120 * Loads a vector from a byte array starting at an offset. 121 * <p> 122 * Bytes are composed into primitive lane elements according to the 123 * native byte order of the underlying platform 124 * <p> 125 * This method behaves as if it returns the result of calling the 126 * byte buffer, offset, and mask accepting 127 * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask) method} as follows: 128 * <pre>{@code 129 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); 130 * }</pre> 131 * 132 * @param species species of desired vector 133 * @param a the byte array 134 * @param ix the offset into the array 135 * @return a vector loaded from a byte array 136 * @throws IndexOutOfBoundsException if {@code i < 0} or 137 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 138 */ 139 @ForceInline 140 @SuppressWarnings("unchecked") 141 public static ByteVector fromByteArray(Species<Byte> species, byte[] a, int ix) { 142 Objects.requireNonNull(a); 143 ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE); 144 return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(), 145 a, ((long) ix) + Unsafe.ARRAY_BYTE_BASE_OFFSET, 146 a, ix, species, 147 (c, idx, s) -> { 148 ByteBuffer bbc = ByteBuffer.wrap(c, idx, a.length - idx).order(ByteOrder.nativeOrder()); 149 ByteBuffer tb = bbc; 150 return ((ByteSpecies)s).op(i -> tb.get()); 151 }); 152 } 153 154 /** 155 * Loads a vector from a byte array starting at an offset and using a 156 * mask. 157 * <p> 158 * Bytes are composed into primitive lane elements according to the 159 * native byte order of the underlying platform. 160 * <p> 161 * This method behaves as if it returns the result of calling the 162 * byte buffer, offset, and mask accepting 163 * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask) method} as follows: 164 * <pre>{@code 165 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m); 166 * }</pre> 167 * 168 * @param species species of desired vector 169 * @param a the byte array 170 * @param ix the offset into the array 171 * @param m the mask 172 * @return a vector loaded from a byte array 173 * @throws IndexOutOfBoundsException if {@code i < 0} or 174 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 175 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 176 * or {@code > a.length}, 177 * for any vector lane index {@code N} where the mask at lane {@code N} 178 * is set 179 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} 180 */ 181 @ForceInline 182 public static ByteVector fromByteArray(Species<Byte> species, byte[] a, int ix, Mask<Byte> m) { 183 return zero(species).blend(fromByteArray(species, a, ix), m); 184 } 185 186 /** 187 * Loads a vector from an array starting at offset. 188 * <p> 189 * For each vector lane, where {@code N} is the vector lane index, the 190 * array element at index {@code i + N} is placed into the 191 * resulting vector at lane index {@code N}. 192 * 193 * @param species species of desired vector 194 * @param a the array 195 * @param i the offset into the array 196 * @return the vector loaded from an array 197 * @throws IndexOutOfBoundsException if {@code i < 0}, or 198 * {@code i > a.length - this.length()} 199 */ 200 @ForceInline 201 @SuppressWarnings("unchecked") 202 public static ByteVector fromArray(Species<Byte> species, byte[] a, int i){ 203 Objects.requireNonNull(a); 204 i = VectorIntrinsics.checkIndex(i, a.length, species.length()); 205 return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(), 206 a, (((long) i) << ARRAY_SHIFT) + Unsafe.ARRAY_BYTE_BASE_OFFSET, 207 a, i, species, 208 (c, idx, s) -> ((ByteSpecies)s).op(n -> c[idx + n])); 209 } 210 211 212 /** 213 * Loads a vector from an array starting at offset and using a mask. 214 * <p> 215 * For each vector lane, where {@code N} is the vector lane index, 216 * if the mask lane at index {@code N} is set then the array element at 217 * index {@code i + N} is placed into the resulting vector at lane index 218 * {@code N}, otherwise the default element value is placed into the 219 * resulting vector at lane index {@code N}. 220 * 221 * @param species species of desired vector 222 * @param a the array 223 * @param i the offset into the array 224 * @param m the mask 225 * @return the vector loaded from an array 226 * @throws IndexOutOfBoundsException if {@code i < 0}, or 227 * for any vector lane index {@code N} where the mask at lane {@code N} 228 * is set {@code i > a.length - N} 229 */ 230 @ForceInline 231 public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, Mask<Byte> m) { 232 return zero(species).blend(fromArray(species, a, i), m); 233 } 234 235 /** 236 * Loads a vector from an array using indexes obtained from an index 237 * map. 238 * <p> 239 * For each vector lane, where {@code N} is the vector lane index, the 240 * array element at index {@code i + indexMap[j + N]} is placed into the 241 * resulting vector at lane index {@code N}. 242 * 243 * @param species species of desired vector 244 * @param a the array 245 * @param i the offset into the array, may be negative if relative 246 * indexes in the index map compensate to produce a value within the 247 * array bounds 248 * @param indexMap the index map 249 * @param j the offset into the index map 250 * @return the vector loaded from an array 251 * @throws IndexOutOfBoundsException if {@code j < 0}, or 252 * {@code j > indexMap.length - this.length()}, 253 * or for any vector lane index {@code N} the result of 254 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 255 */ 256 public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, int[] indexMap, int j) { 257 return ((ByteSpecies)species).op(n -> a[i + indexMap[j + n]]); 258 } 259 /** 260 * Loads a vector from an array using indexes obtained from an index 261 * map and using a mask. 262 * <p> 263 * For each vector lane, where {@code N} is the vector lane index, 264 * if the mask lane at index {@code N} is set then the array element at 265 * index {@code i + indexMap[j + N]} is placed into the resulting vector 266 * at lane index {@code N}. 267 * 268 * @param species species of desired vector 269 * @param a the array 270 * @param i the offset into the array, may be negative if relative 271 * indexes in the index map compensate to produce a value within the 272 * array bounds 273 * @param m the mask 274 * @param indexMap the index map 275 * @param j the offset into the index map 276 * @return the vector loaded from an array 277 * @throws IndexOutOfBoundsException if {@code j < 0}, or 278 * {@code j > indexMap.length - this.length()}, 279 * or for any vector lane index {@code N} where the mask at lane 280 * {@code N} is set the result of {@code i + indexMap[j + N]} is 281 * {@code < 0} or {@code >= a.length} 282 */ 283 public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) { 284 return ((ByteSpecies)species).op(m, n -> a[i + indexMap[j + n]]); 285 } 286 287 /** 288 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an 289 * offset into the byte buffer. 290 * <p> 291 * Bytes are composed into primitive lane elements according to the 292 * native byte order of the underlying platform. 293 * <p> 294 * This method behaves as if it returns the result of calling the 295 * byte buffer, offset, and mask accepting 296 * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask)} method} as follows: 297 * <pre>{@code 298 * return this.fromByteBuffer(b, i, this.maskAllTrue()) 299 * }</pre> 300 * 301 * @param species species of desired vector 302 * @param bb the byte buffer 303 * @param ix the offset into the byte buffer 304 * @return a vector loaded from a byte buffer 305 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 306 * or {@code > b.limit()}, 307 * or if there are fewer than 308 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 309 * remaining in the byte buffer from the given offset 310 */ 311 @ForceInline 312 @SuppressWarnings("unchecked") 313 public static ByteVector fromByteBuffer(Species<Byte> species, ByteBuffer bb, int ix) { 314 if (bb.order() != ByteOrder.nativeOrder()) { 315 throw new IllegalArgumentException(); 316 } 317 ix = VectorIntrinsics.checkIndex(ix, bb.limit(), species.bitSize() / Byte.SIZE); 318 return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(), 319 U.getReference(bb, BYTE_BUFFER_HB), U.getLong(bb, BUFFER_ADDRESS) + ix, 320 bb, ix, species, 321 (c, idx, s) -> { 322 ByteBuffer bbc = c.duplicate().position(idx).order(ByteOrder.nativeOrder()); 323 ByteBuffer tb = bbc; 324 return ((ByteSpecies)s).op(i -> tb.get()); 325 }); 326 } 327 328 /** 329 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an 330 * offset into the byte buffer and using a mask. 331 * <p> 332 * This method behaves as if the byte buffer is viewed as a primitive 333 * {@link java.nio.Buffer buffer} for the primitive element type, 334 * according to the native byte order of the underlying platform, and 335 * the returned vector is loaded with a mask from a primitive array 336 * obtained from the primitive buffer. 337 * The following pseudocode expresses the behaviour, where 338 * {@coce EBuffer} is the primitive buffer type, {@code e} is the 339 * primitive element type, and {@code ESpecies<S>} is the primitive 340 * species for {@code e}: 341 * <pre>{@code 342 * EBuffer eb = b.duplicate(). 343 * order(ByteOrder.nativeOrder()).position(i). 344 * asEBuffer(); 345 * e[] es = new e[this.length()]; 346 * for (int n = 0; n < t.length; n++) { 347 * if (m.isSet(n)) 348 * es[n] = eb.get(n); 349 * } 350 * Vector<E> r = ((ESpecies<S>)this).fromArray(es, 0, m); 351 * }</pre> 352 * 353 * @param species species of desired vector 354 * @param bb the byte buffer 355 * @param ix the offset into the byte buffer 356 * @param m the mask 357 * @return a vector loaded from a byte buffer 358 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 359 * or {@code > b.limit()}, 360 * for any vector lane index {@code N} where the mask at lane {@code N} 361 * is set 362 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} 363 */ 364 @ForceInline 365 public static ByteVector fromByteBuffer(Species<Byte> species, ByteBuffer bb, int ix, Mask<Byte> m) { 366 return zero(species).blend(fromByteBuffer(species, bb, ix), m); 367 } 368 369 /** 370 * Returns a vector where all lane elements are set to the primitive 371 * value {@code e}. 372 * 373 * @param s species of the desired vector 374 * @param e the value 375 * @return a vector of vector where all lane elements are set to 376 * the primitive value {@code e} 377 */ 378 @ForceInline 379 @SuppressWarnings("unchecked") 380 public static ByteVector broadcast(Species<Byte> s, byte e) { 381 return VectorIntrinsics.broadcastCoerced( 382 (Class<ByteVector>) s.boxType(), byte.class, s.length(), 383 e, s, 384 ((bits, sp) -> ((ByteSpecies)sp).op(i -> (byte)bits))); 385 } 386 387 /** 388 * Returns a vector where each lane element is set to a given 389 * primitive value. 390 * <p> 391 * For each vector lane, where {@code N} is the vector lane index, the 392 * the primitive value at index {@code N} is placed into the resulting 393 * vector at lane index {@code N}. 394 * 395 * @param s species of the desired vector 396 * @param es the given primitive values 397 * @return a vector where each lane element is set to a given primitive 398 * value 399 * @throws IndexOutOfBoundsException if {@code es.length < this.length()} 400 */ 401 @ForceInline 402 @SuppressWarnings("unchecked") 403 public static ByteVector scalars(Species<Byte> s, byte... es) { 404 Objects.requireNonNull(es); 405 int ix = VectorIntrinsics.checkIndex(0, es.length, s.length()); 406 return VectorIntrinsics.load((Class<ByteVector>) s.boxType(), byte.class, s.length(), 407 es, Unsafe.ARRAY_BYTE_BASE_OFFSET, 408 es, ix, s, 409 (c, idx, sp) -> ((ByteSpecies)sp).op(n -> c[idx + n])); 410 } 411 412 /** 413 * Returns a vector where the first lane element is set to the primtive 414 * value {@code e}, all other lane elements are set to the default 415 * value. 416 * 417 * @param s species of the desired vector 418 * @param e the value 419 * @return a vector where the first lane element is set to the primitive 420 * value {@code e} 421 */ 422 @ForceInline 423 public static final ByteVector single(Species<Byte> s, byte e) { 424 return zero(s).with(0, e); 425 } 426 427 /** 428 * Returns a vector where each lane element is set to a randomly 429 * generated primitive value. 430 * 431 * The semantics are equivalent to calling 432 * (byte){@link ThreadLocalRandom#nextInt()} 433 * 434 * @param s species of the desired vector 435 * @return a vector where each lane elements is set to a randomly 436 * generated primitive value 437 */ 438 public static ByteVector random(Species<Byte> s) { 439 ThreadLocalRandom r = ThreadLocalRandom.current(); 440 return ((ByteSpecies)s).op(i -> (byte) r.nextInt()); 441 } 442 443 /** 444 * Returns a mask where each lane is set or unset according to given 445 * {@code boolean} values 446 * <p> 447 * For each mask lane, where {@code N} is the mask lane index, 448 * if the given {@code boolean} value at index {@code N} is {@code true} 449 * then the mask lane at index {@code N} is set, otherwise it is unset. 450 * 451 * @param species mask species 452 * @param bits the given {@code boolean} values 453 * @return a mask where each lane is set or unset according to the given {@code boolean} value 454 * @throws IndexOutOfBoundsException if {@code bits.length < species.length()} 455 */ 456 @ForceInline 457 public static Mask<Byte> maskFromValues(Species<Byte> species, boolean... bits) { 458 if (species.boxType() == ByteMaxVector.class) 459 return new ByteMaxVector.ByteMaxMask(bits); 460 switch (species.bitSize()) { 461 case 64: return new Byte64Vector.Byte64Mask(bits); 462 case 128: return new Byte128Vector.Byte128Mask(bits); 463 case 256: return new Byte256Vector.Byte256Mask(bits); 464 case 512: return new Byte512Vector.Byte512Mask(bits); 465 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 466 } 467 } 468 469 // @@@ This is a bad implementation -- makes lambdas capturing -- fix this 470 static Mask<Byte> trueMask(Species<Byte> species) { 471 if (species.boxType() == ByteMaxVector.class) 472 return ByteMaxVector.ByteMaxMask.TRUE_MASK; 473 switch (species.bitSize()) { 474 case 64: return Byte64Vector.Byte64Mask.TRUE_MASK; 475 case 128: return Byte128Vector.Byte128Mask.TRUE_MASK; 476 case 256: return Byte256Vector.Byte256Mask.TRUE_MASK; 477 case 512: return Byte512Vector.Byte512Mask.TRUE_MASK; 478 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 479 } 480 } 481 482 static Mask<Byte> falseMask(Species<Byte> species) { 483 if (species.boxType() == ByteMaxVector.class) 484 return ByteMaxVector.ByteMaxMask.FALSE_MASK; 485 switch (species.bitSize()) { 486 case 64: return Byte64Vector.Byte64Mask.FALSE_MASK; 487 case 128: return Byte128Vector.Byte128Mask.FALSE_MASK; 488 case 256: return Byte256Vector.Byte256Mask.FALSE_MASK; 489 case 512: return Byte512Vector.Byte512Mask.FALSE_MASK; 490 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 491 } 492 } 493 494 /** 495 * Loads a mask from a {@code boolean} array starting at an offset. 496 * <p> 497 * For each mask lane, where {@code N} is the mask lane index, 498 * if the array element at index {@code ix + N} is {@code true} then the 499 * mask lane at index {@code N} is set, otherwise it is unset. 500 * 501 * @param species mask species 502 * @param bits the {@code boolean} array 503 * @param ix the offset into the array 504 * @return the mask loaded from a {@code boolean} array 505 * @throws IndexOutOfBoundsException if {@code ix < 0}, or 506 * {@code ix > bits.length - species.length()} 507 */ 508 @ForceInline 509 @SuppressWarnings("unchecked") 510 public static Mask<Byte> maskFromArray(Species<Byte> species, boolean[] bits, int ix) { 511 Objects.requireNonNull(bits); 512 ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length()); 513 return VectorIntrinsics.load((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(), 514 bits, (((long) ix) << ARRAY_SHIFT) + Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, 515 bits, ix, species, 516 (c, idx, s) -> (Mask<Byte>) ((ByteSpecies)s).opm(n -> c[idx + n])); 517 } 518 519 /** 520 * Returns a mask where all lanes are set. 521 * 522 * @param species mask species 523 * @return a mask where all lanes are set 524 */ 525 @ForceInline 526 @SuppressWarnings("unchecked") 527 public static Mask<Byte> maskAllTrue(Species<Byte> species) { 528 return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(), 529 (byte)-1, species, 530 ((z, s) -> trueMask(s))); 531 } 532 533 /** 534 * Returns a mask where all lanes are unset. 535 * 536 * @param species mask species 537 * @return a mask where all lanes are unset 538 */ 539 @ForceInline 540 @SuppressWarnings("unchecked") 541 public static Mask<Byte> maskAllFalse(Species<Byte> species) { 542 return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(), 543 0, species, 544 ((z, s) -> falseMask(s))); 545 } 546 547 /** 548 * Returns a shuffle of mapped indexes where each lane element is 549 * the result of applying a mapping function to the corresponding lane 550 * index. 551 * <p> 552 * Care should be taken to ensure Shuffle values produced from this 553 * method are consumed as constants to ensure optimal generation of 554 * code. For example, values held in static final fields or values 555 * held in loop constant local variables. 556 * <p> 557 * This method behaves as if a shuffle is created from an array of 558 * mapped indexes as follows: 559 * <pre>{@code 560 * int[] a = new int[species.length()]; 561 * for (int i = 0; i < a.length; i++) { 562 * a[i] = f.applyAsInt(i); 563 * } 564 * return this.shuffleFromValues(a); 565 * }</pre> 566 * 567 * @param species shuffle species 568 * @param f the lane index mapping function 569 * @return a shuffle of mapped indexes 570 */ 571 @ForceInline 572 public static Shuffle<Byte> shuffle(Species<Byte> species, IntUnaryOperator f) { 573 if (species.boxType() == ByteMaxVector.class) 574 return new ByteMaxVector.ByteMaxShuffle(f); 575 switch (species.bitSize()) { 576 case 64: return new Byte64Vector.Byte64Shuffle(f); 577 case 128: return new Byte128Vector.Byte128Shuffle(f); 578 case 256: return new Byte256Vector.Byte256Shuffle(f); 579 case 512: return new Byte512Vector.Byte512Shuffle(f); 580 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 581 } 582 } 583 584 /** 585 * Returns a shuffle where each lane element is the value of its 586 * corresponding lane index. 587 * <p> 588 * This method behaves as if a shuffle is created from an identity 589 * index mapping function as follows: 590 * <pre>{@code 591 * return this.shuffle(i -> i); 592 * }</pre> 593 * 594 * @param species shuffle species 595 * @return a shuffle of lane indexes 596 */ 597 @ForceInline 598 public static Shuffle<Byte> shuffleIota(Species<Byte> species) { 599 if (species.boxType() == ByteMaxVector.class) 600 return new ByteMaxVector.ByteMaxShuffle(AbstractShuffle.IDENTITY); 601 switch (species.bitSize()) { 602 case 64: return new Byte64Vector.Byte64Shuffle(AbstractShuffle.IDENTITY); 603 case 128: return new Byte128Vector.Byte128Shuffle(AbstractShuffle.IDENTITY); 604 case 256: return new Byte256Vector.Byte256Shuffle(AbstractShuffle.IDENTITY); 605 case 512: return new Byte512Vector.Byte512Shuffle(AbstractShuffle.IDENTITY); 606 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 607 } 608 } 609 610 /** 611 * Returns a shuffle where each lane element is set to a given 612 * {@code int} value logically AND'ed by the species length minus one. 613 * <p> 614 * For each shuffle lane, where {@code N} is the shuffle lane index, the 615 * the {@code int} value at index {@code N} logically AND'ed by 616 * {@code species.length() - 1} is placed into the resulting shuffle at 617 * lane index {@code N}. 618 * 619 * @param species shuffle species 620 * @param ixs the given {@code int} values 621 * @return a shuffle where each lane element is set to a given 622 * {@code int} value 623 * @throws IndexOutOfBoundsException if the number of int values is 624 * {@code < species.length()} 625 */ 626 @ForceInline 627 public static Shuffle<Byte> shuffleFromValues(Species<Byte> species, int... ixs) { 628 if (species.boxType() == ByteMaxVector.class) 629 return new ByteMaxVector.ByteMaxShuffle(ixs); 630 switch (species.bitSize()) { 631 case 64: return new Byte64Vector.Byte64Shuffle(ixs); 632 case 128: return new Byte128Vector.Byte128Shuffle(ixs); 633 case 256: return new Byte256Vector.Byte256Shuffle(ixs); 634 case 512: return new Byte512Vector.Byte512Shuffle(ixs); 635 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 636 } 637 } 638 639 /** 640 * Loads a shuffle from an {@code int} array starting at an offset. 641 * <p> 642 * For each shuffle lane, where {@code N} is the shuffle lane index, the 643 * array element at index {@code i + N} logically AND'ed by 644 * {@code species.length() - 1} is placed into the resulting shuffle at lane 645 * index {@code N}. 646 * 647 * @param species shuffle species 648 * @param ixs the {@code int} array 649 * @param i the offset into the array 650 * @return a shuffle loaded from the {@code int} array 651 * @throws IndexOutOfBoundsException if {@code i < 0}, or 652 * {@code i > a.length - species.length()} 653 */ 654 @ForceInline 655 public static Shuffle<Byte> shuffleFromArray(Species<Byte> species, int[] ixs, int i) { 656 if (species.boxType() == ByteMaxVector.class) 657 return new ByteMaxVector.ByteMaxShuffle(ixs, i); 658 switch (species.bitSize()) { 659 case 64: return new Byte64Vector.Byte64Shuffle(ixs, i); 660 case 128: return new Byte128Vector.Byte128Shuffle(ixs, i); 661 case 256: return new Byte256Vector.Byte256Shuffle(ixs, i); 662 case 512: return new Byte512Vector.Byte512Shuffle(ixs, i); 663 default: throw new IllegalArgumentException(Integer.toString(species.bitSize())); 664 } 665 } 666 667 // Ops 668 669 @Override 670 public abstract ByteVector add(Vector<Byte> v); 671 672 /** 673 * Adds this vector to the broadcast of an input scalar. 674 * <p> 675 * This is a vector binary operation where the primitive addition operation 676 * ({@code +}) is applied to lane elements. 677 * 678 * @param s the input scalar 679 * @return the result of adding this vector to the broadcast of an input 680 * scalar 681 */ 682 public abstract ByteVector add(byte s); 683 684 @Override 685 public abstract ByteVector add(Vector<Byte> v, Mask<Byte> m); 686 687 /** 688 * Adds this vector to broadcast of an input scalar, 689 * selecting lane elements controlled by a mask. 690 * <p> 691 * This is a vector binary operation where the primitive addition operation 692 * ({@code +}) is applied to lane elements. 693 * 694 * @param s the input scalar 695 * @param m the mask controlling lane selection 696 * @return the result of adding this vector to the broadcast of an input 697 * scalar 698 */ 699 public abstract ByteVector add(byte s, Mask<Byte> m); 700 701 @Override 702 public abstract ByteVector sub(Vector<Byte> v); 703 704 /** 705 * Subtracts the broadcast of an input scalar from this vector. 706 * <p> 707 * This is a vector binary operation where the primitive subtraction 708 * operation ({@code -}) is applied to lane elements. 709 * 710 * @param s the input scalar 711 * @return the result of subtracting the broadcast of an input 712 * scalar from this vector 713 */ 714 public abstract ByteVector sub(byte s); 715 716 @Override 717 public abstract ByteVector sub(Vector<Byte> v, Mask<Byte> m); 718 719 /** 720 * Subtracts the broadcast of an input scalar from this vector, selecting 721 * lane elements controlled by a mask. 722 * <p> 723 * This is a vector binary operation where the primitive subtraction 724 * operation ({@code -}) is applied to lane elements. 725 * 726 * @param s the input scalar 727 * @param m the mask controlling lane selection 728 * @return the result of subtracting the broadcast of an input 729 * scalar from this vector 730 */ 731 public abstract ByteVector sub(byte s, Mask<Byte> m); 732 733 @Override 734 public abstract ByteVector mul(Vector<Byte> v); 735 736 /** 737 * Multiplies this vector with the broadcast of an input scalar. 738 * <p> 739 * This is a vector binary operation where the primitive multiplication 740 * operation ({@code *}) is applied to lane elements. 741 * 742 * @param s the input scalar 743 * @return the result of multiplying this vector with the broadcast of an 744 * input scalar 745 */ 746 public abstract ByteVector mul(byte s); 747 748 @Override 749 public abstract ByteVector mul(Vector<Byte> v, Mask<Byte> m); 750 751 /** 752 * Multiplies this vector with the broadcast of an input scalar, selecting 753 * lane elements controlled by a mask. 754 * <p> 755 * This is a vector binary operation where the primitive multiplication 756 * operation ({@code *}) is applied to lane elements. 757 * 758 * @param s the input scalar 759 * @param m the mask controlling lane selection 760 * @return the result of multiplying this vector with the broadcast of an 761 * input scalar 762 */ 763 public abstract ByteVector mul(byte s, Mask<Byte> m); 764 765 @Override 766 public abstract ByteVector neg(); 767 768 @Override 769 public abstract ByteVector neg(Mask<Byte> m); 770 771 @Override 772 public abstract ByteVector abs(); 773 774 @Override 775 public abstract ByteVector abs(Mask<Byte> m); 776 777 @Override 778 public abstract ByteVector min(Vector<Byte> v); 779 780 @Override 781 public abstract ByteVector min(Vector<Byte> v, Mask<Byte> m); 782 783 /** 784 * Returns the minimum of this vector and the broadcast of an input scalar. 785 * <p> 786 * This is a vector binary operation where the operation 787 * {@code (a, b) -> Math.min(a, b)} is applied to lane elements. 788 * 789 * @param s the input scalar 790 * @return the minimum of this vector and the broadcast of an input scalar 791 */ 792 public abstract ByteVector min(byte s); 793 794 @Override 795 public abstract ByteVector max(Vector<Byte> v); 796 797 @Override 798 public abstract ByteVector max(Vector<Byte> v, Mask<Byte> m); 799 800 /** 801 * Returns the maximum of this vector and the broadcast of an input scalar. 802 * <p> 803 * This is a vector binary operation where the operation 804 * {@code (a, b) -> Math.max(a, b)} is applied to lane elements. 805 * 806 * @param s the input scalar 807 * @return the maximum of this vector and the broadcast of an input scalar 808 */ 809 public abstract ByteVector max(byte s); 810 811 @Override 812 public abstract Mask<Byte> equal(Vector<Byte> v); 813 814 /** 815 * Tests if this vector is equal to the broadcast of an input scalar. 816 * <p> 817 * This is a vector binary test operation where the primitive equals 818 * operation ({@code ==}) is applied to lane elements. 819 * 820 * @param s the input scalar 821 * @return the result mask of testing if this vector is equal to the 822 * broadcast of an input scalar 823 */ 824 public abstract Mask<Byte> equal(byte s); 825 826 @Override 827 public abstract Mask<Byte> notEqual(Vector<Byte> v); 828 829 /** 830 * Tests if this vector is not equal to the broadcast of an input scalar. 831 * <p> 832 * This is a vector binary test operation where the primitive not equals 833 * operation ({@code !=}) is applied to lane elements. 834 * 835 * @param s the input scalar 836 * @return the result mask of testing if this vector is not equal to the 837 * broadcast of an input scalar 838 */ 839 public abstract Mask<Byte> notEqual(byte s); 840 841 @Override 842 public abstract Mask<Byte> lessThan(Vector<Byte> v); 843 844 /** 845 * Tests if this vector is less than the broadcast of an input scalar. 846 * <p> 847 * This is a vector binary test operation where the primitive less than 848 * operation ({@code <}) is applied to lane elements. 849 * 850 * @param s the input scalar 851 * @return the mask result of testing if this vector is less than the 852 * broadcast of an input scalar 853 */ 854 public abstract Mask<Byte> lessThan(byte s); 855 856 @Override 857 public abstract Mask<Byte> lessThanEq(Vector<Byte> v); 858 859 /** 860 * Tests if this vector is less or equal to the broadcast of an input scalar. 861 * <p> 862 * This is a vector binary test operation where the primitive less than 863 * or equal to operation ({@code <=}) is applied to lane elements. 864 * 865 * @param s the input scalar 866 * @return the mask result of testing if this vector is less than or equal 867 * to the broadcast of an input scalar 868 */ 869 public abstract Mask<Byte> lessThanEq(byte s); 870 871 @Override 872 public abstract Mask<Byte> greaterThan(Vector<Byte> v); 873 874 /** 875 * Tests if this vector is greater than the broadcast of an input scalar. 876 * <p> 877 * This is a vector binary test operation where the primitive greater than 878 * operation ({@code >}) is applied to lane elements. 879 * 880 * @param s the input scalar 881 * @return the mask result of testing if this vector is greater than the 882 * broadcast of an input scalar 883 */ 884 public abstract Mask<Byte> greaterThan(byte s); 885 886 @Override 887 public abstract Mask<Byte> greaterThanEq(Vector<Byte> v); 888 889 /** 890 * Tests if this vector is greater than or equal to the broadcast of an 891 * input scalar. 892 * <p> 893 * This is a vector binary test operation where the primitive greater than 894 * or equal to operation ({@code >=}) is applied to lane elements. 895 * 896 * @param s the input scalar 897 * @return the mask result of testing if this vector is greater than or 898 * equal to the broadcast of an input scalar 899 */ 900 public abstract Mask<Byte> greaterThanEq(byte s); 901 902 @Override 903 public abstract ByteVector blend(Vector<Byte> v, Mask<Byte> m); 904 905 /** 906 * Blends the lane elements of this vector with those of the broadcast of an 907 * input scalar, selecting lanes controlled by a mask. 908 * <p> 909 * For each lane of the mask, at lane index {@code N}, if the mask lane 910 * is set then the lane element at {@code N} from the input vector is 911 * selected and placed into the resulting vector at {@code N}, 912 * otherwise the the lane element at {@code N} from this input vector is 913 * selected and placed into the resulting vector at {@code N}. 914 * 915 * @param s the input scalar 916 * @param m the mask controlling lane selection 917 * @return the result of blending the lane elements of this vector with 918 * those of the broadcast of an input scalar 919 */ 920 public abstract ByteVector blend(byte s, Mask<Byte> m); 921 922 @Override 923 public abstract ByteVector rearrange(Vector<Byte> v, 924 Shuffle<Byte> s, Mask<Byte> m); 925 926 @Override 927 public abstract ByteVector rearrange(Shuffle<Byte> m); 928 929 @Override 930 public abstract ByteVector reshape(Species<Byte> s); 931 932 @Override 933 public abstract ByteVector rotateEL(int i); 934 935 @Override 936 public abstract ByteVector rotateER(int i); 937 938 @Override 939 public abstract ByteVector shiftEL(int i); 940 941 @Override 942 public abstract ByteVector shiftER(int i); 943 944 945 946 /** 947 * Bitwise ANDs this vector with an input vector. 948 * <p> 949 * This is a vector binary operation where the primitive bitwise AND 950 * operation ({@code &}) is applied to lane elements. 951 * 952 * @param v the input vector 953 * @return the bitwise AND of this vector with the input vector 954 */ 955 public abstract ByteVector and(Vector<Byte> v); 956 957 /** 958 * Bitwise ANDs this vector with the broadcast of an input scalar. 959 * <p> 960 * This is a vector binary operation where the primitive bitwise AND 961 * operation ({@code &}) is applied to lane elements. 962 * 963 * @param s the input scalar 964 * @return the bitwise AND of this vector with the broadcast of an input 965 * scalar 966 */ 967 public abstract ByteVector and(byte s); 968 969 /** 970 * Bitwise ANDs this vector with an input vector, selecting lane elements 971 * controlled by a mask. 972 * <p> 973 * This is a vector binary operation where the primitive bitwise AND 974 * operation ({@code &}) is applied to lane elements. 975 * 976 * @param v the input vector 977 * @param m the mask controlling lane selection 978 * @return the bitwise AND of this vector with the input vector 979 */ 980 public abstract ByteVector and(Vector<Byte> v, Mask<Byte> m); 981 982 /** 983 * Bitwise ANDs this vector with the broadcast of an input scalar, selecting 984 * lane elements controlled by a mask. 985 * <p> 986 * This is a vector binary operation where the primitive bitwise AND 987 * operation ({@code &}) is applied to lane elements. 988 * 989 * @param s the input scalar 990 * @param m the mask controlling lane selection 991 * @return the bitwise AND of this vector with the broadcast of an input 992 * scalar 993 */ 994 public abstract ByteVector and(byte s, Mask<Byte> m); 995 996 /** 997 * Bitwise ORs this vector with an input vector. 998 * <p> 999 * This is a vector binary operation where the primitive bitwise OR 1000 * operation ({@code |}) is applied to lane elements. 1001 * 1002 * @param v the input vector 1003 * @return the bitwise OR of this vector with the input vector 1004 */ 1005 public abstract ByteVector or(Vector<Byte> v); 1006 1007 /** 1008 * Bitwise ORs this vector with the broadcast of an input scalar. 1009 * <p> 1010 * This is a vector binary operation where the primitive bitwise OR 1011 * operation ({@code |}) is applied to lane elements. 1012 * 1013 * @param s the input scalar 1014 * @return the bitwise OR of this vector with the broadcast of an input 1015 * scalar 1016 */ 1017 public abstract ByteVector or(byte s); 1018 1019 /** 1020 * Bitwise ORs this vector with an input vector, selecting lane elements 1021 * controlled by a mask. 1022 * <p> 1023 * This is a vector binary operation where the primitive bitwise OR 1024 * operation ({@code |}) is applied to lane elements. 1025 * 1026 * @param v the input vector 1027 * @param m the mask controlling lane selection 1028 * @return the bitwise OR of this vector with the input vector 1029 */ 1030 public abstract ByteVector or(Vector<Byte> v, Mask<Byte> m); 1031 1032 /** 1033 * Bitwise ORs this vector with the broadcast of an input scalar, selecting 1034 * lane elements controlled by a mask. 1035 * <p> 1036 * This is a vector binary operation where the primitive bitwise OR 1037 * operation ({@code |}) is applied to lane elements. 1038 * 1039 * @param s the input scalar 1040 * @param m the mask controlling lane selection 1041 * @return the bitwise OR of this vector with the broadcast of an input 1042 * scalar 1043 */ 1044 public abstract ByteVector or(byte s, Mask<Byte> m); 1045 1046 /** 1047 * Bitwise XORs this vector with an input vector. 1048 * <p> 1049 * This is a vector binary operation where the primitive bitwise XOR 1050 * operation ({@code ^}) is applied to lane elements. 1051 * 1052 * @param v the input vector 1053 * @return the bitwise XOR of this vector with the input vector 1054 */ 1055 public abstract ByteVector xor(Vector<Byte> v); 1056 1057 /** 1058 * Bitwise XORs this vector with the broadcast of an input scalar. 1059 * <p> 1060 * This is a vector binary operation where the primitive bitwise XOR 1061 * operation ({@code ^}) is applied to lane elements. 1062 * 1063 * @param s the input scalar 1064 * @return the bitwise XOR of this vector with the broadcast of an input 1065 * scalar 1066 */ 1067 public abstract ByteVector xor(byte s); 1068 1069 /** 1070 * Bitwise XORs this vector with an input vector, selecting lane elements 1071 * controlled by a mask. 1072 * <p> 1073 * This is a vector binary operation where the primitive bitwise XOR 1074 * operation ({@code ^}) is applied to lane elements. 1075 * 1076 * @param v the input vector 1077 * @param m the mask controlling lane selection 1078 * @return the bitwise XOR of this vector with the input vector 1079 */ 1080 public abstract ByteVector xor(Vector<Byte> v, Mask<Byte> m); 1081 1082 /** 1083 * Bitwise XORs this vector with the broadcast of an input scalar, selecting 1084 * lane elements controlled by a mask. 1085 * <p> 1086 * This is a vector binary operation where the primitive bitwise XOR 1087 * operation ({@code ^}) is applied to lane elements. 1088 * 1089 * @param s the input scalar 1090 * @param m the mask controlling lane selection 1091 * @return the bitwise XOR of this vector with the broadcast of an input 1092 * scalar 1093 */ 1094 public abstract ByteVector xor(byte s, Mask<Byte> m); 1095 1096 /** 1097 * Bitwise NOTs this vector. 1098 * <p> 1099 * This is a vector unary operation where the primitive bitwise NOT 1100 * operation ({@code ~}) is applied to lane elements. 1101 * 1102 * @return the bitwise NOT of this vector 1103 */ 1104 public abstract ByteVector not(); 1105 1106 /** 1107 * Bitwise NOTs this vector, selecting lane elements controlled by a mask. 1108 * <p> 1109 * This is a vector unary operation where the primitive bitwise NOT 1110 * operation ({@code ~}) is applied to lane elements. 1111 * 1112 * @param m the mask controlling lane selection 1113 * @return the bitwise NOT of this vector 1114 */ 1115 public abstract ByteVector not(Mask<Byte> m); 1116 1117 /** 1118 * Logically left shifts this vector by the broadcast of an input scalar. 1119 * <p> 1120 * This is a vector binary operation where the primitive logical left shift 1121 * operation ({@code <<}) is applied to lane elements to left shift the 1122 * element by shift value as specified by the input scalar. Only the 3 1123 * lowest-order bits of shift value are used. It is as if the shift value 1124 * were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1125 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1126 * 1127 * @param s the input scalar; the number of the bits to left shift 1128 * @return the result of logically left shifting left this vector by the 1129 * broadcast of an input scalar 1130 */ 1131 public abstract ByteVector shiftL(int s); 1132 1133 /** 1134 * Logically left shifts this vector by the broadcast of an input scalar, 1135 * selecting lane elements controlled by a mask. 1136 * <p> 1137 * This is a vector binary operation where the primitive logical left shift 1138 * operation ({@code <<}) is applied to lane elements to left shift the 1139 * element by shift value as specified by the input scalar. Only the 3 1140 * lowest-order bits of shift value are used. It is as if the shift value 1141 * were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1142 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1143 * 1144 * @param s the input scalar; the number of the bits to left shift 1145 * @param m the mask controlling lane selection 1146 * @return the result of logically left shifting left this vector by the 1147 * broadcast of an input scalar 1148 */ 1149 public abstract ByteVector shiftL(int s, Mask<Byte> m); 1150 1151 1152 // logical, or unsigned, shift right 1153 1154 /** 1155 * Logically right shifts (or unsigned right shifts) this vector by the 1156 * broadcast of an input scalar. 1157 * <p> 1158 * This is a vector binary operation where the primitive logical right shift 1159 * operation ({@code >>>}) is applied to lane elements to logically right shift the 1160 * element by shift value as specified by the input scalar. Only the 3 1161 * lowest-order bits of shift value are used. It is as if the shift value 1162 * were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1163 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1164 * 1165 * @param s the input scalar; the number of the bits to right shift 1166 * @return the result of logically right shifting this vector by the 1167 * broadcast of an input scalar 1168 */ 1169 public abstract ByteVector shiftR(int s); 1170 1171 /** 1172 * Logically right shifts (or unsigned right shifts) this vector by the 1173 * broadcast of an input scalar, selecting lane elements controlled by a 1174 * mask. 1175 * <p> 1176 * This is a vector binary operation where the primitive logical right shift 1177 * operation ({@code >>>}) is applied to lane elements to logically right shift the 1178 * element by shift value as specified by the input scalar. Only the 3 1179 * lowest-order bits of shift value are used. It is as if the shift value 1180 * were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1181 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1182 * 1183 * @param s the input scalar; the number of the bits to right shift 1184 * @param m the mask controlling lane selection 1185 * @return the result of logically right shifting this vector by the 1186 * broadcast of an input scalar 1187 */ 1188 public abstract ByteVector shiftR(int s, Mask<Byte> m); 1189 1190 1191 /** 1192 * Arithmetically right shifts (or signed right shifts) this vector by the 1193 * broadcast of an input scalar. 1194 * <p> 1195 * This is a vector binary operation where the primitive arithmetic right 1196 * shift operation ({@code >>}) is applied to lane elements to arithmetically 1197 * right shift the element by shift value as specified by the input scalar. 1198 * Only the 3 lowest-order bits of shift value are used. It is as if the shift 1199 * value were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1200 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1201 * 1202 * @param s the input scalar; the number of the bits to right shift 1203 * @return the result of arithmetically right shifting this vector by the 1204 * broadcast of an input scalar 1205 */ 1206 public abstract ByteVector aShiftR(int s); 1207 1208 /** 1209 * Arithmetically right shifts (or signed right shifts) this vector by the 1210 * broadcast of an input scalar, selecting lane elements controlled by a 1211 * mask. 1212 * <p> 1213 * This is a vector binary operation where the primitive arithmetic right 1214 * shift operation ({@code >>}) is applied to lane elements to arithmetically 1215 * right shift the element by shift value as specified by the input scalar. 1216 * Only the 3 lowest-order bits of shift value are used. It is as if the shift 1217 * value were subjected to a bitwise logical AND operator ({@code &}) with the mask value 0x7. 1218 * The shift distance actually used is therefore always in the range 0 to 7, inclusive. 1219 * 1220 * @param s the input scalar; the number of the bits to right shift 1221 * @param m the mask controlling lane selection 1222 * @return the result of arithmetically right shifting this vector by the 1223 * broadcast of an input scalar 1224 */ 1225 public abstract ByteVector aShiftR(int s, Mask<Byte> m); 1226 1227 1228 @Override 1229 public abstract void intoByteArray(byte[] a, int ix); 1230 1231 @Override 1232 public abstract void intoByteArray(byte[] a, int ix, Mask<Byte> m); 1233 1234 @Override 1235 public abstract void intoByteBuffer(ByteBuffer bb, int ix); 1236 1237 @Override 1238 public abstract void intoByteBuffer(ByteBuffer bb, int ix, Mask<Byte> m); 1239 1240 1241 // Type specific horizontal reductions 1242 /** 1243 * Adds all lane elements of this vector. 1244 * <p> 1245 * This is an associative vector reduction operation where the addition 1246 * operation ({@code +}) is applied to lane elements, 1247 * and the identity value is {@code 0}. 1248 * 1249 * @return the addition of all the lane elements of this vector 1250 */ 1251 public abstract byte addAll(); 1252 1253 /** 1254 * Adds all lane elements of this vector, selecting lane elements 1255 * controlled by a mask. 1256 * <p> 1257 * This is an associative vector reduction operation where the addition 1258 * operation ({@code +}) is applied to lane elements, 1259 * and the identity value is {@code 0}. 1260 * 1261 * @param m the mask controlling lane selection 1262 * @return the addition of the selected lane elements of this vector 1263 */ 1264 public abstract byte addAll(Mask<Byte> m); 1265 1266 /** 1267 * Multiplies all lane elements of this vector. 1268 * <p> 1269 * This is an associative vector reduction operation where the 1270 * multiplication operation ({@code *}) is applied to lane elements, 1271 * and the identity value is {@code 1}. 1272 * 1273 * @return the multiplication of all the lane elements of this vector 1274 */ 1275 public abstract byte mulAll(); 1276 1277 /** 1278 * Multiplies all lane elements of this vector, selecting lane elements 1279 * controlled by a mask. 1280 * <p> 1281 * This is an associative vector reduction operation where the 1282 * multiplication operation ({@code *}) is applied to lane elements, 1283 * and the identity value is {@code 1}. 1284 * 1285 * @param m the mask controlling lane selection 1286 * @return the multiplication of all the lane elements of this vector 1287 */ 1288 public abstract byte mulAll(Mask<Byte> m); 1289 1290 /** 1291 * Returns the minimum lane element of this vector. 1292 * <p> 1293 * This is an associative vector reduction operation where the operation 1294 * {@code (a, b) -> Math.min(a, b)} is applied to lane elements, 1295 * and the identity value is 1296 * {@link Byte#MAX_VALUE}. 1297 * 1298 * @return the minimum lane element of this vector 1299 */ 1300 public abstract byte minAll(); 1301 1302 /** 1303 * Returns the minimum lane element of this vector, selecting lane elements 1304 * controlled by a mask. 1305 * <p> 1306 * This is an associative vector reduction operation where the operation 1307 * {@code (a, b) -> Math.min(a, b)} is applied to lane elements, 1308 * and the identity value is 1309 * {@link Byte#MAX_VALUE}. 1310 * 1311 * @param m the mask controlling lane selection 1312 * @return the minimum lane element of this vector 1313 */ 1314 public abstract byte minAll(Mask<Byte> m); 1315 1316 /** 1317 * Returns the maximum lane element of this vector. 1318 * <p> 1319 * This is an associative vector reduction operation where the operation 1320 * {@code (a, b) -> Math.max(a, b)} is applied to lane elements, 1321 * and the identity value is 1322 * {@link Byte#MIN_VALUE}. 1323 * 1324 * @return the maximum lane element of this vector 1325 */ 1326 public abstract byte maxAll(); 1327 1328 /** 1329 * Returns the maximum lane element of this vector, selecting lane elements 1330 * controlled by a mask. 1331 * <p> 1332 * This is an associative vector reduction operation where the operation 1333 * {@code (a, b) -> Math.max(a, b)} is applied to lane elements, 1334 * and the identity value is 1335 * {@link Byte#MIN_VALUE}. 1336 * 1337 * @param m the mask controlling lane selection 1338 * @return the maximum lane element of this vector 1339 */ 1340 public abstract byte maxAll(Mask<Byte> m); 1341 1342 /** 1343 * Logically ORs all lane elements of this vector. 1344 * <p> 1345 * This is an associative vector reduction operation where the logical OR 1346 * operation ({@code |}) is applied to lane elements, 1347 * and the identity value is {@code 0}. 1348 * 1349 * @return the logical OR all the lane elements of this vector 1350 */ 1351 public abstract byte orAll(); 1352 1353 /** 1354 * Logically ORs all lane elements of this vector, selecting lane elements 1355 * controlled by a mask. 1356 * <p> 1357 * This is an associative vector reduction operation where the logical OR 1358 * operation ({@code |}) is applied to lane elements, 1359 * and the identity value is {@code 0}. 1360 * 1361 * @param m the mask controlling lane selection 1362 * @return the logical OR all the lane elements of this vector 1363 */ 1364 public abstract byte orAll(Mask<Byte> m); 1365 1366 /** 1367 * Logically ANDs all lane elements of this vector. 1368 * <p> 1369 * This is an associative vector reduction operation where the logical AND 1370 * operation ({@code |}) is applied to lane elements, 1371 * and the identity value is {@code -1}. 1372 * 1373 * @return the logical AND all the lane elements of this vector 1374 */ 1375 public abstract byte andAll(); 1376 1377 /** 1378 * Logically ANDs all lane elements of this vector, selecting lane elements 1379 * controlled by a mask. 1380 * <p> 1381 * This is an associative vector reduction operation where the logical AND 1382 * operation ({@code |}) is applied to lane elements, 1383 * and the identity value is {@code -1}. 1384 * 1385 * @param m the mask controlling lane selection 1386 * @return the logical AND all the lane elements of this vector 1387 */ 1388 public abstract byte andAll(Mask<Byte> m); 1389 1390 /** 1391 * Logically XORs all lane elements of this vector. 1392 * <p> 1393 * This is an associative vector reduction operation where the logical XOR 1394 * operation ({@code ^}) is applied to lane elements, 1395 * and the identity value is {@code 0}. 1396 * 1397 * @return the logical XOR all the lane elements of this vector 1398 */ 1399 public abstract byte xorAll(); 1400 1401 /** 1402 * Logically XORs all lane elements of this vector, selecting lane elements 1403 * controlled by a mask. 1404 * <p> 1405 * This is an associative vector reduction operation where the logical XOR 1406 * operation ({@code ^}) is applied to lane elements, 1407 * and the identity value is {@code 0}. 1408 * 1409 * @param m the mask controlling lane selection 1410 * @return the logical XOR all the lane elements of this vector 1411 */ 1412 public abstract byte xorAll(Mask<Byte> m); 1413 1414 // Type specific accessors 1415 1416 /** 1417 * Gets the lane element at lane index {@code i} 1418 * 1419 * @param i the lane index 1420 * @return the lane element at lane index {@code i} 1421 * @throws IllegalArgumentException if the index is is out of range 1422 * ({@code < 0 || >= length()}) 1423 */ 1424 public abstract byte get(int i); 1425 1426 /** 1427 * Replaces the lane element of this vector at lane index {@code i} with 1428 * value {@code e}. 1429 * <p> 1430 * This is a cross-lane operation and behaves as if it returns the result 1431 * of blending this vector with an input vector that is the result of 1432 * broadcasting {@code e} and a mask that has only one lane set at lane 1433 * index {@code i}. 1434 * 1435 * @param i the lane index of the lane element to be replaced 1436 * @param e the value to be placed 1437 * @return the result of replacing the lane element of this vector at lane 1438 * index {@code i} with value {@code e}. 1439 * @throws IllegalArgumentException if the index is is out of range 1440 * ({@code < 0 || >= length()}) 1441 */ 1442 public abstract ByteVector with(int i, byte e); 1443 1444 // Type specific extractors 1445 1446 /** 1447 * Returns an array containing the lane elements of this vector. 1448 * <p> 1449 * This method behaves as if it {@link #intoArray(byte[], int)} stores} 1450 * this vector into an allocated array and returns the array as follows: 1451 * <pre>{@code 1452 * byte[] a = new byte[this.length()]; 1453 * this.intoArray(a, 0); 1454 * return a; 1455 * }</pre> 1456 * 1457 * @return an array containing the the lane elements of this vector 1458 */ 1459 @ForceInline 1460 public final byte[] toArray() { 1461 byte[] a = new byte[species().length()]; 1462 intoArray(a, 0); 1463 return a; 1464 } 1465 1466 /** 1467 * Stores this vector into an array starting at offset. 1468 * <p> 1469 * For each vector lane, where {@code N} is the vector lane index, 1470 * the lane element at index {@code N} is stored into the array at index 1471 * {@code i + N}. 1472 * 1473 * @param a the array 1474 * @param i the offset into the array 1475 * @throws IndexOutOfBoundsException if {@code i < 0}, or 1476 * {@code i > a.length - this.length()} 1477 */ 1478 public abstract void intoArray(byte[] a, int i); 1479 1480 /** 1481 * Stores this vector into an array starting at offset and using a mask. 1482 * <p> 1483 * For each vector lane, where {@code N} is the vector lane index, 1484 * if the mask lane at index {@code N} is set then the lane element at 1485 * index {@code N} is stored into the array index {@code i + N}. 1486 * 1487 * @param a the array 1488 * @param i the offset into the array 1489 * @param m the mask 1490 * @throws IndexOutOfBoundsException if {@code i < 0}, or 1491 * for any vector lane index {@code N} where the mask at lane {@code N} 1492 * is set {@code i >= a.length - N} 1493 */ 1494 public abstract void intoArray(byte[] a, int i, Mask<Byte> m); 1495 1496 /** 1497 * Stores this vector into an array using indexes obtained from an index 1498 * map. 1499 * <p> 1500 * For each vector lane, where {@code N} is the vector lane index, the 1501 * lane element at index {@code N} is stored into the array at index 1502 * {@code i + indexMap[j + N]}. 1503 * 1504 * @param a the array 1505 * @param i the offset into the array, may be negative if relative 1506 * indexes in the index map compensate to produce a value within the 1507 * array bounds 1508 * @param indexMap the index map 1509 * @param j the offset into the index map 1510 * @throws IndexOutOfBoundsException if {@code j < 0}, or 1511 * {@code j > indexMap.length - this.length()}, 1512 * or for any vector lane index {@code N} the result of 1513 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 1514 */ 1515 public void intoArray(byte[] a, int i, int[] indexMap, int j) { 1516 forEach((n, e) -> a[i + indexMap[j + n]] = e); 1517 } 1518 1519 /** 1520 * Stores this vector into an array using indexes obtained from an index 1521 * map and using a mask. 1522 * <p> 1523 * For each vector lane, where {@code N} is the vector lane index, 1524 * if the mask lane at index {@code N} is set then the lane element at 1525 * index {@code N} is stored into the array at index 1526 * {@code i + indexMap[j + N]}. 1527 * 1528 * @param a the array 1529 * @param i the offset into the array, may be negative if relative 1530 * indexes in the index map compensate to produce a value within the 1531 * array bounds 1532 * @param m the mask 1533 * @param indexMap the index map 1534 * @param j the offset into the index map 1535 * @throws IndexOutOfBoundsException if {@code j < 0}, or 1536 * {@code j > indexMap.length - this.length()}, 1537 * or for any vector lane index {@code N} where the mask at lane 1538 * {@code N} is set the result of {@code i + indexMap[j + N]} is 1539 * {@code < 0} or {@code >= a.length} 1540 */ 1541 public void intoArray(byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) { 1542 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e); 1543 } 1544 // Species 1545 1546 @Override 1547 public abstract Species<Byte> species(); 1548 1549 /** 1550 * Class representing {@link ByteVector}'s of the same {@link Vector.Shape Shape}. 1551 */ 1552 static final class ByteSpecies extends Vector.AbstractSpecies<Byte> { 1553 final Function<byte[], ByteVector> vectorFactory; 1554 final Function<boolean[], Vector.Mask<Byte>> maskFactory; 1555 1556 private ByteSpecies(Vector.Shape shape, 1557 Class<?> boxType, 1558 Class<?> maskType, 1559 Function<byte[], ByteVector> vectorFactory, 1560 Function<boolean[], Vector.Mask<Byte>> maskFactory) { 1561 super(shape, byte.class, Byte.SIZE, boxType, maskType); 1562 this.vectorFactory = vectorFactory; 1563 this.maskFactory = maskFactory; 1564 } 1565 1566 interface FOp { 1567 byte apply(int i); 1568 } 1569 1570 interface FOpm { 1571 boolean apply(int i); 1572 } 1573 1574 ByteVector op(FOp f) { 1575 byte[] res = new byte[length()]; 1576 for (int i = 0; i < length(); i++) { 1577 res[i] = f.apply(i); 1578 } 1579 return vectorFactory.apply(res); 1580 } 1581 1582 ByteVector op(Vector.Mask<Byte> o, FOp f) { 1583 byte[] res = new byte[length()]; 1584 boolean[] mbits = ((AbstractMask<Byte>)o).getBits(); 1585 for (int i = 0; i < length(); i++) { 1586 if (mbits[i]) { 1587 res[i] = f.apply(i); 1588 } 1589 } 1590 return vectorFactory.apply(res); 1591 } 1592 1593 Vector.Mask<Byte> opm(IntVector.IntSpecies.FOpm f) { 1594 boolean[] res = new boolean[length()]; 1595 for (int i = 0; i < length(); i++) { 1596 res[i] = (boolean)f.apply(i); 1597 } 1598 return maskFactory.apply(res); 1599 } 1600 } 1601 1602 /** 1603 * Finds the preferred species for an element type of {@code byte}. 1604 * <p> 1605 * A preferred species is a species chosen by the platform that has a 1606 * shape of maximal bit size. A preferred species for different element 1607 * types will have the same shape, and therefore vectors, masks, and 1608 * shuffles created from such species will be shape compatible. 1609 * 1610 * @return the preferred species for an element type of {@code byte} 1611 */ 1612 private static ByteSpecies preferredSpecies() { 1613 return (ByteSpecies) Species.ofPreferred(byte.class); 1614 } 1615 1616 /** 1617 * Finds a species for an element type of {@code byte} and shape. 1618 * 1619 * @param s the shape 1620 * @return a species for an element type of {@code byte} and shape 1621 * @throws IllegalArgumentException if no such species exists for the shape 1622 */ 1623 static ByteSpecies species(Vector.Shape s) { 1624 Objects.requireNonNull(s); 1625 switch (s) { 1626 case S_64_BIT: return (ByteSpecies) SPECIES_64; 1627 case S_128_BIT: return (ByteSpecies) SPECIES_128; 1628 case S_256_BIT: return (ByteSpecies) SPECIES_256; 1629 case S_512_BIT: return (ByteSpecies) SPECIES_512; 1630 case S_Max_BIT: return (ByteSpecies) SPECIES_MAX; 1631 default: throw new IllegalArgumentException("Bad shape: " + s); 1632 } 1633 } 1634 1635 /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */ 1636 public static final Species<Byte> SPECIES_64 = new ByteSpecies(Shape.S_64_BIT, Byte64Vector.class, Byte64Vector.Byte64Mask.class, 1637 Byte64Vector::new, Byte64Vector.Byte64Mask::new); 1638 1639 /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */ 1640 public static final Species<Byte> SPECIES_128 = new ByteSpecies(Shape.S_128_BIT, Byte128Vector.class, Byte128Vector.Byte128Mask.class, 1641 Byte128Vector::new, Byte128Vector.Byte128Mask::new); 1642 1643 /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */ 1644 public static final Species<Byte> SPECIES_256 = new ByteSpecies(Shape.S_256_BIT, Byte256Vector.class, Byte256Vector.Byte256Mask.class, 1645 Byte256Vector::new, Byte256Vector.Byte256Mask::new); 1646 1647 /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */ 1648 public static final Species<Byte> SPECIES_512 = new ByteSpecies(Shape.S_512_BIT, Byte512Vector.class, Byte512Vector.Byte512Mask.class, 1649 Byte512Vector::new, Byte512Vector.Byte512Mask::new); 1650 1651 /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */ 1652 public static final Species<Byte> SPECIES_MAX = new ByteSpecies(Shape.S_Max_BIT, ByteMaxVector.class, ByteMaxVector.ByteMaxMask.class, 1653 ByteMaxVector::new, ByteMaxVector.ByteMaxMask::new); 1654 1655 /** 1656 * Preferred species for {@link ByteVector}s. 1657 * A preferred species is a species of maximal bit size for the platform. 1658 */ 1659 public static final Species<Byte> SPECIES_PREFERRED = (Species<Byte>) preferredSpecies(); 1660 }