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