rev 54658 : refactored mask and shuffle creation methods, moved classes to top-level
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 a 46 * faster time 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 56 * {@link VectorShape}, that governs the total {@link #bitSize() size} in bits 57 * of the sequence of values. 58 * <p> 59 * The number of values in the sequence is referred to as the Vector 60 * {@link #length() length}. The length also corresponds to the number of 61 * Vector lanes. The lane element at lane index {@code N} (from {@code 0}, 62 * inclusive, to length, exclusive) corresponds to the {@code N + 1}'th value in 63 * the sequence. 64 * Note: this arrangement 65 * of Vector bit size, Vector length, element bit size, and lane element index 66 * has no bearing on how a Vector instance and its sequence of elements may be 67 * arranged in memory or represented as a value in a vector hardware register. 68 * <p> 69 * Vector declares a set of vector operations (methods) that are common to all 70 * element types (such as addition). Sub-classes of Vector with a concrete 71 * boxed element type declare further operations that are specific to that 72 * element type (such as access to element values in lanes, logical operations 73 * on values of integral elements types, or transcendental operations on values 74 * of floating point element types). 75 * There are six sub-classes of Vector corresponding to the supported set 76 * of element types, {@link ByteVector}, {@link ShortVector}, 77 * {@link IntVector} {@link LongVector}, {@link FloatVector}, and 78 * {@link DoubleVector}. 79 * <p> 80 * Vector values, instances of Vector, are created from a special kind of 81 * factory called a {@link VectorSpecies}. A VectorSpecies has an 82 * element type and shape and creates Vector values of the same element type 83 * and shape. 84 * A species can be {@link VectorSpecies#of(Class, VectorShape)} obtained} given an element 85 * type and shape, or a preferred species can be 86 * {@link VectorSpecies#ofPreferred(Class)} obtained} given just an element type where the most 87 * optimal shape is selected for the current platform. It is recommended that 88 * VectorSpecies instances be held in {@code static final} fields for optimal creation 89 * and usage of Vector values by the runtime compiler. 90 * <p> 91 * Vector operations can be grouped into various categories and their behaviour 92 * generally specified as follows: 93 * <ul> 94 * <li> 95 * A vector unary operation (1-ary) operates on one input vector to produce 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 behaviour 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<S> 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<S> r = a.species().fromArray(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 vector binary operation (2-ary) operates on two input 118 * vectors to produce a result vector. 119 * For each lane of the two input vectors, 120 * a and b say, 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 behaviour of this operation category: 124 * 125 * <pre>{@code 126 * EVector<S> a = ...; 127 * EVector<S> 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<S> r = a.species().fromArray(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 (1-ary) and binary (2-ary) operations, a vector n-ary 140 * operation operates in n input vectors to produce a 141 * result vector. 142 * N lane elements from each input vector are operated on 143 * using the specified n-ary scalar operation and the element result is placed 144 * into the vector result at the same lane. 145 * Unless otherwise specified the n input and result vectors will have the same 146 * element type and shape. 147 * 148 * <li> 149 * A vector reduction operation operates on all the lane 150 * elements of an input vector. 151 * An accumulation function is applied to all the 152 * lane elements to produce a scalar result. 153 * If the reduction operation is associative then the result may be accumulated 154 * by operating on the lane elements in any order using a specified associative 155 * scalar binary operation and identity value. Otherwise, the reduction 156 * operation specifies the behaviour of the accumulation function. 157 * The following pseudocode expresses the behaviour of this operation category 158 * if it is associative: 159 * <pre>{@code 160 * EVector<S> a = ...; 161 * e r = <identity value>; 162 * for (int i = 0; i < a.length(); i++) { 163 * r = assoc_scalar_binary_op(r, a.get(i)); 164 * } 165 * }</pre> 166 * 167 * Unless otherwise specified the scalar result type and element type will be 168 * the same. 169 * 170 * <li> 171 * A vector binary test operation operates on two input vectors to produce a 172 * result mask. For each lane of the two input vectors, a and b say, the 173 * the corresponding lane elements from a and b are operated on using the 174 * specified scalar binary test operation and the boolean result is placed 175 * into the mask at the same lane. 176 * The following pseudocode expresses the behaviour of this operation category: 177 * <pre>{@code 178 * EVector<S> a = ...; 179 * EVector<S> b = ...; 180 * boolean[] ar = new boolean[a.length()]; 181 * for (int i = 0; i < a.length(); i++) { 182 * ar[i] = scalar_binary_test_op(a.get(i), b.get(i)); 183 * } 184 * VectorMask<E> r = a.species().maskFromArray(ar, 0); 185 * }</pre> 186 * 187 * Unless otherwise specified the two input vectors and result mask will have 188 * the same element type and shape. 189 * 190 * <li> 191 * The prior categories of operation can be said to operate within the vector 192 * lanes, where lane access is uniformly applied to all vectors, specifically 193 * the scalar operation is applied to elements taken from input vectors at the 194 * same lane, and if appropriate applied to the result vector at the same lane. 195 * A further category of operation is a cross-lane vector operation where lane 196 * access is defined by the arguments to the operation. Cross-lane operations 197 * generally rearrange lane elements, for example by permutation (commonly 198 * controlled by a {@link VectorShuffle}) or by blending (commonly controlled by a 199 * {@link VectorMask}). Such an operation explicitly specifies how it rearranges lane 200 * elements. 201 * </ul> 202 * 203 * If a vector operation is represented as an instance method then first input 204 * vector corresponds to {@code this} vector and subsequent input vectors are 205 * arguments of the method. Otherwise, if the an operation is represented as a 206 * static method then all input vectors are arguments of the method. 207 * <p> 208 * If a vector operation does not belong to one of the above categories then 209 * the operation explicitly specifies how it processes the lane elements of 210 * input vectors, and where appropriate expresses the behaviour using 211 * pseudocode. 212 * 213 * <p> 214 * Many vector operations provide an additional {@link VectorMask mask} accepting 215 * variant. 216 * The mask controls which lanes are selected for application of the scalar 217 * operation. Masks are a key component for the support of control flow in 218 * vector computations. 219 * <p> 220 * For certain operation categories the mask accepting variants can be specified 221 * in generic terms. If a lane of the mask is set then the scalar operation is 222 * applied to corresponding lane elements, otherwise if a lane of a mask is not 223 * set then a default scalar operation is applied and its result is placed into 224 * the vector result at the same lane. The default operation is specified for 225 * the following operation categories: 226 * <ul> 227 * <li> 228 * For a vector n-ary operation the default operation is a function that returns 229 * it's first argument, specifically a 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 vector 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 behaviour using pseudocode. 240 * 241 * <p> 242 * For convenience many vector operations, of arity greater than one, provide 243 * an additional scalar accepting variant. This variant accepts compatible 244 * scalar values instead of vectors for the second and subsequent input vectors, 245 * if any. 246 * Unless otherwise specified the scalar variant behaves as if each scalar value 247 * is transformed to a vector using the vector species 248 * {@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 vector binary operation where the primitive addition operation 312 * ({@code +}) is applied to lane elements. 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 vector binary operation where the primitive addition operation 324 * ({@code +}) is applied to lane elements. 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 vector binary operation where the primitive subtraction 336 * operation ({@code -}) is applied to lane elements. 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 vector binary operation where the primitive subtraction 348 * operation ({@code -}) is applied to lane elements. 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 vector binary operation where the primitive multiplication 360 * operation ({@code *}) is applied to lane elements. 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 vector binary operation where the primitive multiplication 372 * operation ({@code *}) is applied to lane elements. 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 vector unary operation where the primitive negation operation 384 * ({@code -}) is applied to lane elements. 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 vector unary operation where the primitive negation operation 394 * ({@code -})is applied to lane elements. 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 vector unary operation where the operation 407 * {@code (a) -> (a < 0) ? -a : a} is applied to lane elements. 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 vector unary operation where the operation 418 * {@code (a) -> (a < 0) ? -a : a} is applied to lane elements. 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 vector binary operation where the operation 429 * {@code (a, b) -> a < b ? a : b} is applied to lane elements. 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 vector binary operation where the operation 441 * {@code (a, b) -> a < b ? a : b} is applied to lane elements. 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 vector binary operation where the operation 453 * {@code (a, b) -> a > b ? a : b} is applied to lane elements. 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 vector binary operation where the operation 465 * {@code (a, b) -> a > b ? a : b} is applied to lane elements. 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 vector binary test operation where the primitive equals 479 * operation ({@code ==}) is applied to lane elements. 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 vector binary test operation where the primitive not equals 491 * operation ({@code !=}) is applied to lane elements. 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 vector binary test operation where the primitive less than 503 * operation ({@code <}) is applied to lane elements. 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 vector binary test operation where the primitive less than 515 * or equal to operation ({@code <=}) is applied to lane elements. 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 vector binary test operation where the primitive greater than 527 * operation ({@code >}) is applied to lane elements. 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 vector binary test operation where the primitive greater than 539 * or equal to operation ({@code >=}) is applied to lane elements. 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 to the result vector at lane index 557 * {@code (i + N) % this.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 and behaves as if rotating left the lane elements by 571 * {@code this.length() - (i % this.length())} lanes. 572 * 573 * @param i the number of lanes to rotate left 574 * @return the result of rotating right lane elements of this vector by the 575 * given number of lanes 576 */ 577 public abstract Vector<E> rotateER(int i); 578 579 /** 580 * Shift left the lane elements of this vector by the given number of 581 * lanes, {@code i}, modulus the vector length. 582 * <p> 583 * This is a cross-lane operation that permutes the lane elements of this 584 * vector and behaves as if rotating left the lane elements by {@code i}, 585 * and then the zero value is placed into the result vector at lane indexes 586 * less than {@code i % this.length()}. 587 * 588 * @param i the number of lanes to shift left 589 * @return the result of shifting left lane elements of this vector by the 590 * given number of lanes 591 * @throws IllegalArgumentException if {@code i} is {@code < 0}. 592 */ 593 public abstract Vector<E> shiftEL(int i); 594 595 /** 596 * Shift right the lane elements of this vector by the given number of 597 * lanes, {@code i}, modulus the vector length. 598 * <p> 599 * This is a cross-lane operation that permutes the lane elements of this 600 * vector and behaves as if rotating right the lane elements by {@code i}, 601 * and then the zero value is placed into the result vector at lane indexes 602 * greater or equal to {@code this.length() - (i % this.length())}. 603 * 604 * @param i the number of lanes to shift left 605 * @return the result of shifting left lane elements of this vector by the 606 * given number of lanes 607 * @throws IllegalArgumentException if {@code i} is {@code < 0}. 608 */ 609 public abstract Vector<E> shiftER(int i); 610 611 /** 612 * Blends the lane elements of this vector with those of an input vector, 613 * selecting lanes controlled by a mask. 614 * <p> 615 * For each lane of the mask, at lane index {@code N}, if the mask lane 616 * is set then the lane element at {@code N} from the input vector is 617 * selected and placed into the resulting vector at {@code N}, 618 * otherwise the the lane element at {@code N} from this input vector is 619 * selected and placed into the resulting vector at {@code N}. 620 * 621 * @param v the input vector 622 * @param m the mask controlling lane selection 623 * @return the result of blending the lane elements of this vector with 624 * those of an input vector 625 */ 626 public abstract Vector<E> blend(Vector<E> v, VectorMask<E> m); 627 628 /** 629 * Rearranges the lane elements of this vector and those of an input vector, 630 * selecting lane indexes controlled by shuffles and a mask. 631 * <p> 632 * This is a cross-lane operation that rearranges the lane elements of this 633 * vector and the input vector. This method behaves as if it rearranges 634 * each vector with the corresponding shuffle and then blends the two 635 * results with the mask: 636 * <pre>{@code 637 * return this.rearrange(s1).blend(v.rearrange(s2), m); 638 * }</pre> 639 * 640 * @param v the input vector 641 * @param s the shuffle controlling lane index selection of the input vector 642 * if corresponding mask lanes are set, otherwise controlling lane 643 * index selection of this vector 644 * @param m the mask controlling shuffled lane selection 645 * @return the rearrangement of lane elements of this vector and 646 * those of an input vector 647 */ 648 @ForceInline 649 // rearrange 650 public abstract Vector<E> rearrange(Vector<E> v, 651 VectorShuffle<E> s, VectorMask<E> m); 652 653 /** 654 * Rearranges the lane elements of this vector selecting lane indexes 655 * controlled by a shuffle. 656 * <p> 657 * This is a cross-lane operation that rearranges the lane elements of this 658 * vector. 659 * For each lane of the shuffle, at lane index {@code N} with lane 660 * element {@code I}, the lane element at {@code I} from this vector is 661 * selected and placed into the resulting vector at {@code N}. 662 * 663 * @param s the shuffle controlling lane index selection 664 * @return the rearrangement of the lane elements of this vector 665 */ 666 // rearrange 667 public abstract Vector<E> rearrange(VectorShuffle<E> s); 668 669 670 // Conversions 671 672 /** 673 * Converts this vector into a shuffle, creating a shuffle from vector 674 * lane elements cast to {@code int} then logically AND'ed with the 675 * shuffle length minus one. 676 * <p> 677 * This methods behaves as if it returns the result of creating a shuffle 678 * given an array of the vector lane elements, as follows: 679 * <pre>{@code 680 * $type$[] a = this.toArray(); 681 * int[] sa = new int[a.length]; 682 * for (int i = 0; i < a.length; i++) { 683 * sa[i] = (int) a[i]; 684 * } 685 * return this.species().shuffleFromValues(sa); 686 * }</pre> 687 * 688 * @return a shuffle representation of this vector 689 */ 690 public abstract VectorShuffle<E> toShuffle(); 691 692 // Bitwise preserving 693 694 /** 695 * Transforms this vector to a vector of the given species of element type {@code F}. 696 * <p> 697 * The underlying bits of this vector are copied to the resulting 698 * vector without modification, but those bits, before copying, may be 699 * truncated if the this vector's bit size is greater than desired vector's bit 700 * size, or appended to with zero bits if this vector's bit size is less 701 * than desired vector's bit size. 702 * <p> 703 * The method behaves as if this vector is stored into a byte buffer 704 * and then the desired vector is loaded from the byte buffer using 705 * native byte ordering. The implication is that ByteBuffer reads bytes 706 * and then composes them based on the byte ordering so the result 707 * depends on this composition. 708 * <p> 709 * For example, on a system with ByteOrder.LITTLE_ENDIAN, loading from 710 * byte array with values {0,1,2,3} and reshaping to int, leads to bytes 711 * being composed in order 0x3 0x2 0x1 0x0 which is decimal value 50462976. 712 * On a system with ByteOrder.BIG_ENDIAN, the value is instead 66051 because 713 * bytes are composed in order 0x0 0x1 0x2 0x3. 714 * <p> 715 * The following pseudocode expresses the behaviour: 716 * <pre>{@code 717 * int blen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; 718 * ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 719 * this.intoByteBuffer(bb, 0); 720 * return $type$Vector.fromByteBuffer(s, bb, 0); 721 * }</pre> 722 * 723 * @param s species of desired vector 724 * @param <F> the boxed element type of the species 725 * @return a vector transformed, by shape and element type, from this vector 726 */ 727 @ForceInline 728 public abstract <F> Vector<F> reinterpret(VectorSpecies<F> s); 729 730 @ForceInline 731 @SuppressWarnings("unchecked") 732 <F> Vector<F> defaultReinterpret(VectorSpecies<F> s) { 733 int blen = Math.max(s.bitSize(), this.species().bitSize()) / Byte.SIZE; 734 ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 735 this.intoByteBuffer(bb, 0); 736 737 Class<?> stype = s.elementType(); 738 if (stype == byte.class) { 739 return (Vector) ByteVector.fromByteBuffer((ByteVector.ByteSpecies)s, bb, 0); 740 } else if (stype == short.class) { 741 return (Vector) ShortVector.fromByteBuffer((ShortVector.ShortSpecies)s, bb, 0); 742 } else if (stype == int.class) { 743 return (Vector) IntVector.fromByteBuffer((IntVector.IntSpecies)s, bb, 0); 744 } else if (stype == long.class) { 745 return (Vector) LongVector.fromByteBuffer((LongVector.LongSpecies)s, bb, 0); 746 } else if (stype == float.class) { 747 return (Vector) FloatVector.fromByteBuffer((FloatVector.FloatSpecies)s, bb, 0); 748 } else if (stype == double.class) { 749 return (Vector) DoubleVector.fromByteBuffer((DoubleVector.DoubleSpecies)s, bb, 0); 750 } else { 751 throw new UnsupportedOperationException("Bad lane type for reinterpret."); 752 } 753 } 754 755 /** 756 * Transforms this vector to a vector of same element type but different shape identified by species. 757 * <p> 758 * The lane elements of this vector are copied without 759 * modification to the resulting vector, but those lane elements, before 760 * copying, may be truncated if this vector's length is greater than the desired 761 * vector's length, or appended to with default element values if this 762 * vector's length is less than desired vector's length. 763 * <p> 764 * The method behaves as if this vector is stored into a byte array 765 * and then the returned vector is loaded from the byte array. 766 * The following pseudocode expresses the behaviour: 767 * <pre>{@code 768 * int alen = Math.max(this.bitSize(), s.bitSize()) / Byte.SIZE; 769 * byte[] a = new byte[alen]; 770 * this.intoByteArray(a, 0); 771 * return $type$Vector.fromByteArray(s, a, 0); 772 * }</pre> 773 * 774 * @param s species of the desired vector 775 * @return a vector transformed, by shape, from this vector 776 */ 777 public abstract Vector<E> reshape(VectorSpecies<E> s); 778 779 // Cast 780 781 /** 782 * Converts this vector to a vector of the given species element type {@code F}. 783 * <p> 784 * For each vector lane up to the length of this vector or 785 * desired vector, which ever is the minimum, and where {@code N} is the 786 * vector lane index, the element at index {@code N} of primitive type 787 * {@code E} is converted, according to primitive conversion rules 788 * specified by the Java Language Specification, to a value of primitive 789 * type {@code F} and placed into the resulting vector at lane index 790 * {@code N}. If desired vector's length is greater than this 791 * vector's length then the default primitive value is placed into 792 * subsequent lanes of the resulting vector. 793 * 794 * @param s species of the desired vector 795 * @param <F> the boxed element type of the species 796 * @return a vector converted by shape and element type from this vector 797 */ 798 public abstract <F> Vector<F> cast(VectorSpecies<F> s); 799 800 //Array stores 801 802 /** 803 * Stores this vector into a byte array starting at an offset. 804 * <p> 805 * Bytes are extracted from primitive lane elements according to the 806 * native byte order of the underlying platform. 807 * <p> 808 * This method behaves as it calls the 809 * byte buffer, offset, and mask accepting 810 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: 811 * <pre>{@code 812 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue()); 813 * }</pre> 814 * 815 * @param a the byte array 816 * @param i the offset into the array 817 * @return a vector loaded from a byte array 818 * @throws IndexOutOfBoundsException if {@code i < 0} or 819 * {@code i > a.length - (this.length() * this.elementSize() / Byte.SIZE)} 820 */ 821 public abstract void intoByteArray(byte[] a, int i); 822 823 /** 824 * Stores this vector into a byte array starting at an offset and using a mask. 825 * <p> 826 * Bytes are extracted from primitive lane elements according to the 827 * native byte order of the underlying platform. 828 * <p> 829 * This method behaves as it calls the 830 * byte buffer, offset, and mask accepting 831 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask) method} as follows: 832 * <pre>{@code 833 * return this.intoByteBuffer(ByteBuffer.wrap(a), i, m); 834 * }</pre> 835 * 836 * @param a the byte array 837 * @param i the offset into the array 838 * @param m the mask controlling lane selection 839 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 840 * or {@code > a.length}, 841 * for any vector lane index {@code N} where the mask at lane {@code N} 842 * is set 843 * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)} 844 */ 845 public abstract void intoByteArray(byte[] a, int i, VectorMask<E> m); 846 847 /** 848 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 849 * offset into the byte buffer. 850 * <p> 851 * Bytes are extracted from primitive lane elements according to the 852 * native byte order of the underlying platform. 853 * <p> 854 * This method behaves as if it calls the byte buffer, offset, and mask 855 * accepting 856 * {@link #intoByteBuffer(ByteBuffer, int, VectorMask)} method} as follows: 857 * <pre>{@code 858 * this.intoByteBuffer(b, i, this.maskAllTrue()) 859 * }</pre> 860 * 861 * @param b the byte buffer 862 * @param i the offset into the byte buffer 863 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 864 * or {@code > b.limit()}, 865 * or if there are fewer than 866 * {@code this.length() * this.elementSize() / Byte.SIZE} bytes 867 * remaining in the byte buffer from the given offset 868 */ 869 public abstract void intoByteBuffer(ByteBuffer b, int i); 870 871 /** 872 * Stores this vector into a {@link ByteBuffer byte buffer} starting at an 873 * offset into the byte buffer and using a mask. 874 * <p> 875 * This method behaves as if the byte buffer is viewed as a primitive 876 * {@link java.nio.Buffer buffer} for the primitive element type, 877 * according to the native byte order of the underlying platform, and 878 * the lane elements of this vector are put into the buffer if the 879 * corresponding mask lane is set. 880 * The following pseudocode expresses the behaviour, where 881 * {@coce EBuffer} is the primitive buffer type, {@code e} is the 882 * primitive element type, and {@code EVector<S>} is the primitive 883 * vector type for this vector: 884 * <pre>{@code 885 * EBuffer eb = b.duplicate(). 886 * order(ByteOrder.nativeOrder()).position(i). 887 * asEBuffer(); 888 * e[] es = ((EVector<S>)this).toArray(); 889 * for (int n = 0; n < t.length; n++) { 890 * if (m.isSet(n)) { 891 * eb.put(n, es[n]); 892 * } 893 * } 894 * }</pre> 895 * 896 * @param b the byte buffer 897 * @param i the offset into the byte buffer 898 * @param m the mask 899 * @throws IndexOutOfBoundsException if the offset is {@code < 0}, 900 * or {@code > b.limit()}, 901 * for any vector lane index {@code N} where the mask at lane {@code N} 902 * is set 903 * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)} bytes 904 */ 905 public abstract void intoByteBuffer(ByteBuffer b, int i, VectorMask<E> m); 906 907 /** 908 * Find bit size based on element type and number of elements. 909 * 910 * @param c the element type 911 * @param numElem number of lanes in the vector 912 * @return size in bits for vector 913 */ 914 public static int bitSizeForVectorLength(Class<?> c, int numElem) { 915 if (c == float.class) { 916 return Float.SIZE * numElem; 917 } 918 else if (c == double.class) { 919 return Double.SIZE * numElem; 920 } 921 else if (c == byte.class) { 922 return Byte.SIZE * numElem; 923 } 924 else if (c == short.class) { 925 return Short.SIZE * numElem; 926 } 927 else if (c == int.class) { 928 return Integer.SIZE * numElem; 929 } 930 else if (c == long.class) { 931 return Long.SIZE * numElem; 932 } 933 else { 934 throw new IllegalArgumentException("Bad vector type: " + c.getName()); 935 } 936 } 937 } --- EOF ---