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 import jdk.internal.vm.annotation.Stable; 30 31 import java.nio.ByteBuffer; 32 import java.nio.ByteOrder; 33 import java.util.Objects; 34 import java.util.function.Function; 35 import java.util.function.IntUnaryOperator; 36 import java.util.function.UnaryOperator; 37 38 import jdk.incubator.vector.*; 39 40 /** 41 * A {@code Vector} is designed for use in computations that can be transformed 42 * by a runtime compiler, on supported hardware, to Single Instruction Multiple 43 * Data (SIMD) computations leveraging vector hardware registers and vector 44 * hardware instructions. Such SIMD computations exploit data parallelism to 45 * perform the same operation on multiple data points simultaneously in 46 * less time than it would ordinarily take to perform the same operation 47 * sequentially on each data point. 48 * <p> 49 * A Vector represents an ordered immutable sequence of values of the same 50 * element type {@code e} that is one of the following primitive types 51 * {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, or 52 * {@code double}). The type variable {@code E} corresponds to the boxed 53 * element type, specifically the class that wraps a value of {@code e} in an 54 * object (such the {@code Integer} class that wraps a value of {@code int}}. 55 * A Vector has a {@link #shape() shape} {@code S}, extending type {@link VectorShape}, 56 * that governs the total {@link #bitSize() size} in bits of the sequence of values. 57 * The combination of element type and shape determines a <em>vector species</em>, 58 * represented by {@link jdk.incubator.vector.VectorSpecies}. 59 * <p> 60 * The number of values in the sequence is referred to as the Vector 61 * {@link #length() length}. The length also corresponds to the number of 62 * Vector lanes. The lane element at lane index {@code N} (from {@code 0}, 63 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th value in 64 * the sequence. 65 * Note: this arrangement 66 * of Vector bit size, Vector length, element bit size, and lane element index 67 * has no bearing on how a Vector instance and its sequence of elements may be 68 * arranged in memory or represented as a value in a vector hardware register. 69 * <p> 70 * Vector declares a set of vector operations (methods) that are common to all 71 * element types (such as addition). Sub-classes of Vector with a concrete 72 * boxed element type declare further operations that are specific to that 73 * element type (such as access to element values in lanes, logical operations 74 * on values of integral elements types, or transcendental operations on values 75 * of floating point element types). 76 * There are six abstract sub-classes of Vector corresponding to the supported set 77 * of element types, {@link ByteVector}, {@link ShortVector}, 78 * {@link IntVector} {@link LongVector}, {@link FloatVector}, and 79 * {@link DoubleVector}. Along with type-specific operations these classes 80 * support creation of vector values (instances of Vector). 81 * They expose static constants corresponding to the supported species, 82 * and static methods on these types generally take a species as a parameter. 83 * For example, 84 * {@link jdk.incubator.vector.FloatVector#fromArray(VectorSpecies, float[], int) FloatVector.fromArray()} 85 * creates and returns a float vector of the specified species, with elements 86 * loaded from the specified float array. 87 * <p> 88 * It is recommended that Species instances be held in {@code static final} 89 * fields for optimal creation and usage of Vector values by the runtime compiler. 90 * <p> 91 * Vector operations can be grouped into various categories and their behavior 92 * generally specified as follows: 93 * <ul> 94 * <li> 95 * A lane-wise unary operation operates on one input vector and produces a 96 * result vector. 97 * For each lane of the input vector the 98 * lane element is operated on using the specified scalar unary operation and 99 * the element result is placed into the vector result at the same lane. 100 * The following pseudocode expresses the behavior of this operation category, 101 * where {@code e} is the element type and {@code EVector} corresponds to the 102 * primitive Vector type: 103 * 104 * <pre>{@code 105 * EVector a = ...; 106 * e[] ar = new e[a.length()]; 107 * for (int i = 0; i < a.length(); i++) { 108 * ar[i] = scalar_unary_op(a.get(i)); 109 * } 110 * EVector r = EVector.fromArray(a.species(), ar, 0); 111 * }</pre> 112 * 113 * Unless otherwise specified the input and result vectors will have the same 114 * element type and shape. 115 * 116 * <li> 117 * A lane-wise binary operation operates on two input 118 * vectors and produces a result vector. 119 * For each lane of the two input vectors a and b, 120 * the corresponding lane elements from a and b are operated on 121 * using the specified scalar binary operation and the element result is placed 122 * into the vector result at the same lane. 123 * The following pseudocode expresses the behavior of this operation category: 124 * 125 * <pre>{@code 126 * EVector a = ...; 127 * EVector b = ...; 128 * e[] ar = new e[a.length()]; 129 * for (int i = 0; i < a.length(); i++) { 130 * ar[i] = scalar_binary_op(a.get(i), b.get(i)); 131 * } 132 * EVector r = EVector.fromArray(a.species(), ar, 0); 133 * }</pre> 134 * 135 * Unless otherwise specified the two input and result vectors will have the 136 * same element type and shape. 137 * 138 * <li> 139 * Generalizing from unary and binary operations, a lane-wise n-ary 140 * operation operates on n input vectors and produces a result vector. 141 * N lane elements from each input vector are operated on 142 * using the specified n-ary scalar operation and the element result is placed 143 * into the vector result at the same lane. 144 * Unless otherwise specified the n input and result vectors will have the same 145 * element type and shape. 146 * 147 * <li> 148 * A cross-lane vector reduction operation operates on all the lane 149 * elements of an input vector. 150 * An accumulation function is applied to all the 151 * lane elements to produce a scalar result. 152 * If the reduction operation is associative then the result may be accumulated 153 * by operating on the lane elements in any order using a specified associative 154 * scalar binary operation and identity value. Otherwise, the reduction 155 * operation specifies the behavior of the accumulation function. 156 * The following pseudocode expresses the behavior of this operation category 157 * if it is associative: 158 * <pre>{@code 159 * EVector a = ...; 160 * e r = <identity value>; 161 * for (int i = 0; i < a.length(); i++) { 162 * r = assoc_scalar_binary_op(r, a.get(i)); 163 * } 164 * }</pre> 165 * 166 * Unless otherwise specified the scalar result type and element type will be 167 * the same. 168 * 169 * <li> 170 * A lane-wise binary test operation operates on two input vectors and produces a 171 * result mask. For each lane of the two input vectors, a and b say, the 172 * the corresponding lane elements from a and b are operated on using the 173 * specified scalar binary test operation and the boolean result is placed 174 * into the mask at the same lane. 175 * The following pseudocode expresses the behavior of this operation category: 176 * <pre>{@code 177 * EVector a = ...; 178 * EVector b = ...; 179 * boolean[] ar = new boolean[a.length()]; 180 * for (int i = 0; i < a.length(); i++) { 181 * ar[i] = scalar_binary_test_op(a.get(i), b.get(i)); 182 * } 183 * VectorMask r = VectorMask.fromArray(a.species(), ar, 0); 184 * }</pre> 185 * 186 * Unless otherwise specified the two input vectors and result mask will have 187 * the same element type and shape. 188 * 189 * <li> 190 * The prior categories of operation can be said to operate within the vector 191 * lanes, where lane access is uniformly applied to all vectors, specifically 192 * the scalar operation is applied to elements taken from input vectors at the 193 * same lane, and if appropriate applied to the result vector at the same lane. 194 * A further category of operation is a cross-lane vector operation where lane 195 * access is defined by the arguments to the operation. Cross-lane operations 196 * generally rearrange lane elements, for example by permutation (commonly 197 * controlled by a {@link jdk.incubator.vector.VectorShuffle}) or by blending (commonly controlled by a 198 * {@link jdk.incubator.vector.VectorMask}). Such an operation explicitly specifies how it rearranges lane 199 * elements. 200 * </ul> 201 * 202 * <p> 203 * If a vector operation does not belong to one of the above categories then 204 * the operation explicitly specifies how it processes the lane elements of 205 * input vectors, and where appropriate expresses the behavior using 206 * pseudocode. 207 * 208 * <p> 209 * Many vector operations provide an additional {@link VectorMask mask} accepting 210 * variant. 211 * The mask controls which lanes are selected for application of the scalar 212 * operation. Masks are a key component for the support of control flow in 213 * vector computations. 214 * <p> 215 * Many vector operations provide an additional {@link jdk.incubator.vector.VectorMask mask}-accepting 216 * variant. 217 * The mask controls which lanes are selected for application of the scalar 218 * operation. Masks are a key component for the support of control flow in 219 * vector computations. 220 * <p> 221 * For certain operation categories the mask accepting variants can be specified 222 * in generic terms. If a lane of the mask is set then the scalar operation is 223 * applied to corresponding lane elements, otherwise if a lane of a mask is not 224 * set then a default scalar operation is applied and its result is placed into 225 * the vector result at the same lane. The default operation is specified as follows: 226 * <ul> 227 * <li> 228 * For a lane-wise n-ary operation the default operation is a function that returns 229 * it's first argument, specifically the lane element of the first input vector. 230 * <li> 231 * For an associative vector reduction operation the default operation is a 232 * function that returns the identity value. 233 * <li> 234 * For lane-wise binary test operation the default operation is a function that 235 * returns false. 236 * </ul> 237 * Otherwise, the mask accepting variant of the operation explicitly specifies 238 * how it processes the lane elements of input vectors, and where appropriate 239 * expresses the behavior using pseudocode. 240 * 241 * <p> 242 * For convenience, many vector operations of arity greater than one provide 243 * an additional scalar-accepting variant (such as adding a constant scalar 244 * value to all lanes of a vector). This variant accepts compatible 245 * scalar values instead of vectors for the second and subsequent input vectors, 246 * if any. 247 * Unless otherwise specified the scalar variant behaves as if each scalar value 248 * is transformed to a vector using the appropriate vector {@code broadcast} operation, and 249 * then the vector accepting vector operation is applied using the transformed 250 * values. 251 * 252 * <p> 253 * This is a value-based 254 * class; use of identity-sensitive operations (including reference equality 255 * ({@code ==}), identity hash code, or synchronization) on instances of 256 * {@code Vector} may have unpredictable results and should be avoided. 257 * 258 * @param <E> the boxed element type of elements in this vector 259 */ 260 public abstract class Vector<E> { 261 262 Vector() {} 263 264 /** 265 * Returns the species of this vector. 266 * 267 * @return the species of this vector 268 */ 269 public abstract VectorSpecies<E> species(); 270 271 /** 272 * Returns the primitive element type of this vector. 273 * 274 * @return the primitive element type of this vector 275 */ 276 public Class<E> elementType() { return species().elementType(); } 277 278 /** 279 * Returns the element size, in bits, of this vector. 280 * 281 * @return the element size, in bits 282 */ 283 public int elementSize() { return species().elementSize(); } 284 285 /** 286 * Returns the shape of this vector. 287 * 288 * @return the shape of this vector 289 */ 290 public VectorShape shape() { return species().shape(); } 291 292 /** 293 * Returns the number of vector lanes (the length). 294 * 295 * @return the number of vector lanes 296 */ 297 public int length() { return species().length(); } 298 299 /** 300 * Returns the total vector size, in bits. 301 * 302 * @return the total vector size, in bits 303 */ 304 public int bitSize() { return species().bitSize(); } 305 306 //Arithmetic 307 308 /** 309 * Adds this vector to an input vector. 310 * <p> 311 * This is a lane-wise binary operation which applies the primitive addition operation 312 * ({@code +}) to each lane. 313 * 314 * @param v the input vector 315 * @return the result of adding this vector to the input vector 316 */ 317 public abstract Vector<E> add(Vector<E> v); 318 319 /** 320 * Adds this vector to an input vector, selecting lane elements 321 * controlled by a mask. 322 * <p> 323 * This is a lane-wise binary operation which applies the primitive addition operation 324 * ({@code +}) to each lane. 325 * 326 * @param v the input vector 327 * @param m the mask controlling lane selection 328 * @return the result of adding this vector to the given vector 329 */ 330 public abstract Vector<E> add(Vector<E> v, VectorMask<E> m); 331 332 /** 333 * Subtracts an input vector from this vector. 334 * <p> 335 * This is a lane-wise binary operation which applies the primitive subtraction 336 * operation ({@code -}) to each lane. 337 * 338 * @param v the input vector 339 * @return the result of subtracting the input vector from this vector 340 */ 341 public abstract Vector<E> sub(Vector<E> v); 342 343 /** 344 * Subtracts an input vector from this vector, selecting lane elements 345 * controlled by a mask. 346 * <p> 347 * This is a lane-wise binary operation which applies the primitive subtraction 348 * operation ({@code -}) to each lane. 349 * 350 * @param v the input vector 351 * @param m the mask controlling lane selection 352 * @return the result of subtracting the input vector from this vector 353 */ 354 public abstract Vector<E> sub(Vector<E> v, VectorMask<E> m); 355 356 /** 357 * Multiplies this vector with an input vector. 358 * <p> 359 * This is a lane-wise binary operation which applies the primitive multiplication 360 * operation ({@code *}) to each lane. 361 * 362 * @param v the input vector 363 * @return the result of multiplying this vector with the input vector 364 */ 365 public abstract Vector<E> mul(Vector<E> v); 366 367 /** 368 * Multiplies this vector with an input vector, selecting lane elements 369 * controlled by a mask. 370 * <p> 371 * This is a lane-wise binary operation which applies the primitive multiplication 372 * operation ({@code *}) to each lane. 373 * 374 * @param v the input vector 375 * @param m the mask controlling lane selection 376 * @return the result of multiplying this vector with the input vector 377 */ 378 public abstract Vector<E> mul(Vector<E> v, VectorMask<E> m); 379 380 /** 381 * Negates this vector. 382 * <p> 383 * This is a lane-wise unary operation which applies the primitive negation operation 384 * ({@code -}) to each lane. 385 * 386 * @return the negation this vector 387 */ 388 public abstract Vector<E> neg(); 389 390 /** 391 * Negates this vector, selecting lane elements controlled by a mask. 392 * <p> 393 * This is a lane-wise unary operation which applies the primitive negation operation 394 * ({@code -})to each lane. 395 * 396 * @param m the mask controlling lane selection 397 * @return the negation this vector 398 */ 399 public abstract Vector<E> neg(VectorMask<E> m); 400 401 // Maths from java.math 402 403 /** 404 * Returns the modulus of this vector. 405 * <p> 406 * This is a lane-wise unary operation which applies the operation 407 * {@code (a) -> (a < 0) ? -a : a} to each lane. 408 * 409 * @return the modulus this vector 410 */ 411 public abstract Vector<E> abs(); 412 413 /** 414 * Returns the modulus of this vector, selecting lane elements controlled by 415 * a mask. 416 * <p> 417 * This is a lane-wise unary operation which applies the operation 418 * {@code (a) -> (a < 0) ? -a : a} to each lane. 419 * 420 * @param m the mask controlling lane selection 421 * @return the modulus this vector 422 */ 423 public abstract Vector<E> abs(VectorMask<E> m); 424 425 /** 426 * Returns the minimum of this vector and an input vector. 427 * <p> 428 * This is a lane-wise binary operation which applies the operation 429 * {@code (a, b) -> a < b ? a : b} to each lane. 430 * 431 * @param v the input vector 432 * @return the minimum of this vector and the input vector 433 */ 434 public abstract Vector<E> min(Vector<E> v); 435 436 /** 437 * Returns the minimum of this vector and an input vector, 438 * selecting lane elements controlled by a mask. 439 * <p> 440 * This is a lane-wise binary operation which applies the operation 441 * {@code (a, b) -> a < b ? a : b} to each lane. 442 * 443 * @param v the input vector 444 * @param m the mask controlling lane selection 445 * @return the minimum of this vector and the input vector 446 */ 447 public abstract Vector<E> min(Vector<E> v, VectorMask<E> m); 448 449 /** 450 * Returns the maximum of this vector and an input vector. 451 * <p> 452 * This is a lane-wise binary operation which applies the operation 453 * {@code (a, b) -> a > b ? a : b} to each lane. 454 * 455 * @param v the input vector 456 * @return the maximum of this vector and the input vector 457 */ 458 public abstract Vector<E> max(Vector<E> v); 459 460 /** 461 * Returns the maximum of this vector and an input vector, 462 * selecting lane elements controlled by a mask. 463 * <p> 464 * This is a lane-wise binary operation which applies the operation 465 * {@code (a, b) -> a > b ? a : b} to each lane. 466 * 467 * @param v the input vector 468 * @param m the mask controlling lane selection 469 * @return the maximum of this vector and the input vector 470 */ 471 public abstract Vector<E> max(Vector<E> v, VectorMask<E> m); 472 473 // Comparisons 474 475 /** 476 * Tests if this vector is equal to an input vector. 477 * <p> 478 * This is a lane-wise binary test operation where the primitive equals 479 * operation ({@code ==}) to each lane. 480 * 481 * @param v the input vector 482 * @return the result mask of testing if this vector is equal to the input 483 * vector 484 */ 485 public abstract VectorMask<E> equal(Vector<E> v); 486 487 /** 488 * Tests if this vector is not equal to an input vector. 489 * <p> 490 * This is a lane-wise binary test operation where the primitive not equals 491 * operation ({@code !=}) to each lane. 492 * 493 * @param v the input vector 494 * @return the result mask of testing if this vector is not equal to the 495 * input vector 496 */ 497 public abstract VectorMask<E> notEqual(Vector<E> v); 498 499 /** 500 * Tests if this vector is less than an input vector. 501 * <p> 502 * This is a lane-wise binary test operation where the primitive less than 503 * operation ({@code <}) to each lane. 504 * 505 * @param v the input vector 506 * @return the mask result of testing if this vector is less than the input 507 * vector 508 */ 509 public abstract VectorMask<E> lessThan(Vector<E> v); 510 511 /** 512 * Tests if this vector is less or equal to an input vector. 513 * <p> 514 * This is a lane-wise binary test operation where the primitive less than 515 * or equal to operation ({@code <=}) to each lane. 516 * 517 * @param v the input vector 518 * @return the mask result of testing if this vector is less than or equal 519 * to the input vector 520 */ 521 public abstract VectorMask<E> lessThanEq(Vector<E> v); 522 523 /** 524 * Tests if this vector is greater than an input vector. 525 * <p> 526 * This is a lane-wise binary test operation where the primitive greater than 527 * operation ({@code >}) to each lane. 528 * 529 * @param v the input vector 530 * @return the mask result of testing if this vector is greater than the 531 * input vector 532 */ 533 public abstract VectorMask<E> greaterThan(Vector<E> v); 534 535 /** 536 * Tests if this vector is greater than or equal to an input vector. 537 * <p> 538 * This is a lane-wise binary test operation where the primitive greater than 539 * or equal to operation ({@code >=}) to each lane. 540 * 541 * @param v the input vector 542 * @return the mask result of testing if this vector is greater than or 543 * equal to the given vector 544 */ 545 public abstract VectorMask<E> greaterThanEq(Vector<E> v); 546 547 // Elemental shifting 548 549 /** 550 * Rotates left the lane elements of this vector by the given number of 551 * lanes, {@code i}, modulus the vector length. 552 * <p> 553 * This is a cross-lane operation that permutes the lane elements of this 554 * vector. 555 * For each lane of the input vector, at lane index {@code N}, the lane 556 * element is placed into the result vector at lane index 557 * {@code (N + i) % length()}. 558 * 559 * @param i the number of lanes to rotate left 560 * @return the result of rotating left lane elements of this vector by the 561 * given number of lanes 562 */ 563 public abstract Vector<E> rotateEL(int i); 564 565 /** 566 * Rotates right the lane elements of this vector by the given number of 567 * lanes, {@code i}, modulus the vector length. 568 * <p> 569 * This is a cross-lane operation that permutes the lane elements of this 570 * vector. 571 * For each lane of the input vector, at lane index {@code N}, the lane 572 * element is placed into the result vector at lane index 573 * {@code (N + length() - (i % length())) % length()} 574 * 575 * @param i the number of lanes to rotate left 576 * @return the result of rotating right lane elements of this vector by the 577 * given number of lanes 578 */ 579 public abstract Vector<E> rotateER(int i); 580 581 /** 582 * Shift left the lane elements of this vector by the given number of 583 * lanes, {@code i}, modulus the vector length. 584 * <p> 585 * This is a cross-lane operation that permutes the lane elements of this 586 * vector and behaves as if rotating left the lane elements by {@code i}, 587 * and then the zero value is placed into the result vector at lane indexes 588 * less than {@code i % length()}. 589 * 590 * @param i the number of lanes to shift left 591 * @return the result of shifting left lane elements of this vector by the 592 * given number of lanes 593 * @throws IllegalArgumentException if {@code i} is {@code < 0}. 594 */ 595 public abstract Vector<E> shiftEL(int i); 596 597 /** 598 * Shift right the lane elements of this vector by the given number of 599 * lanes, {@code i}, modulus the vector length. 600 * <p> 601 * This is a cross-lane operation that permutes the lane elements of this 602 * vector and behaves as if rotating right the lane elements by {@code i}, 603 * and then the zero value is placed into the result vector at lane indexes 604 * greater or equal to {@code length() - (i % length())}. 605 * 606 * @param i the number of lanes to shift right 607 * @return the result of shifting right lane elements of this vector by the 608 * given number of lanes 609 * @throws IllegalArgumentException if {@code i} is {@code < 0}. 610 */ 611 public abstract Vector<E> shiftER(int i); 612 613 /** 614 * Blends the lane elements of this vector with those of an input vector, 615 * selecting lanes controlled by a mask. 616 * <p> 617 * For each lane of the mask, at lane index {@code N}, if the mask lane 618 * is set then the lane element at {@code N} from the input vector is 619 * selected and placed into the resulting vector at {@code N}, 620 * otherwise the lane element at {@code N} from this input vector is 621 * selected and placed into the resulting vector at {@code N}. 622 * 623 * @param v the input vector 624 * @param m the mask controlling lane selection 625 * @return the result of blending the lane elements of this vector with 626 * those of an input vector 627 */ 628 public abstract Vector<E> blend(Vector<E> v, VectorMask<E> m); 629 630 /** 631 * Rearranges the lane elements of this vector and those of an input vector, 632 * selecting lane indexes controlled by shuffles and a mask. 633 * <p> 634 * This is a cross-lane operation that rearranges the lane elements of this 635 * vector and the input vector. This method behaves as if it rearranges 636 * each vector with the corresponding shuffle and then blends the two 637 * results with the mask: 638 * <pre>{@code 639 * return this.rearrange(s1).blend(v.rearrange(s2), m); 640 * }</pre> 641 * 642 * @param v the input vector 643 * @param s the shuffle controlling lane index selection of the input vector 644 * if corresponding mask lanes are set, otherwise controlling lane 645 * index selection of this vector 646 * @param m the mask controlling shuffled lane selection 647 * @return the rearrangement of lane elements of this vector and 648 * those of an input vector 649 */ 650 @ForceInline 651 // rearrange 652 public abstract Vector<E> rearrange(Vector<E> v, 653 VectorShuffle<E> s, VectorMask<E> m); 654 655 /** 656 * Rearranges the lane elements of this vector selecting lane indexes 657 * controlled by a shuffle. 658 * <p> 659 * This is a cross-lane operation that rearranges the lane elements of this 660 * vector. 661 * For each lane of the shuffle, at lane index {@code N} with lane 662 * element {@code I}, the lane element at {@code I} from this vector is 663 * selected and placed into the resulting vector at {@code N}. 664 * 665 * @param s the shuffle controlling lane index selection 666 * @return the rearrangement of the lane elements of this vector 667 */ 668 // rearrange 669 public abstract Vector<E> rearrange(VectorShuffle<E> s); 670 671 672 // Conversions 673 674 /** 675 * Converts this vector into a shuffle, creating a shuffle from vector 676 * lane elements cast to {@code int} then logically AND'ed with the 677 * shuffle length minus one. 678 * <p> 679 * This methods behaves as if it returns the result of creating a shuffle 680 * given an array of the vector lane elements, as follows: 681 * <pre>{@code 682 * $type$[] a = this.toArray(); 683 * int[] sa = new int[a.length]; 684 * for (int i = 0; i < a.length; i++) { 685 * sa[i] = (int) a[i]; 686 * } 687 * return this.species().shuffleFromValues(sa); 688 * }</pre> 689 * 690 * @return a shuffle representation of this vector 691 */ 692 public abstract VectorShuffle<E> toShuffle(); 693 694 // Bitwise preserving 695 696 /** 697 * Transforms this vector to a vector of the given species of element type {@code F}. 698 * <p> 699 * The underlying bits of this vector are copied to the resulting 700 * vector without modification, but those bits, before copying, may be 701 * truncated if the this vector's bit size is greater than desired vector's bit 702 * size, or appended to with zero bits if this vector's bit size is less 703 * than desired vector's bit size. 704 * <p> 705 * The method behaves as if this vector is stored into a byte buffer 706 * and then the desired vector is loaded from the byte buffer using 707 * native byte ordering. The implication is that ByteBuffer reads bytes 708 * and then composes them based on the byte ordering so the result 709 * depends on this composition. 710 * <p> 711 * For example, on a system with ByteOrder.LITTLE_ENDIAN, loading from 712 * byte array with values {0,1,2,3} and reshaping to int, leads to bytes 713 * being composed in order 0x3 0x2 0x1 0x0 which is decimal value 50462976. 714 * On a system with ByteOrder.BIG_ENDIAN, the value is instead 66051 because 715 * bytes are composed in order 0x0 0x1 0x2 0x3. 716 * <p> 717 * The following pseudocode expresses the behavior: 718 * <pre>{@code 719 * int blen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; 720 * ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 721 * this.intoByteBuffer(bb, 0); 722 * return $type$Vector.fromByteBuffer(s, bb, 0); 723 * }</pre> 724 * 725 * @param s species of desired vector 726 * @param <F> the boxed element type of the species 727 * @return a vector transformed, by shape and element type, from this vector 728 */ 729 @ForceInline 730 public abstract <F> Vector<F> reinterpret(VectorSpecies<F> s); 731 732 @ForceInline 733 @SuppressWarnings("unchecked") 734 <F> Vector<F> defaultReinterpret(VectorSpecies<F> s) { 735 int blen = Math.max(s.bitSize(), this.species().bitSize()) / Byte.SIZE; 736 ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 737 this.intoByteBuffer(bb, 0); 738 739 Class<?> stype = s.elementType(); 740 if (stype == byte.class) { 741 return (Vector) ByteVector.fromByteBuffer((ByteVector.ByteSpecies)s, bb, 0); 742 } else if (stype == short.class) { 743 return (Vector) ShortVector.fromByteBuffer((ShortVector.ShortSpecies)s, bb, 0); 744 } else if (stype == int.class) { 745 return (Vector) IntVector.fromByteBuffer((IntVector.IntSpecies)s, bb, 0); 746 } else if (stype == long.class) { 747 return (Vector) LongVector.fromByteBuffer((LongVector.LongSpecies)s, bb, 0); 748 } else if (stype == float.class) { 749 return (Vector) FloatVector.fromByteBuffer((FloatVector.FloatSpecies)s, bb, 0); 750 } else if (stype == double.class) { 751 return (Vector) DoubleVector.fromByteBuffer((DoubleVector.DoubleSpecies)s, bb, 0); 752 } else { 753 throw new UnsupportedOperationException("Bad lane type for reinterpret."); 754 } 755 } 756 757 /** 758 * Transforms this vector to a vector of same element type but different shape identified by species. 759 * <p> 760 * The lane elements of this vector are copied without 761 * modification to the resulting vector, but those lane elements, before 762 * copying, may be truncated if this vector's length is greater than the desired 763 * vector's length, or appended to with default element values if this 764 * vector's length is less than desired vector's length. 765 * <p> 766 * The method behaves as if this vector is stored into a byte array 767 * and then the returned vector is loaded from the byte array. 768 * The following pseudocode expresses the behavior: 769 * <pre>{@code 770 * int alen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; 771 * byte[] a = new byte[alen]; 772 * this.intoByteArray(a, 0); 773 * return $type$Vector.fromByteArray(s, a, 0); 774 * }</pre> 775 * 776 * @param s species of the desired vector 777 * @return a vector transformed, by shape, from this vector 778 */ 779 public abstract Vector<E> reshape(VectorSpecies<E> s); 780 781 // Cast 782 783 /** 784 * Converts this vector to a vector of the given species element type {@code F}. 785 * <p> 786 * For each vector lane up to the length of this vector or 787 * desired vector, which ever is the minimum, and where {@code N} is the 788 * vector lane index, the element at index {@code N} of primitive type 789 * {@code E} is converted, according to primitive conversion rules 790 * specified by the Java Language Specification, to a value of primitive 791 * type {@code F} and placed into the resulting vector at lane index 792 * {@code N}. If desired vector's length is greater than this 793 * vector's length then the default primitive value is placed into 794 * subsequent lanes of the resulting vector. 795 * 796 * @param s species of the desired vector 797 * @param <F> the boxed element type of the species 798 * @return a vector converted by shape and element type from this vector 799 */ 800 public abstract <F> Vector<F> cast(VectorSpecies<F> s); 801 802 //Array stores 803 804 /** 805 * Stores this vector into a byte array starting at an offset. 806 * <p> 807 * Bytes are extracted from primitive lane elements according to the 808 * native byte order of the underlying platform. 809 * <p> 810 * This method behaves as it calls the 811 * byte buffer, offset, and mask accepting 812 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: 813 * <pre>{@code 814 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); 815 * }</pre> 816 * 817 * @param a the byte array 818 * @param i the offset into the array 819 * @return a vector loaded from a byte array 820 * @throws IndexOutOfBoundsException if {@code i < 0} or 821 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 822 */ 823 public abstract void intoByteArray(byte[] a, int i); 824 825 /** 826 * Stores this vector into a byte array starting at an offset and using a mask. 827 * <p> 828 * Bytes are extracted from primitive lane elements according to the 829 * native byte order of the underlying platform. 830 * <p> 831 * This method behaves as it calls the 832 * byte buffer, offset, and mask accepting 833 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: 834 * <pre>{@code 835 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m); 836 * }</pre> 837 * 838 * @param a the byte array 839 * @param i the offset into the array 840 * @param m the mask controlling lane selection 841 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 842 * or {@code > a.length}, 843 * for any vector lane index {@code N} where the mask at lane {@code N} 844 * is set 845 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} 846 */ 847 public abstract void intoByteArray(byte[] a, int i, VectorMask<E> m); 848 849 /** 850 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 851 * offset into the byte buffer. 852 * <p> 853 * Bytes are extracted from primitive lane elements according to the 854 * native byte order of the underlying platform. 855 * <p> 856 * This method behaves as if it calls the byte buffer, offset, and mask 857 * accepting 858 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask)} method} as follows: 859 * <pre>{@code 860 * this.intoByteBuffer(b, i, this.maskAllTrue()) 861 * }</pre> 862 * 863 * @param b the byte buffer 864 * @param i the offset into the byte buffer 865 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 866 * or {@code > b.limit()}, 867 * or if there are fewer than 868 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 869 * remaining in the byte buffer from the given offset 870 */ 871 public abstract void intoByteBuffer(ByteBuffer b, int i); 872 873 /** 874 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 875 * offset into the byte buffer and using a mask. 876 * <p> 877 * This method behaves as if the byte buffer is viewed as a primitive 878 * {@link java.nio.Buffer buffer} for the primitive element type, 879 * according to the native byte order of the underlying platform, and 880 * the lane elements of this vector are put into the buffer if the 881 * corresponding mask lane is set. 882 * The following pseudocode expresses the behavior, where 883 * {@coce EBuffer} is the primitive buffer type, {@code e} is the 884 * primitive element type, and {@code EVector} is the primitive 885 * vector type for this vector: 886 * <pre>{@code 887 * EBuffer eb = b.duplicate(). 888 * order(ByteOrder.nativeOrder()).position(i). 889 * asEBuffer(); 890 * e[] es = ((EVector)this).toArray(); 891 * for (int n = 0; n < t.length; n++) { 892 * if (m.isSet(n)) { 893 * eb.put(n, es[n]); 894 * } 895 * } 896 * }</pre> 897 * 898 * @param b the byte buffer 899 * @param i the offset into the byte buffer 900 * @param m the mask 901 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 902 * or {@code > b.limit()}, 903 * for any vector lane index {@code N} where the mask at lane {@code N} 904 * is set 905 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes 906 */ 907 public abstract void intoByteBuffer(ByteBuffer b, int i, VectorMask<E> m); 908 909 /** 910 * Find bit size based on element type and number of elements. 911 * 912 * @param c the element type 913 * @param numElem number of lanes in the vector 914 * @return size in bits for vector 915 */ 916 public static int bitSizeForVectorLength(Class<?> c, int numElem) { 917 if (c == float.class) { 918 return Float.SIZE * numElem; 919 } 920 else if (c == double.class) { 921 return Double.SIZE * numElem; 922 } 923 else if (c == byte.class) { 924 return Byte.SIZE * numElem; 925 } 926 else if (c == short.class) { 927 return Short.SIZE * numElem; 928 } 929 else if (c == int.class) { 930 return Integer.SIZE * numElem; 931 } 932 else if (c == long.class) { 933 return Long.SIZE * numElem; 934 } 935 else { 936 throw new IllegalArgumentException("Bad vector type: " + c.getName()); 937 } 938 } 939 }