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