1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have 23 * questions. 24 */ 25 package jdk.incubator.vector; 26 27 import jdk.internal.vm.annotation.ForceInline; 28 29 import java.nio.ByteBuffer; 30 import java.nio.ByteOrder; 31 import java.nio.DoubleBuffer; 32 import java.util.Objects; 33 import java.util.concurrent.ThreadLocalRandom; 34 35 36 /** 37 * A specialized {@link Vector} representing an ordered immutable sequence of 38 * {@code double} values. 39 * 40 * @param <S> the type of shape of this vector 41 */ 42 @SuppressWarnings("cast") 43 public abstract class DoubleVector<S extends Vector.Shape> extends Vector<Double,S> { 44 45 DoubleVector() {} 46 47 // Unary operator 48 49 interface FUnOp { 50 double apply(int i, double a); 51 } 52 53 abstract DoubleVector<S> uOp(FUnOp f); 54 55 abstract DoubleVector<S> uOp(Mask<Double, S> m, FUnOp f); 56 57 // Binary operator 58 59 interface FBinOp { 60 double apply(int i, double a, double b); 61 } 62 63 abstract DoubleVector<S> bOp(Vector<Double,S> o, FBinOp f); 64 65 abstract DoubleVector<S> bOp(Vector<Double,S> o, Mask<Double, S> m, FBinOp f); 66 67 // Trinary operator 68 69 interface FTriOp { 70 double apply(int i, double a, double b, double c); 71 } 72 73 abstract DoubleVector<S> tOp(Vector<Double,S> o1, Vector<Double,S> o2, FTriOp f); 74 75 abstract DoubleVector<S> tOp(Vector<Double,S> o1, Vector<Double,S> o2, Mask<Double, S> m, FTriOp f); 76 77 // Reduction operator 78 79 abstract double rOp(double v, FBinOp f); 80 81 // Binary test 82 83 interface FBinTest { 84 boolean apply(int i, double a, double b); 85 } 86 87 abstract Mask<Double, S> bTest(Vector<Double,S> o, FBinTest f); 88 89 // Foreach 90 91 interface FUnCon { 92 void apply(int i, double a); 93 } 94 95 abstract void forEach(FUnCon f); 96 97 abstract void forEach(Mask<Double, S> m, FUnCon f); 98 99 // 100 101 @Override 102 public DoubleVector<S> add(Vector<Double,S> o) { 103 return bOp(o, (i, a, b) -> (double) (a + b)); 104 } 105 106 /** 107 * Adds this vector to the result of broadcasting an input scalar. 108 * <p> 109 * This is a vector binary operation where the primitive addition operation 110 * ({@code +}) is applied to lane elements. 111 * 112 * @param b the input scalar 113 * @return the result of adding this vector to the broadcast of an input 114 * scalar 115 */ 116 public abstract DoubleVector<S> add(double b); 117 118 @Override 119 public DoubleVector<S> add(Vector<Double,S> o, Mask<Double, S> m) { 120 return bOp(o, m, (i, a, b) -> (double) (a + b)); 121 } 122 123 /** 124 * Adds this vector to the result of broadcasting an input scalar, 125 * selecting lane elements controlled by a mask. 126 * <p> 127 * This is a vector binary operation where the primitive addition operation 128 * ({@code +}) is applied to lane elements. 129 * 130 * @param b the input vector 131 * @param m the mask controlling lane selection 132 * @return the result of adding this vector to the broadcast of an input 133 * scalar 134 */ 135 public abstract DoubleVector<S> add(double b, Mask<Double, S> m); 136 137 @Override 138 public DoubleVector<S> addSaturate(Vector<Double,S> o) { 139 return bOp(o, (i, a, b) -> (double) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b)); 140 } 141 142 public abstract DoubleVector<S> addSaturate(double o); 143 144 @Override 145 public DoubleVector<S> addSaturate(Vector<Double,S> o, Mask<Double, S> m) { 146 return bOp(o, m, (i, a, b) -> (double) ((a >= Integer.MAX_VALUE || Integer.MAX_VALUE - b > a) ? Integer.MAX_VALUE : a + b)); 147 } 148 149 public abstract DoubleVector<S> addSaturate(double o, Mask<Double, S> m); 150 151 @Override 152 public DoubleVector<S> sub(Vector<Double,S> o) { 153 return bOp(o, (i, a, b) -> (double) (a - b)); 154 } 155 156 public abstract DoubleVector<S> sub(double o); 157 158 @Override 159 public DoubleVector<S> sub(Vector<Double,S> o, Mask<Double, S> m) { 160 return bOp(o, m, (i, a, b) -> (double) (a - b)); 161 } 162 163 public abstract DoubleVector<S> sub(double o, Mask<Double, S> m); 164 165 @Override 166 public DoubleVector<S> subSaturate(Vector<Double,S> o) { 167 return bOp(o, (i, a, b) -> (double) ((a >= Double.MIN_VALUE || Double.MIN_VALUE + b > a) ? Double.MAX_VALUE : a - b)); 168 } 169 170 public abstract DoubleVector<S> subSaturate(double o); 171 172 @Override 173 public DoubleVector<S> subSaturate(Vector<Double,S> o, Mask<Double, S> m) { 174 return bOp(o, m, (i, a, b) -> (double) ((a >= Double.MIN_VALUE || Double.MIN_VALUE + b > a) ? Double.MAX_VALUE : a - b)); 175 } 176 177 public abstract DoubleVector<S> subSaturate(double o, Mask<Double, S> m); 178 179 @Override 180 public DoubleVector<S> mul(Vector<Double,S> o) { 181 return bOp(o, (i, a, b) -> (double) (a * b)); 182 } 183 184 public abstract DoubleVector<S> mul(double o); 185 186 @Override 187 public DoubleVector<S> mul(Vector<Double,S> o, Mask<Double, S> m) { 188 return bOp(o, m, (i, a, b) -> (double) (a * b)); 189 } 190 191 public abstract DoubleVector<S> mul(double o, Mask<Double, S> m); 192 193 @Override 194 public DoubleVector<S> neg() { 195 return uOp((i, a) -> (double) (-a)); 196 } 197 198 @Override 199 public DoubleVector<S> neg(Mask<Double, S> m) { 200 return uOp(m, (i, a) -> (double) (-a)); 201 } 202 203 @Override 204 public DoubleVector<S> abs() { 205 return uOp((i, a) -> (double) Math.abs(a)); 206 } 207 208 @Override 209 public DoubleVector<S> abs(Mask<Double, S> m) { 210 return uOp(m, (i, a) -> (double) Math.abs(a)); 211 } 212 213 @Override 214 public DoubleVector<S> min(Vector<Double,S> o) { 215 return bOp(o, (i, a, b) -> (a <= b) ? a : b); 216 } 217 218 public abstract DoubleVector<S> min(double o); 219 220 @Override 221 public DoubleVector<S> max(Vector<Double,S> o) { 222 return bOp(o, (i, a, b) -> (a >= b) ? a : b); 223 } 224 225 public abstract DoubleVector<S> max(double o); 226 227 @Override 228 public Mask<Double, S> equal(Vector<Double,S> o) { 229 return bTest(o, (i, a, b) -> a == b); 230 } 231 232 public abstract Mask<Double, S> equal(double o); 233 234 @Override 235 public Mask<Double, S> notEqual(Vector<Double,S> o) { 236 return bTest(o, (i, a, b) -> a != b); 237 } 238 239 public abstract Mask<Double, S> notEqual(double o); 240 241 @Override 242 public Mask<Double, S> lessThan(Vector<Double,S> o) { 243 return bTest(o, (i, a, b) -> a < b); 244 } 245 246 public abstract Mask<Double, S> lessThan(double o); 247 248 @Override 249 public Mask<Double, S> lessThanEq(Vector<Double,S> o) { 250 return bTest(o, (i, a, b) -> a <= b); 251 } 252 253 public abstract Mask<Double, S> lessThanEq(double o); 254 255 @Override 256 public Mask<Double, S> greaterThan(Vector<Double,S> o) { 257 return bTest(o, (i, a, b) -> a > b); 258 } 259 260 public abstract Mask<Double, S> greaterThan(double o); 261 262 @Override 263 public Mask<Double, S> greaterThanEq(Vector<Double,S> o) { 264 return bTest(o, (i, a, b) -> a >= b); 265 } 266 267 public abstract Mask<Double, S> greaterThanEq(double o); 268 269 @Override 270 public DoubleVector<S> blend(Vector<Double,S> o, Mask<Double, S> m) { 271 return bOp(o, (i, a, b) -> m.getElement(i) ? b : a); 272 } 273 274 public abstract DoubleVector<S> blend(double o, Mask<Double, S> m); 275 276 @Override 277 public abstract DoubleVector<S> shuffle(Vector<Double,S> o, Shuffle<Double, S> m); 278 279 @Override 280 public abstract DoubleVector<S> swizzle(Shuffle<Double, S> m); 281 282 @Override 283 @ForceInline 284 public <T extends Shape> DoubleVector<T> resize(Species<Double, T> species) { 285 return (DoubleVector<T>) species.reshape(this); 286 } 287 288 @Override 289 public abstract DoubleVector<S> rotateEL(int i); 290 291 @Override 292 public abstract DoubleVector<S> rotateER(int i); 293 294 @Override 295 public abstract DoubleVector<S> shiftEL(int i); 296 297 @Override 298 public abstract DoubleVector<S> shiftER(int i); 299 300 public DoubleVector<S> div(Vector<Double,S> o) { 301 return bOp(o, (i, a, b) -> (double) (a / b)); 302 } 303 304 public abstract DoubleVector<S> div(double o); 305 306 public DoubleVector<S> div(Vector<Double,S> o, Mask<Double, S> m) { 307 return bOp(o, m, (i, a, b) -> (double) (a / b)); 308 } 309 310 public abstract DoubleVector<S> div(double o, Mask<Double, S> m); 311 312 public DoubleVector<S> sqrt() { 313 return uOp((i, a) -> (double) Math.sqrt((double) a)); 314 } 315 316 public DoubleVector<S> sqrt(Mask<Double,S> m) { 317 return uOp(m, (i, a) -> (double) Math.sqrt((double) a)); 318 } 319 320 public DoubleVector<S> tan() { 321 return uOp((i, a) -> (double) Math.tan((double) a)); 322 } 323 324 public DoubleVector<S> tan(Mask<Double,S> m) { 325 return uOp(m, (i, a) -> (double) Math.tan((double) a)); 326 } 327 328 public DoubleVector<S> tanh() { 329 return uOp((i, a) -> (double) Math.tanh((double) a)); 330 } 331 332 public DoubleVector<S> tanh(Mask<Double,S> m) { 333 return uOp(m, (i, a) -> (double) Math.tanh((double) a)); 334 } 335 336 public DoubleVector<S> sin() { 337 return uOp((i, a) -> (double) Math.sin((double) a)); 338 } 339 340 public DoubleVector<S> sin(Mask<Double,S> m) { 341 return uOp(m, (i, a) -> (double) Math.sin((double) a)); 342 } 343 344 public DoubleVector<S> sinh() { 345 return uOp((i, a) -> (double) Math.sinh((double) a)); 346 } 347 348 public DoubleVector<S> sinh(Mask<Double,S> m) { 349 return uOp(m, (i, a) -> (double) Math.sinh((double) a)); 350 } 351 352 public DoubleVector<S> cos() { 353 return uOp((i, a) -> (double) Math.cos((double) a)); 354 } 355 356 public DoubleVector<S> cos(Mask<Double,S> m) { 357 return uOp(m, (i, a) -> (double) Math.cos((double) a)); 358 } 359 360 public DoubleVector<S> cosh() { 361 return uOp((i, a) -> (double) Math.cosh((double) a)); 362 } 363 364 public DoubleVector<S> cosh(Mask<Double,S> m) { 365 return uOp(m, (i, a) -> (double) Math.cosh((double) a)); 366 } 367 368 public DoubleVector<S> asin() { 369 return uOp((i, a) -> (double) Math.asin((double) a)); 370 } 371 372 public DoubleVector<S> asin(Mask<Double,S> m) { 373 return uOp(m, (i, a) -> (double) Math.asin((double) a)); 374 } 375 376 public DoubleVector<S> acos() { 377 return uOp((i, a) -> (double) Math.acos((double) a)); 378 } 379 380 public DoubleVector<S> acos(Mask<Double,S> m) { 381 return uOp(m, (i, a) -> (double) Math.acos((double) a)); 382 } 383 384 public DoubleVector<S> atan() { 385 return uOp((i, a) -> (double) Math.atan((double) a)); 386 } 387 388 public DoubleVector<S> atan(Mask<Double,S> m) { 389 return uOp(m, (i, a) -> (double) Math.atan((double) a)); 390 } 391 392 public DoubleVector<S> atan2(Vector<Double,S> o) { 393 return bOp(o, (i, a, b) -> (double) Math.atan2((double) a, (double) b)); 394 } 395 396 public abstract DoubleVector<S> atan2(double o); 397 398 public DoubleVector<S> atan2(Vector<Double,S> o, Mask<Double,S> m) { 399 return bOp(o, m, (i, a, b) -> (double) Math.atan2((double) a, (double) b)); 400 } 401 402 public abstract DoubleVector<S> atan2(double o, Mask<Double,S> m); 403 404 public DoubleVector<S> cbrt() { 405 return uOp((i, a) -> (double) Math.cbrt((double) a)); 406 } 407 408 public DoubleVector<S> cbrt(Mask<Double,S> m) { 409 return uOp(m, (i, a) -> (double) Math.cbrt((double) a)); 410 } 411 412 public DoubleVector<S> log() { 413 return uOp((i, a) -> (double) Math.log((double) a)); 414 } 415 416 public DoubleVector<S> log(Mask<Double,S> m) { 417 return uOp(m, (i, a) -> (double) Math.log((double) a)); 418 } 419 420 public DoubleVector<S> log10() { 421 return uOp((i, a) -> (double) Math.log10((double) a)); 422 } 423 424 public DoubleVector<S> log10(Mask<Double,S> m) { 425 return uOp(m, (i, a) -> (double) Math.log10((double) a)); 426 } 427 428 public DoubleVector<S> log1p() { 429 return uOp((i, a) -> (double) Math.log1p((double) a)); 430 } 431 432 public DoubleVector<S> log1p(Mask<Double,S> m) { 433 return uOp(m, (i, a) -> (double) Math.log1p((double) a)); 434 } 435 436 public DoubleVector<S> pow(Vector<Double,S> o) { 437 return bOp(o, (i, a, b) -> (double) Math.pow((double) a, (double) b)); 438 } 439 440 public abstract DoubleVector<S> pow(double o); 441 442 public DoubleVector<S> pow(Vector<Double,S> o, Mask<Double,S> m) { 443 return bOp(o, m, (i, a, b) -> (double) Math.pow((double) a, (double) b)); 444 } 445 446 public abstract DoubleVector<S> pow(double o, Mask<Double,S> m); 447 448 public DoubleVector<S> exp() { 449 return uOp((i, a) -> (double) Math.exp((double) a)); 450 } 451 452 public DoubleVector<S> exp(Mask<Double,S> m) { 453 return uOp(m, (i, a) -> (double) Math.exp((double) a)); 454 } 455 456 public DoubleVector<S> expm1() { 457 return uOp((i, a) -> (double) Math.expm1((double) a)); 458 } 459 460 public DoubleVector<S> expm1(Mask<Double,S> m) { 461 return uOp(m, (i, a) -> (double) Math.expm1((double) a)); 462 } 463 464 public DoubleVector<S> fma(Vector<Double,S> o1, Vector<Double,S> o2) { 465 return tOp(o1, o2, (i, a, b, c) -> Math.fma(a, b, c)); 466 } 467 468 public abstract DoubleVector<S> fma(double o1, double o2); 469 470 public DoubleVector<S> fma(Vector<Double,S> o1, Vector<Double,S> o2, Mask<Double,S> m) { 471 return tOp(o1, o2, m, (i, a, b, c) -> Math.fma(a, b, c)); 472 } 473 474 public abstract DoubleVector<S> fma(double o1, double o2, Mask<Double,S> m); 475 476 public DoubleVector<S> hypot(Vector<Double,S> o) { 477 return bOp(o, (i, a, b) -> (double) Math.hypot((double) a, (double) b)); 478 } 479 480 public abstract DoubleVector<S> hypot(double o); 481 482 public DoubleVector<S> hypot(Vector<Double,S> o, Mask<Double,S> m) { 483 return bOp(o, m, (i, a, b) -> (double) Math.hypot((double) a, (double) b)); 484 } 485 486 public abstract DoubleVector<S> hypot(double o, Mask<Double,S> m); 487 488 489 @Override 490 public void intoByteArray(byte[] a, int ix) { 491 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder()); 492 intoByteBuffer(bb); 493 } 494 495 @Override 496 public void intoByteArray(byte[] a, int ix, Mask<Double, S> m) { 497 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder()); 498 intoByteBuffer(bb, m); 499 } 500 501 @Override 502 public void intoByteBuffer(ByteBuffer bb) { 503 DoubleBuffer fb = bb.asDoubleBuffer(); 504 forEach((i, a) -> fb.put(a)); 505 } 506 507 @Override 508 public void intoByteBuffer(ByteBuffer bb, Mask<Double, S> m) { 509 DoubleBuffer fb = bb.asDoubleBuffer(); 510 forEach((i, a) -> { 511 if (m.getElement(i)) 512 fb.put(a); 513 else 514 fb.position(fb.position() + 1); 515 }); 516 } 517 518 @Override 519 public void intoByteBuffer(ByteBuffer bb, int ix) { 520 bb = bb.duplicate().position(ix); 521 DoubleBuffer fb = bb.asDoubleBuffer(); 522 forEach((i, a) -> fb.put(i, a)); 523 } 524 525 @Override 526 public void intoByteBuffer(ByteBuffer bb, int ix, Mask<Double, S> m) { 527 bb = bb.duplicate().position(ix); 528 DoubleBuffer fb = bb.asDoubleBuffer(); 529 forEach(m, (i, a) -> fb.put(i, a)); 530 } 531 532 533 // Type specific horizontal reductions 534 535 public double addAll() { 536 return rOp((double) 0, (i, a, b) -> (double) (a + b)); 537 } 538 539 public double subAll() { 540 return rOp((double) 0, (i, a, b) -> (double) (a - b)); 541 } 542 543 public double mulAll() { 544 return rOp((double) 1, (i, a, b) -> (double) (a * b)); 545 } 546 547 public double minAll() { 548 return rOp(Double.MAX_VALUE, (i, a, b) -> a > b ? b : a); 549 } 550 551 public double maxAll() { 552 return rOp(Double.MIN_VALUE, (i, a, b) -> a < b ? b : a); 553 } 554 555 556 // Type specific accessors 557 558 /** 559 * Gets the lane element at lane index {@code i} 560 * 561 * @param i the lane index 562 * @return the lane element at lane index {@code i} 563 */ 564 public abstract double get(int i); 565 566 /** 567 * Replaces the lane element of this vector at lane index {@code i} with 568 * value {@code e}. 569 * <p> 570 * This is a cross-lane operation and behaves it returns the result of 571 * blending this vector with an input vector that is the result of 572 * broadcasting {@code e} and a mask that has only one lane set at lane 573 * index {@code i}. 574 * 575 * @param i the lane index of the lane element to be replaced 576 * @param e the value to be placed 577 * @return the result of replacing the lane element of this vector at lane 578 * index {@code i} with value {@code e}. 579 */ 580 public abstract DoubleVector<S> with(int i, double e); 581 582 // Type specific extractors 583 584 /** 585 * Returns an array containing the lane elements of this vector. 586 * <p> 587 * This method behaves as if it {@link #intoArray(double[], int)} stores} 588 * this vector into an allocated array and returns the array as follows: 589 * <pre>{@code 590 * double[] a = new double[this.length()]; 591 * this.intoArray(a, 0); 592 * return a; 593 * }</pre> 594 * 595 * @return an array containing the the lane elements of this vector 596 */ 597 @ForceInline 598 public double[] toArray() { 599 double[] a = new double[species().length()]; 600 intoArray(a, 0); 601 return a; 602 } 603 604 /** 605 * Stores this vector into an array starting at offset. 606 * <p> 607 * For each vector lane, where {@code N} is the vector lane index, 608 * the lane element at index {@code N} is stored into the array at index 609 * {@code i + N}. 610 * 611 * @param a the array 612 * @param i the offset into the array 613 * @throws IndexOutOfBoundsException if {@code i < 0}, or 614 * {@code i > a.length - this.length()} 615 */ 616 public void intoArray(double[] a, int i) { 617 forEach((n, e) -> a[i + n] = e); 618 } 619 620 /** 621 * Stores this vector into an array starting at offset and using a mask. 622 * <p> 623 * For each vector lane, where {@code N} is the vector lane index, 624 * if the mask lane at index {@code N} is set then the lane element at 625 * index {@code N} is stored into the array index {@code i + N}. 626 * 627 * @param a the array 628 * @param i the offset into the array 629 * @param m the mask 630 * @throws IndexOutOfBoundsException if {@code i < 0}, or 631 * for any vector lane index {@code N} where the mask at lane {@code N} 632 * is set {@code i >= a.length - N} 633 */ 634 public void intoArray(double[] a, int i, Mask<Double, S> m) { 635 forEach(m, (n, e) -> a[i + n] = e); 636 } 637 638 /** 639 * Stores this vector into an array using indexes obtained from an index 640 * map. 641 * <p> 642 * For each vector lane, where {@code N} is the vector lane index, the 643 * lane element at index {@code N} is stored into the array at index 644 * {@code i + indexMap[j + N]}. 645 * 646 * @param a the array 647 * @param i the offset into the array, may be negative if relative 648 * indexes in the index map compensate to produce a value within the 649 * array bounds 650 * @param indexMap the index map 651 * @param j the offset into the index map 652 * @throws IndexOutOfBoundsException if {@code j < 0}, or 653 * {@code j > indexMap.length - this.length()}, 654 * or for any vector lane index {@code N} the result of 655 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 656 */ 657 public void intoArray(double[] a, int i, int[] indexMap, int j) { 658 forEach((n, e) -> a[i + indexMap[j + n]] = e); 659 } 660 661 /** 662 * Stores this vector into an array using indexes obtained from an index 663 * map and using a mask. 664 * <p> 665 * For each vector lane, where {@code N} is the vector lane index, 666 * if the mask lane at index {@code N} is set then the lane element at 667 * index {@code N} is stored into the array at index 668 * {@code i + indexMap[j + N]}. 669 * 670 * @param a the array 671 * @param i the offset into the array, may be negative if relative 672 * indexes in the index map compensate to produce a value within the 673 * array bounds 674 * @param m the mask 675 * @param indexMap the index map 676 * @param j the offset into the index map 677 * @throws IndexOutOfBoundsException if {@code j < 0}, or 678 * {@code j > indexMap.length - this.length()}, 679 * or for any vector lane index {@code N} where the mask at lane 680 * {@code N} is set the result of {@code i + indexMap[j + N]} is 681 * {@code < 0} or {@code >= a.length} 682 */ 683 public void intoArray(double[] a, int i, Mask<Double, S> m, int[] indexMap, int j) { 684 forEach(m, (n, e) -> a[i + indexMap[j + n]] = e); 685 } 686 687 // Species 688 689 @Override 690 public abstract DoubleSpecies<S> species(); 691 692 /** 693 * A specialized factory for creating {@link DoubleVector} value of the same 694 * shape, and a {@link Mask} and {@link Shuffle} values of the same shape 695 * and {@code int} element type. 696 * 697 * @param <S> the type of shape of this species 698 */ 699 public static abstract class DoubleSpecies<S extends Vector.Shape> extends Vector.Species<Double, S> { 700 interface FOp { 701 double apply(int i); 702 } 703 704 abstract DoubleVector<S> op(FOp f); 705 706 abstract DoubleVector<S> op(Mask<Double, S> m, FOp f); 707 708 // Factories 709 710 @Override 711 public DoubleVector<S> zero() { 712 return op(i -> 0); 713 } 714 715 /** 716 * Returns a vector where all lane elements are set to the primitive 717 * value {@code e}. 718 * 719 * @param e the value 720 * @return a vector of vector where all lane elements are set to 721 * the primitive value {@code e} 722 */ 723 public DoubleVector<S> broadcast(double e) { 724 return op(i -> e); 725 } 726 727 /** 728 * Returns a vector where the first lane element is set to the primtive 729 * value {@code e}, all other lane elements are set to the default 730 * value. 731 * 732 * @param e the value 733 * @return a vector where the first lane element is set to the primitive 734 * value {@code e} 735 */ 736 public DoubleVector<S> single(double e) { 737 return op(i -> i == 0 ? e : (double) 0); 738 } 739 740 /** 741 * Returns a vector where each lane element is set to a randomly 742 * generated primitive value. 743 * @@@ what are the properties of the random number generator? 744 * 745 * @return a vector where each lane elements is set to a randomly 746 * generated primitive value 747 */ 748 public DoubleVector<S> random() { 749 ThreadLocalRandom r = ThreadLocalRandom.current(); 750 return op(i -> r.nextDouble()); 751 } 752 753 /** 754 * Returns a vector where each lane element is set to a given 755 * primitive value. 756 * <p> 757 * For each vector lane, where {@code N} is the vector lane index, the 758 * the primitive value at index {@code N} is placed into the resulting 759 * vector at lane index {@code N}. 760 * 761 * @@@ What should happen if es.length < this.length() ? use the default 762 * value or throw IndexOutOfBoundsException 763 * 764 * @param es the given primitive values 765 * @return a vector where each lane element is set to a given primitive 766 * value 767 */ 768 public DoubleVector<S> scalars(double... es) { 769 return op(i -> es[i]); 770 } 771 772 /** 773 * Loads a vector from an array starting at offset. 774 * <p> 775 * For each vector lane, where {@code N} is the vector lane index, the 776 * array element at index {@code i + N} is placed into the 777 * resulting vector at lane index {@code N}. 778 * 779 * @param a the array 780 * @param i the offset into the array 781 * @return the vector loaded from an array 782 * @throws IndexOutOfBoundsException if {@code i < 0}, or 783 * {@code i > a.length - this.length()} 784 */ 785 public DoubleVector<S> fromArray(double[] a, int i) { 786 return op(n -> a[i + n]); 787 } 788 789 /** 790 * Loads a vector from an array starting at offset and using a mask. 791 * <p> 792 * For each vector lane, where {@code N} is the vector lane index, 793 * if the mask lane at index {@code N} is set then the array element at 794 * index {@code i + N} is placed into the resulting vector at lane index 795 * {@code N}, otherwise the default element value is placed into the 796 * resulting vector at lane index {@code N}. 797 * 798 * @param a the array 799 * @param i the offset into the array 800 * @param m the mask 801 * @return the vector loaded from an array 802 * @throws IndexOutOfBoundsException if {@code i < 0}, or 803 * for any vector lane index {@code N} where the mask at lane {@code N} 804 * is set {@code i > a.length - N} 805 */ 806 public DoubleVector<S> fromArray(double[] a, int i, Mask<Double, S> m) { 807 return op(m, n -> a[i + n]); 808 } 809 810 /** 811 * Loads a vector from an array using indexes obtained from an index 812 * map. 813 * <p> 814 * For each vector lane, where {@code N} is the vector lane index, the 815 * array element at index {@code i + indexMap[j + N]} is placed into the 816 * resulting vector at lane index {@code N}. 817 * 818 * @param a the array 819 * @param i the offset into the array, may be negative if relative 820 * indexes in the index map compensate to produce a value within the 821 * array bounds 822 * @param indexMap the index map 823 * @param j the offset into the index map 824 * @return the vector loaded from an array 825 * @throws IndexOutOfBoundsException if {@code j < 0}, or 826 * {@code j > indexMap.length - this.length()}, 827 * or for any vector lane index {@code N} the result of 828 * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length} 829 */ 830 public DoubleVector<S> fromArray(double[] a, int i, int[] indexMap, int j) { 831 return op(n -> a[i + indexMap[j + n]]); 832 } 833 834 /** 835 * Loads a vector from an array using indexes obtained from an index 836 * map and using a mask. 837 * <p> 838 * For each vector lane, where {@code N} is the vector lane index, 839 * if the mask lane at index {@code N} is set then the array element at 840 * index {@code i + indexMap[j + N]} is placed into the resulting vector 841 * at lane index {@code N}. 842 * 843 * @param a the array 844 * @param i the offset into the array, may be negative if relative 845 * indexes in the index map compensate to produce a value within the 846 * array bounds 847 * @param indexMap the index map 848 * @param j the offset into the index map 849 * @return the vector loaded from an array 850 * @throws IndexOutOfBoundsException if {@code j < 0}, or 851 * {@code j > indexMap.length - this.length()}, 852 * or for any vector lane index {@code N} where the mask at lane 853 * {@code N} is set the result of {@code i + indexMap[j + N]} is 854 * {@code < 0} or {@code >= a.length} 855 */ 856 public DoubleVector<S> fromArray(double[] a, int i, Mask<Double, S> m, int[] indexMap, int j) { 857 return op(m, n -> a[i + indexMap[j + n]]); 858 } 859 860 @Override 861 public DoubleVector<S> fromByteArray(byte[] a, int ix) { 862 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder()); 863 return fromByteBuffer(bb); 864 } 865 866 @Override 867 public DoubleVector<S> fromByteArray(byte[] a, int ix, Mask<Double, S> m) { 868 ByteBuffer bb = ByteBuffer.wrap(a, ix, a.length - ix).order(ByteOrder.nativeOrder()); 869 return fromByteBuffer(bb, m); 870 } 871 872 @Override 873 public DoubleVector<S> fromByteBuffer(ByteBuffer bb) { 874 DoubleBuffer fb = bb.asDoubleBuffer(); 875 return op(i -> fb.get()); 876 } 877 878 @Override 879 public DoubleVector<S> fromByteBuffer(ByteBuffer bb, Mask<Double, S> m) { 880 DoubleBuffer fb = bb.asDoubleBuffer(); 881 return op(i -> { 882 if(m.getElement(i)) 883 return fb.get(); 884 else { 885 fb.position(fb.position() + 1); 886 return (double) 0; 887 } 888 }); 889 } 890 891 @Override 892 public DoubleVector<S> fromByteBuffer(ByteBuffer bb, int ix) { 893 bb = bb.duplicate().order(ByteOrder.nativeOrder()).position(ix); 894 DoubleBuffer fb = bb.asDoubleBuffer(); 895 return op(i -> fb.get(i)); 896 } 897 898 @Override 899 public DoubleVector<S> fromByteBuffer(ByteBuffer bb, int ix, Mask<Double, S> m) { 900 bb = bb.duplicate().order(ByteOrder.nativeOrder()).position(ix); 901 DoubleBuffer fb = bb.asDoubleBuffer(); 902 return op(m, i -> fb.get(i)); 903 } 904 905 @Override 906 public <F, T extends Shape> DoubleVector<S> reshape(Vector<F, T> o) { 907 int blen = Math.max(o.species().bitSize(), bitSize()) / Byte.SIZE; 908 ByteBuffer bb = ByteBuffer.allocate(blen).order(ByteOrder.nativeOrder()); 909 o.intoByteBuffer(bb, 0); 910 return fromByteBuffer(bb, 0); 911 } 912 913 @Override 914 @ForceInline 915 public <F> DoubleVector<S> rebracket(Vector<F, S> o) { 916 return reshape(o); 917 } 918 919 @Override 920 @ForceInline 921 public <T extends Shape> DoubleVector<S> resize(Vector<Double, T> o) { 922 return reshape(o); 923 } 924 925 @Override 926 @SuppressWarnings("unchecked") 927 public <F, T extends Shape> DoubleVector<S> cast(Vector<F, T> v) { 928 // Allocate array of required size 929 double[] a = new double[length()]; 930 931 Class<?> vtype = v.species().elementType(); 932 int limit = Math.min(v.species().length(), length()); 933 if (vtype == byte.class) { 934 ByteVector<T> tv = (ByteVector<T>)v; 935 for (int i = 0; i < limit; i++) { 936 a[i] = (double) tv.get(i); 937 } 938 } else if (vtype == short.class) { 939 ShortVector<T> tv = (ShortVector<T>)v; 940 for (int i = 0; i < limit; i++) { 941 a[i] = (double) tv.get(i); 942 } 943 } else if (vtype == int.class) { 944 IntVector<T> tv = (IntVector<T>)v; 945 for (int i = 0; i < limit; i++) { 946 a[i] = (double) tv.get(i); 947 } 948 } else if (vtype == long.class){ 949 LongVector<T> tv = (LongVector<T>)v; 950 for (int i = 0; i < limit; i++) { 951 a[i] = (double) tv.get(i); 952 } 953 } else if (vtype == float.class){ 954 FloatVector<T> tv = (FloatVector<T>)v; 955 for (int i = 0; i < limit; i++) { 956 a[i] = (double) tv.get(i); 957 } 958 } else if (vtype == double.class){ 959 DoubleVector<T> tv = (DoubleVector<T>)v; 960 for (int i = 0; i < limit; i++) { 961 a[i] = (double) tv.get(i); 962 } 963 } else { 964 throw new UnsupportedOperationException("Bad lane type for casting."); 965 } 966 967 return scalars(a); 968 } 969 970 } 971 972 /** 973 * Finds the preferred species for an element type of {@code double}. 974 * <p> 975 * A preferred species is a species chosen by the platform that has a 976 * shape of maximal bit size. A preferred species for different element 977 * types will have the same shape, and therefore vectors, masks, and 978 * shuffles created from such species will be shape compatible. 979 * 980 * @return the preferred species for an element type of {@code double} 981 */ 982 @SuppressWarnings("unchecked") 983 public static DoubleSpecies<?> preferredSpeciesInstance() { 984 return (DoubleSpecies<?>) Vector.preferredSpeciesInstance(double.class); 985 } 986 987 /** 988 * Finds a species for an element type of {@code double} and shape. 989 * 990 * @param s the shape 991 * @param <S> the type of shape 992 * @return a species for an element type of {@code double} and shape 993 * @throws IllegalArgumentException if no such species exists for the shape 994 */ 995 @SuppressWarnings("unchecked") 996 public static <S extends Shape> DoubleSpecies<S> speciesInstance(S s) { 997 Objects.requireNonNull(s); 998 if (s == Shapes.S_64_BIT) { 999 return (DoubleSpecies<S>) Double64Vector.SPECIES; 1000 } else if (s == Shapes.S_128_BIT) { 1001 return (DoubleSpecies<S>) Double128Vector.SPECIES; 1002 } else if (s == Shapes.S_256_BIT) { 1003 return (DoubleSpecies<S>) Double256Vector.SPECIES; 1004 } else if (s == Shapes.S_512_BIT) { 1005 return (DoubleSpecies<S>) Double512Vector.SPECIES; 1006 } else { 1007 throw new IllegalArgumentException("Bad shape: " + s); 1008 } 1009 } 1010 }