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.nio.BufferUnderflowException; 31 import java.nio.ByteBuffer; 32 33 /** 34 * A {@code Vector} is designed for use in computations that can be transformed 35 * by a runtime compiler, on supported hardware, to Single Instruction Multiple 36 * Data (SIMD) computations leveraging vector hardware registers and vector 37 * hardware instructions. Such SIMD computations exploit data parallelism to 38 * perform the same operation on multiple data points simultaneously in a 39 * faster time it would ordinarily take to perform the same operation 40 * sequentially on each data point. 41 * <p> 42 * A Vector represents an ordered immutable sequence of values of the same 43 * element type {@code e} that is one of the following primitive types 44 * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or 45 * {@code double}). The type variable {@code E} corresponds to the boxed 46 * element type, specifically the class that wraps a value of {@code e} in an 47 * object (such the {@code Integer} class that wraps a value of {@code int}}. 48 * A Vector has a {@link #shape() shape} {@code S}, extending type 49 * {@link Shape}, that governs the total {@link #bitSize() size} in bits 50 * of the sequence of values. 51 * <p> 52 * The number of values in the sequence is referred to as the Vector 53 * {@link #length() length}. The length also corresponds to the number of 54 * Vector lanes. The lane element at lane index {@code N} (from {@code 0}, 55 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th value in 56 * the sequence. 57 * Note: this arrangement 58 * of Vector bit size, Vector length, element bit size, and lane element index 59 * has no bearing on how a Vector instance and its sequence of elements may be 60 * arranged in memory or represented as a value in a vector hardware register. 61 * <p> 62 * Vector declares a set of vector operations (methods) that are common to all 63 * element types (such as addition). Sub-classes of Vector with a concrete 64 * boxed element type declare further operations that are specific to that 65 * element type (such as access to element values in lanes, logical operations 66 * on values of integral elements types, or transcendental operations on values 67 * of floating point element types). 68 * There are six sub-classes of Vector corresponding to the supported set 69 * of element types, {@link ByteVector<S>}, {@link ShortVector<S>}, 70 * {@link IntVector<S>} {@link LongVector<S>}, {@link FloatVector<S>}, and 71 * {@link DoubleVector<S>}. 72 * <p> 73 * Vector values, instances of Vector, are created from a special kind of 74 * factory called a {@link Species}. A Species has an 75 * element type and shape and creates Vector values of the same element type 76 * and shape. 77 * A species can be {@link #speciesInstance obtained} given an element type and 78 * shape, or a preferred species can be {@link #speciesInstance obtained} given 79 * just an element type where the most optimal shape is selected for the current 80 * platform. It is recommended that Species instances be held in 81 * {@code static final} fields for optimal creation and usage of Vector values 82 * by the runtime compiler. 83 * <p> 84 * Vector operations can be grouped into various categories and their behaviour 85 * generally specified as follows: 86 * <ul> 87 * <li> 88 * A vector unary operation (1-ary) operates on one input vector to produce a 89 * result vector. 90 * For each lane of the input vector the 91 * lane element is operated on using the specified scalar unary operation and 92 * the element result is placed into the vector result at the same lane. 93 * The following pseudocode expresses the behaviour of this operation category, 94 * where {@code e} is the element type and {@code EVector} corresponds to the 95 * primitive Vector type: 96 * 97 * <pre>{@code 98 * EVector<S> a = ...; 99 * e[] ar = new e[a.length()]; 100 * for (int i = 0; i < a.length(); i++) { 101 * ar[i] = scalar_unary_op(a.get(i)); 102 * } 103 * EVector<S> r = a.species().fromArray(ar, 0); 104 * }</pre> 105 * 106 * Unless otherwise specified the input and result vectors will have the same 107 * element type and shape. 108 * 109 * <li> 110 * A vector binary operation (2-ary) operates on two input 111 * vectors to produce a result vector. 112 * For each lane of the two input vectors, 113 * a and b say, the corresponding lane elements from a and b are operated on 114 * using the specified scalar binary operation and the element result is placed 115 * into the vector result at the same lane. 116 * The following pseudocode expresses the behaviour of this operation category: 117 * 118 * <pre>{@code 119 * EVector<S> a = ...; 120 * EVector<S> b = ...; 121 * e[] ar = new e[a.length()]; 122 * for (int i = 0; i < a.length(); i++) { 123 * ar[i] = scalar_binary_op(a.get(i), b.get(i)); 124 * } 125 * EVector<S> r = a.species().fromArray(ar, 0); 126 * }</pre> 127 * 128 * Unless otherwise specified the two input and result vectors will have the 129 * same element type and shape. 130 * 131 * <li> 132 * Generalizing from unary (1-ary) and binary (2-ary) operations, a vector n-ary 133 * operation operates in n input vectors to produce a 134 * result vector. 135 * N lane elements from each input vector are operated on 136 * using the specified n-ary scalar operation and the element result is placed 137 * into the vector result at the same lane. 138 * Unless otherwise specified the n input and result vectors will have the same 139 * element type and shape. 140 * 141 * <li> 142 * A vector reduction operation operates on all the lane 143 * elements of an input vector. 144 * An accumulation function is applied to all the 145 * lane elements to produce a scalar result. 146 * If the reduction operation is associative then the result may be accumulated 147 * by operating on the lane elements in any order using a specified associative 148 * scalar binary operation and identity value. Otherwise, the reduction 149 * operation specifies the behaviour of the accumulation function. 150 * The following pseudocode expresses the behaviour of this operation category 151 * if it is associative: 152 * <pre>{@code 153 * EVector<S> a = ...; 154 * e r = <identity value>; 155 * for (int i = 0; i < a.length(); i++) { 156 * r = assoc_scalar_binary_op(r, a.get(i)); 157 * } 158 * }</pre> 159 * 160 * Unless otherwise specified the scalar result type and element type will be 161 * the same. 162 * 163 * <li> 164 * A vector binary test operation operates on two input vectors to produce a 165 * result mask. For each lane of the two input vectors, a and b say, the 166 * the corresponding lane elements from a and b are operated on using the 167 * specified scalar binary test operation and the boolean result is placed 168 * into the mask at the same lane. 169 * The following pseudocode expresses the behaviour of this operation category: 170 * <pre>{@code 171 * EVector<S> a = ...; 172 * EVector<S> b = ...; 173 * boolean[] ar = new boolean[a.length()]; 174 * for (int i = 0; i < a.length(); i++) { 175 * ar[i] = scalar_binary_test_op(a.get(i), b.get(i)); 176 * } 177 * Mask<E, S> r = a.species().maskFromArray(ar, 0); 178 * }</pre> 179 * 180 * Unless otherwise specified the two input vectors and result mask will have 181 * the same element type and shape. 182 * 183 * <li> 184 * The prior categories of operation can be said to operate within the vector 185 * lanes, where lane access is uniformly applied to all vectors, specifically 186 * the scalar operation is applied to elements taken from input vectors at the 187 * same lane, and if appropriate applied to the result vector at the same lane. 188 * A further category of operation is a cross-lane vector operation where lane 189 * access is defined by the arguments to the operation. Cross-lane operations 190 * generally rearrange lane elements, by permutation (commonly controlled by a 191 * {@link Shuffle}) or by blending (commonly controlled by a {@link Mask}). 192 * Such an operation explicitly specifies how it rearranges lane elements. 193 * </ul> 194 * 195 * If a vector operation is represented as an instance method then first input 196 * vector corresponds to {@code this} vector and subsequent input vectors are 197 * arguments of the method. Otherwise, if the an operation is represented as a 198 * static method then all input vectors are arguments of the method. 199 * <p> 200 * If a vector operation does not belong to one of the above categories then 201 * the operation explicitly specifies how it processes the lane elements of 202 * input vectors, and where appropriate expresses the behaviour using 203 * pseudocode. 204 * 205 * <p> 206 * Many vector operations provide an additional {@link Mask mask} accepting 207 * variant. 208 * The mask controls which lanes are selected for application of the scalar 209 * operation. Masks are a key component for the support of control flow in 210 * vector computations. 211 * <p> 212 * For certain operation categories the mask accepting variants can be specified 213 * in generic terms. If a lane of the mask is set then the scalar operation is 214 * applied to corresponding lane elements, otherwise if a lane of a mask is not 215 * set then a default scalar operation is applied and its result is placed into 216 * the vector result at the same lane. The default operation is specified for 217 * the following operation categories: 218 * <ul> 219 * <li> 220 * For a vector n-ary operation the default operation is a function that returns 221 * it's first argument, specifically a lane element of the first input vector. 222 * <li> 223 * For an associative vector reduction operation the default operation is a 224 * function that returns the identity value. 225 * <li> 226 * For vector binary test operation the default operation is a function that 227 * returns false. 228 *</ul> 229 * Otherwise, the mask accepting variant of the operation explicitly specifies 230 * how it processes the lane elements of input vectors, and where appropriate 231 * expresses the behaviour using pseudocode. 232 * 233 * <p> 234 * For convenience many vector operations, of arity greater than one, provide 235 * an additional scalar accepting variant. This variant accepts compatible 236 * scalar values instead of vectors for the second and subsequent input vectors, 237 * if any. 238 * Unless otherwise specified the scalar variant behaves as if each scalar value 239 * is transformed to a vector using the vector Species 240 * {@code broadcast} operation, and 241 * then the vector accepting vector operation is applied using the transformed 242 * values. 243 * 244 * <p> 245 * This is a value-based 246 * class; use of identity-sensitive operations (including reference equality 247 * ({@code ==}), identity hash code, or synchronization) on instances of 248 * {@code Vector} may have unpredictable results and should be avoided. 249 * 250 * @param <E> the boxed element type of elements in this vector 251 * @param <S> the type of shape of this vector 252 */ 253 public abstract class Vector<E, S extends Vector.Shape> { 254 255 Vector() {} 256 257 /** 258 * Returns the species of this vector. 259 * 260 * @return the species of this vector 261 */ 262 public abstract Species<E, S> species(); 263 264 // @@@ 265 266 /** 267 * Returns the primitive element type of this vector. 268 * 269 * @return the primitive element type of this vector 270 */ 271 public Class<E> elementType() { return species().elementType(); } 272 273 /** 274 * Returns the element size, in bits, of this vector. 275 * 276 * @return the element size, in bits 277 */ 278 public int elementSize() { return species().elementSize(); } 279 280 /** 281 * Returns the shape of this vector. 282 * 283 * @return the shape of this vector 284 */ 285 public S shape() { return species().shape(); } 286 287 /** 288 * Returns the number of vector lanes (the length). 289 * 290 * @return the number of vector lanes 291 */ 292 public int length() { return species().length(); } 293 294 /** 295 * Returns the total vector size, in bits. 296 * 297 * @return the total vector size, in bits 298 */ 299 public int bitSize() { return species().bitSize(); } 300 301 //Arithmetic 302 303 /** 304 * Adds this vector to an input vector. 305 * <p> 306 * This is a vector binary operation where the primitive addition operation 307 * ({@code +}) is applied to lane elements. 308 * 309 * @param b the input vector 310 * @return the result of adding this vector to the input vector 311 */ 312 public abstract Vector<E, S> add(Vector<E, S> b); 313 314 /** 315 * Adds this vector to an input vector, selecting lane elements 316 * controlled by a mask. 317 * <p> 318 * This is a vector binary operation where the primitive addition operation 319 * ({@code +}) is applied to lane elements. 320 * 321 * @param b the input vector 322 * @param m the mask controlling lane selection 323 * @return the result of adding this vector to the given vector 324 */ 325 public abstract Vector<E, S> add(Vector<E, S> b, Mask<E, S> m); 326 327 public abstract Vector<E, S> addSaturate(Vector<E, S> o); 328 329 public abstract Vector<E, S> addSaturate(Vector<E, S> o, Mask<E, S> m); 330 331 public abstract Vector<E, S> sub(Vector<E, S> o); 332 333 public abstract Vector<E, S> sub(Vector<E, S> o, Mask<E, S> m); 334 335 public abstract Vector<E, S> subSaturate(Vector<E, S> o); 336 337 public abstract Vector<E, S> subSaturate(Vector<E, S> o, Mask<E, S> m); 338 339 public abstract Vector<E, S> mul(Vector<E, S> o); 340 341 public abstract Vector<E, S> mul(Vector<E, S> o, Mask<E, S> m); 342 343 /** 344 * Negates this vector. 345 * <p> 346 * This is a vector unary operation where the primitive negation operation 347 * ({@code -})is applied to lane elements. 348 * 349 * @return the result of negating this vector 350 */ 351 public abstract Vector<E, S> neg(); 352 353 public abstract Vector<E, S> neg(Mask<E, S> m); 354 355 //Maths from java.math 356 public abstract Vector<E, S> abs(); 357 358 public abstract Vector<E, S> abs(Mask<E, S> m); 359 360 public abstract Vector<E, S> min(Vector<E, S> o); 361 362 public abstract Vector<E, S> max(Vector<E, S> o); 363 364 //TODO: Parity 365 366 //Comparisons 367 368 //TODO: N.B. Floating point NaN behaviors? 369 //TODO: Check the JLS 370 371 /** 372 * Tests if this vector is equal to the given vector. 373 * <p> 374 * This is a vector binary test operation where the primitive equals 375 * operation ({@code ==}) is applied to lane elements. 376 * 377 * @param b the given vector 378 * @return the result mask of testing if this vector is equal to the given 379 * vector 380 */ 381 public abstract Mask<E, S> equal(Vector<E, S> b); 382 383 public abstract Mask<E, S> notEqual(Vector<E, S> o); 384 385 /** 386 * Tests if this vector is less than the given vector. 387 * <p> 388 * This is a vector binary test operation where the primitive less than 389 * operation ({@code <}) is applied to lane elements. 390 * 391 * @param b the given vector 392 * @return the mask result of testing if this vector is less than the given 393 * vector 394 */ 395 public abstract Mask<E, S> lessThan(Vector<E, S> b); 396 397 public abstract Mask<E, S> lessThanEq(Vector<E, S> o); 398 399 public abstract Mask<E, S> greaterThan(Vector<E, S> o); 400 401 public abstract Mask<E, S> greaterThanEq(Vector<E, S> o); 402 403 //Elemental shifting 404 405 /** 406 * Rotates left the lane elements of this vector by the given number of 407 * lanes, {@code i}, modulus the vector length. 408 * <p> 409 * This is a cross-lane operation that permutes the lane elements of this 410 * vector. 411 * For each lane of the input vector, at lane index {@code N}, the lane 412 * element is assigned to the result vector at lane index 413 * {@code (i + N) % this.length()}. 414 * 415 * @param i the number of lanes to rotate left 416 * @return the result of rotating left lane elements of this vector by the 417 * given number of lanes 418 */ 419 public abstract Vector<E, S> rotateEL(int i); //Rotate elements left 420 421 /** 422 * Rotates right the lane elements of this vector by the given number of 423 * lanes, {@code i}, modulus the vector length. 424 * <p> 425 * This is a cross-lane operation that permutes the lane elements of this 426 * vector and behaves as if rotating left the lane elements by 427 * {@code this.length() - (i % this.length())} lanes. 428 * 429 * @param i the number of lanes to rotate left 430 * @return the result of rotating right lane elements of this vector by the 431 * given number of lanes 432 */ 433 public abstract Vector<E, S> rotateER(int i); //Rotate elements right 434 435 public abstract Vector<E, S> shiftEL(int i); //shift elements left 436 437 public abstract Vector<E, S> shiftER(int i); //shift elements right 438 439 /** 440 * Blends the lane elements of this vector with those of an input vector, 441 * selecting lanes controlled by a mask. 442 * <p> 443 * For each lane of the mask, at lane index {@code N}, if the mask lane 444 * is set then the lane element at {@code N} from the input vector is 445 * selected and placed into the resulting vector at {@code N}, 446 * otherwise the the lane element at {@code N} from this input vector is 447 * selected and placed into the resulting vector at {@code N}. 448 * 449 * @param b the input vector 450 * @param m the mask controlling lane selection 451 * @return the result of blending the lane elements of this vector with 452 * those of an input vector 453 */ 454 public abstract Vector<E, S> blend(Vector<E, S> b, Mask<E, S> m); 455 456 /** 457 * Shuffles the lane elements of this vector and those of an input vector, 458 * selecting lane indexes controlled by a shuffle. 459 * <p> 460 * This is a cross-lane operation that permutes the lane elements of this 461 * vector and tine input vector. 462 * For each lane of the shuffle, at lane index {@code N}, if the shuffle 463 * lane element, {@code I}, is less than the length of this vector then the 464 * lane element at {@code I} from this vector is selected and placed into 465 * the resulting vector at {@code N}, otherwise the lane element at 466 * {@code I - this.length()} from the input vector is selected and placed 467 * into the resulting vector at {@code N}. 468 * 469 * @param b the input vector 470 * @param s the shuffle controlling lane index selection 471 * @return the result of shuffling the lane elements of this vector and 472 * those of an input vector 473 * @throws IndexOutOfBoundsException if any lane element is {@code < 0} or 474 * {@code >= 2 * this.length()) 475 */ 476 public abstract Vector<E, S> shuffle(Vector<E, S> b, Shuffle<E, S> s); 477 478 /** 479 * Shuffles the lane elements of this vector selecting lane indexes 480 * controlled by a shuffle. 481 * <p> 482 * This is a cross-lane operation that permutes the lane elements of this 483 * vector. 484 * For each lane of the shuffle, at lane index {@code N} with lane 485 * element {@code I}, the lane element at {@code I} from this vector is 486 * selected and placed into the resulting vector at {@code N}. 487 * 488 * @param s the shuffle controlling lane index selection 489 * @return the result of shuffling the lane elements of this vector 490 * @throws IndexOutOfBoundsException if any lane element is {@code < 0} or 491 * {@code >= this.length()) 492 */ 493 public abstract Vector<E, S> swizzle(Shuffle<E, S> s); 494 495 496 // Conversions 497 498 // Bitwise preserving 499 500 /** 501 * Transforms this vector to a vector of the given species shape {@code T} 502 * and element type {@code F}. 503 * <p> 504 * This method behaves as if it returns the result of calling 505 * {@link Species#reshape(Vector) reshape} on the given species with this 506 * vector: 507 * <pre>{@code 508 * return species.reshape(this); 509 * }</pre> 510 * 511 * @param species the species 512 * @param <F> the boxed element type of the species 513 * @param <T> the type of shape of the species 514 * @return a vector transformed by shape and element type 515 * @see Species#reshape(Vector) 516 */ 517 @ForceInline 518 public <F, T extends Shape> Vector<F, T> reshape(Species<F, T> species) { 519 return species.reshape(this); 520 } 521 522 /** 523 * Transforms this vector to a vector of the given species element type 524 * {@code F}, where this vector's shape {@code S} is preserved. 525 * <p> 526 * This method behaves as if it returns the result of calling 527 * {@link Species#rebracket(Vector) rebracket} on the given species with this 528 * vector: 529 * <pre>{@code 530 * return species.rebracket(this); 531 * }</pre> 532 * 533 * @param species the species 534 * @param <F> the boxed element type of the species 535 * @return a vector transformed element type 536 * @see Species#rebracket(Vector) 537 */ 538 @ForceInline 539 public <F> Vector<F, S> rebracket(Species<F, S> species) { 540 return species.reshape(this); 541 } 542 543 /** 544 * Transforms this vector to a vector of the given species shape {@code T}, 545 * where this vector's element type {@code E} is preserved. 546 * <p> 547 * This method behaves as if it returns the result of calling 548 * {@link Species#resize(Vector) resize} on the given species with this vector: 549 * <pre>{@code 550 * return species.resize(this); 551 * }</pre> 552 * 553 * @param species the species 554 * @param <T> the type of shape of the species 555 * @return a vector transformed by shape 556 * @see Species#resize(Vector) 557 */ 558 public abstract <T extends Shape> Vector<E, T> resize(Species<E, T> species); 559 560 // Cast 561 562 /** 563 * Converts this vector to a vector of the given species shape {@code T} and 564 * element type {@code F}. 565 * <p> 566 * This method behaves as if it returns the result of calling 567 * {@link Species#cast(Vector) cast} on the given species with this vector: 568 * <pre>{@code 569 * return species.cast(this); 570 * }</pre> 571 * 572 * @param species the species 573 * @param <F> the boxed element type of the species 574 * @param <T> the type of shape of the species 575 * @return a vector converted by shape and element type 576 * @see Species#cast(Vector) 577 */ 578 @ForceInline 579 public <F, T extends Shape> Vector<F, T> cast(Species<F, T> species) { 580 return species.cast(this); 581 } 582 583 //Array stores 584 585 /** 586 * Stores this vector into a byte array starting at an offset. 587 * <p> 588 * Bytes are extracted from primitive lane elements according to the 589 * native byte order of the underlying platform. 590 * <p> 591 * This method behaves as it calls the 592 * byte buffer, offset, and mask accepting 593 * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows: 594 * <pre>{@code 595 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); 596 * }</pre> 597 * 598 * @param a the byte array 599 * @param i the offset into the array 600 * @return a vector loaded from a byte array 601 * @throws IndexOutOfBoundsException if {@code i < 0} or 602 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 603 */ 604 public abstract void intoByteArray(byte[] a, int i); 605 606 /** 607 * Stores this vector into a byte array starting at an offset and using a mask. 608 * <p> 609 * Bytes are extracted from primitive lane elements according to the 610 * native byte order of the underlying platform. 611 * <p> 612 * This method behaves as it calls the 613 * byte buffer, offset, and mask accepting 614 * {@link #intoByteBuffer(ByteBuffer, int, Mask) method} as follows: 615 * <pre>{@code 616 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m); 617 * }</pre> 618 * 619 * @param a the byte array 620 * @param i the offset into the array 621 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 622 * or {@code > a.length}, 623 * for any vector lane index {@code N} where the mask at lane {@code N} 624 * is set 625 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} 626 */ 627 public abstract void intoByteArray(byte[] a, int i, Mask<E, S> m); 628 629 /** 630 * Stores this vector into a {@link ByteBuffer byte buffer} starting at the 631 * buffer's position. 632 * <p> 633 * Bytes are extracted from primitive lane elements according to the 634 * native byte order of the underlying platform. 635 * <p> 636 * This method behaves as if it calls the byte buffer, offset, and mask 637 * accepting 638 * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows: 639 * <pre>{@code 640 * this.intoByteBuffer(b, b.position(), this.maskAllTrue()) 641 * }</pre> 642 * 643 * @param b the byte buffer 644 * @throws IndexOutOfBoundsException if there are fewer than 645 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 646 * remaining in the byte buffer 647 */ 648 public abstract void intoByteBuffer(ByteBuffer b); 649 650 /** 651 * Stores this vector into a {@link ByteBuffer byte buffer} starting at the 652 * buffer's position and using a mask. 653 * <p> 654 * Bytes are extracted from primitive lane elements according to the 655 * native byte order of the underlying platform. 656 * <p> 657 * This method behaves as if it calls the byte buffer, offset, and mask 658 * accepting 659 * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows: 660 * <pre>{@code 661 * this.intoByteBuffer(b, b.position(), m) 662 * }</pre> 663 * 664 * @param b the byte buffer 665 * @param m the mask 666 * @throws IndexOutOfBoundsException if for any vector lane index 667 * {@code N} where the mask at lane {@code N} is set 668 * {@code b.position() >= b.limit() - (N * this.elementSize() / Byte.SIZE)} 669 */ 670 public abstract void intoByteBuffer(ByteBuffer b, Mask<E, S> m); 671 672 /** 673 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 674 * offset into the byte buffer. 675 * <p> 676 * Bytes are extracted from primitive lane elements according to the 677 * native byte order of the underlying platform. 678 * <p> 679 * This method behaves as if it calls the byte buffer, offset, and mask 680 * accepting 681 * {@link #intoByteBuffer(ByteBuffer, int, Mask)} method} as follows: 682 * <pre>{@code 683 * this.intoByteBuffer(b, i, this.maskAllTrue()) 684 * }</pre> 685 * 686 * @param b the byte buffer 687 * @param i the offset into the byte buffer 688 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 689 * or {@code > b.limit()}, 690 * or if there are fewer than 691 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 692 * remaining in the byte buffer from the given offset 693 */ 694 public abstract void intoByteBuffer(ByteBuffer b, int i); 695 696 /** 697 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 698 * offset into the byte buffer and using a mask. 699 * <p> 700 * This method behaves as if the byte buffer is viewed as a primitive 701 * {@link java.nio.Buffer buffer} for the primitive element type, 702 * according to the native byte order of the underlying platform, and 703 * the lane elements of this vector are put into the buffer if the 704 * corresponding mask lane is set. 705 * The following pseudocode expresses the behaviour, where 706 * {@coce EBuffer} is the primitive buffer type, {@code e} is the 707 * primitive element type, and {@code EVector<S>} is the primitive 708 * vector type for this vector: 709 * <pre>{@code 710 * EBuffer eb = b.duplicate(). 711 * order(ByteOrder.nativeOrder()).position(i). 712 * asEBuffer(); 713 * e[] es = ((EVector<S>)this).toArray(); 714 * for (int n = 0; n < t.length && m.isSet(n); n++) { 715 * eb.put(n, es[n]); 716 * } 717 * }</pre> 718 * 719 * @param b the byte buffer 720 * @param i the offset into the byte buffer 721 * @param m the mask 722 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 723 * or {@code > b.limit()}, 724 * for any vector lane index {@code N} where the mask at lane {@code N} 725 * is set 726 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes 727 */ 728 public abstract void intoByteBuffer(ByteBuffer b, int i, Mask<E, S> m); 729 730 731 /** 732 * A factory for creating {@link Vector}, {@link Mask} and {@link Shuffle} 733 * values of the same element type and shape. 734 * 735 * @param <E> the boxed element type of this species 736 * @param <S> the type of shape of this species 737 */ 738 public static abstract class Species<E, S extends Shape> { 739 Species() {} 740 741 /** 742 * Returns the primitive element type of vectors produced by this 743 * species. 744 * 745 * @return the primitive element type 746 */ 747 public abstract Class<E> elementType(); 748 749 /** 750 * Returns the element size, in bits, of vectors produced by this 751 * species. 752 * 753 * @return the element size, in bits 754 */ 755 public abstract int elementSize(); 756 757 /** 758 * Returns the shape of masks, shuffles, and vectors produced by this 759 * species. 760 * 761 * @return the primitive element type 762 */ 763 public abstract S shape(); 764 765 /** 766 * Returns the mask, shuffe, or vector lanes produced by this species. 767 * 768 * @return the the number of lanes 769 */ 770 public int length() { return shape().length(this); } 771 772 /** 773 * Returns the total vector size, in bits, of vectors produced by this 774 * species. 775 * 776 * @return the total vector size, in bits 777 */ 778 public int bitSize() { return shape().bitSize(); } 779 780 // Factory 781 782 /** 783 * Returns a vector where all lane elements are set to the default 784 * primitive value. 785 * 786 * @return a zero vector 787 */ 788 public abstract Vector<E, S> zero(); 789 790 /** 791 * Loads a vector from a byte array starting at an offset. 792 * <p> 793 * Bytes are composed into primitive lane elements according to the 794 * native byte order of the underlying platform 795 * <p> 796 * This method behaves as if it returns the result of calling the 797 * byte buffer, offset, and mask accepting 798 * {@link #fromByteBuffer(ByteBuffer, int, Mask) method} as follows: 799 * <pre>{@code 800 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); 801 * }</pre> 802 * 803 * @param a the byte array 804 * @param i the offset into the array 805 * @return a vector loaded from a byte array 806 * @throws IndexOutOfBoundsException if {@code i < 0} or 807 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 808 */ 809 public abstract Vector<E, S> fromByteArray(byte[] a, int i); 810 811 /** 812 * Loads a vector from a byte array starting at an offset and using a 813 * mask. 814 * <p> 815 * Bytes are composed into primitive lane elements according to the 816 * native byte order of the underlying platform. 817 * <p> 818 * This method behaves as if it returns the result of calling the 819 * byte buffer, offset, and mask accepting 820 * {@link #fromByteBuffer(ByteBuffer, int, Mask) method} as follows: 821 * <pre>{@code 822 * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m); 823 * }</pre> 824 * 825 * @param a the byte array 826 * @param i the offset into the array 827 * @param m the mask 828 * @return a vector loaded from a byte array 829 * @throws IndexOutOfBoundsException if {@code i < 0} or 830 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 831 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 832 * or {@code > a.length}, 833 * for any vector lane index {@code N} where the mask at lane {@code N} 834 * is set 835 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} 836 */ 837 public abstract Vector<E, S> fromByteArray(byte[] a, int i, Mask<E, S> m); 838 839 /** 840 * Loads a vector from a {@link ByteBuffer byte buffer} starting at the 841 * buffer's position. 842 * <p> 843 * Bytes are composed into primitive lane elements according to the 844 * native byte order of the underlying platform. 845 * <p> 846 * This method behaves as if it returns the result of calling the 847 * byte buffer, offset, and mask accepting 848 * {@link #fromByteBuffer(ByteBuffer, int, Mask) method} as follows: 849 * <pre>{@code 850 * return this.fromByteBuffer(b, b.position(), this.maskAllTrue()) 851 * }</pre> 852 * 853 * @param b the byte buffer 854 * @return a vector loaded from a byte buffer 855 * @throws IndexOutOfBoundsException if there are fewer than 856 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 857 * remaining in the byte buffer 858 */ 859 public abstract Vector<E, S> fromByteBuffer(ByteBuffer b); 860 861 /** 862 * Loads a vector from a {@link ByteBuffer byte buffer} starting at the 863 * buffer's position and using a mask. 864 * <p> 865 * Bytes are composed into primitive lane elements according to the 866 * native byte order of the underlying platform. 867 * <p> 868 * This method behaves as if it returns the result of calling the 869 * byte buffer, offset, and mask accepting 870 * {@link #fromByteBuffer(ByteBuffer, int, Mask)} method} as follows: 871 * <pre>{@code 872 * return this.fromByteBuffer(b, b.position(), m) 873 * }</pre> 874 * 875 * @param b the byte buffer 876 * @param m the mask 877 * @return a vector loaded from a byte buffer 878 * @throws IndexOutOfBoundsException if for any vector lane index 879 * {@code N} where the mask at lane {@code N} is set 880 * {@code b.position() >= b.limit() - (N * this.elementSize() / Byte.SIZE)} 881 */ 882 public abstract Vector<E, S> fromByteBuffer(ByteBuffer b, Mask<E, S> m); 883 884 /** 885 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an 886 * offset into the byte buffer. 887 * <p> 888 * Bytes are composed into primitive lane elements according to the 889 * native byte order of the underlying platform. 890 * <p> 891 * This method behaves as if it returns the result of calling the 892 * byte buffer, offset, and mask accepting 893 * {@link #fromByteBuffer(ByteBuffer, int, Mask)} method} as follows: 894 * <pre>{@code 895 * return this.fromByteBuffer(b, i, this.maskAllTrue()) 896 * }</pre> 897 * 898 * @param b the byte buffer 899 * @param i the offset into the byte buffer 900 * @return a vector loaded from a byte buffer 901 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 902 * or {@code > b.limit()}, 903 * or if there are fewer than 904 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 905 * remaining in the byte buffer from the given offset 906 */ 907 public abstract Vector<E, S> fromByteBuffer(ByteBuffer b, int i); 908 909 /** 910 * Loads a vector from a {@link ByteBuffer byte buffer} starting at an 911 * offset into the byte buffer and using a mask. 912 * <p> 913 * This method behaves as if the byte buffer is viewed as a primitive 914 * {@link java.nio.Buffer buffer} for the primitive element type, 915 * according to the native byte order of the underlying platform, and 916 * the returned vector is loaded with a mask from a primitive array 917 * obtained from the primitive buffer. 918 * The following pseudocode expresses the behaviour, where 919 * {@coce EBuffer} is the primitive buffer type, {@code e} is the 920 * primitive element type, and {@code ESpecies<S>} is the primitive 921 * species for {@code e}: 922 * <pre>{@code 923 * EBuffer eb = b.duplicate(). 924 * order(ByteOrder.nativeOrder()).position(i). 925 * asEBuffer(); 926 * e[] es = new e[this.length()]; 927 * for (int n = 0; n < t.length && m.isSet(n); n++) { 928 * es[n] = eb.get(n); 929 * } 930 * Vector<E, S> r = ((ESpecies<S>)this).fromArray(es, 0, m); 931 * }</pre> 932 * 933 * @param b the byte buffer 934 * @param i the offset into the byte buffer 935 * @return a vector loaded from a byte buffer 936 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 937 * or {@code > b.limit()}, 938 * for any vector lane index {@code N} where the mask at lane {@code N} 939 * is set 940 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} 941 */ 942 public abstract Vector<E, S> fromByteBuffer(ByteBuffer b, int i, Mask<E, S> m); 943 944 //Mask and shuffle constructions 945 946 /** 947 * Returns a mask where each lane is set or unset according to a given 948 * {@code boolean} value. 949 * <p> 950 * For each mask lane, where {@code N} is the mask lane index, 951 * if the given {@code boolean} value at index {@code N} is {@code true} 952 * then the mask lane at index {@code N} is set, otherwise it is unset. 953 * 954 * @@@ What should happen if bits.length < this.length() ? use the 955 * default value or throw IndexOutOfBoundsException 956 * 957 * @param bits the given {@code boolean} values 958 * @return a mask where each lane is set or unset according to a given 959 * {@code boolean} value 960 */ 961 public abstract Mask<E, S> maskFromValues(boolean... bits); 962 963 /** 964 * Loads a mask from a {@code boolean} array starting at an offset. 965 * <p> 966 * For each mask lane, where {@code N} is the mask lane index, 967 * if the array element at index {@code i + N} is {@code true} then the 968 * mask lane at index {@code N} is set, otherwise it is unset. 969 * 970 * @param a the {@code boolean} array 971 * @param i the offset into the array 972 * @return the mask loaded from a {@code boolean} array 973 * @throws IndexOutOfBoundsException if {@code i < 0}, or 974 * {@code i > a.length - this.length()} 975 */ 976 public abstract Mask<E, S> maskFromArray(boolean[] a, int i); 977 978 /** 979 * Returns a mask where all lanes are a set. 980 * 981 * @return a mask where all lanes are a set 982 */ 983 public abstract Mask<E, S> maskAllTrue(); 984 985 /** 986 * Returns a mask where all lanes are unset. 987 * 988 * @return a mask where all lanes are unset 989 */ 990 public abstract Mask<E, S> maskAllFalse(); 991 992 /** 993 * Returns a shuffle where each lane element to a given {@code int} 994 * value. 995 * <p> 996 * For each shuffle lane, where {@code N} is the shuffle lane index, the 997 * the {@code int} value at index {@code N} is placed into the resulting 998 * shuffle at lane index {@code N}. 999 * 1000 * @@@ What should happen if indexes.length < this.length() ? use the 1001 * default value or throw IndexOutOfBoundsException 1002 * 1003 * @param indexes the given {@code int} values 1004 * @return a shufle where each lane element is set to a given 1005 * {@code int} value 1006 */ 1007 public abstract Shuffle<E, S> shuffleFromValues(int... indexes); 1008 1009 /** 1010 * Loads a shuffle from an {@code int} array starting at offset. 1011 * <p> 1012 * For each shuffle lane, where {@code N} is the shuffle lane index, the 1013 * array element at index {@code i + N} is placed into the 1014 * resulting shuffle at lane index {@code N}. 1015 * 1016 * @param a the {@code int} array 1017 * @param i the offset into the array 1018 * @return the shuffle loaded from an {@code int} array 1019 * @throws IndexOutOfBoundsException if {@code i < 0}, or 1020 * {@code i > a.length - this.length()} 1021 */ 1022 public abstract Shuffle<E, S> shuffleFromArray(int[] a, int i); 1023 1024 /** 1025 * Returns a shuffle containing lane elements of an {@code int} 1026 * vector. 1027 * <p> 1028 * For each vector lane, where {@code N} is the vector lane index, the 1029 * lane element at index {@code N} is placed into the resulting shuffle 1030 * at lane index {@code N}. 1031 * 1032 * @param v the {@code int} vector 1033 * @return a shuffle containing lane elements of an {@code int} vector 1034 */ 1035 public abstract Shuffle<E, S> shuffleFromVector(Vector<Integer, S> v); 1036 1037 // Shuffle iota, 0...N 1038 1039 // Vector type/shape transformations 1040 1041 /** 1042 * Transforms an input vector of shape {@code T} and element type 1043 * {@code F} to a vector of this species shape {@code S} and element 1044 * type {@code E}. 1045 * <p> 1046 * The underlying bits of the input vector are copied to the resulting 1047 * vector without modification, but those bits, before copying, may be 1048 * truncated if the vector bit size is greater than this species bit 1049 * size, or appended to with zero bits if the vector bit size is less 1050 * than this species bit size. 1051 * <p> 1052 * The method behaves as if the input vector is stored into a byte buffer 1053 * and then the returned vector is loaded from the byte buffer using 1054 * native byte ordering. The implication is that ByteBuffer reads bytes 1055 * and then composes them based on the byte ordering so the result 1056 * depends on this composition. 1057 * <p> 1058 * For example, on a system with ByteOrder.LITTLE_ENDIAN, loading from 1059 * byte array with values {0,1,2,3} and reshaping to int, leads to bytes 1060 * being composed in order 0x3 0x2 0x1 0x0 which is decimal value 50462976. 1061 * On a system with ByteOrder.BIG_ENDIAN, the value is instead 66051 because 1062 * bytes are composed in order 0x0 0x1 0x2 0x3. 1063 * <p> 1064 * The following pseudocode expresses the behaviour: 1065 * <pre>{@code 1066 * int blen = Math.max(v.bitSize(), bitSize()) / Byte.SIZE; 1067 * ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 1068 * v.intoByteBuffer(bb, 0); 1069 * return fromByteBuffer(bb, 0); 1070 * }</pre> 1071 * 1072 * @param v the input vector 1073 * @param <F> the boxed element type of the vector 1074 * @param <T> the type of shape of the vector 1075 * @return a vector transformed, by shape and element type, from an 1076 * input vector 1077 */ 1078 public abstract <F, T extends Shape> Vector<E, S> reshape(Vector<F, T> v); 1079 1080 /** 1081 * Transforms an input vector of element type {@code F} to a vector of 1082 * this species element type {@code E}, where the this species shape 1083 * {@code S} is preserved. 1084 * <p> 1085 * The underlying bits of the input vector are copied without 1086 * modification to the resulting vector. 1087 * <p> 1088 * The method behaves as if the input vector is stored into a byte buffer 1089 * and then the returned vector is loaded from the byte buffer using 1090 * native byte ordering. The implication is that ByteBuffer reads bytes 1091 * and then composes them based on the byte ordering so the result 1092 * depends on this composition. 1093 * <p> 1094 * For example, on a system with ByteOrder.LITTLE_ENDIAN, loading from 1095 * byte array with values {0,1,2,3} and rebracketing to int, leads to bytes 1096 * being composed in order 0x3 0x2 0x1 0x0 which is decimal value 50462976. 1097 * On a system with ByteOrder.BIG_ENDIAN, the value is instead 66051 because 1098 * bytes are composed in order 0x0 0x1 0x2 0x3. 1099 * <p> 1100 * The following pseudocode expresses the behaviour: 1101 * <pre>{@code 1102 * ByteBuffer bb = ByteBuffer.allocate(v.bitSize()).order(ByteOrder.nativeOrder()); 1103 * v.intoByteBuffer(bb, 0); 1104 * return fromByteBuffer(bb, 0); 1105 * }</pre> 1106 * 1107 * @param v the input vector 1108 * @param <F> the boxed element type of the vector 1109 * @return a vector transformed, by element type, from an input vector 1110 */ 1111 public abstract <F> Vector<E, S> rebracket(Vector<F, S> v); 1112 1113 /** 1114 * Transforms an input vector of shape {@code T} to a vector of this 1115 * species shape {@code S}, where the this species element type 1116 * {@code E} is preserved. 1117 * <p> 1118 * The lane elements of the input vector are copied without 1119 * modification to the resulting vector, but those lane elements, before 1120 * copying, may be truncated if the vector length is greater than this 1121 * species length, or appended to with default element values if the 1122 * vector length is less than this species length. 1123 * <p> 1124 * The method behaves as if the input vector is stored into a byte array 1125 * and then the returned vector is loaded from the byte array. 1126 * The following pseudocode expresses the behaviour: 1127 * <pre>{@code 1128 * int alen = Math.max(v.bitSize(), this.bitSize()) / Byte.SIZE; 1129 * byte[] a = new byte[alen]; 1130 * v.intoByteArray(a, 0); 1131 * return fromByteArray(a, 0); 1132 * }</pre> 1133 * 1134 * @param v the input vector 1135 * @param <T> the type of shape of the vector 1136 * @return a vector transformed, by shape, from an input vector 1137 */ 1138 public abstract <T extends Shape> Vector<E, S> resize(Vector<E, T> v); 1139 1140 /** 1141 * Converts an input vector of shape {@code T} and element type 1142 * {@code F} to a vector of this species shape {@code S} and element 1143 * type {@code E}. 1144 * <p> 1145 * For each input vector lane up to the length of the input vector or 1146 * this species, which ever is the minimum, and where {@code N} is the 1147 * vector lane index, the element at index {@code N} of primitive type 1148 * {@code F} is converted, according to primitive conversion rules 1149 * specified by the Java Language Specification, to a value of primitive 1150 * type {@code E} and placed into the resulting vector at lane index 1151 * {@code N}. If this species length is greater than the input 1152 * vector length then the default primitive value is placed into 1153 * subsequent lanes of the resulting vector. 1154 * 1155 * @param v the input vector 1156 * @param <F> the boxed element type of the vector 1157 * @param <T> the type of shape of the vector 1158 * @return a vector, converted by shape and element type, from an input 1159 * vector. 1160 */ 1161 public abstract <F, T extends Shape> Vector<E, S> cast(Vector<F, T> v); 1162 1163 1164 // Mask type/shape transformations 1165 1166 /** 1167 * Transforms an input mask of shape {@code T} and element type 1168 * {@code F} to a vector of this species shape {@code S} and element 1169 * type {@code E}. 1170 * <p> 1171 * The lane elements of the input mask are copied to the resulting 1172 * mask without modification, but those lane elements, before copying, 1173 * may be truncated if the mask length is greater than this species 1174 * length, or appended to with false values if the mask length less than 1175 * this species length. 1176 * <p> 1177 * The method behaves as if the input mask is stored into a boolean 1178 * array and then the returned mask is loaded from the boolean array. 1179 * The following pseudocode expresses the behaviour: 1180 * <pre>{@code 1181 * int alen = Math.max(m.length(), this.length()); 1182 * boolean[] a = new boolean[alen]; 1183 * m.intoArray(a, 0); 1184 * return this.maskFromArray(a, 0); 1185 * }</pre> 1186 * 1187 * @param m the input mask 1188 * @param <F> the boxed element type of the mask 1189 * @param <T> the type of shape of the mask 1190 * @return a mask transformed, by shape and element type, from an 1191 * input mask 1192 */ 1193 public <F, T extends Shape> Mask<E, S> reshape(Mask<F, T> m) { 1194 return maskFromValues(m.toArray()); 1195 } 1196 1197 /** 1198 * Transforms an input mask of element type {@code F} to a mask of 1199 * this species element type {@code E}, where the this species shape 1200 * {@code S} is preserved. 1201 * <p> 1202 * The lane elements of the input mask are copied without 1203 * modification to the resulting mask. 1204 * <p> 1205 * The method behaves as if the input mask is stored into a boolean 1206 * array and then the returned mask is loaded from the boolean array. 1207 * The following pseudocode expresses the behaviour: 1208 * <pre>{@code 1209 * boolean[] a = new byte[m.length()]; 1210 * m.intoArray(a, 0); 1211 * return this.maskFromArray(a, 0); 1212 * }</pre> 1213 * 1214 * @param m the input mask 1215 * @param <F> the boxed element type of the mask 1216 * @return a mask transformed, by element type, from an input mask 1217 */ 1218 @ForceInline 1219 public <F> Mask<E, S> rebracket(Mask<F, S> m) { 1220 return reshape(m); 1221 } 1222 1223 /** 1224 * Transforms an input mask of shape {@code T} to a mask of this 1225 * species shape {@code S}, where the this species element type 1226 * {@code E} is preserved. 1227 * <p> 1228 * The lane elements of the input mask are copied to the resulting 1229 * mask without modification, but those lane elements, before copying, 1230 * may be truncated if the mask length is greater than this species 1231 * length, or appended to with false values if the mask length less than 1232 * this species length. 1233 * <p> 1234 * The method behaves as if the input mask is stored into a boolean 1235 * array and then the returned mask is loaded from the boolean array. 1236 * The following pseudocode expresses the behaviour: 1237 * <pre>{@code 1238 * int alen = Math.max(m.length(), this.length()); 1239 * boolean[] a = new boolean[alen]; 1240 * m.intoArray(a, 0); 1241 * return this.maskFromArray(a, 0); 1242 * }</pre> 1243 * 1244 * @param m the input mask 1245 * @param <T> the type of shape of the mask 1246 * @return a mask transformed, by shape, from an input mask 1247 */ 1248 @ForceInline 1249 public <T extends Shape> Mask<E, S> resize(Mask<E, T> m) { 1250 return reshape(m); 1251 } 1252 1253 1254 // Shuffle type/shape transformations 1255 1256 /** 1257 * Transforms an input shuffle of shape {@code T} and element type 1258 * {@code F} to a shuffle of this species shape {@code S} and element 1259 * type {@code E}. 1260 * <p> 1261 * The lane elements of the input shuffle are copied to the resulting 1262 * shuffle without modification, but those lane elements, before copying, 1263 * may be truncated if the shuffle length is greater than this species 1264 * length, or appended to with zero values if the shuffle length less than 1265 * this species length. 1266 * <p> 1267 * The method behaves as if the input shuffle is stored into a int 1268 * array and then the returned shuffle is loaded from the int array. 1269 * The following pseudocode expresses the behaviour: 1270 * <pre>{@code 1271 * int alen = Math.max(s.length(), this.length()); 1272 * int[] a = new int[blen]; 1273 * s.intoArray(a, 0); 1274 * return this.shuffleFromArray(a, 0); 1275 * }</pre> 1276 * 1277 * @param s the input shuffle 1278 * @param <F> the boxed element type of the shuffle 1279 * @param <T> the type of shape of the shuffle 1280 * @return a shuffle transformed, by shape and element type, from an 1281 * input shuffle 1282 */ 1283 public <F, T extends Shape> Shuffle<E, S> reshape(Shuffle<F, T> s) { 1284 return shuffleFromValues(s.toArray()); 1285 } 1286 1287 /** 1288 * Transforms an input shuffle of element type {@code F} to a shuffle of 1289 * this species element type {@code E}, where the this species shape 1290 * {@code S} is preserved. 1291 * <p> 1292 * The lane elements of the input shuffle are copied without 1293 * modification to the resulting shuffle. 1294 * <p> 1295 * The method behaves as if the input shuffle is stored into a int 1296 * array and then the returned shuffle is loaded from the int array. 1297 * The following pseudocode expresses the behaviour: 1298 * <pre>{@code 1299 * int[] a = new byte[s.length()]; 1300 * s.intoArray(a, 0); 1301 * return this.shuffleFromArray(a, 0); 1302 * }</pre> 1303 * 1304 * @param s the input shuffle 1305 * @param <F> the boxed element type of the shuffle 1306 * @return a shuffle transformed, by element type, from an input shuffle 1307 */ 1308 @ForceInline 1309 public <F> Shuffle<E, S> rebracket(Shuffle<F, S> s) { 1310 return reshape(s); 1311 } 1312 1313 /** 1314 * Transforms an input shuffle of shape {@code T} to a shuffle of this 1315 * species shape {@code S}, where the this species element type 1316 * {@code E} is preserved. 1317 * <p> 1318 * The lane elements of the input shuffle are copied to the resulting 1319 * shuffle without modification, but those lane elements, before copying, 1320 * may be truncated if the shuffle length is greater than this species 1321 * length, or appended to with zero values if the shuffle length less than 1322 * this species length. 1323 * <p> 1324 * The method behaves as if the input shuffle is stored into a int 1325 * array and then the returned shuffle is loaded from the int array. 1326 * The following pseudocode expresses the behaviour: 1327 * <pre>{@code 1328 * int alen = Math.max(m.length(), this.length()); 1329 * boolean[] a = new boolean[alen]; 1330 * m.intoArray(a, 0); 1331 * return this.maskFromArray(a, 0); 1332 * }</pre> 1333 * 1334 * @param s the input shuffle 1335 * @param <T> the type of shape of the shuffle 1336 * @return a shuffle transformed, by shape, from an input shuffle 1337 */ 1338 @ForceInline 1339 public <T extends Shape> Shuffle<E, S> resize(Shuffle<E, T> s) { 1340 return reshape(s); 1341 } 1342 1343 1344 // Species/species transformations 1345 1346 // Returns a species for a given element type and the length of this 1347 // species. 1348 // The length of the returned species will be equal to the length of 1349 // this species. 1350 // 1351 // Throws IAE if no shape exists for the element type and this species length, 1352 // public <F> Species<F, ?> toSpeciesWithSameNumberOfLanes(Class<F> c) { 1353 // // @@@ TODO implement and find better name 1354 // throw new UnsupportedOperationException(); 1355 // } 1356 1357 } 1358 1359 /** 1360 * A {@code Shape} governs the total size, in bits, of a 1361 * {@link Vector}, {@link Mask}, or {@code Shuffle}. The shape in 1362 * combination with the element type together govern the number of lanes. 1363 */ 1364 public static abstract class Shape { 1365 Shape() {} 1366 1367 /** 1368 * Returns the size, in bits, of this shape. 1369 * 1370 * @return the size, in bits, of this shape. 1371 */ 1372 public abstract int bitSize(); 1373 1374 // @@@ remove this method 1375 public int length(Species<?, ?> s) { return bitSize() / s.elementSize(); } 1376 } 1377 1378 /** 1379 * A {@code Mask} represents an ordered immutable sequence of {@code boolean} 1380 * values. A Mask can be used with a mask accepting vector operation to 1381 * control the selection and operation of lane elements of input vectors. 1382 * <p> 1383 * The number of values in the sequence is referred to as the Mask 1384 * {@link #length() length}. The length also corresponds to the number of 1385 * Mask lanes. The lane element at lane index {@code N} (from {@code 0}, 1386 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th 1387 * value in the sequence. 1388 * A Mask and Vector of the same element type and shape have the same number 1389 * of lanes. 1390 * <p> 1391 * A lane is said to be <em>set</em> if the lane element is {@code true}, 1392 * otherwise a lane is said to be <em>unset</em> if the lane element is 1393 * {@code false}. 1394 * <p> 1395 * Mask declares a limited set of unary, binary and reductive mask 1396 * operations. 1397 * <ul> 1398 * <li> 1399 * A mask unary operation (1-ary) operates on one input mask to produce a 1400 * result mask. 1401 * For each lane of the input mask the 1402 * lane element is operated on using the specified scalar unary operation and 1403 * the boolean result is placed into the mask result at the same lane. 1404 * The following pseudocode expresses the behaviour of this operation category: 1405 * 1406 * <pre>{@code 1407 * Mask<E, S> a = ...; 1408 * boolean[] ar = new boolean[a.length()]; 1409 * for (int i = 0; i < a.length(); i++) { 1410 * ar[i] = boolean_unary_op(a.isSet(i)); 1411 * } 1412 * Mask<E, S> r = a.species().maskFromArray(ar, 0); 1413 * }</pre> 1414 * 1415 * <li> 1416 * A mask binary operation (2-ary) operates on two input 1417 * masks to produce a result mask. 1418 * For each lane of the two input masks, 1419 * a and b say, the corresponding lane elements from a and b are operated on 1420 * using the specified scalar binary operation and the boolean result is placed 1421 * into the mask result at the same lane. 1422 * The following pseudocode expresses the behaviour of this operation category: 1423 * 1424 * <pre>{@code 1425 * Mask<E, S> a = ...; 1426 * Mask<E, S> b = ...; 1427 * boolean[] ar = new boolean[a.length()]; 1428 * for (int i = 0; i < a.length(); i++) { 1429 * ar[i] = scalar_binary_op(a.isSet(i), b.isSet(i)); 1430 * } 1431 * Mask<E, S> r = a.species().maskFromArray(ar, 0); 1432 * }</pre> 1433 * 1434 * @param <E> the boxed element type of this mask 1435 * @param <S> the type of shape of this mask 1436 */ 1437 public static abstract class Mask<E, S extends Shape> { 1438 Mask() {} 1439 1440 /** 1441 * Returns the species of this mask. 1442 * 1443 * @return the species of this mask 1444 */ 1445 public abstract Species<E, S> species(); 1446 1447 /** 1448 * Returns the number of mask lanes (the length). 1449 * 1450 * @return the number of mask lanes 1451 */ 1452 public int length() { return species().length(); } 1453 1454 /** 1455 * Returns the lane elements of this mask packed into a {@code long} 1456 * value for at most the first 64 lane elements. 1457 * <p> 1458 * The lane elements are packed in the order of least significant bit 1459 * to most significant bit. 1460 * For each mask lane where {@code N} is the mask lane index, if the 1461 * mask lane is set then the {@code N}'th bit is set to one in the 1462 * resulting {@code long} value, otherwise the {@code N}'th bit is set 1463 * to zero. 1464 * 1465 * @return the lane elements of this mask packed into a {@code long} 1466 * value. 1467 */ 1468 public abstract long toLong(); 1469 1470 /** 1471 * Returns an {@code boolean} array containing the lane elements of this 1472 * mask. 1473 * <p> 1474 * This method behaves as if it {@link #intoArray(boolean[], int)} stores} 1475 * this mask into an allocated array and returns that array as 1476 * follows: 1477 * <pre>{@code 1478 * boolean[] a = new boolean[this.length()]; 1479 * this.intoArray(a, 0); 1480 * return a; 1481 * }</pre> 1482 * 1483 * @return an array containing the the lane elements of this vector 1484 */ 1485 public abstract boolean[] toArray(); 1486 1487 /** 1488 * Stores this mask into a {@code boolean} array starting at offset. 1489 * <p> 1490 * For each mask lane, where {@code N} is the mask lane index, 1491 * the lane element at index {@code N} is stored into the array at index 1492 * {@code i + N}. 1493 * 1494 * @param a the array 1495 * @param i the offset into the array 1496 * @throws IndexOutOfBoundsException if {@code i < 0}, or 1497 * {@code i > a.length - this.length()} 1498 */ 1499 public abstract void intoArray(boolean[] a, int i); 1500 1501 /** 1502 * Returns {@code true} if any of the mask lanes are set. 1503 * 1504 * @return {@code true} if any of the mask lanes are set, otherwise 1505 * {@code false}. 1506 */ 1507 public abstract boolean anyTrue(); 1508 1509 /** 1510 * Returns {@code true} if all of the mask lanes are set. 1511 * 1512 * @return {@code true} if all of the mask lanes are set, otherwise 1513 * {@code false}. 1514 */ 1515 public abstract boolean allTrue(); 1516 1517 /** 1518 * Returns the number of mask lanes that are set. 1519 * 1520 * @return the number of mask lanes that are set. 1521 */ 1522 public abstract int trueCount(); 1523 1524 // TODO: LZ count/numberOfLeadingZeros 1525 // TODO: xor, shiftl, shiftr 1526 1527 /** 1528 * Logically ands this mask with an input mask. 1529 * <p> 1530 * This is a mask binary operation where the logical and operation 1531 * ({@code &&} is applied to lane elements. 1532 * 1533 * @param o the input mask 1534 * @return the result of logically and'ing this mask with an input mask 1535 */ 1536 public abstract Mask<E, S> and(Mask<E, S> o); 1537 1538 /** 1539 * Logically ors this mask with an input mask. 1540 * <p> 1541 * This is a mask binary operation where the logical or operation 1542 * ({@code ||} is applied to lane elements. 1543 * 1544 * @param o the input mask 1545 * @return the result of logically or'ing this mask with an input mask 1546 */ 1547 public abstract Mask<E, S> or(Mask<E, S> o); 1548 1549 /** 1550 * Logically negates this mask. 1551 * <p> 1552 * This is a mask unary operation where the logical not operation 1553 * ({@code !} is applied to lane elements. 1554 * 1555 * @return the result of logically negating this mask. 1556 */ 1557 public abstract Mask<E, S> not(); 1558 1559 /** 1560 * Returns a vector representation of this mask. 1561 * <p> 1562 * For each mask lane, where {@code N} is the mask lane index, 1563 * if the mask lane is set then an element value whose most significant 1564 * bit is set is placed into the resulting vector at lane index 1565 * {@code N}, otherwise the default element value is placed into the 1566 * resulting vector at lane index {@code N}. 1567 * 1568 * @return a vector representation of this mask. 1569 */ 1570 public abstract Vector<E, S> toVector(); 1571 1572 /** 1573 * Tests if the lane at index {@code i} is set 1574 * @param i the lane index 1575 * 1576 * @return true if the lane at index {@code i} is set, otherwise false 1577 */ 1578 // @@@ Rename to isSet 1579 public abstract boolean getElement(int i); 1580 1581 /** 1582 * Transforms this mask to a mask of the given species shape {@code T} 1583 * and element type {@code F}. 1584 * <p> 1585 * This method behaves as if it returns the result of calling 1586 * {@link Species#reshape(Mask) reshape} on the given species with this 1587 * mask: 1588 * <pre>{@code 1589 * return species.reshape(this); 1590 * }</pre> 1591 * 1592 * @param species the species 1593 * @param <F> the boxed element type of the species 1594 * @param <T> the type of shape of the species 1595 * @return a mask transformed by shape and element type 1596 * @see Species#reshape(Mask) 1597 */ 1598 @ForceInline 1599 public <F, T extends Shape> Mask<F, T> reshape(Species<F, T> species) { 1600 return species.reshape(this); 1601 } 1602 1603 /** 1604 * Transforms this mask to a mask of the given species element type 1605 * {@code F}, where this mask's shape {@code S} is preserved. 1606 * <p> 1607 * This method behaves as if it returns the result of calling 1608 * {@link Species#rebracket(Mask) rebracket} on the given species with 1609 * this mask: 1610 * <pre>{@code 1611 * return species.rebracket(this); 1612 * }</pre> 1613 * 1614 * @param species the species 1615 * @param <F> the boxed element type of the species 1616 * @return a mask transformed element type 1617 * @see Species#rebracket(Mask) 1618 */ 1619 @ForceInline 1620 public <F> Mask<F, S> rebracket(Species<F, S> species) { 1621 return species.reshape(this); 1622 } 1623 1624 /** 1625 * Transforms this mask to a mask of the given species shape {@code T}, 1626 * where this mask's element type {@code E} is preserved. 1627 * <p> 1628 * This method behaves as if it returns the result of calling 1629 * {@link Species#resize(Mask) resize} on the given species with this 1630 * mask: 1631 * <pre>{@code 1632 * return species.resize(this); 1633 * }</pre> 1634 * 1635 * @param species the species 1636 * @param <T> the type of shape of the species 1637 * @return a mask transformed by shape 1638 * @see Species#resize(Mask) 1639 */ 1640 @ForceInline 1641 public <T extends Shape> Mask<E, T> resize(Species<E, T> species) { 1642 return species.reshape(this); 1643 } 1644 } 1645 1646 /** 1647 * A {@code Shuffle} represents an ordered immutable sequence of 1648 * {@code int} values. A Shuffle can be used with a shuffle accepting 1649 * vector operation to control the rearrangement of lane elements of input 1650 * vectors 1651 * <p> 1652 * The number of values in the sequence is referred to as the Shuffle 1653 * {@link #length() length}. The length also corresponds to the number of 1654 * Shuffle lanes. The lane element at lane index {@code N} (from {@code 0}, 1655 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th 1656 * value in the sequence. 1657 * A Shuffle and Vector of the same element type and shape have the same 1658 * number of lanes. 1659 * <p> 1660 * A {@code Shuffle<E, S>} is a specialized and limited form of an 1661 * {@code IntVector<S>} where the Shuffle's lane elements correspond to 1662 * lane index values. 1663 * A Shuffle describes how a lane element of a vector may cross lanes from 1664 * its lane index, {@code i} say, to another lane index whose value is the 1665 * Shuffle's lane element at lane index {@code i}. 1666 * 1667 * @param <E> the boxed element type of this mask 1668 * @param <S> the type of shape of this mask 1669 */ 1670 public static abstract class Shuffle<E, S extends Shape> { 1671 Shuffle() {} 1672 1673 /** 1674 * Returns the species of this shuffle. 1675 * 1676 * @return the species of this shuffle 1677 */ 1678 public abstract Species<E, S> species(); 1679 1680 /** 1681 * Returns the specialized {@code int} species of this shuffle. 1682 * 1683 * @return the specialized {@code int} species of this shuffle 1684 * @see #toVector 1685 */ 1686 public abstract IntVector.IntSpecies<S> intSpecies(); 1687 1688 /** 1689 * Returns the number of shuffle lanes (the length). 1690 * 1691 * @return the number of shuffle lanes 1692 */ 1693 public int length() { return species().length(); } 1694 1695 /** 1696 * Returns an {@code int} array containing the lane elements of this 1697 * shuffle. 1698 * <p> 1699 * This method behaves as if it {@link #intoArray(int[], int)} stores} 1700 * this shuffle into an allocated array and returns that array as 1701 * follows: 1702 * <pre>{@code 1703 * int[] a = new int[this.length()]; 1704 * this.intoArray(a, 0); 1705 * return a; 1706 * }</pre> 1707 * 1708 * @return an array containing the the lane elements of this vector 1709 */ 1710 public abstract int[] toArray(); 1711 1712 /** 1713 * Stores this shuffle into an {@code int} array starting at offset. 1714 * <p> 1715 * For each shuffle lane, where {@code N} is the shuffle lane index, 1716 * the lane element at index {@code N} is stored into the array at index 1717 * {@code i + N}. 1718 * 1719 * @param a the array 1720 * @param i the offset into the array 1721 * @throws IndexOutOfBoundsException if {@code i < 0}, or 1722 * {@code i > a.length - this.length()} 1723 */ 1724 public abstract void intoArray(int[] a, int i); 1725 1726 // @@@ rotate/shift/EL/ER 1727 1728 /** 1729 * Returns an {@link IntVector}, of the same shape as this shuffle, 1730 * containing the lane elements of this shuffle. 1731 * <p> 1732 * This method behaves as if it returns the result of creating an 1733 * {@link IntVector} given this shuffle's {@code int} species and an 1734 * {@code int} array obtained from this shuffle's lane elements, as 1735 * follows: 1736 * <pre>{@code 1737 * int[] a = this.toArray(); 1738 * return this.intSpecies().fromArray(a, 0); 1739 * }</pre> 1740 * 1741 * @return an {@link IntVector}, of the same shape as this shuffle, 1742 * containing the lane elements of this shuffle 1743 */ 1744 public abstract IntVector<S> toVector(); 1745 1746 /** 1747 * Gets the {@code int} lane element at lane index {@code i} 1748 * 1749 * @param i the lane index 1750 * @return the {@code int} lane element at lane index {@code i} 1751 */ 1752 public int getElement(int i) { return toArray()[i]; } 1753 1754 /** 1755 * Transforms this shuffle to a shuffle of the given species shape {@code T} 1756 * and element type {@code F}. 1757 * <p> 1758 * This method behaves as if it returns the result of calling 1759 * {@link Species#reshape(Shuffle) reshape} on the given species with this 1760 * shuffle: 1761 * <pre>{@code 1762 * return species.reshape(this); 1763 * }</pre> 1764 * 1765 * @param species the species 1766 * @param <F> the boxed element type of the species 1767 * @param <T> the type of shape of the species 1768 * @return a shuffle transformed by shape and element type 1769 * @see Species#reshape(Shuffle) 1770 */ 1771 @ForceInline 1772 public <F, T extends Shape> Shuffle<F, T> reshape(Species<F, T> species) { 1773 return species.reshape(this); 1774 } 1775 1776 /** 1777 * Transforms this shuffle to a shuffle of the given species element type 1778 * {@code F}, where this shuffle's shape {@code S} is preserved. 1779 * <p> 1780 * This method behaves as if it returns the result of calling 1781 * {@link Species#rebracket(Shuffle) rebracket} on the given species with this 1782 * shuffle: 1783 * <pre>{@code 1784 * return species.rebracket(this); 1785 * }</pre> 1786 * 1787 * @param species the species 1788 * @param <F> the boxed element type of the species 1789 * @return a shuffle transformed element type 1790 * @see Species#rebracket(Shuffle) 1791 */ 1792 @ForceInline 1793 public <F> Shuffle<F, S> rebracket(Species<F, S> species) { 1794 return species.reshape(this); 1795 } 1796 1797 /** 1798 * Transforms this shuffle to a shuffle of the given species shape {@code T}, 1799 * where this shuffle's element type {@code E} is preserved. 1800 * <p> 1801 * This method behaves as if it returns the result of calling 1802 * {@link Species#resize(Shuffle) resize} on the given species with this shuffle: 1803 * <pre>{@code 1804 * return species.resize(this); 1805 * }</pre> 1806 * 1807 * @param species the species 1808 * @param <T> the type of shape of the species 1809 * @return a shuffle transformed by shape 1810 * @see Species#resize(Shuffle) 1811 */ 1812 @ForceInline 1813 public <T extends Shape> Shuffle<E, T> resize(Species<E, T> species) { 1814 return species.reshape(this); 1815 } 1816 } 1817 1818 /** 1819 * Finds a preferred species for an element type. 1820 * <p> 1821 * A preferred species is a species chosen by the platform that has a 1822 * shape of maximal bit size. A preferred species for different element 1823 * types will have the same shape, and therefore vectors created from 1824 * such species will be shape compatible. 1825 * 1826 * @param c the element type 1827 * @param <E> the boxed element type 1828 * @return a preferred species for an element type 1829 * @throws IllegalArgumentException if no such species exists for the 1830 * element type 1831 */ 1832 @SuppressWarnings("unchecked") 1833 public static <E> Vector.Species<E, ?> preferredSpeciesInstance(Class<E> c) { 1834 Unsafe u = Unsafe.getUnsafe(); 1835 1836 int vectorLength = u.getMaxVectorSize(c); 1837 int vectorBitSize = bitSizeForVectorLength(c, vectorLength); 1838 Shape s = shapeForVectorBitSize(vectorBitSize); 1839 return speciesInstance(c, s); 1840 } 1841 1842 // @@@ public static method on Species? 1843 private static int bitSizeForVectorLength(Class<?> c, int elementSize) { 1844 if (c == float.class) { 1845 return Float.SIZE * elementSize; 1846 } 1847 else if (c == double.class) { 1848 return Double.SIZE * elementSize; 1849 } 1850 else if (c == byte.class) { 1851 return Byte.SIZE * elementSize; 1852 } 1853 else if (c == short.class) { 1854 return Short.SIZE * elementSize; 1855 } 1856 else if (c == int.class) { 1857 return Integer.SIZE * elementSize; 1858 } 1859 else if (c == long.class) { 1860 return Long.SIZE * elementSize; 1861 } 1862 else { 1863 throw new IllegalArgumentException("Bad vector type: " + c.getName()); 1864 } 1865 } 1866 1867 // @@@ public static method on Shape? 1868 private static Shape shapeForVectorBitSize(int bitSize) { 1869 switch (bitSize) { 1870 case 64: 1871 return Shapes.S_64_BIT; 1872 case 128: 1873 return Shapes.S_128_BIT; 1874 case 256: 1875 return Shapes.S_256_BIT; 1876 case 512: 1877 return Shapes.S_512_BIT; 1878 default: 1879 throw new IllegalArgumentException("Bad vector bit size: " + bitSize); 1880 } 1881 } 1882 1883 /** 1884 * Finds a species for an element type and shape. 1885 * 1886 * @param c the element type 1887 * @param s the shape 1888 * @param <E> the boxed element type 1889 * @param <S> the type of shape 1890 * @return a species for an element type and shape 1891 * @throws IllegalArgumentException if no such species exists for the 1892 * element type and/or shape 1893 */ 1894 @SuppressWarnings("unchecked") 1895 public static <E, S extends Shape> Vector.Species<E, S> speciesInstance(Class<E> c, S s) { 1896 if (c == float.class) { 1897 return (Vector.Species<E, S>) FloatVector.speciesInstance(s); 1898 } 1899 else if (c == double.class) { 1900 return (Vector.Species<E, S>) DoubleVector.speciesInstance(s); 1901 } 1902 else if (c == byte.class) { 1903 return (Vector.Species<E, S>) ByteVector.speciesInstance(s); 1904 } 1905 else if (c == short.class) { 1906 return (Vector.Species<E, S>) ShortVector.speciesInstance(s); 1907 } 1908 else if (c == int.class) { 1909 return (Vector.Species<E, S>) IntVector.speciesInstance(s); 1910 } 1911 else if (c == long.class) { 1912 return (Vector.Species<E, S>) LongVector.speciesInstance(s); 1913 } 1914 else { 1915 throw new IllegalArgumentException("Bad vector element type: " + c.getName()); 1916 } 1917 } 1918 }