1 /* 2 * Copyright (c) 2017, 2020, 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 any 23 * questions. 24 */ 25 package jdk.incubator.vector; 26 27 import java.nio.ByteBuffer; 28 import java.nio.ByteOrder; 29 import java.nio.ReadOnlyBufferException; 30 import java.util.Arrays; 31 import java.util.Objects; 32 import java.util.function.BinaryOperator; 33 import java.util.function.Function; 34 import java.util.function.UnaryOperator; 35 36 import jdk.internal.misc.Unsafe; 37 import jdk.internal.vm.annotation.ForceInline; 38 import jdk.internal.vm.vector.VectorSupport; 39 40 import static jdk.internal.vm.vector.VectorSupport.*; 41 import static jdk.incubator.vector.VectorIntrinsics.*; 42 43 import static jdk.incubator.vector.VectorOperators.*; 44 45 // -- This file was mechanically generated: Do not edit! -- // 46 47 /** 48 * A specialized {@link Vector} representing an ordered immutable sequence of 49 * {@code int} values. 50 */ 51 @SuppressWarnings("cast") // warning: redundant cast 52 public abstract class IntVector extends AbstractVector<Integer> { 53 IntVector(int[] vec)54 IntVector(int[] vec) { 55 super(vec); 56 } 57 58 static final int FORBID_OPCODE_KIND = VO_ONLYFP; 59 60 @ForceInline opCode(Operator op)61 static int opCode(Operator op) { 62 return VectorOperators.opCode(op, VO_OPCODE_VALID, FORBID_OPCODE_KIND); 63 } 64 @ForceInline opCode(Operator op, int requireKind)65 static int opCode(Operator op, int requireKind) { 66 requireKind |= VO_OPCODE_VALID; 67 return VectorOperators.opCode(op, requireKind, FORBID_OPCODE_KIND); 68 } 69 @ForceInline opKind(Operator op, int bit)70 static boolean opKind(Operator op, int bit) { 71 return VectorOperators.opKind(op, bit); 72 } 73 74 // Virtualized factories and operators, 75 // coded with portable definitions. 76 // These are all @ForceInline in case 77 // they need to be used performantly. 78 // The various shape-specific subclasses 79 // also specialize them by wrapping 80 // them in a call like this: 81 // return (Byte128Vector) 82 // super.bOp((Byte128Vector) o); 83 // The purpose of that is to forcibly inline 84 // the generic definition from this file 85 // into a sharply type- and size-specific 86 // wrapper in the subclass file, so that 87 // the JIT can specialize the code. 88 // The code is only inlined and expanded 89 // if it gets hot. Think of it as a cheap 90 // and lazy version of C++ templates. 91 92 // Virtualized getter 93 94 /*package-private*/ vec()95 abstract int[] vec(); 96 97 // Virtualized constructors 98 99 /** 100 * Build a vector directly using my own constructor. 101 * It is an error if the array is aliased elsewhere. 102 */ 103 /*package-private*/ vectorFactory(int[] vec)104 abstract IntVector vectorFactory(int[] vec); 105 106 /** 107 * Build a mask directly using my species. 108 * It is an error if the array is aliased elsewhere. 109 */ 110 /*package-private*/ 111 @ForceInline 112 final maskFactory(boolean[] bits)113 AbstractMask<Integer> maskFactory(boolean[] bits) { 114 return vspecies().maskFactory(bits); 115 } 116 117 // Constant loader (takes dummy as vector arg) 118 interface FVOp { apply(int i)119 int apply(int i); 120 } 121 122 /*package-private*/ 123 @ForceInline 124 final vOp(FVOp f)125 IntVector vOp(FVOp f) { 126 int[] res = new int[length()]; 127 for (int i = 0; i < res.length; i++) { 128 res[i] = f.apply(i); 129 } 130 return vectorFactory(res); 131 } 132 133 @ForceInline 134 final vOp(VectorMask<Integer> m, FVOp f)135 IntVector vOp(VectorMask<Integer> m, FVOp f) { 136 int[] res = new int[length()]; 137 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 138 for (int i = 0; i < res.length; i++) { 139 if (mbits[i]) { 140 res[i] = f.apply(i); 141 } 142 } 143 return vectorFactory(res); 144 } 145 146 // Unary operator 147 148 /*package-private*/ 149 interface FUnOp { apply(int i, int a)150 int apply(int i, int a); 151 } 152 153 /*package-private*/ 154 abstract uOp(FUnOp f)155 IntVector uOp(FUnOp f); 156 @ForceInline 157 final uOpTemplate(FUnOp f)158 IntVector uOpTemplate(FUnOp f) { 159 int[] vec = vec(); 160 int[] res = new int[length()]; 161 for (int i = 0; i < res.length; i++) { 162 res[i] = f.apply(i, vec[i]); 163 } 164 return vectorFactory(res); 165 } 166 167 /*package-private*/ 168 abstract uOp(VectorMask<Integer> m, FUnOp f)169 IntVector uOp(VectorMask<Integer> m, 170 FUnOp f); 171 @ForceInline 172 final uOpTemplate(VectorMask<Integer> m, FUnOp f)173 IntVector uOpTemplate(VectorMask<Integer> m, 174 FUnOp f) { 175 int[] vec = vec(); 176 int[] res = new int[length()]; 177 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 178 for (int i = 0; i < res.length; i++) { 179 res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i]; 180 } 181 return vectorFactory(res); 182 } 183 184 // Binary operator 185 186 /*package-private*/ 187 interface FBinOp { apply(int i, int a, int b)188 int apply(int i, int a, int b); 189 } 190 191 /*package-private*/ 192 abstract bOp(Vector<Integer> o, FBinOp f)193 IntVector bOp(Vector<Integer> o, 194 FBinOp f); 195 @ForceInline 196 final bOpTemplate(Vector<Integer> o, FBinOp f)197 IntVector bOpTemplate(Vector<Integer> o, 198 FBinOp f) { 199 int[] res = new int[length()]; 200 int[] vec1 = this.vec(); 201 int[] vec2 = ((IntVector)o).vec(); 202 for (int i = 0; i < res.length; i++) { 203 res[i] = f.apply(i, vec1[i], vec2[i]); 204 } 205 return vectorFactory(res); 206 } 207 208 /*package-private*/ 209 abstract bOp(Vector<Integer> o, VectorMask<Integer> m, FBinOp f)210 IntVector bOp(Vector<Integer> o, 211 VectorMask<Integer> m, 212 FBinOp f); 213 @ForceInline 214 final bOpTemplate(Vector<Integer> o, VectorMask<Integer> m, FBinOp f)215 IntVector bOpTemplate(Vector<Integer> o, 216 VectorMask<Integer> m, 217 FBinOp f) { 218 int[] res = new int[length()]; 219 int[] vec1 = this.vec(); 220 int[] vec2 = ((IntVector)o).vec(); 221 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 222 for (int i = 0; i < res.length; i++) { 223 res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i]) : vec1[i]; 224 } 225 return vectorFactory(res); 226 } 227 228 // Ternary operator 229 230 /*package-private*/ 231 interface FTriOp { apply(int i, int a, int b, int c)232 int apply(int i, int a, int b, int c); 233 } 234 235 /*package-private*/ 236 abstract tOp(Vector<Integer> o1, Vector<Integer> o2, FTriOp f)237 IntVector tOp(Vector<Integer> o1, 238 Vector<Integer> o2, 239 FTriOp f); 240 @ForceInline 241 final tOpTemplate(Vector<Integer> o1, Vector<Integer> o2, FTriOp f)242 IntVector tOpTemplate(Vector<Integer> o1, 243 Vector<Integer> o2, 244 FTriOp f) { 245 int[] res = new int[length()]; 246 int[] vec1 = this.vec(); 247 int[] vec2 = ((IntVector)o1).vec(); 248 int[] vec3 = ((IntVector)o2).vec(); 249 for (int i = 0; i < res.length; i++) { 250 res[i] = f.apply(i, vec1[i], vec2[i], vec3[i]); 251 } 252 return vectorFactory(res); 253 } 254 255 /*package-private*/ 256 abstract tOp(Vector<Integer> o1, Vector<Integer> o2, VectorMask<Integer> m, FTriOp f)257 IntVector tOp(Vector<Integer> o1, 258 Vector<Integer> o2, 259 VectorMask<Integer> m, 260 FTriOp f); 261 @ForceInline 262 final tOpTemplate(Vector<Integer> o1, Vector<Integer> o2, VectorMask<Integer> m, FTriOp f)263 IntVector tOpTemplate(Vector<Integer> o1, 264 Vector<Integer> o2, 265 VectorMask<Integer> m, 266 FTriOp f) { 267 int[] res = new int[length()]; 268 int[] vec1 = this.vec(); 269 int[] vec2 = ((IntVector)o1).vec(); 270 int[] vec3 = ((IntVector)o2).vec(); 271 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 272 for (int i = 0; i < res.length; i++) { 273 res[i] = mbits[i] ? f.apply(i, vec1[i], vec2[i], vec3[i]) : vec1[i]; 274 } 275 return vectorFactory(res); 276 } 277 278 // Reduction operator 279 280 /*package-private*/ 281 abstract rOp(int v, FBinOp f)282 int rOp(int v, FBinOp f); 283 @ForceInline 284 final rOpTemplate(int v, FBinOp f)285 int rOpTemplate(int v, FBinOp f) { 286 int[] vec = vec(); 287 for (int i = 0; i < vec.length; i++) { 288 v = f.apply(i, v, vec[i]); 289 } 290 return v; 291 } 292 293 // Memory reference 294 295 /*package-private*/ 296 interface FLdOp<M> { apply(M memory, int offset, int i)297 int apply(M memory, int offset, int i); 298 } 299 300 /*package-private*/ 301 @ForceInline 302 final ldOp(M memory, int offset, FLdOp<M> f)303 <M> IntVector ldOp(M memory, int offset, 304 FLdOp<M> f) { 305 //dummy; no vec = vec(); 306 int[] res = new int[length()]; 307 for (int i = 0; i < res.length; i++) { 308 res[i] = f.apply(memory, offset, i); 309 } 310 return vectorFactory(res); 311 } 312 313 /*package-private*/ 314 @ForceInline 315 final ldOp(M memory, int offset, VectorMask<Integer> m, FLdOp<M> f)316 <M> IntVector ldOp(M memory, int offset, 317 VectorMask<Integer> m, 318 FLdOp<M> f) { 319 //int[] vec = vec(); 320 int[] res = new int[length()]; 321 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 322 for (int i = 0; i < res.length; i++) { 323 if (mbits[i]) { 324 res[i] = f.apply(memory, offset, i); 325 } 326 } 327 return vectorFactory(res); 328 } 329 330 interface FStOp<M> { apply(M memory, int offset, int i, int a)331 void apply(M memory, int offset, int i, int a); 332 } 333 334 /*package-private*/ 335 @ForceInline 336 final stOp(M memory, int offset, FStOp<M> f)337 <M> void stOp(M memory, int offset, 338 FStOp<M> f) { 339 int[] vec = vec(); 340 for (int i = 0; i < vec.length; i++) { 341 f.apply(memory, offset, i, vec[i]); 342 } 343 } 344 345 /*package-private*/ 346 @ForceInline 347 final stOp(M memory, int offset, VectorMask<Integer> m, FStOp<M> f)348 <M> void stOp(M memory, int offset, 349 VectorMask<Integer> m, 350 FStOp<M> f) { 351 int[] vec = vec(); 352 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 353 for (int i = 0; i < vec.length; i++) { 354 if (mbits[i]) { 355 f.apply(memory, offset, i, vec[i]); 356 } 357 } 358 } 359 360 // Binary test 361 362 /*package-private*/ 363 interface FBinTest { apply(int cond, int i, int a, int b)364 boolean apply(int cond, int i, int a, int b); 365 } 366 367 /*package-private*/ 368 @ForceInline 369 final bTest(int cond, Vector<Integer> o, FBinTest f)370 AbstractMask<Integer> bTest(int cond, 371 Vector<Integer> o, 372 FBinTest f) { 373 int[] vec1 = vec(); 374 int[] vec2 = ((IntVector)o).vec(); 375 boolean[] bits = new boolean[length()]; 376 for (int i = 0; i < length(); i++){ 377 bits[i] = f.apply(cond, i, vec1[i], vec2[i]); 378 } 379 return maskFactory(bits); 380 } 381 382 /*package-private*/ 383 @ForceInline doBinTest(int cond, int a, int b)384 static boolean doBinTest(int cond, int a, int b) { 385 switch (cond) { 386 case BT_eq: return a == b; 387 case BT_ne: return a != b; 388 case BT_lt: return a < b; 389 case BT_le: return a <= b; 390 case BT_gt: return a > b; 391 case BT_ge: return a >= b; 392 } 393 throw new AssertionError(Integer.toHexString(cond)); 394 } 395 396 /*package-private*/ 397 @Override vspecies()398 abstract IntSpecies vspecies(); 399 400 /*package-private*/ 401 @ForceInline toBits(int e)402 static long toBits(int e) { 403 return e; 404 } 405 406 /*package-private*/ 407 @ForceInline fromBits(long bits)408 static int fromBits(long bits) { 409 return ((int)bits); 410 } 411 412 // Static factories (other than memory operations) 413 414 // Note: A surprising behavior in javadoc 415 // sometimes makes a lone /** {@inheritDoc} */ 416 // comment drop the method altogether, 417 // apparently if the method mentions an 418 // parameter or return type of Vector<Integer> 419 // instead of Vector<E> as originally specified. 420 // Adding an empty HTML fragment appears to 421 // nudge javadoc into providing the desired 422 // inherited documentation. We use the HTML 423 // comment <!--workaround--> for this. 424 425 /** 426 * Returns a vector of the given species 427 * where all lane elements are set to 428 * zero, the default primitive value. 429 * 430 * @param species species of the desired zero vector 431 * @return a zero vector 432 */ 433 @ForceInline zero(VectorSpecies<Integer> species)434 public static IntVector zero(VectorSpecies<Integer> species) { 435 IntSpecies vsp = (IntSpecies) species; 436 return VectorSupport.broadcastCoerced(vsp.vectorType(), int.class, species.length(), 437 0, vsp, 438 ((bits_, s_) -> s_.rvOp(i -> bits_))); 439 } 440 441 /** 442 * Returns a vector of the same species as this one 443 * where all lane elements are set to 444 * the primitive value {@code e}. 445 * 446 * The contents of the current vector are discarded; 447 * only the species is relevant to this operation. 448 * 449 * <p> This method returns the value of this expression: 450 * {@code IntVector.broadcast(this.species(), e)}. 451 * 452 * @apiNote 453 * Unlike the similar method named {@code broadcast()} 454 * in the supertype {@code Vector}, this method does not 455 * need to validate its argument, and cannot throw 456 * {@code IllegalArgumentException}. This method is 457 * therefore preferable to the supertype method. 458 * 459 * @param e the value to broadcast 460 * @return a vector where all lane elements are set to 461 * the primitive value {@code e} 462 * @see #broadcast(VectorSpecies,long) 463 * @see Vector#broadcast(long) 464 * @see VectorSpecies#broadcast(long) 465 */ broadcast(int e)466 public abstract IntVector broadcast(int e); 467 468 /** 469 * Returns a vector of the given species 470 * where all lane elements are set to 471 * the primitive value {@code e}. 472 * 473 * @param species species of the desired vector 474 * @param e the value to broadcast 475 * @return a vector where all lane elements are set to 476 * the primitive value {@code e} 477 * @see #broadcast(long) 478 * @see Vector#broadcast(long) 479 * @see VectorSpecies#broadcast(long) 480 */ 481 @ForceInline broadcast(VectorSpecies<Integer> species, int e)482 public static IntVector broadcast(VectorSpecies<Integer> species, int e) { 483 IntSpecies vsp = (IntSpecies) species; 484 return vsp.broadcast(e); 485 } 486 487 /*package-private*/ 488 @ForceInline broadcastTemplate(int e)489 final IntVector broadcastTemplate(int e) { 490 IntSpecies vsp = vspecies(); 491 return vsp.broadcast(e); 492 } 493 494 /** 495 * {@inheritDoc} <!--workaround--> 496 * @apiNote 497 * When working with vector subtypes like {@code IntVector}, 498 * {@linkplain #broadcast(int) the more strongly typed method} 499 * is typically selected. It can be explicitly selected 500 * using a cast: {@code v.broadcast((int)e)}. 501 * The two expressions will produce numerically identical results. 502 */ 503 @Override broadcast(long e)504 public abstract IntVector broadcast(long e); 505 506 /** 507 * Returns a vector of the given species 508 * where all lane elements are set to 509 * the primitive value {@code e}. 510 * 511 * The {@code long} value must be accurately representable 512 * by the {@code ETYPE} of the vector species, so that 513 * {@code e==(long)(ETYPE)e}. 514 * 515 * @param species species of the desired vector 516 * @param e the value to broadcast 517 * @return a vector where all lane elements are set to 518 * the primitive value {@code e} 519 * @throws IllegalArgumentException 520 * if the given {@code long} value cannot 521 * be represented by the vector's {@code ETYPE} 522 * @see #broadcast(VectorSpecies,int) 523 * @see VectorSpecies#checkValue(long) 524 */ 525 @ForceInline broadcast(VectorSpecies<Integer> species, long e)526 public static IntVector broadcast(VectorSpecies<Integer> species, long e) { 527 IntSpecies vsp = (IntSpecies) species; 528 return vsp.broadcast(e); 529 } 530 531 /*package-private*/ 532 @ForceInline broadcastTemplate(long e)533 final IntVector broadcastTemplate(long e) { 534 return vspecies().broadcast(e); 535 } 536 537 // Unary lanewise support 538 539 /** 540 * {@inheritDoc} <!--workaround--> 541 */ 542 public abstract lanewise(VectorOperators.Unary op)543 IntVector lanewise(VectorOperators.Unary op); 544 545 @ForceInline 546 final lanewiseTemplate(VectorOperators.Unary op)547 IntVector lanewiseTemplate(VectorOperators.Unary op) { 548 if (opKind(op, VO_SPECIAL)) { 549 if (op == ZOMO) { 550 return blend(broadcast(-1), compare(NE, 0)); 551 } 552 if (op == NOT) { 553 return broadcast(-1).lanewiseTemplate(XOR, this); 554 } else if (op == NEG) { 555 // FIXME: Support this in the JIT. 556 return broadcast(0).lanewiseTemplate(SUB, this); 557 } 558 } 559 int opc = opCode(op); 560 return VectorSupport.unaryOp( 561 opc, getClass(), int.class, length(), 562 this, 563 UN_IMPL.find(op, opc, (opc_) -> { 564 switch (opc_) { 565 case VECTOR_OP_NEG: return v0 -> 566 v0.uOp((i, a) -> (int) -a); 567 case VECTOR_OP_ABS: return v0 -> 568 v0.uOp((i, a) -> (int) Math.abs(a)); 569 default: return null; 570 }})); 571 } 572 private static final 573 ImplCache<Unary,UnaryOperator<IntVector>> UN_IMPL 574 = new ImplCache<>(Unary.class, IntVector.class); 575 576 /** 577 * {@inheritDoc} <!--workaround--> 578 */ 579 @ForceInline 580 public final 581 IntVector lanewise(VectorOperators.Unary op, 582 VectorMask<Integer> m) { 583 return blend(lanewise(op), m); 584 } 585 586 // Binary lanewise support 587 588 /** 589 * {@inheritDoc} <!--workaround--> 590 * @see #lanewise(VectorOperators.Binary,int) 591 * @see #lanewise(VectorOperators.Binary,int,VectorMask) 592 */ 593 @Override 594 public abstract 595 IntVector lanewise(VectorOperators.Binary op, 596 Vector<Integer> v); 597 @ForceInline 598 final 599 IntVector lanewiseTemplate(VectorOperators.Binary op, 600 Vector<Integer> v) { 601 IntVector that = (IntVector) v; 602 that.check(this); 603 if (opKind(op, VO_SPECIAL | VO_SHIFT)) { 604 if (op == FIRST_NONZERO) { 605 // FIXME: Support this in the JIT. 606 VectorMask<Integer> thisNZ 607 = this.viewAsIntegralLanes().compare(NE, (int) 0); 608 that = that.blend((int) 0, thisNZ.cast(vspecies())); 609 op = OR_UNCHECKED; 610 } 611 if (opKind(op, VO_SHIFT)) { 612 // As per shift specification for Java, mask the shift count. 613 // This allows the JIT to ignore some ISA details. 614 that = that.lanewise(AND, SHIFT_MASK); 615 } 616 if (op == ROR || op == ROL) { // FIXME: JIT should do this 617 IntVector neg = that.lanewise(NEG); 618 IntVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that); 619 IntVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg); 620 return hi.lanewise(OR, lo); 621 } else if (op == AND_NOT) { 622 // FIXME: Support this in the JIT. 623 that = that.lanewise(NOT); 624 op = AND; 625 } else if (op == DIV) { 626 VectorMask<Integer> eqz = that.eq((int)0); 627 if (eqz.anyTrue()) { 628 throw that.divZeroException(); 629 } 630 } 631 } 632 int opc = opCode(op); 633 return VectorSupport.binaryOp( 634 opc, getClass(), int.class, length(), 635 this, that, 636 BIN_IMPL.find(op, opc, (opc_) -> { 637 switch (opc_) { 638 case VECTOR_OP_ADD: return (v0, v1) -> 639 v0.bOp(v1, (i, a, b) -> (int)(a + b)); 640 case VECTOR_OP_SUB: return (v0, v1) -> 641 v0.bOp(v1, (i, a, b) -> (int)(a - b)); 642 case VECTOR_OP_MUL: return (v0, v1) -> 643 v0.bOp(v1, (i, a, b) -> (int)(a * b)); 644 case VECTOR_OP_DIV: return (v0, v1) -> 645 v0.bOp(v1, (i, a, b) -> (int)(a / b)); 646 case VECTOR_OP_MAX: return (v0, v1) -> 647 v0.bOp(v1, (i, a, b) -> (int)Math.max(a, b)); 648 case VECTOR_OP_MIN: return (v0, v1) -> 649 v0.bOp(v1, (i, a, b) -> (int)Math.min(a, b)); 650 case VECTOR_OP_AND: return (v0, v1) -> 651 v0.bOp(v1, (i, a, b) -> (int)(a & b)); 652 case VECTOR_OP_OR: return (v0, v1) -> 653 v0.bOp(v1, (i, a, b) -> (int)(a | b)); 654 case VECTOR_OP_XOR: return (v0, v1) -> 655 v0.bOp(v1, (i, a, b) -> (int)(a ^ b)); 656 case VECTOR_OP_LSHIFT: return (v0, v1) -> 657 v0.bOp(v1, (i, a, n) -> (int)(a << n)); 658 case VECTOR_OP_RSHIFT: return (v0, v1) -> 659 v0.bOp(v1, (i, a, n) -> (int)(a >> n)); 660 case VECTOR_OP_URSHIFT: return (v0, v1) -> 661 v0.bOp(v1, (i, a, n) -> (int)((a & LSHR_SETUP_MASK) >>> n)); 662 default: return null; 663 }})); 664 } 665 private static final 666 ImplCache<Binary,BinaryOperator<IntVector>> BIN_IMPL 667 = new ImplCache<>(Binary.class, IntVector.class); 668 669 /** 670 * {@inheritDoc} <!--workaround--> 671 * @see #lanewise(VectorOperators.Binary,int,VectorMask) 672 */ 673 @ForceInline 674 public final 675 IntVector lanewise(VectorOperators.Binary op, 676 Vector<Integer> v, 677 VectorMask<Integer> m) { 678 IntVector that = (IntVector) v; 679 if (op == DIV) { 680 VectorMask<Integer> eqz = that.eq((int)0); 681 if (eqz.and(m).anyTrue()) { 682 throw that.divZeroException(); 683 } 684 // suppress div/0 exceptions in unset lanes 685 that = that.lanewise(NOT, eqz); 686 return blend(lanewise(DIV, that), m); 687 } 688 return blend(lanewise(op, v), m); 689 } 690 // FIXME: Maybe all of the public final methods in this file (the 691 // simple ones that just call lanewise) should be pushed down to 692 // the X-VectorBits template. They can't optimize properly at 693 // this level, and must rely on inlining. Does it work? 694 // (If it works, of course keep the code here.) 695 696 /** 697 * Combines the lane values of this vector 698 * with the value of a broadcast scalar. 699 * 700 * This is a lane-wise binary operation which applies 701 * the selected operation to each lane. 702 * The return value will be equal to this expression: 703 * {@code this.lanewise(op, this.broadcast(e))}. 704 * 705 * @param op the operation used to process lane values 706 * @param e the input scalar 707 * @return the result of applying the operation lane-wise 708 * to the two input vectors 709 * @throws UnsupportedOperationException if this vector does 710 * not support the requested operation 711 * @see #lanewise(VectorOperators.Binary,Vector) 712 * @see #lanewise(VectorOperators.Binary,int,VectorMask) 713 */ 714 @ForceInline 715 public final 716 IntVector lanewise(VectorOperators.Binary op, 717 int e) { 718 if (opKind(op, VO_SHIFT) && (int)(int)e == e) { 719 return lanewiseShift(op, (int) e); 720 } 721 if (op == AND_NOT) { 722 op = AND; e = (int) ~e; 723 } 724 return lanewise(op, broadcast(e)); 725 } 726 727 /** 728 * Combines the lane values of this vector 729 * with the value of a broadcast scalar, 730 * with selection of lane elements controlled by a mask. 731 * 732 * This is a masked lane-wise binary operation which applies 733 * the selected operation to each lane. 734 * The return value will be equal to this expression: 735 * {@code this.lanewise(op, this.broadcast(e), m)}. 736 * 737 * @param op the operation used to process lane values 738 * @param e the input scalar 739 * @param m the mask controlling lane selection 740 * @return the result of applying the operation lane-wise 741 * to the input vector and the scalar 742 * @throws UnsupportedOperationException if this vector does 743 * not support the requested operation 744 * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) 745 * @see #lanewise(VectorOperators.Binary,int) 746 */ 747 @ForceInline 748 public final 749 IntVector lanewise(VectorOperators.Binary op, 750 int e, 751 VectorMask<Integer> m) { 752 return blend(lanewise(op, e), m); 753 } 754 755 /** 756 * {@inheritDoc} <!--workaround--> 757 * @apiNote 758 * When working with vector subtypes like {@code IntVector}, 759 * {@linkplain #lanewise(VectorOperators.Binary,int) 760 * the more strongly typed method} 761 * is typically selected. It can be explicitly selected 762 * using a cast: {@code v.lanewise(op,(int)e)}. 763 * The two expressions will produce numerically identical results. 764 */ 765 @ForceInline 766 public final 767 IntVector lanewise(VectorOperators.Binary op, 768 long e) { 769 int e1 = (int) e; 770 if ((long)e1 != e 771 // allow shift ops to clip down their int parameters 772 && !(opKind(op, VO_SHIFT) && (int)e1 == e) 773 ) { 774 vspecies().checkValue(e); // for exception 775 } 776 return lanewise(op, e1); 777 } 778 779 /** 780 * {@inheritDoc} <!--workaround--> 781 * @apiNote 782 * When working with vector subtypes like {@code IntVector}, 783 * {@linkplain #lanewise(VectorOperators.Binary,int,VectorMask) 784 * the more strongly typed method} 785 * is typically selected. It can be explicitly selected 786 * using a cast: {@code v.lanewise(op,(int)e,m)}. 787 * The two expressions will produce numerically identical results. 788 */ 789 @ForceInline 790 public final 791 IntVector lanewise(VectorOperators.Binary op, 792 long e, VectorMask<Integer> m) { 793 return blend(lanewise(op, e), m); 794 } 795 796 /*package-private*/ 797 abstract IntVector 798 lanewiseShift(VectorOperators.Binary op, int e); 799 800 /*package-private*/ 801 @ForceInline 802 final IntVector 803 lanewiseShiftTemplate(VectorOperators.Binary op, int e) { 804 // Special handling for these. FIXME: Refactor? 805 assert(opKind(op, VO_SHIFT)); 806 // As per shift specification for Java, mask the shift count. 807 e &= SHIFT_MASK; 808 if (op == ROR || op == ROL) { // FIXME: JIT should do this 809 IntVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e); 810 IntVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e); 811 return hi.lanewise(OR, lo); 812 } 813 int opc = opCode(op); 814 return VectorSupport.broadcastInt( 815 opc, getClass(), int.class, length(), 816 this, e, 817 BIN_INT_IMPL.find(op, opc, (opc_) -> { 818 switch (opc_) { 819 case VECTOR_OP_LSHIFT: return (v, n) -> 820 v.uOp((i, a) -> (int)(a << n)); 821 case VECTOR_OP_RSHIFT: return (v, n) -> 822 v.uOp((i, a) -> (int)(a >> n)); 823 case VECTOR_OP_URSHIFT: return (v, n) -> 824 v.uOp((i, a) -> (int)((a & LSHR_SETUP_MASK) >>> n)); 825 default: return null; 826 }})); 827 } 828 private static final 829 ImplCache<Binary,VectorBroadcastIntOp<IntVector>> BIN_INT_IMPL 830 = new ImplCache<>(Binary.class, IntVector.class); 831 832 // As per shift specification for Java, mask the shift count. 833 // We mask 0X3F (long), 0X1F (int), 0x0F (short), 0x7 (byte). 834 // The latter two maskings go beyond the JLS, but seem reasonable 835 // since our lane types are first-class types, not just dressed 836 // up ints. 837 private static final int SHIFT_MASK = (Integer.SIZE - 1); 838 private static final int LSHR_SETUP_MASK = -1; 839 840 // Ternary lanewise support 841 842 // Ternary operators come in eight variations: 843 // lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2]) 844 // lanewise(op, [broadcast(e1)|v1], [broadcast(e2)|v2], mask) 845 846 // It is annoying to support all of these variations of masking 847 // and broadcast, but it would be more surprising not to continue 848 // the obvious pattern started by unary and binary. 849 850 /** 851 * {@inheritDoc} <!--workaround--> 852 * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask) 853 * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask) 854 * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask) 855 * @see #lanewise(VectorOperators.Ternary,int,int) 856 * @see #lanewise(VectorOperators.Ternary,Vector,int) 857 * @see #lanewise(VectorOperators.Ternary,int,Vector) 858 */ 859 @Override 860 public abstract 861 IntVector lanewise(VectorOperators.Ternary op, 862 Vector<Integer> v1, 863 Vector<Integer> v2); 864 @ForceInline 865 final 866 IntVector lanewiseTemplate(VectorOperators.Ternary op, 867 Vector<Integer> v1, 868 Vector<Integer> v2) { 869 IntVector that = (IntVector) v1; 870 IntVector tother = (IntVector) v2; 871 // It's a word: https://www.dictionary.com/browse/tother 872 // See also Chapter 11 of Dickens, Our Mutual Friend: 873 // "Totherest Governor," replied Mr Riderhood... 874 that.check(this); 875 tother.check(this); 876 if (op == BITWISE_BLEND) { 877 // FIXME: Support this in the JIT. 878 that = this.lanewise(XOR, that).lanewise(AND, tother); 879 return this.lanewise(XOR, that); 880 } 881 int opc = opCode(op); 882 return VectorSupport.ternaryOp( 883 opc, getClass(), int.class, length(), 884 this, that, tother, 885 TERN_IMPL.find(op, opc, (opc_) -> { 886 switch (opc_) { 887 default: return null; 888 }})); 889 } 890 private static final 891 ImplCache<Ternary,TernaryOperation<IntVector>> TERN_IMPL 892 = new ImplCache<>(Ternary.class, IntVector.class); 893 894 /** 895 * {@inheritDoc} <!--workaround--> 896 * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask) 897 * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask) 898 * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask) 899 */ 900 @ForceInline 901 public final 902 IntVector lanewise(VectorOperators.Ternary op, 903 Vector<Integer> v1, 904 Vector<Integer> v2, 905 VectorMask<Integer> m) { 906 return blend(lanewise(op, v1, v2), m); 907 } 908 909 /** 910 * Combines the lane values of this vector 911 * with the values of two broadcast scalars. 912 * 913 * This is a lane-wise ternary operation which applies 914 * the selected operation to each lane. 915 * The return value will be equal to this expression: 916 * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2))}. 917 * 918 * @param op the operation used to combine lane values 919 * @param e1 the first input scalar 920 * @param e2 the second input scalar 921 * @return the result of applying the operation lane-wise 922 * to the input vector and the scalars 923 * @throws UnsupportedOperationException if this vector does 924 * not support the requested operation 925 * @see #lanewise(VectorOperators.Ternary,Vector,Vector) 926 * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask) 927 */ 928 @ForceInline 929 public final 930 IntVector lanewise(VectorOperators.Ternary op, //(op,e1,e2) 931 int e1, 932 int e2) { 933 return lanewise(op, broadcast(e1), broadcast(e2)); 934 } 935 936 /** 937 * Combines the lane values of this vector 938 * with the values of two broadcast scalars, 939 * with selection of lane elements controlled by a mask. 940 * 941 * This is a masked lane-wise ternary operation which applies 942 * the selected operation to each lane. 943 * The return value will be equal to this expression: 944 * {@code this.lanewise(op, this.broadcast(e1), this.broadcast(e2), m)}. 945 * 946 * @param op the operation used to combine lane values 947 * @param e1 the first input scalar 948 * @param e2 the second input scalar 949 * @param m the mask controlling lane selection 950 * @return the result of applying the operation lane-wise 951 * to the input vector and the scalars 952 * @throws UnsupportedOperationException if this vector does 953 * not support the requested operation 954 * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) 955 * @see #lanewise(VectorOperators.Ternary,int,int) 956 */ 957 @ForceInline 958 public final 959 IntVector lanewise(VectorOperators.Ternary op, //(op,e1,e2,m) 960 int e1, 961 int e2, 962 VectorMask<Integer> m) { 963 return blend(lanewise(op, e1, e2), m); 964 } 965 966 /** 967 * Combines the lane values of this vector 968 * with the values of another vector and a broadcast scalar. 969 * 970 * This is a lane-wise ternary operation which applies 971 * the selected operation to each lane. 972 * The return value will be equal to this expression: 973 * {@code this.lanewise(op, v1, this.broadcast(e2))}. 974 * 975 * @param op the operation used to combine lane values 976 * @param v1 the other input vector 977 * @param e2 the input scalar 978 * @return the result of applying the operation lane-wise 979 * to the input vectors and the scalar 980 * @throws UnsupportedOperationException if this vector does 981 * not support the requested operation 982 * @see #lanewise(VectorOperators.Ternary,int,int) 983 * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask) 984 */ 985 @ForceInline 986 public final 987 IntVector lanewise(VectorOperators.Ternary op, //(op,v1,e2) 988 Vector<Integer> v1, 989 int e2) { 990 return lanewise(op, v1, broadcast(e2)); 991 } 992 993 /** 994 * Combines the lane values of this vector 995 * with the values of another vector and a broadcast scalar, 996 * with selection of lane elements controlled by a mask. 997 * 998 * This is a masked lane-wise ternary operation which applies 999 * the selected operation to each lane. 1000 * The return value will be equal to this expression: 1001 * {@code this.lanewise(op, v1, this.broadcast(e2), m)}. 1002 * 1003 * @param op the operation used to combine lane values 1004 * @param v1 the other input vector 1005 * @param e2 the input scalar 1006 * @param m the mask controlling lane selection 1007 * @return the result of applying the operation lane-wise 1008 * to the input vectors and the scalar 1009 * @throws UnsupportedOperationException if this vector does 1010 * not support the requested operation 1011 * @see #lanewise(VectorOperators.Ternary,Vector,Vector) 1012 * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask) 1013 * @see #lanewise(VectorOperators.Ternary,Vector,int) 1014 */ 1015 @ForceInline 1016 public final 1017 IntVector lanewise(VectorOperators.Ternary op, //(op,v1,e2,m) 1018 Vector<Integer> v1, 1019 int e2, 1020 VectorMask<Integer> m) { 1021 return blend(lanewise(op, v1, e2), m); 1022 } 1023 1024 /** 1025 * Combines the lane values of this vector 1026 * with the values of another vector and a broadcast scalar. 1027 * 1028 * This is a lane-wise ternary operation which applies 1029 * the selected operation to each lane. 1030 * The return value will be equal to this expression: 1031 * {@code this.lanewise(op, this.broadcast(e1), v2)}. 1032 * 1033 * @param op the operation used to combine lane values 1034 * @param e1 the input scalar 1035 * @param v2 the other input vector 1036 * @return the result of applying the operation lane-wise 1037 * to the input vectors and the scalar 1038 * @throws UnsupportedOperationException if this vector does 1039 * not support the requested operation 1040 * @see #lanewise(VectorOperators.Ternary,Vector,Vector) 1041 * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask) 1042 */ 1043 @ForceInline 1044 public final 1045 IntVector lanewise(VectorOperators.Ternary op, //(op,e1,v2) 1046 int e1, 1047 Vector<Integer> v2) { 1048 return lanewise(op, broadcast(e1), v2); 1049 } 1050 1051 /** 1052 * Combines the lane values of this vector 1053 * with the values of another vector and a broadcast scalar, 1054 * with selection of lane elements controlled by a mask. 1055 * 1056 * This is a masked lane-wise ternary operation which applies 1057 * the selected operation to each lane. 1058 * The return value will be equal to this expression: 1059 * {@code this.lanewise(op, this.broadcast(e1), v2, m)}. 1060 * 1061 * @param op the operation used to combine lane values 1062 * @param e1 the input scalar 1063 * @param v2 the other input vector 1064 * @param m the mask controlling lane selection 1065 * @return the result of applying the operation lane-wise 1066 * to the input vectors and the scalar 1067 * @throws UnsupportedOperationException if this vector does 1068 * not support the requested operation 1069 * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) 1070 * @see #lanewise(VectorOperators.Ternary,int,Vector) 1071 */ 1072 @ForceInline 1073 public final 1074 IntVector lanewise(VectorOperators.Ternary op, //(op,e1,v2,m) 1075 int e1, 1076 Vector<Integer> v2, 1077 VectorMask<Integer> m) { 1078 return blend(lanewise(op, e1, v2), m); 1079 } 1080 1081 // (Thus endeth the Great and Mighty Ternary Ogdoad.) 1082 // https://en.wikipedia.org/wiki/Ogdoad 1083 1084 /// FULL-SERVICE BINARY METHODS: ADD, SUB, MUL, DIV 1085 // 1086 // These include masked and non-masked versions. 1087 // This subclass adds broadcast (masked or not). 1088 1089 /** 1090 * {@inheritDoc} <!--workaround--> 1091 * @see #add(int) 1092 */ 1093 @Override 1094 @ForceInline 1095 public final IntVector add(Vector<Integer> v) { 1096 return lanewise(ADD, v); 1097 } 1098 1099 /** 1100 * Adds this vector to the broadcast of an input scalar. 1101 * 1102 * This is a lane-wise binary operation which applies 1103 * the primitive addition operation ({@code +}) to each lane. 1104 * 1105 * This method is also equivalent to the expression 1106 * {@link #lanewise(VectorOperators.Binary,int) 1107 * lanewise}{@code (}{@link VectorOperators#ADD 1108 * ADD}{@code , e)}. 1109 * 1110 * @param e the input scalar 1111 * @return the result of adding each lane of this vector to the scalar 1112 * @see #add(Vector) 1113 * @see #broadcast(int) 1114 * @see #add(int,VectorMask) 1115 * @see VectorOperators#ADD 1116 * @see #lanewise(VectorOperators.Binary,Vector) 1117 * @see #lanewise(VectorOperators.Binary,int) 1118 */ 1119 @ForceInline 1120 public final 1121 IntVector add(int e) { 1122 return lanewise(ADD, e); 1123 } 1124 1125 /** 1126 * {@inheritDoc} <!--workaround--> 1127 * @see #add(int,VectorMask) 1128 */ 1129 @Override 1130 @ForceInline 1131 public final IntVector add(Vector<Integer> v, 1132 VectorMask<Integer> m) { 1133 return lanewise(ADD, v, m); 1134 } 1135 1136 /** 1137 * Adds this vector to the broadcast of an input scalar, 1138 * selecting lane elements controlled by a mask. 1139 * 1140 * This is a masked lane-wise binary operation which applies 1141 * the primitive addition operation ({@code +}) to each lane. 1142 * 1143 * This method is also equivalent to the expression 1144 * {@link #lanewise(VectorOperators.Binary,int,VectorMask) 1145 * lanewise}{@code (}{@link VectorOperators#ADD 1146 * ADD}{@code , s, m)}. 1147 * 1148 * @param e the input scalar 1149 * @param m the mask controlling lane selection 1150 * @return the result of adding each lane of this vector to the scalar 1151 * @see #add(Vector,VectorMask) 1152 * @see #broadcast(int) 1153 * @see #add(int) 1154 * @see VectorOperators#ADD 1155 * @see #lanewise(VectorOperators.Binary,Vector) 1156 * @see #lanewise(VectorOperators.Binary,int) 1157 */ 1158 @ForceInline 1159 public final IntVector add(int e, 1160 VectorMask<Integer> m) { 1161 return lanewise(ADD, e, m); 1162 } 1163 1164 /** 1165 * {@inheritDoc} <!--workaround--> 1166 * @see #sub(int) 1167 */ 1168 @Override 1169 @ForceInline 1170 public final IntVector sub(Vector<Integer> v) { 1171 return lanewise(SUB, v); 1172 } 1173 1174 /** 1175 * Subtracts an input scalar from this vector. 1176 * 1177 * This is a masked lane-wise binary operation which applies 1178 * the primitive subtraction operation ({@code -}) to each lane. 1179 * 1180 * This method is also equivalent to the expression 1181 * {@link #lanewise(VectorOperators.Binary,int) 1182 * lanewise}{@code (}{@link VectorOperators#SUB 1183 * SUB}{@code , e)}. 1184 * 1185 * @param e the input scalar 1186 * @return the result of subtracting the scalar from each lane of this vector 1187 * @see #sub(Vector) 1188 * @see #broadcast(int) 1189 * @see #sub(int,VectorMask) 1190 * @see VectorOperators#SUB 1191 * @see #lanewise(VectorOperators.Binary,Vector) 1192 * @see #lanewise(VectorOperators.Binary,int) 1193 */ 1194 @ForceInline 1195 public final IntVector sub(int e) { 1196 return lanewise(SUB, e); 1197 } 1198 1199 /** 1200 * {@inheritDoc} <!--workaround--> 1201 * @see #sub(int,VectorMask) 1202 */ 1203 @Override 1204 @ForceInline 1205 public final IntVector sub(Vector<Integer> v, 1206 VectorMask<Integer> m) { 1207 return lanewise(SUB, v, m); 1208 } 1209 1210 /** 1211 * Subtracts an input scalar from this vector 1212 * under the control of a mask. 1213 * 1214 * This is a masked lane-wise binary operation which applies 1215 * the primitive subtraction operation ({@code -}) to each lane. 1216 * 1217 * This method is also equivalent to the expression 1218 * {@link #lanewise(VectorOperators.Binary,int,VectorMask) 1219 * lanewise}{@code (}{@link VectorOperators#SUB 1220 * SUB}{@code , s, m)}. 1221 * 1222 * @param e the input scalar 1223 * @param m the mask controlling lane selection 1224 * @return the result of subtracting the scalar from each lane of this vector 1225 * @see #sub(Vector,VectorMask) 1226 * @see #broadcast(int) 1227 * @see #sub(int) 1228 * @see VectorOperators#SUB 1229 * @see #lanewise(VectorOperators.Binary,Vector) 1230 * @see #lanewise(VectorOperators.Binary,int) 1231 */ 1232 @ForceInline 1233 public final IntVector sub(int e, 1234 VectorMask<Integer> m) { 1235 return lanewise(SUB, e, m); 1236 } 1237 1238 /** 1239 * {@inheritDoc} <!--workaround--> 1240 * @see #mul(int) 1241 */ 1242 @Override 1243 @ForceInline 1244 public final IntVector mul(Vector<Integer> v) { 1245 return lanewise(MUL, v); 1246 } 1247 1248 /** 1249 * Multiplies this vector by the broadcast of an input scalar. 1250 * 1251 * This is a lane-wise binary operation which applies 1252 * the primitive multiplication operation ({@code *}) to each lane. 1253 * 1254 * This method is also equivalent to the expression 1255 * {@link #lanewise(VectorOperators.Binary,int) 1256 * lanewise}{@code (}{@link VectorOperators#MUL 1257 * MUL}{@code , e)}. 1258 * 1259 * @param e the input scalar 1260 * @return the result of multiplying this vector by the given scalar 1261 * @see #mul(Vector) 1262 * @see #broadcast(int) 1263 * @see #mul(int,VectorMask) 1264 * @see VectorOperators#MUL 1265 * @see #lanewise(VectorOperators.Binary,Vector) 1266 * @see #lanewise(VectorOperators.Binary,int) 1267 */ 1268 @ForceInline 1269 public final IntVector mul(int e) { 1270 return lanewise(MUL, e); 1271 } 1272 1273 /** 1274 * {@inheritDoc} <!--workaround--> 1275 * @see #mul(int,VectorMask) 1276 */ 1277 @Override 1278 @ForceInline 1279 public final IntVector mul(Vector<Integer> v, 1280 VectorMask<Integer> m) { 1281 return lanewise(MUL, v, m); 1282 } 1283 1284 /** 1285 * Multiplies this vector by the broadcast of an input scalar, 1286 * selecting lane elements controlled by a mask. 1287 * 1288 * This is a masked lane-wise binary operation which applies 1289 * the primitive multiplication operation ({@code *}) to each lane. 1290 * 1291 * This method is also equivalent to the expression 1292 * {@link #lanewise(VectorOperators.Binary,int,VectorMask) 1293 * lanewise}{@code (}{@link VectorOperators#MUL 1294 * MUL}{@code , s, m)}. 1295 * 1296 * @param e the input scalar 1297 * @param m the mask controlling lane selection 1298 * @return the result of muling each lane of this vector to the scalar 1299 * @see #mul(Vector,VectorMask) 1300 * @see #broadcast(int) 1301 * @see #mul(int) 1302 * @see VectorOperators#MUL 1303 * @see #lanewise(VectorOperators.Binary,Vector) 1304 * @see #lanewise(VectorOperators.Binary,int) 1305 */ 1306 @ForceInline 1307 public final IntVector mul(int e, 1308 VectorMask<Integer> m) { 1309 return lanewise(MUL, e, m); 1310 } 1311 1312 /** 1313 * {@inheritDoc} <!--workaround--> 1314 * @apiNote If there is a zero divisor, {@code 1315 * ArithmeticException} will be thrown. 1316 */ 1317 @Override 1318 @ForceInline 1319 public final IntVector div(Vector<Integer> v) { 1320 return lanewise(DIV, v); 1321 } 1322 1323 /** 1324 * Divides this vector by the broadcast of an input scalar. 1325 * 1326 * This is a lane-wise binary operation which applies 1327 * the primitive division operation ({@code /}) to each lane. 1328 * 1329 * This method is also equivalent to the expression 1330 * {@link #lanewise(VectorOperators.Binary,int) 1331 * lanewise}{@code (}{@link VectorOperators#DIV 1332 * DIV}{@code , e)}. 1333 * 1334 * @apiNote If there is a zero divisor, {@code 1335 * ArithmeticException} will be thrown. 1336 * 1337 * @param e the input scalar 1338 * @return the result of dividing each lane of this vector by the scalar 1339 * @see #div(Vector) 1340 * @see #broadcast(int) 1341 * @see #div(int,VectorMask) 1342 * @see VectorOperators#DIV 1343 * @see #lanewise(VectorOperators.Binary,Vector) 1344 * @see #lanewise(VectorOperators.Binary,int) 1345 */ 1346 @ForceInline 1347 public final IntVector div(int e) { 1348 return lanewise(DIV, e); 1349 } 1350 1351 /** 1352 * {@inheritDoc} <!--workaround--> 1353 * @see #div(int,VectorMask) 1354 * @apiNote If there is a zero divisor, {@code 1355 * ArithmeticException} will be thrown. 1356 */ 1357 @Override 1358 @ForceInline 1359 public final IntVector div(Vector<Integer> v, 1360 VectorMask<Integer> m) { 1361 return lanewise(DIV, v, m); 1362 } 1363 1364 /** 1365 * Divides this vector by the broadcast of an input scalar, 1366 * selecting lane elements controlled by a mask. 1367 * 1368 * This is a masked lane-wise binary operation which applies 1369 * the primitive division operation ({@code /}) to each lane. 1370 * 1371 * This method is also equivalent to the expression 1372 * {@link #lanewise(VectorOperators.Binary,int,VectorMask) 1373 * lanewise}{@code (}{@link VectorOperators#DIV 1374 * DIV}{@code , s, m)}. 1375 * 1376 * @apiNote If there is a zero divisor, {@code 1377 * ArithmeticException} will be thrown. 1378 * 1379 * @param e the input scalar 1380 * @param m the mask controlling lane selection 1381 * @return the result of dividing each lane of this vector by the scalar 1382 * @see #div(Vector,VectorMask) 1383 * @see #broadcast(int) 1384 * @see #div(int) 1385 * @see VectorOperators#DIV 1386 * @see #lanewise(VectorOperators.Binary,Vector) 1387 * @see #lanewise(VectorOperators.Binary,int) 1388 */ 1389 @ForceInline 1390 public final IntVector div(int e, 1391 VectorMask<Integer> m) { 1392 return lanewise(DIV, e, m); 1393 } 1394 1395 /// END OF FULL-SERVICE BINARY METHODS 1396 1397 /// SECOND-TIER BINARY METHODS 1398 // 1399 // There are no masked versions. 1400 1401 /** 1402 * {@inheritDoc} <!--workaround--> 1403 */ 1404 @Override 1405 @ForceInline 1406 public final IntVector min(Vector<Integer> v) { 1407 return lanewise(MIN, v); 1408 } 1409 1410 // FIXME: "broadcast of an input scalar" is really wordy. Reduce? 1411 /** 1412 * Computes the smaller of this vector and the broadcast of an input scalar. 1413 * 1414 * This is a lane-wise binary operation which applies the 1415 * operation {@code Math.min()} to each pair of 1416 * corresponding lane values. 1417 * 1418 * This method is also equivalent to the expression 1419 * {@link #lanewise(VectorOperators.Binary,int) 1420 * lanewise}{@code (}{@link VectorOperators#MIN 1421 * MIN}{@code , e)}. 1422 * 1423 * @param e the input scalar 1424 * @return the result of multiplying this vector by the given scalar 1425 * @see #min(Vector) 1426 * @see #broadcast(int) 1427 * @see VectorOperators#MIN 1428 * @see #lanewise(VectorOperators.Binary,int,VectorMask) 1429 */ 1430 @ForceInline 1431 public final IntVector min(int e) { 1432 return lanewise(MIN, e); 1433 } 1434 1435 /** 1436 * {@inheritDoc} <!--workaround--> 1437 */ 1438 @Override 1439 @ForceInline 1440 public final IntVector max(Vector<Integer> v) { 1441 return lanewise(MAX, v); 1442 } 1443 1444 /** 1445 * Computes the larger of this vector and the broadcast of an input scalar. 1446 * 1447 * This is a lane-wise binary operation which applies the 1448 * operation {@code Math.max()} to each pair of 1449 * corresponding lane values. 1450 * 1451 * This method is also equivalent to the expression 1452 * {@link #lanewise(VectorOperators.Binary,int) 1453 * lanewise}{@code (}{@link VectorOperators#MAX 1454 * MAX}{@code , e)}. 1455 * 1456 * @param e the input scalar 1457 * @return the result of multiplying this vector by the given scalar 1458 * @see #max(Vector) 1459 * @see #broadcast(int) 1460 * @see VectorOperators#MAX 1461 * @see #lanewise(VectorOperators.Binary,int,VectorMask) 1462 */ 1463 @ForceInline 1464 public final IntVector max(int e) { 1465 return lanewise(MAX, e); 1466 } 1467 1468 // common bitwise operators: and, or, not (with scalar versions) 1469 /** 1470 * Computes the bitwise logical conjunction ({@code &}) 1471 * of this vector and a second input vector. 1472 * 1473 * This is a lane-wise binary operation which applies the 1474 * the primitive bitwise "and" operation ({@code &}) 1475 * to each pair of corresponding lane values. 1476 * 1477 * This method is also equivalent to the expression 1478 * {@link #lanewise(VectorOperators.Binary,Vector) 1479 * lanewise}{@code (}{@link VectorOperators#AND 1480 * AND}{@code , v)}. 1481 * 1482 * <p> 1483 * This is not a full-service named operation like 1484 * {@link #add(Vector) add}. A masked version of 1485 * this operation is not directly available 1486 * but may be obtained via the masked version of 1487 * {@code lanewise}. 1488 * 1489 * @param v a second input vector 1490 * @return the bitwise {@code &} of this vector and the second input vector 1491 * @see #and(int) 1492 * @see #or(Vector) 1493 * @see #not() 1494 * @see VectorOperators#AND 1495 * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) 1496 */ 1497 @ForceInline 1498 public final IntVector and(Vector<Integer> v) { 1499 return lanewise(AND, v); 1500 } 1501 1502 /** 1503 * Computes the bitwise logical conjunction ({@code &}) 1504 * of this vector and a scalar. 1505 * 1506 * This is a lane-wise binary operation which applies the 1507 * the primitive bitwise "and" operation ({@code &}) 1508 * to each pair of corresponding lane values. 1509 * 1510 * This method is also equivalent to the expression 1511 * {@link #lanewise(VectorOperators.Binary,Vector) 1512 * lanewise}{@code (}{@link VectorOperators#AND 1513 * AND}{@code , e)}. 1514 * 1515 * @param e an input scalar 1516 * @return the bitwise {@code &} of this vector and scalar 1517 * @see #and(Vector) 1518 * @see VectorOperators#AND 1519 * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) 1520 */ 1521 @ForceInline 1522 public final IntVector and(int e) { 1523 return lanewise(AND, e); 1524 } 1525 1526 /** 1527 * Computes the bitwise logical disjunction ({@code |}) 1528 * of this vector and a second input vector. 1529 * 1530 * This is a lane-wise binary operation which applies the 1531 * the primitive bitwise "or" operation ({@code |}) 1532 * to each pair of corresponding lane values. 1533 * 1534 * This method is also equivalent to the expression 1535 * {@link #lanewise(VectorOperators.Binary,Vector) 1536 * lanewise}{@code (}{@link VectorOperators#OR 1537 * AND}{@code , v)}. 1538 * 1539 * <p> 1540 * This is not a full-service named operation like 1541 * {@link #add(Vector) add}. A masked version of 1542 * this operation is not directly available 1543 * but may be obtained via the masked version of 1544 * {@code lanewise}. 1545 * 1546 * @param v a second input vector 1547 * @return the bitwise {@code |} of this vector and the second input vector 1548 * @see #or(int) 1549 * @see #and(Vector) 1550 * @see #not() 1551 * @see VectorOperators#OR 1552 * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) 1553 */ 1554 @ForceInline 1555 public final IntVector or(Vector<Integer> v) { 1556 return lanewise(OR, v); 1557 } 1558 1559 /** 1560 * Computes the bitwise logical disjunction ({@code |}) 1561 * of this vector and a scalar. 1562 * 1563 * This is a lane-wise binary operation which applies the 1564 * the primitive bitwise "or" operation ({@code |}) 1565 * to each pair of corresponding lane values. 1566 * 1567 * This method is also equivalent to the expression 1568 * {@link #lanewise(VectorOperators.Binary,Vector) 1569 * lanewise}{@code (}{@link VectorOperators#OR 1570 * OR}{@code , e)}. 1571 * 1572 * @param e an input scalar 1573 * @return the bitwise {@code |} of this vector and scalar 1574 * @see #or(Vector) 1575 * @see VectorOperators#OR 1576 * @see #lanewise(VectorOperators.Binary,Vector,VectorMask) 1577 */ 1578 @ForceInline 1579 public final IntVector or(int e) { 1580 return lanewise(OR, e); 1581 } 1582 1583 1584 1585 /// UNARY METHODS 1586 1587 /** 1588 * {@inheritDoc} <!--workaround--> 1589 */ 1590 @Override 1591 @ForceInline 1592 public final 1593 IntVector neg() { 1594 return lanewise(NEG); 1595 } 1596 1597 /** 1598 * {@inheritDoc} <!--workaround--> 1599 */ 1600 @Override 1601 @ForceInline 1602 public final 1603 IntVector abs() { 1604 return lanewise(ABS); 1605 } 1606 1607 // not (~) 1608 /** 1609 * Computes the bitwise logical complement ({@code ~}) 1610 * of this vector. 1611 * 1612 * This is a lane-wise binary operation which applies the 1613 * the primitive bitwise "not" operation ({@code ~}) 1614 * to each lane value. 1615 * 1616 * This method is also equivalent to the expression 1617 * {@link #lanewise(VectorOperators.Unary) 1618 * lanewise}{@code (}{@link VectorOperators#NOT 1619 * NOT}{@code )}. 1620 * 1621 * <p> 1622 * This is not a full-service named operation like 1623 * {@link #add(Vector) add}. A masked version of 1624 * this operation is not directly available 1625 * but may be obtained via the masked version of 1626 * {@code lanewise}. 1627 * 1628 * @return the bitwise complement {@code ~} of this vector 1629 * @see #and(Vector) 1630 * @see VectorOperators#NOT 1631 * @see #lanewise(VectorOperators.Unary,VectorMask) 1632 */ 1633 @ForceInline 1634 public final IntVector not() { 1635 return lanewise(NOT); 1636 } 1637 1638 1639 /// COMPARISONS 1640 1641 /** 1642 * {@inheritDoc} <!--workaround--> 1643 */ 1644 @Override 1645 @ForceInline 1646 public final 1647 VectorMask<Integer> eq(Vector<Integer> v) { 1648 return compare(EQ, v); 1649 } 1650 1651 /** 1652 * Tests if this vector is equal to an input scalar. 1653 * 1654 * This is a lane-wise binary test operation which applies 1655 * the primitive equals operation ({@code ==}) to each lane. 1656 * The result is the same as {@code compare(VectorOperators.Comparison.EQ, e)}. 1657 * 1658 * @param e the input scalar 1659 * @return the result mask of testing if this vector 1660 * is equal to {@code e} 1661 * @see #compare(VectorOperators.Comparison,int) 1662 */ 1663 @ForceInline 1664 public final 1665 VectorMask<Integer> eq(int e) { 1666 return compare(EQ, e); 1667 } 1668 1669 /** 1670 * {@inheritDoc} <!--workaround--> 1671 */ 1672 @Override 1673 @ForceInline 1674 public final 1675 VectorMask<Integer> lt(Vector<Integer> v) { 1676 return compare(LT, v); 1677 } 1678 1679 /** 1680 * Tests if this vector is less than an input scalar. 1681 * 1682 * This is a lane-wise binary test operation which applies 1683 * the primitive less than operation ({@code <}) to each lane. 1684 * The result is the same as {@code compare(VectorOperators.LT, e)}. 1685 * 1686 * @param e the input scalar 1687 * @return the mask result of testing if this vector 1688 * is less than the input scalar 1689 * @see #compare(VectorOperators.Comparison,int) 1690 */ 1691 @ForceInline 1692 public final 1693 VectorMask<Integer> lt(int e) { 1694 return compare(LT, e); 1695 } 1696 1697 /** 1698 * {@inheritDoc} <!--workaround--> 1699 */ 1700 @Override 1701 public abstract 1702 VectorMask<Integer> test(VectorOperators.Test op); 1703 1704 /*package-private*/ 1705 @ForceInline 1706 final 1707 <M extends VectorMask<Integer>> 1708 M testTemplate(Class<M> maskType, Test op) { 1709 IntSpecies vsp = vspecies(); 1710 if (opKind(op, VO_SPECIAL)) { 1711 IntVector bits = this.viewAsIntegralLanes(); 1712 VectorMask<Integer> m; 1713 if (op == IS_DEFAULT) { 1714 m = bits.compare(EQ, (int) 0); 1715 } else if (op == IS_NEGATIVE) { 1716 m = bits.compare(LT, (int) 0); 1717 } 1718 else { 1719 throw new AssertionError(op); 1720 } 1721 return maskType.cast(m); 1722 } 1723 int opc = opCode(op); 1724 throw new AssertionError(op); 1725 } 1726 1727 /** 1728 * {@inheritDoc} <!--workaround--> 1729 */ 1730 @Override 1731 @ForceInline 1732 public final 1733 VectorMask<Integer> test(VectorOperators.Test op, 1734 VectorMask<Integer> m) { 1735 return test(op).and(m); 1736 } 1737 1738 /** 1739 * {@inheritDoc} <!--workaround--> 1740 */ 1741 @Override 1742 public abstract 1743 VectorMask<Integer> compare(VectorOperators.Comparison op, Vector<Integer> v); 1744 1745 /*package-private*/ 1746 @ForceInline 1747 final 1748 <M extends VectorMask<Integer>> 1749 M compareTemplate(Class<M> maskType, Comparison op, Vector<Integer> v) { 1750 Objects.requireNonNull(v); 1751 IntSpecies vsp = vspecies(); 1752 IntVector that = (IntVector) v; 1753 that.check(this); 1754 int opc = opCode(op); 1755 return VectorSupport.compare( 1756 opc, getClass(), maskType, int.class, length(), 1757 this, that, 1758 (cond, v0, v1) -> { 1759 AbstractMask<Integer> m 1760 = v0.bTest(cond, v1, (cond_, i, a, b) 1761 -> compareWithOp(cond, a, b)); 1762 @SuppressWarnings("unchecked") 1763 M m2 = (M) m; 1764 return m2; 1765 }); 1766 } 1767 1768 @ForceInline 1769 private static 1770 boolean compareWithOp(int cond, int a, int b) { 1771 switch (cond) { 1772 case BT_eq: return a == b; 1773 case BT_ne: return a != b; 1774 case BT_lt: return a < b; 1775 case BT_le: return a <= b; 1776 case BT_gt: return a > b; 1777 case BT_ge: return a >= b; 1778 } 1779 throw new AssertionError(); 1780 } 1781 1782 /** 1783 * {@inheritDoc} <!--workaround--> 1784 */ 1785 @Override 1786 @ForceInline 1787 public final 1788 VectorMask<Integer> compare(VectorOperators.Comparison op, 1789 Vector<Integer> v, 1790 VectorMask<Integer> m) { 1791 return compare(op, v).and(m); 1792 } 1793 1794 /** 1795 * Tests this vector by comparing it with an input scalar, 1796 * according to the given comparison operation. 1797 * 1798 * This is a lane-wise binary test operation which applies 1799 * the comparison operation to each lane. 1800 * <p> 1801 * The result is the same as 1802 * {@code compare(op, broadcast(species(), e))}. 1803 * That is, the scalar may be regarded as broadcast to 1804 * a vector of the same species, and then compared 1805 * against the original vector, using the selected 1806 * comparison operation. 1807 * 1808 * @param op the operation used to compare lane values 1809 * @param e the input scalar 1810 * @return the mask result of testing lane-wise if this vector 1811 * compares to the input, according to the selected 1812 * comparison operator 1813 * @see IntVector#compare(VectorOperators.Comparison,Vector) 1814 * @see #eq(int) 1815 * @see #lt(int) 1816 */ 1817 public abstract 1818 VectorMask<Integer> compare(Comparison op, int e); 1819 1820 /*package-private*/ 1821 @ForceInline 1822 final 1823 <M extends VectorMask<Integer>> 1824 M compareTemplate(Class<M> maskType, Comparison op, int e) { 1825 return compareTemplate(maskType, op, broadcast(e)); 1826 } 1827 1828 /** 1829 * Tests this vector by comparing it with an input scalar, 1830 * according to the given comparison operation, 1831 * in lanes selected by a mask. 1832 * 1833 * This is a masked lane-wise binary test operation which applies 1834 * to each pair of corresponding lane values. 1835 * 1836 * The returned result is equal to the expression 1837 * {@code compare(op,s).and(m)}. 1838 * 1839 * @param op the operation used to compare lane values 1840 * @param e the input scalar 1841 * @param m the mask controlling lane selection 1842 * @return the mask result of testing lane-wise if this vector 1843 * compares to the input, according to the selected 1844 * comparison operator, 1845 * and only in the lanes selected by the mask 1846 * @see IntVector#compare(VectorOperators.Comparison,Vector,VectorMask) 1847 */ 1848 @ForceInline 1849 public final VectorMask<Integer> compare(VectorOperators.Comparison op, 1850 int e, 1851 VectorMask<Integer> m) { 1852 return compare(op, e).and(m); 1853 } 1854 1855 /** 1856 * {@inheritDoc} <!--workaround--> 1857 */ 1858 @Override 1859 public abstract 1860 VectorMask<Integer> compare(Comparison op, long e); 1861 1862 /*package-private*/ 1863 @ForceInline 1864 final 1865 <M extends VectorMask<Integer>> 1866 M compareTemplate(Class<M> maskType, Comparison op, long e) { 1867 return compareTemplate(maskType, op, broadcast(e)); 1868 } 1869 1870 /** 1871 * {@inheritDoc} <!--workaround--> 1872 */ 1873 @Override 1874 @ForceInline 1875 public final 1876 VectorMask<Integer> compare(Comparison op, long e, VectorMask<Integer> m) { 1877 return compare(op, broadcast(e), m); 1878 } 1879 1880 1881 1882 /** 1883 * {@inheritDoc} <!--workaround--> 1884 */ 1885 @Override public abstract 1886 IntVector blend(Vector<Integer> v, VectorMask<Integer> m); 1887 1888 /*package-private*/ 1889 @ForceInline 1890 final 1891 <M extends VectorMask<Integer>> 1892 IntVector 1893 blendTemplate(Class<M> maskType, IntVector v, M m) { 1894 v.check(this); 1895 return VectorSupport.blend( 1896 getClass(), maskType, int.class, length(), 1897 this, v, m, 1898 (v0, v1, m_) -> v0.bOp(v1, m_, (i, a, b) -> b)); 1899 } 1900 1901 /** 1902 * {@inheritDoc} <!--workaround--> 1903 */ 1904 @Override public abstract IntVector addIndex(int scale); 1905 1906 /*package-private*/ 1907 @ForceInline 1908 final IntVector addIndexTemplate(int scale) { 1909 IntSpecies vsp = vspecies(); 1910 // make sure VLENGTH*scale doesn't overflow: 1911 vsp.checkScale(scale); 1912 return VectorSupport.indexVector( 1913 getClass(), int.class, length(), 1914 this, scale, vsp, 1915 (v, scale_, s) 1916 -> { 1917 // If the platform doesn't support an INDEX 1918 // instruction directly, load IOTA from memory 1919 // and multiply. 1920 IntVector iota = s.iota(); 1921 int sc = (int) scale_; 1922 return v.add(sc == 1 ? iota : iota.mul(sc)); 1923 }); 1924 } 1925 1926 /** 1927 * Replaces selected lanes of this vector with 1928 * a scalar value 1929 * under the control of a mask. 1930 * 1931 * This is a masked lane-wise binary operation which 1932 * selects each lane value from one or the other input. 1933 * 1934 * The returned result is equal to the expression 1935 * {@code blend(broadcast(e),m)}. 1936 * 1937 * @param e the input scalar, containing the replacement lane value 1938 * @param m the mask controlling lane selection of the scalar 1939 * @return the result of blending the lane elements of this vector with 1940 * the scalar value 1941 */ 1942 @ForceInline 1943 public final IntVector blend(int e, 1944 VectorMask<Integer> m) { 1945 return blend(broadcast(e), m); 1946 } 1947 1948 /** 1949 * Replaces selected lanes of this vector with 1950 * a scalar value 1951 * under the control of a mask. 1952 * 1953 * This is a masked lane-wise binary operation which 1954 * selects each lane value from one or the other input. 1955 * 1956 * The returned result is equal to the expression 1957 * {@code blend(broadcast(e),m)}. 1958 * 1959 * @param e the input scalar, containing the replacement lane value 1960 * @param m the mask controlling lane selection of the scalar 1961 * @return the result of blending the lane elements of this vector with 1962 * the scalar value 1963 */ 1964 @ForceInline 1965 public final IntVector blend(long e, 1966 VectorMask<Integer> m) { 1967 return blend(broadcast(e), m); 1968 } 1969 1970 /** 1971 * {@inheritDoc} <!--workaround--> 1972 */ 1973 @Override 1974 public abstract 1975 IntVector slice(int origin, Vector<Integer> v1); 1976 1977 /*package-private*/ 1978 final 1979 @ForceInline 1980 IntVector sliceTemplate(int origin, Vector<Integer> v1) { 1981 IntVector that = (IntVector) v1; 1982 that.check(this); 1983 int[] a0 = this.vec(); 1984 int[] a1 = that.vec(); 1985 int[] res = new int[a0.length]; 1986 int vlen = res.length; 1987 int firstPart = vlen - origin; 1988 System.arraycopy(a0, origin, res, 0, firstPart); 1989 System.arraycopy(a1, 0, res, firstPart, origin); 1990 return vectorFactory(res); 1991 } 1992 1993 /** 1994 * {@inheritDoc} <!--workaround--> 1995 */ 1996 @Override 1997 @ForceInline 1998 public final 1999 IntVector slice(int origin, 2000 Vector<Integer> w, 2001 VectorMask<Integer> m) { 2002 return broadcast(0).blend(slice(origin, w), m); 2003 } 2004 2005 /** 2006 * {@inheritDoc} <!--workaround--> 2007 */ 2008 @Override 2009 public abstract 2010 IntVector slice(int origin); 2011 2012 /** 2013 * {@inheritDoc} <!--workaround--> 2014 */ 2015 @Override 2016 public abstract 2017 IntVector unslice(int origin, Vector<Integer> w, int part); 2018 2019 /*package-private*/ 2020 final 2021 @ForceInline 2022 IntVector 2023 unsliceTemplate(int origin, Vector<Integer> w, int part) { 2024 IntVector that = (IntVector) w; 2025 that.check(this); 2026 int[] slice = this.vec(); 2027 int[] res = that.vec().clone(); 2028 int vlen = res.length; 2029 int firstPart = vlen - origin; 2030 switch (part) { 2031 case 0: 2032 System.arraycopy(slice, 0, res, origin, firstPart); 2033 break; 2034 case 1: 2035 System.arraycopy(slice, firstPart, res, 0, origin); 2036 break; 2037 default: 2038 throw wrongPartForSlice(part); 2039 } 2040 return vectorFactory(res); 2041 } 2042 2043 /*package-private*/ 2044 final 2045 @ForceInline 2046 <M extends VectorMask<Integer>> 2047 IntVector 2048 unsliceTemplate(Class<M> maskType, int origin, Vector<Integer> w, int part, M m) { 2049 IntVector that = (IntVector) w; 2050 that.check(this); 2051 IntVector slice = that.sliceTemplate(origin, that); 2052 slice = slice.blendTemplate(maskType, this, m); 2053 return slice.unsliceTemplate(origin, w, part); 2054 } 2055 2056 /** 2057 * {@inheritDoc} <!--workaround--> 2058 */ 2059 @Override 2060 public abstract 2061 IntVector unslice(int origin, Vector<Integer> w, int part, VectorMask<Integer> m); 2062 2063 /** 2064 * {@inheritDoc} <!--workaround--> 2065 */ 2066 @Override 2067 public abstract 2068 IntVector unslice(int origin); 2069 2070 private ArrayIndexOutOfBoundsException 2071 wrongPartForSlice(int part) { 2072 String msg = String.format("bad part number %d for slice operation", 2073 part); 2074 return new ArrayIndexOutOfBoundsException(msg); 2075 } 2076 2077 /** 2078 * {@inheritDoc} <!--workaround--> 2079 */ 2080 @Override 2081 public abstract 2082 IntVector rearrange(VectorShuffle<Integer> m); 2083 2084 /*package-private*/ 2085 @ForceInline 2086 final 2087 <S extends VectorShuffle<Integer>> 2088 IntVector rearrangeTemplate(Class<S> shuffletype, S shuffle) { 2089 shuffle.checkIndexes(); 2090 return VectorSupport.rearrangeOp( 2091 getClass(), shuffletype, int.class, length(), 2092 this, shuffle, 2093 (v1, s_) -> v1.uOp((i, a) -> { 2094 int ei = s_.laneSource(i); 2095 return v1.lane(ei); 2096 })); 2097 } 2098 2099 /** 2100 * {@inheritDoc} <!--workaround--> 2101 */ 2102 @Override 2103 public abstract 2104 IntVector rearrange(VectorShuffle<Integer> s, 2105 VectorMask<Integer> m); 2106 2107 /*package-private*/ 2108 @ForceInline 2109 final 2110 <S extends VectorShuffle<Integer>> 2111 IntVector rearrangeTemplate(Class<S> shuffletype, 2112 S shuffle, 2113 VectorMask<Integer> m) { 2114 IntVector unmasked = 2115 VectorSupport.rearrangeOp( 2116 getClass(), shuffletype, int.class, length(), 2117 this, shuffle, 2118 (v1, s_) -> v1.uOp((i, a) -> { 2119 int ei = s_.laneSource(i); 2120 return ei < 0 ? 0 : v1.lane(ei); 2121 })); 2122 VectorMask<Integer> valid = shuffle.laneIsValid(); 2123 if (m.andNot(valid).anyTrue()) { 2124 shuffle.checkIndexes(); 2125 throw new AssertionError(); 2126 } 2127 return broadcast((int)0).blend(unmasked, m); 2128 } 2129 2130 /** 2131 * {@inheritDoc} <!--workaround--> 2132 */ 2133 @Override 2134 public abstract 2135 IntVector rearrange(VectorShuffle<Integer> s, 2136 Vector<Integer> v); 2137 2138 /*package-private*/ 2139 @ForceInline 2140 final 2141 <S extends VectorShuffle<Integer>> 2142 IntVector rearrangeTemplate(Class<S> shuffletype, 2143 S shuffle, 2144 IntVector v) { 2145 VectorMask<Integer> valid = shuffle.laneIsValid(); 2146 S ws = shuffletype.cast(shuffle.wrapIndexes()); 2147 IntVector r0 = 2148 VectorSupport.rearrangeOp( 2149 getClass(), shuffletype, int.class, length(), 2150 this, ws, 2151 (v0, s_) -> v0.uOp((i, a) -> { 2152 int ei = s_.laneSource(i); 2153 return v0.lane(ei); 2154 })); 2155 IntVector r1 = 2156 VectorSupport.rearrangeOp( 2157 getClass(), shuffletype, int.class, length(), 2158 v, ws, 2159 (v1, s_) -> v1.uOp((i, a) -> { 2160 int ei = s_.laneSource(i); 2161 return v1.lane(ei); 2162 })); 2163 return r1.blend(r0, valid); 2164 } 2165 2166 /** 2167 * {@inheritDoc} <!--workaround--> 2168 */ 2169 @Override 2170 public abstract 2171 IntVector selectFrom(Vector<Integer> v); 2172 2173 /*package-private*/ 2174 @ForceInline 2175 final IntVector selectFromTemplate(IntVector v) { 2176 return v.rearrange(this.toShuffle()); 2177 } 2178 2179 /** 2180 * {@inheritDoc} <!--workaround--> 2181 */ 2182 @Override 2183 public abstract 2184 IntVector selectFrom(Vector<Integer> s, VectorMask<Integer> m); 2185 2186 /*package-private*/ 2187 @ForceInline 2188 final IntVector selectFromTemplate(IntVector v, 2189 AbstractMask<Integer> m) { 2190 return v.rearrange(this.toShuffle(), m); 2191 } 2192 2193 /// Ternary operations 2194 2195 /** 2196 * Blends together the bits of two vectors under 2197 * the control of a third, which supplies mask bits. 2198 * 2199 * This is a lane-wise ternary operation which performs 2200 * a bitwise blending operation {@code (a&~c)|(b&c)} 2201 * to each lane. 2202 * 2203 * This method is also equivalent to the expression 2204 * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) 2205 * lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND 2206 * BITWISE_BLEND}{@code , bits, mask)}. 2207 * 2208 * @param bits input bits to blend into the current vector 2209 * @param mask a bitwise mask to enable blending of the input bits 2210 * @return the bitwise blend of the given bits into the current vector, 2211 * under control of the bitwise mask 2212 * @see #bitwiseBlend(int,int) 2213 * @see #bitwiseBlend(int,Vector) 2214 * @see #bitwiseBlend(Vector,int) 2215 * @see VectorOperators#BITWISE_BLEND 2216 * @see #lanewise(VectorOperators.Ternary,Vector,Vector,VectorMask) 2217 */ 2218 @ForceInline 2219 public final 2220 IntVector bitwiseBlend(Vector<Integer> bits, Vector<Integer> mask) { 2221 return lanewise(BITWISE_BLEND, bits, mask); 2222 } 2223 2224 /** 2225 * Blends together the bits of a vector and a scalar under 2226 * the control of another scalar, which supplies mask bits. 2227 * 2228 * This is a lane-wise ternary operation which performs 2229 * a bitwise blending operation {@code (a&~c)|(b&c)} 2230 * to each lane. 2231 * 2232 * This method is also equivalent to the expression 2233 * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) 2234 * lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND 2235 * BITWISE_BLEND}{@code , bits, mask)}. 2236 * 2237 * @param bits input bits to blend into the current vector 2238 * @param mask a bitwise mask to enable blending of the input bits 2239 * @return the bitwise blend of the given bits into the current vector, 2240 * under control of the bitwise mask 2241 * @see #bitwiseBlend(Vector,Vector) 2242 * @see VectorOperators#BITWISE_BLEND 2243 * @see #lanewise(VectorOperators.Ternary,int,int,VectorMask) 2244 */ 2245 @ForceInline 2246 public final 2247 IntVector bitwiseBlend(int bits, int mask) { 2248 return lanewise(BITWISE_BLEND, bits, mask); 2249 } 2250 2251 /** 2252 * Blends together the bits of a vector and a scalar under 2253 * the control of another vector, which supplies mask bits. 2254 * 2255 * This is a lane-wise ternary operation which performs 2256 * a bitwise blending operation {@code (a&~c)|(b&c)} 2257 * to each lane. 2258 * 2259 * This method is also equivalent to the expression 2260 * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) 2261 * lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND 2262 * BITWISE_BLEND}{@code , bits, mask)}. 2263 * 2264 * @param bits input bits to blend into the current vector 2265 * @param mask a bitwise mask to enable blending of the input bits 2266 * @return the bitwise blend of the given bits into the current vector, 2267 * under control of the bitwise mask 2268 * @see #bitwiseBlend(Vector,Vector) 2269 * @see VectorOperators#BITWISE_BLEND 2270 * @see #lanewise(VectorOperators.Ternary,int,Vector,VectorMask) 2271 */ 2272 @ForceInline 2273 public final 2274 IntVector bitwiseBlend(int bits, Vector<Integer> mask) { 2275 return lanewise(BITWISE_BLEND, bits, mask); 2276 } 2277 2278 /** 2279 * Blends together the bits of two vectors under 2280 * the control of a scalar, which supplies mask bits. 2281 * 2282 * This is a lane-wise ternary operation which performs 2283 * a bitwise blending operation {@code (a&~c)|(b&c)} 2284 * to each lane. 2285 * 2286 * This method is also equivalent to the expression 2287 * {@link #lanewise(VectorOperators.Ternary,Vector,Vector) 2288 * lanewise}{@code (}{@link VectorOperators#BITWISE_BLEND 2289 * BITWISE_BLEND}{@code , bits, mask)}. 2290 * 2291 * @param bits input bits to blend into the current vector 2292 * @param mask a bitwise mask to enable blending of the input bits 2293 * @return the bitwise blend of the given bits into the current vector, 2294 * under control of the bitwise mask 2295 * @see #bitwiseBlend(Vector,Vector) 2296 * @see VectorOperators#BITWISE_BLEND 2297 * @see #lanewise(VectorOperators.Ternary,Vector,int,VectorMask) 2298 */ 2299 @ForceInline 2300 public final 2301 IntVector bitwiseBlend(Vector<Integer> bits, int mask) { 2302 return lanewise(BITWISE_BLEND, bits, mask); 2303 } 2304 2305 2306 // Type specific horizontal reductions 2307 2308 /** 2309 * Returns a value accumulated from all the lanes of this vector. 2310 * 2311 * This is an associative cross-lane reduction operation which 2312 * applies the specified operation to all the lane elements. 2313 * <p> 2314 * A few reduction operations do not support arbitrary reordering 2315 * of their operands, yet are included here because of their 2316 * usefulness. 2317 * <ul> 2318 * <li> 2319 * In the case of {@code FIRST_NONZERO}, the reduction returns 2320 * the value from the lowest-numbered non-zero lane. 2321 * <li> 2322 * All other reduction operations are fully commutative and 2323 * associative. The implementation can choose any order of 2324 * processing, yet it will always produce the same result. 2325 * </ul> 2326 * 2327 * @param op the operation used to combine lane values 2328 * @return the accumulated result 2329 * @throws UnsupportedOperationException if this vector does 2330 * not support the requested operation 2331 * @see #reduceLanes(VectorOperators.Associative,VectorMask) 2332 * @see #add(Vector) 2333 * @see #mul(Vector) 2334 * @see #min(Vector) 2335 * @see #max(Vector) 2336 * @see #and(Vector) 2337 * @see #or(Vector) 2338 * @see VectorOperators#XOR 2339 * @see VectorOperators#FIRST_NONZERO 2340 */ 2341 public abstract int reduceLanes(VectorOperators.Associative op); 2342 2343 /** 2344 * Returns a value accumulated from selected lanes of this vector, 2345 * controlled by a mask. 2346 * 2347 * This is an associative cross-lane reduction operation which 2348 * applies the specified operation to the selected lane elements. 2349 * <p> 2350 * If no elements are selected, an operation-specific identity 2351 * value is returned. 2352 * <ul> 2353 * <li> 2354 * If the operation is 2355 * {@code ADD}, {@code XOR}, {@code OR}, 2356 * or {@code FIRST_NONZERO}, 2357 * then the identity value is zero, the default {@code int} value. 2358 * <li> 2359 * If the operation is {@code MUL}, 2360 * then the identity value is one. 2361 * <li> 2362 * If the operation is {@code AND}, 2363 * then the identity value is minus one (all bits set). 2364 * <li> 2365 * If the operation is {@code MAX}, 2366 * then the identity value is {@code Integer.MIN_VALUE}. 2367 * <li> 2368 * If the operation is {@code MIN}, 2369 * then the identity value is {@code Integer.MAX_VALUE}. 2370 * </ul> 2371 * <p> 2372 * A few reduction operations do not support arbitrary reordering 2373 * of their operands, yet are included here because of their 2374 * usefulness. 2375 * <ul> 2376 * <li> 2377 * In the case of {@code FIRST_NONZERO}, the reduction returns 2378 * the value from the lowest-numbered non-zero lane. 2379 * <li> 2380 * All other reduction operations are fully commutative and 2381 * associative. The implementation can choose any order of 2382 * processing, yet it will always produce the same result. 2383 * </ul> 2384 * 2385 * @param op the operation used to combine lane values 2386 * @param m the mask controlling lane selection 2387 * @return the reduced result accumulated from the selected lane values 2388 * @throws UnsupportedOperationException if this vector does 2389 * not support the requested operation 2390 * @see #reduceLanes(VectorOperators.Associative) 2391 */ 2392 public abstract int reduceLanes(VectorOperators.Associative op, 2393 VectorMask<Integer> m); 2394 2395 /*package-private*/ 2396 @ForceInline 2397 final 2398 int reduceLanesTemplate(VectorOperators.Associative op, 2399 VectorMask<Integer> m) { 2400 IntVector v = reduceIdentityVector(op).blend(this, m); 2401 return v.reduceLanesTemplate(op); 2402 } 2403 2404 /*package-private*/ 2405 @ForceInline 2406 final 2407 int reduceLanesTemplate(VectorOperators.Associative op) { 2408 if (op == FIRST_NONZERO) { 2409 // FIXME: The JIT should handle this, and other scan ops alos. 2410 VectorMask<Integer> thisNZ 2411 = this.viewAsIntegralLanes().compare(NE, (int) 0); 2412 return this.lane(thisNZ.firstTrue()); 2413 } 2414 int opc = opCode(op); 2415 return fromBits(VectorSupport.reductionCoerced( 2416 opc, getClass(), int.class, length(), 2417 this, 2418 REDUCE_IMPL.find(op, opc, (opc_) -> { 2419 switch (opc_) { 2420 case VECTOR_OP_ADD: return v -> 2421 toBits(v.rOp((int)0, (i, a, b) -> (int)(a + b))); 2422 case VECTOR_OP_MUL: return v -> 2423 toBits(v.rOp((int)1, (i, a, b) -> (int)(a * b))); 2424 case VECTOR_OP_MIN: return v -> 2425 toBits(v.rOp(MAX_OR_INF, (i, a, b) -> (int) Math.min(a, b))); 2426 case VECTOR_OP_MAX: return v -> 2427 toBits(v.rOp(MIN_OR_INF, (i, a, b) -> (int) Math.max(a, b))); 2428 case VECTOR_OP_AND: return v -> 2429 toBits(v.rOp((int)-1, (i, a, b) -> (int)(a & b))); 2430 case VECTOR_OP_OR: return v -> 2431 toBits(v.rOp((int)0, (i, a, b) -> (int)(a | b))); 2432 case VECTOR_OP_XOR: return v -> 2433 toBits(v.rOp((int)0, (i, a, b) -> (int)(a ^ b))); 2434 default: return null; 2435 }}))); 2436 } 2437 private static final 2438 ImplCache<Associative,Function<IntVector,Long>> REDUCE_IMPL 2439 = new ImplCache<>(Associative.class, IntVector.class); 2440 2441 private 2442 @ForceInline 2443 IntVector reduceIdentityVector(VectorOperators.Associative op) { 2444 int opc = opCode(op); 2445 UnaryOperator<IntVector> fn 2446 = REDUCE_ID_IMPL.find(op, opc, (opc_) -> { 2447 switch (opc_) { 2448 case VECTOR_OP_ADD: 2449 case VECTOR_OP_OR: 2450 case VECTOR_OP_XOR: 2451 return v -> v.broadcast(0); 2452 case VECTOR_OP_MUL: 2453 return v -> v.broadcast(1); 2454 case VECTOR_OP_AND: 2455 return v -> v.broadcast(-1); 2456 case VECTOR_OP_MIN: 2457 return v -> v.broadcast(MAX_OR_INF); 2458 case VECTOR_OP_MAX: 2459 return v -> v.broadcast(MIN_OR_INF); 2460 default: return null; 2461 } 2462 }); 2463 return fn.apply(this); 2464 } 2465 private static final 2466 ImplCache<Associative,UnaryOperator<IntVector>> REDUCE_ID_IMPL 2467 = new ImplCache<>(Associative.class, IntVector.class); 2468 2469 private static final int MIN_OR_INF = Integer.MIN_VALUE; 2470 private static final int MAX_OR_INF = Integer.MAX_VALUE; 2471 2472 public @Override abstract long reduceLanesToLong(VectorOperators.Associative op); 2473 public @Override abstract long reduceLanesToLong(VectorOperators.Associative op, 2474 VectorMask<Integer> m); 2475 2476 // Type specific accessors 2477 2478 /** 2479 * Gets the lane element at lane index {@code i} 2480 * 2481 * @param i the lane index 2482 * @return the lane element at lane index {@code i} 2483 * @throws IllegalArgumentException if the index is is out of range 2484 * ({@code < 0 || >= length()}) 2485 */ 2486 public abstract int lane(int i); 2487 2488 /** 2489 * Replaces the lane element of this vector at lane index {@code i} with 2490 * value {@code e}. 2491 * 2492 * This is a cross-lane operation and behaves as if it returns the result 2493 * of blending this vector with an input vector that is the result of 2494 * broadcasting {@code e} and a mask that has only one lane set at lane 2495 * index {@code i}. 2496 * 2497 * @param i the lane index of the lane element to be replaced 2498 * @param e the value to be placed 2499 * @return the result of replacing the lane element of this vector at lane 2500 * index {@code i} with value {@code e}. 2501 * @throws IllegalArgumentException if the index is is out of range 2502 * ({@code < 0 || >= length()}) 2503 */ 2504 public abstract IntVector withLane(int i, int e); 2505 2506 // Memory load operations 2507 2508 /** 2509 * Returns an array of type {@code int[]} 2510 * containing all the lane values. 2511 * The array length is the same as the vector length. 2512 * The array elements are stored in lane order. 2513 * <p> 2514 * This method behaves as if it stores 2515 * this vector into an allocated array 2516 * (using {@link #intoArray(int[], int) intoArray}) 2517 * and returns the array as follows: 2518 * <pre>{@code 2519 * int[] a = new int[this.length()]; 2520 * this.intoArray(a, 0); 2521 * return a; 2522 * }</pre> 2523 * 2524 * @return an array containing the lane values of this vector 2525 */ 2526 @ForceInline 2527 @Override 2528 public final int[] toArray() { 2529 int[] a = new int[vspecies().laneCount()]; 2530 intoArray(a, 0); 2531 return a; 2532 } 2533 2534 /** 2535 * {@inheritDoc} <!--workaround--> 2536 * This is an alias for {@link #toArray()} 2537 * When this method is used on used on vectors 2538 * of type {@code IntVector}, 2539 * there will be no loss of range or precision. 2540 */ 2541 @ForceInline 2542 @Override 2543 public final int[] toIntArray() { 2544 return toArray(); 2545 } 2546 2547 /** {@inheritDoc} <!--workaround--> 2548 * @implNote 2549 * When this method is used on used on vectors 2550 * of type {@code IntVector}, 2551 * there will be no loss of precision or range, 2552 * and so no {@code UnsupportedOperationException} will 2553 * be thrown. 2554 */ 2555 @ForceInline 2556 @Override 2557 public final long[] toLongArray() { 2558 int[] a = toArray(); 2559 long[] res = new long[a.length]; 2560 for (int i = 0; i < a.length; i++) { 2561 int e = a[i]; 2562 res[i] = IntSpecies.toIntegralChecked(e, false); 2563 } 2564 return res; 2565 } 2566 2567 /** {@inheritDoc} <!--workaround--> 2568 * @implNote 2569 * When this method is used on used on vectors 2570 * of type {@code IntVector}, 2571 * there will be no loss of precision. 2572 */ 2573 @ForceInline 2574 @Override 2575 public final double[] toDoubleArray() { 2576 int[] a = toArray(); 2577 double[] res = new double[a.length]; 2578 for (int i = 0; i < a.length; i++) { 2579 res[i] = (double) a[i]; 2580 } 2581 return res; 2582 } 2583 2584 /** 2585 * Loads a vector from a byte array starting at an offset. 2586 * Bytes are composed into primitive lane elements according 2587 * to the specified byte order. 2588 * The vector is arranged into lanes according to 2589 * <a href="Vector.html#lane-order">memory ordering</a>. 2590 * <p> 2591 * This method behaves as if it returns the result of calling 2592 * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask) 2593 * fromByteBuffer()} as follows: 2594 * <pre>{@code 2595 * var bb = ByteBuffer.wrap(a); 2596 * var m = species.maskAll(true); 2597 * return fromByteBuffer(species, bb, offset, bo, m); 2598 * }</pre> 2599 * 2600 * @param species species of desired vector 2601 * @param a the byte array 2602 * @param offset the offset into the array 2603 * @param bo the intended byte order 2604 * @return a vector loaded from a byte array 2605 * @throws IndexOutOfBoundsException 2606 * if {@code offset+N*ESIZE < 0} 2607 * or {@code offset+(N+1)*ESIZE > a.length} 2608 * for any lane {@code N} in the vector 2609 */ 2610 @ForceInline 2611 public static 2612 IntVector fromByteArray(VectorSpecies<Integer> species, 2613 byte[] a, int offset, 2614 ByteOrder bo) { 2615 offset = checkFromIndexSize(offset, species.vectorByteSize(), a.length); 2616 IntSpecies vsp = (IntSpecies) species; 2617 return vsp.dummyVector().fromByteArray0(a, offset).maybeSwap(bo); 2618 } 2619 2620 /** 2621 * Loads a vector from a byte array starting at an offset 2622 * and using a mask. 2623 * Lanes where the mask is unset are filled with the default 2624 * value of {@code int} (zero). 2625 * Bytes are composed into primitive lane elements according 2626 * to the specified byte order. 2627 * The vector is arranged into lanes according to 2628 * <a href="Vector.html#lane-order">memory ordering</a>. 2629 * <p> 2630 * This method behaves as if it returns the result of calling 2631 * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask) 2632 * fromByteBuffer()} as follows: 2633 * <pre>{@code 2634 * var bb = ByteBuffer.wrap(a); 2635 * return fromByteBuffer(species, bb, offset, bo, m); 2636 * }</pre> 2637 * 2638 * @param species species of desired vector 2639 * @param a the byte array 2640 * @param offset the offset into the array 2641 * @param bo the intended byte order 2642 * @param m the mask controlling lane selection 2643 * @return a vector loaded from a byte array 2644 * @throws IndexOutOfBoundsException 2645 * if {@code offset+N*ESIZE < 0} 2646 * or {@code offset+(N+1)*ESIZE > a.length} 2647 * for any lane {@code N} in the vector 2648 * where the mask is set 2649 */ 2650 @ForceInline 2651 public static 2652 IntVector fromByteArray(VectorSpecies<Integer> species, 2653 byte[] a, int offset, 2654 ByteOrder bo, 2655 VectorMask<Integer> m) { 2656 IntSpecies vsp = (IntSpecies) species; 2657 if (offset >= 0 && offset <= (a.length - species.vectorByteSize())) { 2658 IntVector zero = vsp.zero(); 2659 IntVector v = zero.fromByteArray0(a, offset); 2660 return zero.blend(v.maybeSwap(bo), m); 2661 } 2662 2663 // FIXME: optimize 2664 checkMaskFromIndexSize(offset, vsp, m, 4, a.length); 2665 ByteBuffer wb = wrapper(a, bo); 2666 return vsp.ldOp(wb, offset, (AbstractMask<Integer>)m, 2667 (wb_, o, i) -> wb_.getInt(o + i * 4)); 2668 } 2669 2670 /** 2671 * Loads a vector from an array of type {@code int[]} 2672 * starting at an offset. 2673 * For each vector lane, where {@code N} is the vector lane index, the 2674 * array element at index {@code offset + N} is placed into the 2675 * resulting vector at lane index {@code N}. 2676 * 2677 * @param species species of desired vector 2678 * @param a the array 2679 * @param offset the offset into the array 2680 * @return the vector loaded from an array 2681 * @throws IndexOutOfBoundsException 2682 * if {@code offset+N < 0} or {@code offset+N >= a.length} 2683 * for any lane {@code N} in the vector 2684 */ 2685 @ForceInline 2686 public static 2687 IntVector fromArray(VectorSpecies<Integer> species, 2688 int[] a, int offset) { 2689 offset = checkFromIndexSize(offset, species.length(), a.length); 2690 IntSpecies vsp = (IntSpecies) species; 2691 return vsp.dummyVector().fromArray0(a, offset); 2692 } 2693 2694 /** 2695 * Loads a vector from an array of type {@code int[]} 2696 * starting at an offset and using a mask. 2697 * Lanes where the mask is unset are filled with the default 2698 * value of {@code int} (zero). 2699 * For each vector lane, where {@code N} is the vector lane index, 2700 * if the mask lane at index {@code N} is set then the array element at 2701 * index {@code offset + N} is placed into the resulting vector at lane index 2702 * {@code N}, otherwise the default element value is placed into the 2703 * resulting vector at lane index {@code N}. 2704 * 2705 * @param species species of desired vector 2706 * @param a the array 2707 * @param offset the offset into the array 2708 * @param m the mask controlling lane selection 2709 * @return the vector loaded from an array 2710 * @throws IndexOutOfBoundsException 2711 * if {@code offset+N < 0} or {@code offset+N >= a.length} 2712 * for any lane {@code N} in the vector 2713 * where the mask is set 2714 */ 2715 @ForceInline 2716 public static 2717 IntVector fromArray(VectorSpecies<Integer> species, 2718 int[] a, int offset, 2719 VectorMask<Integer> m) { 2720 IntSpecies vsp = (IntSpecies) species; 2721 if (offset >= 0 && offset <= (a.length - species.length())) { 2722 IntVector zero = vsp.zero(); 2723 return zero.blend(zero.fromArray0(a, offset), m); 2724 } 2725 2726 // FIXME: optimize 2727 checkMaskFromIndexSize(offset, vsp, m, 1, a.length); 2728 return vsp.vOp(m, i -> a[offset + i]); 2729 } 2730 2731 /** 2732 * Gathers a new vector composed of elements from an array of type 2733 * {@code int[]}, 2734 * using indexes obtained by adding a fixed {@code offset} to a 2735 * series of secondary offsets from an <em>index map</em>. 2736 * The index map is a contiguous sequence of {@code VLENGTH} 2737 * elements in a second array of {@code int}s, starting at a given 2738 * {@code mapOffset}. 2739 * <p> 2740 * For each vector lane, where {@code N} is the vector lane index, 2741 * the lane is loaded from the array 2742 * element {@code a[f(N)]}, where {@code f(N)} is the 2743 * index mapping expression 2744 * {@code offset + indexMap[mapOffset + N]]}. 2745 * 2746 * @param species species of desired vector 2747 * @param a the array 2748 * @param offset the offset into the array, may be negative if relative 2749 * indexes in the index map compensate to produce a value within the 2750 * array bounds 2751 * @param indexMap the index map 2752 * @param mapOffset the offset into the index map 2753 * @return the vector loaded from the indexed elements of the array 2754 * @throws IndexOutOfBoundsException 2755 * if {@code mapOffset+N < 0} 2756 * or if {@code mapOffset+N >= indexMap.length}, 2757 * or if {@code f(N)=offset+indexMap[mapOffset+N]} 2758 * is an invalid index into {@code a}, 2759 * for any lane {@code N} in the vector 2760 * @see IntVector#toIntArray() 2761 */ 2762 @ForceInline 2763 public static 2764 IntVector fromArray(VectorSpecies<Integer> species, 2765 int[] a, int offset, 2766 int[] indexMap, int mapOffset) { 2767 IntSpecies vsp = (IntSpecies) species; 2768 IntVector.IntSpecies isp = IntVector.species(vsp.indexShape()); 2769 Objects.requireNonNull(a); 2770 Objects.requireNonNull(indexMap); 2771 Class<? extends IntVector> vectorType = vsp.vectorType(); 2772 2773 // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k] 2774 IntVector vix = IntVector 2775 .fromArray(isp, indexMap, mapOffset) 2776 .add(offset); 2777 2778 vix = VectorIntrinsics.checkIndex(vix, a.length); 2779 2780 return VectorSupport.loadWithMap( 2781 vectorType, int.class, vsp.laneCount(), 2782 IntVector.species(vsp.indexShape()).vectorType(), 2783 a, ARRAY_BASE, vix, 2784 a, offset, indexMap, mapOffset, vsp, 2785 (int[] c, int idx, int[] iMap, int idy, IntSpecies s) -> 2786 s.vOp(n -> c[idx + iMap[idy+n]])); 2787 } 2788 2789 /** 2790 * Gathers a new vector composed of elements from an array of type 2791 * {@code int[]}, 2792 * under the control of a mask, and 2793 * using indexes obtained by adding a fixed {@code offset} to a 2794 * series of secondary offsets from an <em>index map</em>. 2795 * The index map is a contiguous sequence of {@code VLENGTH} 2796 * elements in a second array of {@code int}s, starting at a given 2797 * {@code mapOffset}. 2798 * <p> 2799 * For each vector lane, where {@code N} is the vector lane index, 2800 * if the lane is set in the mask, 2801 * the lane is loaded from the array 2802 * element {@code a[f(N)]}, where {@code f(N)} is the 2803 * index mapping expression 2804 * {@code offset + indexMap[mapOffset + N]]}. 2805 * Unset lanes in the resulting vector are set to zero. 2806 * 2807 * @param species species of desired vector 2808 * @param a the array 2809 * @param offset the offset into the array, may be negative if relative 2810 * indexes in the index map compensate to produce a value within the 2811 * array bounds 2812 * @param indexMap the index map 2813 * @param mapOffset the offset into the index map 2814 * @param m the mask controlling lane selection 2815 * @return the vector loaded from the indexed elements of the array 2816 * @throws IndexOutOfBoundsException 2817 * if {@code mapOffset+N < 0} 2818 * or if {@code mapOffset+N >= indexMap.length}, 2819 * or if {@code f(N)=offset+indexMap[mapOffset+N]} 2820 * is an invalid index into {@code a}, 2821 * for any lane {@code N} in the vector 2822 * where the mask is set 2823 * @see IntVector#toIntArray() 2824 */ 2825 @ForceInline 2826 public static 2827 IntVector fromArray(VectorSpecies<Integer> species, 2828 int[] a, int offset, 2829 int[] indexMap, int mapOffset, 2830 VectorMask<Integer> m) { 2831 if (m.allTrue()) { 2832 return fromArray(species, a, offset, indexMap, mapOffset); 2833 } 2834 else { 2835 // FIXME: Cannot vectorize yet, if there's a mask. 2836 IntSpecies vsp = (IntSpecies) species; 2837 return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]); 2838 } 2839 } 2840 2841 /** 2842 * Loads a vector from a {@linkplain ByteBuffer byte buffer} 2843 * starting at an offset into the byte buffer. 2844 * Bytes are composed into primitive lane elements according 2845 * to the specified byte order. 2846 * The vector is arranged into lanes according to 2847 * <a href="Vector.html#lane-order">memory ordering</a>. 2848 * <p> 2849 * This method behaves as if it returns the result of calling 2850 * {@link #fromByteBuffer(VectorSpecies,ByteBuffer,int,ByteOrder,VectorMask) 2851 * fromByteBuffer()} as follows: 2852 * <pre>{@code 2853 * var m = species.maskAll(true); 2854 * return fromByteBuffer(species, bb, offset, bo, m); 2855 * }</pre> 2856 * 2857 * @param species species of desired vector 2858 * @param bb the byte buffer 2859 * @param offset the offset into the byte buffer 2860 * @param bo the intended byte order 2861 * @return a vector loaded from a byte buffer 2862 * @throws IndexOutOfBoundsException 2863 * if {@code offset+N*4 < 0} 2864 * or {@code offset+N*4 >= bb.limit()} 2865 * for any lane {@code N} in the vector 2866 */ 2867 @ForceInline 2868 public static 2869 IntVector fromByteBuffer(VectorSpecies<Integer> species, 2870 ByteBuffer bb, int offset, 2871 ByteOrder bo) { 2872 offset = checkFromIndexSize(offset, species.vectorByteSize(), bb.limit()); 2873 IntSpecies vsp = (IntSpecies) species; 2874 return vsp.dummyVector().fromByteBuffer0(bb, offset).maybeSwap(bo); 2875 } 2876 2877 /** 2878 * Loads a vector from a {@linkplain ByteBuffer byte buffer} 2879 * starting at an offset into the byte buffer 2880 * and using a mask. 2881 * Lanes where the mask is unset are filled with the default 2882 * value of {@code int} (zero). 2883 * Bytes are composed into primitive lane elements according 2884 * to the specified byte order. 2885 * The vector is arranged into lanes according to 2886 * <a href="Vector.html#lane-order">memory ordering</a>. 2887 * <p> 2888 * The following pseudocode illustrates the behavior: 2889 * <pre>{@code 2890 * IntBuffer eb = bb.duplicate() 2891 * .position(offset) 2892 * .order(bo).asIntBuffer(); 2893 * int[] ar = new int[species.length()]; 2894 * for (int n = 0; n < ar.length; n++) { 2895 * if (m.laneIsSet(n)) { 2896 * ar[n] = eb.get(n); 2897 * } 2898 * } 2899 * IntVector r = IntVector.fromArray(species, ar, 0); 2900 * }</pre> 2901 * @implNote 2902 * This operation is likely to be more efficient if 2903 * the specified byte order is the same as 2904 * {@linkplain ByteOrder#nativeOrder() 2905 * the platform native order}, 2906 * since this method will not need to reorder 2907 * the bytes of lane values. 2908 * 2909 * @param species species of desired vector 2910 * @param bb the byte buffer 2911 * @param offset the offset into the byte buffer 2912 * @param bo the intended byte order 2913 * @param m the mask controlling lane selection 2914 * @return a vector loaded from a byte buffer 2915 * @throws IndexOutOfBoundsException 2916 * if {@code offset+N*4 < 0} 2917 * or {@code offset+N*4 >= bb.limit()} 2918 * for any lane {@code N} in the vector 2919 * where the mask is set 2920 */ 2921 @ForceInline 2922 public static 2923 IntVector fromByteBuffer(VectorSpecies<Integer> species, 2924 ByteBuffer bb, int offset, 2925 ByteOrder bo, 2926 VectorMask<Integer> m) { 2927 IntSpecies vsp = (IntSpecies) species; 2928 if (offset >= 0 && offset <= (bb.limit() - species.vectorByteSize())) { 2929 IntVector zero = vsp.zero(); 2930 IntVector v = zero.fromByteBuffer0(bb, offset); 2931 return zero.blend(v.maybeSwap(bo), m); 2932 } 2933 2934 // FIXME: optimize 2935 checkMaskFromIndexSize(offset, vsp, m, 4, bb.limit()); 2936 ByteBuffer wb = wrapper(bb, bo); 2937 return vsp.ldOp(wb, offset, (AbstractMask<Integer>)m, 2938 (wb_, o, i) -> wb_.getInt(o + i * 4)); 2939 } 2940 2941 // Memory store operations 2942 2943 /** 2944 * Stores this vector into an array of type {@code int[]} 2945 * starting at an offset. 2946 * <p> 2947 * For each vector lane, where {@code N} is the vector lane index, 2948 * the lane element at index {@code N} is stored into the array 2949 * element {@code a[offset+N]}. 2950 * 2951 * @param a the array, of type {@code int[]} 2952 * @param offset the offset into the array 2953 * @throws IndexOutOfBoundsException 2954 * if {@code offset+N < 0} or {@code offset+N >= a.length} 2955 * for any lane {@code N} in the vector 2956 */ 2957 @ForceInline 2958 public final 2959 void intoArray(int[] a, int offset) { 2960 offset = checkFromIndexSize(offset, length(), a.length); 2961 IntSpecies vsp = vspecies(); 2962 VectorSupport.store( 2963 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 2964 a, arrayAddress(a, offset), 2965 this, 2966 a, offset, 2967 (arr, off, v) 2968 -> v.stOp(arr, off, 2969 (arr_, off_, i, e) -> arr_[off_ + i] = e)); 2970 } 2971 2972 /** 2973 * Stores this vector into an array of {@code int} 2974 * starting at offset and using a mask. 2975 * <p> 2976 * For each vector lane, where {@code N} is the vector lane index, 2977 * the lane element at index {@code N} is stored into the array 2978 * element {@code a[offset+N]}. 2979 * If the mask lane at {@code N} is unset then the corresponding 2980 * array element {@code a[offset+N]} is left unchanged. 2981 * <p> 2982 * Array range checking is done for lanes where the mask is set. 2983 * Lanes where the mask is unset are not stored and do not need 2984 * to correspond to legitimate elements of {@code a}. 2985 * That is, unset lanes may correspond to array indexes less than 2986 * zero or beyond the end of the array. 2987 * 2988 * @param a the array, of type {@code int[]} 2989 * @param offset the offset into the array 2990 * @param m the mask controlling lane storage 2991 * @throws IndexOutOfBoundsException 2992 * if {@code offset+N < 0} or {@code offset+N >= a.length} 2993 * for any lane {@code N} in the vector 2994 * where the mask is set 2995 */ 2996 @ForceInline 2997 public final 2998 void intoArray(int[] a, int offset, 2999 VectorMask<Integer> m) { 3000 if (m.allTrue()) { 3001 intoArray(a, offset); 3002 } else { 3003 // FIXME: optimize 3004 IntSpecies vsp = vspecies(); 3005 checkMaskFromIndexSize(offset, vsp, m, 1, a.length); 3006 stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = v); 3007 } 3008 } 3009 3010 /** 3011 * Scatters this vector into an array of type {@code int[]} 3012 * using indexes obtained by adding a fixed {@code offset} to a 3013 * series of secondary offsets from an <em>index map</em>. 3014 * The index map is a contiguous sequence of {@code VLENGTH} 3015 * elements in a second array of {@code int}s, starting at a given 3016 * {@code mapOffset}. 3017 * <p> 3018 * For each vector lane, where {@code N} is the vector lane index, 3019 * the lane element at index {@code N} is stored into the array 3020 * element {@code a[f(N)]}, where {@code f(N)} is the 3021 * index mapping expression 3022 * {@code offset + indexMap[mapOffset + N]]}. 3023 * 3024 * @param a the array 3025 * @param offset an offset to combine with the index map offsets 3026 * @param indexMap the index map 3027 * @param mapOffset the offset into the index map 3028 * @throws IndexOutOfBoundsException 3029 * if {@code mapOffset+N < 0} 3030 * or if {@code mapOffset+N >= indexMap.length}, 3031 * or if {@code f(N)=offset+indexMap[mapOffset+N]} 3032 * is an invalid index into {@code a}, 3033 * for any lane {@code N} in the vector 3034 * @see IntVector#toIntArray() 3035 */ 3036 @ForceInline 3037 public final 3038 void intoArray(int[] a, int offset, 3039 int[] indexMap, int mapOffset) { 3040 IntSpecies vsp = vspecies(); 3041 IntVector.IntSpecies isp = IntVector.species(vsp.indexShape()); 3042 // Index vector: vix[0:n] = i -> offset + indexMap[mo + i] 3043 IntVector vix = IntVector 3044 .fromArray(isp, indexMap, mapOffset) 3045 .add(offset); 3046 3047 vix = VectorIntrinsics.checkIndex(vix, a.length); 3048 3049 VectorSupport.storeWithMap( 3050 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3051 isp.vectorType(), 3052 a, arrayAddress(a, 0), vix, 3053 this, 3054 a, offset, indexMap, mapOffset, 3055 (arr, off, v, map, mo) 3056 -> v.stOp(arr, off, 3057 (arr_, off_, i, e) -> { 3058 int j = map[mo + i]; 3059 arr[off + j] = e; 3060 })); 3061 } 3062 3063 /** 3064 * Scatters this vector into an array of type {@code int[]}, 3065 * under the control of a mask, and 3066 * using indexes obtained by adding a fixed {@code offset} to a 3067 * series of secondary offsets from an <em>index map</em>. 3068 * The index map is a contiguous sequence of {@code VLENGTH} 3069 * elements in a second array of {@code int}s, starting at a given 3070 * {@code mapOffset}. 3071 * <p> 3072 * For each vector lane, where {@code N} is the vector lane index, 3073 * if the mask lane at index {@code N} is set then 3074 * the lane element at index {@code N} is stored into the array 3075 * element {@code a[f(N)]}, where {@code f(N)} is the 3076 * index mapping expression 3077 * {@code offset + indexMap[mapOffset + N]]}. 3078 * 3079 * @param a the array 3080 * @param offset an offset to combine with the index map offsets 3081 * @param indexMap the index map 3082 * @param mapOffset the offset into the index map 3083 * @param m the mask 3084 * @throws IndexOutOfBoundsException 3085 * if {@code mapOffset+N < 0} 3086 * or if {@code mapOffset+N >= indexMap.length}, 3087 * or if {@code f(N)=offset+indexMap[mapOffset+N]} 3088 * is an invalid index into {@code a}, 3089 * for any lane {@code N} in the vector 3090 * where the mask is set 3091 * @see IntVector#toIntArray() 3092 */ 3093 @ForceInline 3094 public final 3095 void intoArray(int[] a, int offset, 3096 int[] indexMap, int mapOffset, 3097 VectorMask<Integer> m) { 3098 if (m.allTrue()) { 3099 intoArray(a, offset, indexMap, mapOffset); 3100 } 3101 else { 3102 // FIXME: Cannot vectorize yet, if there's a mask. 3103 stOp(a, offset, m, 3104 (arr, off, i, e) -> { 3105 int j = indexMap[mapOffset + i]; 3106 arr[off + j] = e; 3107 }); 3108 } 3109 } 3110 3111 /** 3112 * {@inheritDoc} <!--workaround--> 3113 */ 3114 @Override 3115 @ForceInline 3116 public final 3117 void intoByteArray(byte[] a, int offset, 3118 ByteOrder bo) { 3119 offset = checkFromIndexSize(offset, byteSize(), a.length); 3120 maybeSwap(bo).intoByteArray0(a, offset); 3121 } 3122 3123 /** 3124 * {@inheritDoc} <!--workaround--> 3125 */ 3126 @Override 3127 @ForceInline 3128 public final 3129 void intoByteArray(byte[] a, int offset, 3130 ByteOrder bo, 3131 VectorMask<Integer> m) { 3132 if (m.allTrue()) { 3133 intoByteArray(a, offset, bo); 3134 } else { 3135 // FIXME: optimize 3136 IntSpecies vsp = vspecies(); 3137 checkMaskFromIndexSize(offset, vsp, m, 4, a.length); 3138 ByteBuffer wb = wrapper(a, bo); 3139 this.stOp(wb, offset, m, 3140 (wb_, o, i, e) -> wb_.putInt(o + i * 4, e)); 3141 } 3142 } 3143 3144 /** 3145 * {@inheritDoc} <!--workaround--> 3146 */ 3147 @Override 3148 @ForceInline 3149 public final 3150 void intoByteBuffer(ByteBuffer bb, int offset, 3151 ByteOrder bo) { 3152 if (bb.isReadOnly()) { 3153 throw new ReadOnlyBufferException(); 3154 } 3155 offset = checkFromIndexSize(offset, byteSize(), bb.limit()); 3156 maybeSwap(bo).intoByteBuffer0(bb, offset); 3157 } 3158 3159 /** 3160 * {@inheritDoc} <!--workaround--> 3161 */ 3162 @Override 3163 @ForceInline 3164 public final 3165 void intoByteBuffer(ByteBuffer bb, int offset, 3166 ByteOrder bo, 3167 VectorMask<Integer> m) { 3168 if (m.allTrue()) { 3169 intoByteBuffer(bb, offset, bo); 3170 } else { 3171 // FIXME: optimize 3172 if (bb.isReadOnly()) { 3173 throw new ReadOnlyBufferException(); 3174 } 3175 IntSpecies vsp = vspecies(); 3176 checkMaskFromIndexSize(offset, vsp, m, 4, bb.limit()); 3177 ByteBuffer wb = wrapper(bb, bo); 3178 this.stOp(wb, offset, m, 3179 (wb_, o, i, e) -> wb_.putInt(o + i * 4, e)); 3180 } 3181 } 3182 3183 // ================================================ 3184 3185 // Low-level memory operations. 3186 // 3187 // Note that all of these operations *must* inline into a context 3188 // where the exact species of the involved vector is a 3189 // compile-time constant. Otherwise, the intrinsic generation 3190 // will fail and performance will suffer. 3191 // 3192 // In many cases this is achieved by re-deriving a version of the 3193 // method in each concrete subclass (per species). The re-derived 3194 // method simply calls one of these generic methods, with exact 3195 // parameters for the controlling metadata, which is either a 3196 // typed vector or constant species instance. 3197 3198 // Unchecked loading operations in native byte order. 3199 // Caller is responsible for applying index checks, masking, and 3200 // byte swapping. 3201 3202 /*package-private*/ 3203 abstract 3204 IntVector fromArray0(int[] a, int offset); 3205 @ForceInline 3206 final 3207 IntVector fromArray0Template(int[] a, int offset) { 3208 IntSpecies vsp = vspecies(); 3209 return VectorSupport.load( 3210 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3211 a, arrayAddress(a, offset), 3212 a, offset, vsp, 3213 (arr, off, s) -> s.ldOp(arr, off, 3214 (arr_, off_, i) -> arr_[off_ + i])); 3215 } 3216 3217 @Override 3218 abstract 3219 IntVector fromByteArray0(byte[] a, int offset); 3220 @ForceInline 3221 final 3222 IntVector fromByteArray0Template(byte[] a, int offset) { 3223 IntSpecies vsp = vspecies(); 3224 return VectorSupport.load( 3225 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3226 a, byteArrayAddress(a, offset), 3227 a, offset, vsp, 3228 (arr, off, s) -> { 3229 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN); 3230 return s.ldOp(wb, off, 3231 (wb_, o, i) -> wb_.getInt(o + i * 4)); 3232 }); 3233 } 3234 3235 abstract 3236 IntVector fromByteBuffer0(ByteBuffer bb, int offset); 3237 @ForceInline 3238 final 3239 IntVector fromByteBuffer0Template(ByteBuffer bb, int offset) { 3240 IntSpecies vsp = vspecies(); 3241 return VectorSupport.load( 3242 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3243 bufferBase(bb), bufferAddress(bb, offset), 3244 bb, offset, vsp, 3245 (buf, off, s) -> { 3246 ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN); 3247 return s.ldOp(wb, off, 3248 (wb_, o, i) -> wb_.getInt(o + i * 4)); 3249 }); 3250 } 3251 3252 // Unchecked storing operations in native byte order. 3253 // Caller is responsible for applying index checks, masking, and 3254 // byte swapping. 3255 3256 abstract 3257 void intoArray0(int[] a, int offset); 3258 @ForceInline 3259 final 3260 void intoArray0Template(int[] a, int offset) { 3261 IntSpecies vsp = vspecies(); 3262 VectorSupport.store( 3263 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3264 a, arrayAddress(a, offset), 3265 this, a, offset, 3266 (arr, off, v) 3267 -> v.stOp(arr, off, 3268 (arr_, off_, i, e) -> arr_[off_+i] = e)); 3269 } 3270 3271 abstract 3272 void intoByteArray0(byte[] a, int offset); 3273 @ForceInline 3274 final 3275 void intoByteArray0Template(byte[] a, int offset) { 3276 IntSpecies vsp = vspecies(); 3277 VectorSupport.store( 3278 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3279 a, byteArrayAddress(a, offset), 3280 this, a, offset, 3281 (arr, off, v) -> { 3282 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN); 3283 v.stOp(wb, off, 3284 (tb_, o, i, e) -> tb_.putInt(o + i * 4, e)); 3285 }); 3286 } 3287 3288 @ForceInline 3289 final 3290 void intoByteBuffer0(ByteBuffer bb, int offset) { 3291 IntSpecies vsp = vspecies(); 3292 VectorSupport.store( 3293 vsp.vectorType(), vsp.elementType(), vsp.laneCount(), 3294 bufferBase(bb), bufferAddress(bb, offset), 3295 this, bb, offset, 3296 (buf, off, v) -> { 3297 ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN); 3298 v.stOp(wb, off, 3299 (wb_, o, i, e) -> wb_.putInt(o + i * 4, e)); 3300 }); 3301 } 3302 3303 // End of low-level memory operations. 3304 3305 private static 3306 void checkMaskFromIndexSize(int offset, 3307 IntSpecies vsp, 3308 VectorMask<Integer> m, 3309 int scale, 3310 int limit) { 3311 ((AbstractMask<Integer>)m) 3312 .checkIndexByLane(offset, limit, vsp.iota(), scale); 3313 } 3314 3315 @ForceInline 3316 private void conditionalStoreNYI(int offset, 3317 IntSpecies vsp, 3318 VectorMask<Integer> m, 3319 int scale, 3320 int limit) { 3321 if (offset < 0 || offset + vsp.laneCount() * scale > limit) { 3322 String msg = 3323 String.format("unimplemented: store @%d in [0..%d), %s in %s", 3324 offset, limit, m, vsp); 3325 throw new AssertionError(msg); 3326 } 3327 } 3328 3329 /*package-private*/ 3330 @Override 3331 @ForceInline 3332 final 3333 IntVector maybeSwap(ByteOrder bo) { 3334 if (bo != NATIVE_ENDIAN) { 3335 return this.reinterpretAsBytes() 3336 .rearrange(swapBytesShuffle()) 3337 .reinterpretAsInts(); 3338 } 3339 return this; 3340 } 3341 3342 static final int ARRAY_SHIFT = 3343 31 - Integer.numberOfLeadingZeros(Unsafe.ARRAY_INT_INDEX_SCALE); 3344 static final long ARRAY_BASE = 3345 Unsafe.ARRAY_INT_BASE_OFFSET; 3346 3347 @ForceInline 3348 static long arrayAddress(int[] a, int index) { 3349 return ARRAY_BASE + (((long)index) << ARRAY_SHIFT); 3350 } 3351 3352 @ForceInline 3353 static long byteArrayAddress(byte[] a, int index) { 3354 return Unsafe.ARRAY_BYTE_BASE_OFFSET + index; 3355 } 3356 3357 // ================================================ 3358 3359 /// Reinterpreting view methods: 3360 // lanewise reinterpret: viewAsXVector() 3361 // keep shape, redraw lanes: reinterpretAsEs() 3362 3363 /** 3364 * {@inheritDoc} <!--workaround--> 3365 */ 3366 @ForceInline 3367 @Override 3368 public final ByteVector reinterpretAsBytes() { 3369 // Going to ByteVector, pay close attention to byte order. 3370 assert(REGISTER_ENDIAN == ByteOrder.LITTLE_ENDIAN); 3371 return asByteVectorRaw(); 3372 //return asByteVectorRaw().rearrange(swapBytesShuffle()); 3373 } 3374 3375 /** 3376 * {@inheritDoc} <!--workaround--> 3377 */ 3378 @ForceInline 3379 @Override 3380 public final IntVector viewAsIntegralLanes() { 3381 return this; 3382 } 3383 3384 /** 3385 * {@inheritDoc} <!--workaround--> 3386 */ 3387 @ForceInline 3388 @Override 3389 public final 3390 FloatVector 3391 viewAsFloatingLanes() { 3392 LaneType flt = LaneType.INT.asFloating(); 3393 return (FloatVector) asVectorRaw(flt); 3394 } 3395 3396 // ================================================ 3397 3398 /// Object methods: toString, equals, hashCode 3399 // 3400 // Object methods are defined as if via Arrays.toString, etc., 3401 // is applied to the array of elements. Two equal vectors 3402 // are required to have equal species and equal lane values. 3403 3404 /** 3405 * Returns a string representation of this vector, of the form 3406 * {@code "[0,1,2...]"}, reporting the lane values of this vector, 3407 * in lane order. 3408 * 3409 * The string is produced as if by a call to {@link 3410 * java.util.Arrays#toString(int[]) Arrays.toString()}, 3411 * as appropriate to the {@code int} array returned by 3412 * {@link #toArray this.toArray()}. 3413 * 3414 * @return a string of the form {@code "[0,1,2...]"} 3415 * reporting the lane values of this vector 3416 */ 3417 @Override 3418 @ForceInline 3419 public final 3420 String toString() { 3421 // now that toArray is strongly typed, we can define this 3422 return Arrays.toString(toArray()); 3423 } 3424 3425 /** 3426 * {@inheritDoc} <!--workaround--> 3427 */ 3428 @Override 3429 @ForceInline 3430 public final 3431 boolean equals(Object obj) { 3432 if (obj instanceof Vector) { 3433 Vector<?> that = (Vector<?>) obj; 3434 if (this.species().equals(that.species())) { 3435 return this.eq(that.check(this.species())).allTrue(); 3436 } 3437 } 3438 return false; 3439 } 3440 3441 /** 3442 * {@inheritDoc} <!--workaround--> 3443 */ 3444 @Override 3445 @ForceInline 3446 public final 3447 int hashCode() { 3448 // now that toArray is strongly typed, we can define this 3449 return Objects.hash(species(), Arrays.hashCode(toArray())); 3450 } 3451 3452 // ================================================ 3453 3454 // Species 3455 3456 /** 3457 * Class representing {@link IntVector}'s of the same {@link VectorShape VectorShape}. 3458 */ 3459 /*package-private*/ 3460 static final class IntSpecies extends AbstractSpecies<Integer> { 3461 private IntSpecies(VectorShape shape, 3462 Class<? extends IntVector> vectorType, 3463 Class<? extends AbstractMask<Integer>> maskType, 3464 Function<Object, IntVector> vectorFactory) { 3465 super(shape, LaneType.of(int.class), 3466 vectorType, maskType, 3467 vectorFactory); 3468 assert(this.elementSize() == Integer.SIZE); 3469 } 3470 3471 // Specializing overrides: 3472 3473 @Override 3474 @ForceInline 3475 public final Class<Integer> elementType() { 3476 return int.class; 3477 } 3478 3479 @Override 3480 @ForceInline 3481 final Class<Integer> genericElementType() { 3482 return Integer.class; 3483 } 3484 3485 @SuppressWarnings("unchecked") 3486 @Override 3487 @ForceInline 3488 public final Class<? extends IntVector> vectorType() { 3489 return (Class<? extends IntVector>) vectorType; 3490 } 3491 3492 @Override 3493 @ForceInline 3494 public final long checkValue(long e) { 3495 longToElementBits(e); // only for exception 3496 return e; 3497 } 3498 3499 /*package-private*/ 3500 @Override 3501 @ForceInline 3502 final IntVector broadcastBits(long bits) { 3503 return (IntVector) 3504 VectorSupport.broadcastCoerced( 3505 vectorType, int.class, laneCount, 3506 bits, this, 3507 (bits_, s_) -> s_.rvOp(i -> bits_)); 3508 } 3509 3510 /*package-private*/ 3511 @ForceInline 3512 final IntVector broadcast(int e) { 3513 return broadcastBits(toBits(e)); 3514 } 3515 3516 @Override 3517 @ForceInline 3518 public final IntVector broadcast(long e) { 3519 return broadcastBits(longToElementBits(e)); 3520 } 3521 3522 /*package-private*/ 3523 final @Override 3524 @ForceInline 3525 long longToElementBits(long value) { 3526 // Do the conversion, and then test it for failure. 3527 int e = (int) value; 3528 if ((long) e != value) { 3529 throw badElementBits(value, e); 3530 } 3531 return toBits(e); 3532 } 3533 3534 /*package-private*/ 3535 @ForceInline 3536 static long toIntegralChecked(int e, boolean convertToInt) { 3537 long value = convertToInt ? (int) e : (long) e; 3538 if ((int) value != e) { 3539 throw badArrayBits(e, convertToInt, value); 3540 } 3541 return value; 3542 } 3543 3544 /* this non-public one is for internal conversions */ 3545 @Override 3546 @ForceInline 3547 final IntVector fromIntValues(int[] values) { 3548 VectorIntrinsics.requireLength(values.length, laneCount); 3549 int[] va = new int[laneCount()]; 3550 for (int i = 0; i < va.length; i++) { 3551 int lv = values[i]; 3552 int v = (int) lv; 3553 va[i] = v; 3554 if ((int)v != lv) { 3555 throw badElementBits(lv, v); 3556 } 3557 } 3558 return dummyVector().fromArray0(va, 0); 3559 } 3560 3561 // Virtual constructors 3562 3563 @ForceInline 3564 @Override final 3565 public IntVector fromArray(Object a, int offset) { 3566 // User entry point: Be careful with inputs. 3567 return IntVector 3568 .fromArray(this, (int[]) a, offset); 3569 } 3570 3571 @ForceInline 3572 @Override final 3573 IntVector dummyVector() { 3574 return (IntVector) super.dummyVector(); 3575 } 3576 3577 /*package-private*/ 3578 final @Override 3579 @ForceInline 3580 IntVector rvOp(RVOp f) { 3581 int[] res = new int[laneCount()]; 3582 for (int i = 0; i < res.length; i++) { 3583 int bits = (int) f.apply(i); 3584 res[i] = fromBits(bits); 3585 } 3586 return dummyVector().vectorFactory(res); 3587 } 3588 3589 IntVector vOp(FVOp f) { 3590 int[] res = new int[laneCount()]; 3591 for (int i = 0; i < res.length; i++) { 3592 res[i] = f.apply(i); 3593 } 3594 return dummyVector().vectorFactory(res); 3595 } 3596 3597 IntVector vOp(VectorMask<Integer> m, FVOp f) { 3598 int[] res = new int[laneCount()]; 3599 boolean[] mbits = ((AbstractMask<Integer>)m).getBits(); 3600 for (int i = 0; i < res.length; i++) { 3601 if (mbits[i]) { 3602 res[i] = f.apply(i); 3603 } 3604 } 3605 return dummyVector().vectorFactory(res); 3606 } 3607 3608 /*package-private*/ 3609 @ForceInline 3610 <M> IntVector ldOp(M memory, int offset, 3611 FLdOp<M> f) { 3612 return dummyVector().ldOp(memory, offset, f); 3613 } 3614 3615 /*package-private*/ 3616 @ForceInline 3617 <M> IntVector ldOp(M memory, int offset, 3618 AbstractMask<Integer> m, 3619 FLdOp<M> f) { 3620 return dummyVector().ldOp(memory, offset, m, f); 3621 } 3622 3623 /*package-private*/ 3624 @ForceInline 3625 <M> void stOp(M memory, int offset, FStOp<M> f) { 3626 dummyVector().stOp(memory, offset, f); 3627 } 3628 3629 /*package-private*/ 3630 @ForceInline 3631 <M> void stOp(M memory, int offset, 3632 AbstractMask<Integer> m, 3633 FStOp<M> f) { 3634 dummyVector().stOp(memory, offset, m, f); 3635 } 3636 3637 // N.B. Make sure these constant vectors and 3638 // masks load up correctly into registers. 3639 // 3640 // Also, see if we can avoid all that switching. 3641 // Could we cache both vectors and both masks in 3642 // this species object? 3643 3644 // Zero and iota vector access 3645 @Override 3646 @ForceInline 3647 public final IntVector zero() { 3648 if ((Class<?>) vectorType() == IntMaxVector.class) 3649 return IntMaxVector.ZERO; 3650 switch (vectorBitSize()) { 3651 case 64: return Int64Vector.ZERO; 3652 case 128: return Int128Vector.ZERO; 3653 case 256: return Int256Vector.ZERO; 3654 case 512: return Int512Vector.ZERO; 3655 } 3656 throw new AssertionError(); 3657 } 3658 3659 @Override 3660 @ForceInline 3661 public final IntVector iota() { 3662 if ((Class<?>) vectorType() == IntMaxVector.class) 3663 return IntMaxVector.IOTA; 3664 switch (vectorBitSize()) { 3665 case 64: return Int64Vector.IOTA; 3666 case 128: return Int128Vector.IOTA; 3667 case 256: return Int256Vector.IOTA; 3668 case 512: return Int512Vector.IOTA; 3669 } 3670 throw new AssertionError(); 3671 } 3672 3673 // Mask access 3674 @Override 3675 @ForceInline 3676 public final VectorMask<Integer> maskAll(boolean bit) { 3677 if ((Class<?>) vectorType() == IntMaxVector.class) 3678 return IntMaxVector.IntMaxMask.maskAll(bit); 3679 switch (vectorBitSize()) { 3680 case 64: return Int64Vector.Int64Mask.maskAll(bit); 3681 case 128: return Int128Vector.Int128Mask.maskAll(bit); 3682 case 256: return Int256Vector.Int256Mask.maskAll(bit); 3683 case 512: return Int512Vector.Int512Mask.maskAll(bit); 3684 } 3685 throw new AssertionError(); 3686 } 3687 } 3688 3689 /** 3690 * Finds a species for an element type of {@code int} and shape. 3691 * 3692 * @param s the shape 3693 * @return a species for an element type of {@code int} and shape 3694 * @throws IllegalArgumentException if no such species exists for the shape 3695 */ 3696 static IntSpecies species(VectorShape s) { 3697 Objects.requireNonNull(s); 3698 switch (s) { 3699 case S_64_BIT: return (IntSpecies) SPECIES_64; 3700 case S_128_BIT: return (IntSpecies) SPECIES_128; 3701 case S_256_BIT: return (IntSpecies) SPECIES_256; 3702 case S_512_BIT: return (IntSpecies) SPECIES_512; 3703 case S_Max_BIT: return (IntSpecies) SPECIES_MAX; 3704 default: throw new IllegalArgumentException("Bad shape: " + s); 3705 } 3706 } 3707 3708 /** Species representing {@link IntVector}s of {@link VectorShape#S_64_BIT VectorShape.S_64_BIT}. */ 3709 public static final VectorSpecies<Integer> SPECIES_64 3710 = new IntSpecies(VectorShape.S_64_BIT, 3711 Int64Vector.class, 3712 Int64Vector.Int64Mask.class, 3713 Int64Vector::new); 3714 3715 /** Species representing {@link IntVector}s of {@link VectorShape#S_128_BIT VectorShape.S_128_BIT}. */ 3716 public static final VectorSpecies<Integer> SPECIES_128 3717 = new IntSpecies(VectorShape.S_128_BIT, 3718 Int128Vector.class, 3719 Int128Vector.Int128Mask.class, 3720 Int128Vector::new); 3721 3722 /** Species representing {@link IntVector}s of {@link VectorShape#S_256_BIT VectorShape.S_256_BIT}. */ 3723 public static final VectorSpecies<Integer> SPECIES_256 3724 = new IntSpecies(VectorShape.S_256_BIT, 3725 Int256Vector.class, 3726 Int256Vector.Int256Mask.class, 3727 Int256Vector::new); 3728 3729 /** Species representing {@link IntVector}s of {@link VectorShape#S_512_BIT VectorShape.S_512_BIT}. */ 3730 public static final VectorSpecies<Integer> SPECIES_512 3731 = new IntSpecies(VectorShape.S_512_BIT, 3732 Int512Vector.class, 3733 Int512Vector.Int512Mask.class, 3734 Int512Vector::new); 3735 3736 /** Species representing {@link IntVector}s of {@link VectorShape#S_Max_BIT VectorShape.S_Max_BIT}. */ 3737 public static final VectorSpecies<Integer> SPECIES_MAX 3738 = new IntSpecies(VectorShape.S_Max_BIT, 3739 IntMaxVector.class, 3740 IntMaxVector.IntMaxMask.class, 3741 IntMaxVector::new); 3742 3743 /** 3744 * Preferred species for {@link IntVector}s. 3745 * A preferred species is a species of maximal bit-size for the platform. 3746 */ 3747 public static final VectorSpecies<Integer> SPECIES_PREFERRED 3748 = (IntSpecies) VectorSpecies.ofPreferred(int.class); 3749 } 3750