001/*- 002 ******************************************************************************* 003 * Copyright (c) 2016 Diamond Light Source Ltd. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Peter Chang - initial API and implementation and/or initial documentation 011 *******************************************************************************/ 012package org.eclipse.january.dataset; 013 014import org.apache.commons.math3.complex.Complex; 015 016/** 017 * @since 2.0 018 */ 019public class Operations { 020 021 /** 022 * This function returns the name of the dataset, bracketed if it already 023 * includes some mathematical symbol 024 * 025 * @param a 026 * @return the bracketed if necessary method name 027 */ 028 public static StringBuilder bracketIfNecessary(final String a) { 029 final String name = a.trim(); 030 StringBuilder newName = new StringBuilder(name); 031 if (name.contains("+") || name.contains("-") || name.contains("*") || name.contains("/") || name.contains("%") 032 || name.contains("^") || name.contains("'")) { 033 newName.insert(0, '('); 034 newName.append(')'); 035 } 036 037 return newName; 038 } 039 040 /** 041 * Create a string for a binary operator and its operands 042 * 043 * @param operator 044 * @param a 045 * 1st operand name 046 * @param b 047 * 2nd operand name 048 * @return name of operation 049 */ 050 public static String createBinaryOperationName(final String operator, final String a, final String b) { 051 StringBuilder newName = bracketIfNecessary(a).append(operator).append(bracketIfNecessary(b)); 052 return newName.toString(); 053 } 054 055 /** 056 * Create a string for a function and its arguments 057 * 058 * @param function 059 * @param arguments 060 * @return name of function 061 */ 062 public static String createFunctionName(final String function, String... arguments) { 063 StringBuilder name = new StringBuilder(function); 064 name.append('('); 065 int length = arguments.length - 1; 066 for (int i = 0; i < length; i++) { 067 name.append(arguments[i]); 068 name.append(", "); 069 } 070 name.append(arguments[length]); 071 name.append(')'); 072 return name.toString(); 073 } 074 075 /** 076 * Negation with boolean not 077 */ 078 public static class Negation implements UnaryOperation { 079 080 @Override 081 public boolean booleanOperate(long a) { 082 return a == 0; 083 } 084 085 @Override 086 public long longOperate(long a) { 087 return -a; 088 } 089 090 @Override 091 public double doubleOperate(double a) { 092 return -a; 093 } 094 095 @Override 096 public void complexOperate(double[] out, double ra, double ia) { 097 out[0] = -ra; 098 out[1] = -ia; 099 } 100 101 @Override 102 public String toString(String a) { 103 return createFunctionName(toString(), a); 104 } 105 106 @Override 107 public String toString() { 108 return "-"; 109 } 110 } 111 112 /** 113 * Addition with boolean or 114 */ 115 public static class Addition implements BinaryOperation { 116 117 @Override 118 public boolean booleanOperate(long a, long b) { 119 return a != 0 || b != 0; 120 } 121 122 @Override 123 public long longOperate(long a, long b) { 124 return a + b; 125 } 126 127 @Override 128 public double doubleOperate(double a, double b) { 129 return a + b; 130 } 131 132 @Override 133 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 134 out[0] = ra + rb; 135 out[1] = ia + ib; 136 } 137 138 @Override 139 public String toString(String a, String b) { 140 return createBinaryOperationName(toString(), a, b); 141 } 142 143 @Override 144 public String toString() { 145 return "+"; 146 } 147 } 148 149 /** 150 * Subtraction with boolean or of negated second operand 151 */ 152 public static class Subtraction implements BinaryOperation { 153 154 @Override 155 public boolean booleanOperate(long a, long b) { 156 return a != 0 || b == 0; 157 } 158 159 @Override 160 public long longOperate(long a, long b) { 161 return a - b; 162 } 163 164 @Override 165 public double doubleOperate(double a, double b) { 166 return a - b; 167 } 168 169 @Override 170 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 171 out[0] = ra - rb; 172 out[1] = ia - ib; 173 } 174 175 @Override 176 public String toString(String a, String b) { 177 return createBinaryOperationName(toString(), a, b); 178 } 179 180 @Override 181 public String toString() { 182 return "-"; 183 } 184 } 185 186 /** 187 * Multiplication with boolean and 188 */ 189 public static class Multiplication implements BinaryOperation { 190 191 @Override 192 public boolean booleanOperate(long a, long b) { 193 return a != 0 && b != 0; 194 } 195 196 @Override 197 public long longOperate(long a, long b) { 198 return a * b; 199 } 200 201 @Override 202 public double doubleOperate(double a, double b) { 203 return a * b; 204 } 205 206 @Override 207 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 208 out[0] = ra * rb - ia * ib; 209 out[1] = ra * ib + ia * rb; 210 } 211 212 @Override 213 public String toString(String a, String b) { 214 return createBinaryOperationName(toString(), a, b); 215 } 216 217 @Override 218 public String toString() { 219 return "*"; 220 } 221 } 222 223 /** 224 * Division with boolean and of negated second operand 225 */ 226 public static class Division implements BinaryOperation { 227 228 @Override 229 public boolean booleanOperate(long a, long b) { 230 return a != 0 && b == 0; 231 } 232 233 @Override 234 public long longOperate(long a, long b) { 235 return b == 0 ? 0 : a / b; 236 } 237 238 @Override 239 public double doubleOperate(double a, double b) { 240 return a / b; 241 } 242 243 @Override 244 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 245 double q; 246 double den; 247 if (ib == 0) { 248 out[0] = ra / rb; 249 out[1] = ia / rb; 250 } else if (rb == 0) { 251 out[0] = ia / ib; 252 out[1] = -ra / ib; 253 } else if (Math.abs(rb) < Math.abs(ib)) { 254 q = rb / ib; 255 den = rb * q + ib; 256 out[0] = (ra * q + ia) / den; 257 out[1] = (ia * q - rb) / den; 258 } else { 259 q = ib / rb; 260 den = ib * q + rb; 261 out[0] = (ia * q + ra) / den; 262 out[1] = (ia - ra * q) / den; 263 } 264 } 265 266 @Override 267 public String toString(String a, String b) { 268 return createBinaryOperationName(toString(), a, b); 269 } 270 271 @Override 272 public String toString() { 273 return "/"; 274 } 275 } 276 277 /** 278 * Division with boolean and of negated second operand and returns zero if 279 * denominator is zero 280 */ 281 public static class DivisionWithZero extends Division { 282 283 @Override 284 public double doubleOperate(double a, double b) { 285 return b == 0 ? 0 : a / b; 286 } 287 288 @Override 289 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 290 double q; 291 double den; 292 if (ib == 0) { 293 if (rb == 0) { 294 out[0] = 0; 295 out[1] = 0; 296 } else { 297 out[0] = ra / rb; 298 out[1] = ia / rb; 299 } 300 } else if (rb == 0) { 301 out[0] = ia / ib; 302 out[1] = -ra / ib; 303 } else if (Math.abs(rb) < Math.abs(ib)) { 304 q = rb / ib; 305 den = rb * q + ib; 306 out[0] = (ra * q + ia) / den; 307 out[1] = (ia * q - rb) / den; 308 } else { 309 q = ib / rb; 310 den = ib * q + rb; 311 out[0] = (ia * q + ra) / den; 312 out[1] = (ia - ra * q) / den; 313 } 314 } 315 } 316 317 /** 318 * Division with boolean and of negated second operand and rounds down to 319 * negative infinity 320 */ 321 public static class DivisionTowardsFloor extends Division { 322 323 @Override 324 public long longOperate(long a, long b) { 325 if (b == 0) 326 return 0; 327 328 long ox = a / b; 329 if (a != ox * b && ((a < 0) ^ (b < 0))) { 330 ox--; 331 } 332 333 return ox; 334 } 335 } 336 337 /** 338 * Remainder 339 */ 340 public static class Remainder implements BinaryOperation { 341 342 @Override 343 public boolean booleanOperate(long a, long b) { 344 throw new IllegalArgumentException("remainder does not support booleans"); 345 } 346 347 @Override 348 public long longOperate(long a, long b) { 349 return b == 0 ? 0 : a % b; 350 } 351 352 @Override 353 public double doubleOperate(double a, double b) { 354 return a % b; 355 } 356 357 @Override 358 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 359 throw new IllegalArgumentException("remainder does not support complex numbers"); 360 } 361 362 @Override 363 public String toString(String a, String b) { 364 return createBinaryOperationName(toString(), a, b); 365 } 366 367 @Override 368 public String toString() { 369 return "%"; 370 } 371 } 372 373 /** 374 * Exponentiation with boolean and 375 */ 376 public static class Exponentiation extends BinaryOperation.Stub { 377 378 @Override 379 public double doubleOperate(double a, double b) { 380 return Math.pow(a, b); 381 } 382 383 @Override 384 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 385 Complex c = new Complex(ra, ia); 386 c = ib == 0 ? c.pow(rb) : c.pow(new Complex(rb, ib)); 387 out[0] = c.getReal(); 388 out[1] = c.getImaginary(); 389 } 390 391 @Override 392 public String toString(String a, String b) { 393 return createBinaryOperationName(toString(), a, b); 394 } 395 396 @Override 397 public String toString() { 398 return "**"; 399 } 400 } 401 402 /** 403 * Select maximum of a and b 404 */ 405 public static class Maximum implements BinaryOperation { 406 @Override 407 public boolean booleanOperate(long a, long b) { 408 return a > b ? a != 0 : b != 0; 409 } 410 411 @Override 412 public long longOperate(long a, long b) { 413 return a > b ? a : b; 414 } 415 416 @Override 417 public double doubleOperate(double a, double b) { 418 return a > b ? a : b; 419 } 420 421 @Override 422 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 423 throw new IllegalArgumentException("select greater than does not support complex numbers"); 424 } 425 426 @Override 427 public String toString(String a, String b) { 428 return createFunctionName(toString(), a, b); 429 } 430 431 @Override 432 public String toString() { 433 return "max"; 434 } 435 } 436 437 /** 438 * Select minimum of a and b 439 */ 440 public static class Minimum implements BinaryOperation { 441 @Override 442 public boolean booleanOperate(long a, long b) { 443 return a < b ? a != 0 : b != 0; 444 } 445 446 @Override 447 public long longOperate(long a, long b) { 448 return a < b ? a : b; 449 } 450 451 @Override 452 public double doubleOperate(double a, double b) { 453 return a < b ? a : b; 454 } 455 456 @Override 457 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 458 throw new IllegalArgumentException("select less than does not support complex numbers"); 459 } 460 461 @Override 462 public String toString(String a, String b) { 463 return createFunctionName(toString(), a, b); 464 } 465 466 @Override 467 public String toString() { 468 return "min"; 469 } 470 } 471 472 /** 473 * Use given value if {@code a > b} else use a 474 */ 475 public static class UseBase implements BinaryOperation { 476 protected boolean br; 477 protected long lr; 478 protected double dr; 479 480 /** 481 * @param br 482 * given value as boolean 483 * @param lr 484 * given value as long 485 * @param dr 486 * given value as double 487 */ 488 UseBase(boolean br, long lr, double dr) { 489 this.br = br; 490 this.lr = lr; 491 this.dr = dr; 492 } 493 494 /** 495 * @param r 496 * given value as Number 497 */ 498 UseBase(Number r) { 499 br = r.intValue() != 0; 500 lr = r.longValue(); 501 dr = r.doubleValue(); 502 } 503 504 @Override 505 public boolean booleanOperate(long a, long b) { 506 return false; 507 } 508 509 @Override 510 public long longOperate(long a, long b) { 511 return 0; 512 } 513 514 @Override 515 public double doubleOperate(double a, double b) { 516 return 0; 517 } 518 519 @Override 520 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 521 } 522 523 @Override 524 public String toString(String a, String b) { 525 return createBinaryOperationName(toString(), a, b); 526 } 527 } 528 529 /** 530 * Use given value if {@code a > b} else use a 531 */ 532 public static class UseIfGreaterThan extends UseBase { 533 /** 534 * @param br 535 * given value as boolean 536 * @param lr 537 * given value as long 538 * @param dr 539 * given value as double 540 */ 541 public UseIfGreaterThan(boolean br, long lr, double dr) { 542 super(br, lr, dr); 543 } 544 545 /** 546 * @param r 547 * given value as Number 548 */ 549 public UseIfGreaterThan(Number r) { 550 super(r); 551 } 552 553 @Override 554 public boolean booleanOperate(long a, long b) { 555 return a > b ? br : a != 0; 556 } 557 558 @Override 559 public long longOperate(long a, long b) { 560 return a > b ? lr : a; 561 } 562 563 @Override 564 public double doubleOperate(double a, double b) { 565 return a > b ? dr : a; 566 } 567 568 @Override 569 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 570 throw new IllegalArgumentException("replace greater than does not support complex numbers"); 571 } 572 573 @Override 574 public String toString() { 575 return ">"; 576 } 577 } 578 579 /** 580 * Use given value if {@code a >= b} else use a 581 */ 582 public static class UseIfGreaterThanOrEqualTo extends UseBase { 583 /** 584 * @param br 585 * given value as boolean 586 * @param lr 587 * given value as long 588 * @param dr 589 * given value as double 590 */ 591 public UseIfGreaterThanOrEqualTo(boolean br, long lr, double dr) { 592 super(br, lr, dr); 593 } 594 595 /** 596 * @param r 597 * given value as Number 598 */ 599 public UseIfGreaterThanOrEqualTo(Number r) { 600 super(r); 601 } 602 603 @Override 604 public boolean booleanOperate(long a, long b) { 605 return a >= b ? br : a != 0; 606 } 607 608 @Override 609 public long longOperate(long a, long b) { 610 return a >= b ? lr : a; 611 } 612 613 @Override 614 public double doubleOperate(double a, double b) { 615 return a >= b ? dr : a; 616 } 617 618 @Override 619 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 620 throw new IllegalArgumentException("replace greater than or equal to does not support complex numbers"); 621 } 622 623 @Override 624 public String toString() { 625 return ">"; 626 } 627 } 628 629 /** 630 * Use given value if {@code a < b} else use a 631 */ 632 public static class UseIfLessThan extends UseBase { 633 /** 634 * @param br 635 * given value as boolean 636 * @param lr 637 * given value as long 638 * @param dr 639 * given value as double 640 */ 641 public UseIfLessThan(boolean br, long lr, double dr) { 642 super(br, lr, dr); 643 } 644 645 /** 646 * @param r 647 * given value as Number 648 */ 649 public UseIfLessThan(Number r) { 650 super(r); 651 } 652 653 @Override 654 public boolean booleanOperate(long a, long b) { 655 return a < b ? br : a != 0; 656 } 657 658 @Override 659 public long longOperate(long a, long b) { 660 return a < b ? lr : a; 661 } 662 663 @Override 664 public double doubleOperate(double a, double b) { 665 return a < b ? dr : a; 666 } 667 668 @Override 669 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 670 throw new IllegalArgumentException("replace less than does not support complex numbers"); 671 } 672 673 @Override 674 public String toString() { 675 return "<"; 676 } 677 } 678 679 /** 680 * Use given value if {@code a <= b} else use a 681 */ 682 public static class UseIfLessThanOrEqualTo extends UseBase { 683 /** 684 * @param br 685 * given value as boolean 686 * @param lr 687 * given value as long 688 * @param dr 689 * given value as double 690 */ 691 public UseIfLessThanOrEqualTo(boolean br, long lr, double dr) { 692 super(br, lr, dr); 693 } 694 695 /** 696 * @param r 697 * given value as Number 698 */ 699 public UseIfLessThanOrEqualTo(Number r) { 700 super(r); 701 } 702 703 @Override 704 public boolean booleanOperate(long a, long b) { 705 return a <= b ? br : a != 0; 706 } 707 708 @Override 709 public long longOperate(long a, long b) { 710 return a <= b ? lr : a; 711 } 712 713 @Override 714 public double doubleOperate(double a, double b) { 715 return a <= b ? dr : a; 716 } 717 718 @Override 719 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 720 throw new IllegalArgumentException("replace less than or equal to does not support complex numbers"); 721 } 722 723 @Override 724 public String toString() { 725 return "<="; 726 } 727 } 728 729 /** 730 * Use given value if {@code a == b} else use a 731 */ 732 public static class UseIfEqualTo extends UseBase { 733 private double di; 734 735 /** 736 * @param br 737 * given value as boolean 738 * @param lr 739 * given value as long 740 * @param dr 741 * given value as double 742 * @param di 743 * given value for imaginary part as double 744 */ 745 public UseIfEqualTo(boolean br, long lr, double dr, double di) { 746 super(br, lr, dr); 747 this.di = di; 748 } 749 750 /** 751 * @param r 752 * given value as Number 753 */ 754 public UseIfEqualTo(Number r) { 755 super(r); 756 di = 0; 757 } 758 759 /** 760 * @param z 761 * given value as Complex 762 */ 763 public UseIfEqualTo(Complex z) { 764 super(z.getReal()); 765 di = z.getImaginary(); 766 } 767 768 @Override 769 public boolean booleanOperate(long a, long b) { 770 return a == b ? br : a != 0; 771 } 772 773 @Override 774 public long longOperate(long a, long b) { 775 return a == b ? lr : a; 776 } 777 778 @Override 779 public double doubleOperate(double a, double b) { 780 return a == b ? dr : a; 781 } 782 783 @Override 784 public void complexOperate(double[] out, double ra, double ia, double rb, double ib) { 785 if (ra == rb && ia == ib) { 786 out[0] = dr; 787 out[1] = di; 788 } else { 789 out[0] = ra; 790 out[1] = ia; 791 } 792 } 793 794 @Override 795 public String toString() { 796 return "=="; 797 } 798 } 799 800 private static long toLong(double d) { 801 if (Double.isInfinite(d) || Double.isNaN(d)) 802 return 0; 803 return (long) d; 804 } 805 806 /** 807 * Operate on a dataset 808 * 809 * @param op 810 * unary operator 811 * @param a 812 * dataset 813 * @param o 814 * output can be null - in which case, a new dataset is created 815 * @return op(a), operation on a 816 */ 817 public static Dataset operate(final UnaryOperation op, final Object a, final Dataset o) { 818 final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a); 819 final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true, true, false); 820 final Dataset result = it.getOutput(); 821 it.setOutputDouble(result.hasFloatingPointElements() || da.isComplex()); 822 final int is = result.getElementsPerItem(); 823 final int dt = result.getDType(); 824 final int as = da.getElementsPerItem(); 825 final double[] z; 826 827 switch (dt) { 828 case Dataset.BOOL: 829 boolean[] bdata = ((BooleanDataset) result).getData(); 830 831 if (!da.isComplex()) { 832 while (it.hasNext()) { 833 bdata[it.oIndex] = op.booleanOperate(it.aLong); 834 } 835 } else { 836 z = new double[2]; 837 while (it.hasNext()) { 838 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 839 bdata[it.oIndex] = z[0] != 0; 840 } 841 } 842 break; 843 case Dataset.INT8: 844 final byte[] i8data = ((ByteDataset) result).getData(); 845 846 if (!da.isComplex()) { 847 while (it.hasNext()) { 848 i8data[it.oIndex] = (byte) op.longOperate(it.aLong); 849 } 850 } else { 851 z = new double[2]; 852 while (it.hasNext()) { 853 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 854 i8data[it.oIndex] = (byte) toLong(z[0]); 855 } 856 } 857 break; 858 case Dataset.INT16: 859 final short[] i16data = ((ShortDataset) result).getData(); 860 861 if (!da.isComplex()) { 862 while (it.hasNext()) { 863 i16data[it.oIndex] = (short) op.longOperate(it.aLong); 864 } 865 } else { 866 z = new double[2]; 867 while (it.hasNext()) { 868 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 869 i16data[it.oIndex] = (short) toLong(z[0]); 870 } 871 } 872 break; 873 case Dataset.INT32: 874 final int[] i32data = ((IntegerDataset) result).getData(); 875 876 if (!da.isComplex()) { 877 while (it.hasNext()) { 878 i32data[it.oIndex] = (int) op.longOperate(it.aLong); 879 } 880 } else { 881 z = new double[2]; 882 while (it.hasNext()) { 883 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 884 i32data[it.oIndex] = (int) toLong(z[0]); 885 } 886 } 887 break; 888 case Dataset.INT64: 889 final long[] i64data = ((LongDataset) result).getData(); 890 891 if (!da.isComplex()) { 892 while (it.hasNext()) { 893 i64data[it.oIndex] = op.longOperate(it.aLong); 894 } 895 } else { 896 z = new double[2]; 897 while (it.hasNext()) { 898 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 899 i64data[it.oIndex] = toLong(z[0]); 900 } 901 } 902 break; 903 case Dataset.ARRAYINT8: 904 final byte[] ai8data = ((CompoundByteDataset) result).getData(); 905 906 if (!da.isComplex()) { 907 if (is == 1) { 908 while (it.hasNext()) { 909 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong); 910 } 911 } else if (as == 1) { // broadcast to other elements of output 912 while (it.hasNext()) { 913 byte ox = (byte) op.longOperate(it.aLong); 914 for (int j = 0; j < is; j++) { 915 ai8data[it.oIndex + j] = ox; 916 } 917 } 918 } else { // use lowest common elements 919 int ms = Math.min(is, as); 920 while (it.hasNext()) { 921 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong); 922 for (int j = 1; j < ms; j++) { 923 ai8data[it.oIndex + j] = (byte) op.longOperate(da.getElementLongAbs(it.aIndex + j)); 924 } 925 } 926 } 927 } else { 928 z = new double[2]; 929 while (it.hasNext()) { 930 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 931 byte ox = (byte) toLong(z[0]); 932 for (int j = 0; j < is; j++) { 933 ai8data[it.oIndex + j] = ox; 934 } 935 } 936 } 937 break; 938 case Dataset.ARRAYINT16: 939 final short[] ai16data = ((CompoundShortDataset) result).getData(); 940 941 if (!da.isComplex()) { 942 if (is == 1) { 943 while (it.hasNext()) { 944 ai16data[it.oIndex] = (short) op.longOperate(it.aLong); 945 } 946 } else if (as == 1) { 947 while (it.hasNext()) { 948 short ox = (short) op.longOperate(it.aLong); 949 for (int j = 0; j < is; j++) { 950 ai16data[it.oIndex + j] = ox; 951 } 952 } 953 } else { 954 int ms = Math.min(is, as); 955 while (it.hasNext()) { 956 ai16data[it.oIndex] = (short) op.longOperate(it.aLong); 957 for (int j = 1; j < ms; j++) { 958 ai16data[it.oIndex + j] = (short) op.longOperate(da.getElementLongAbs(it.aIndex + j)); 959 } 960 } 961 } 962 } else { 963 z = new double[2]; 964 while (it.hasNext()) { 965 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 966 short ox = (short) toLong(z[0]); 967 for (int j = 0; j < is; j++) { 968 ai16data[it.oIndex + j] = ox; 969 } 970 } 971 } 972 break; 973 case Dataset.ARRAYINT32: 974 final int[] ai32data = ((CompoundIntegerDataset) result).getData(); 975 976 if (!da.isComplex()) { 977 if (is == 1) { 978 while (it.hasNext()) { 979 ai32data[it.oIndex] = (int) op.longOperate(it.aLong); 980 } 981 } else if (as == 1) { 982 while (it.hasNext()) { 983 int ox = (int) op.longOperate(it.aLong); 984 for (int j = 0; j < is; j++) { 985 ai32data[it.oIndex + j] = ox; 986 } 987 } 988 } else { 989 final int ms = Math.min(is, as); 990 while (it.hasNext()) { 991 ai32data[it.oIndex] = (int) op.longOperate(it.aLong); 992 for (int j = 1; j < ms; j++) { 993 ai32data[it.oIndex + j] = (int) op.longOperate(da.getElementLongAbs(it.aIndex + j)); 994 } 995 } 996 } 997 } else { 998 z = new double[2]; 999 while (it.hasNext()) { 1000 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1001 int ox = (int) toLong(z[0]); 1002 for (int j = 0; j < is; j++) { 1003 ai32data[it.oIndex + j] = ox; 1004 } 1005 } 1006 } 1007 break; 1008 case Dataset.ARRAYINT64: 1009 final long[] ai64data = ((CompoundLongDataset) result).getData(); 1010 1011 if (!da.isComplex()) { 1012 if (is == 1) { 1013 while (it.hasNext()) { 1014 ai64data[it.oIndex] = op.longOperate(it.aLong); 1015 } 1016 } else if (as == 1) { 1017 while (it.hasNext()) { 1018 long ox = op.longOperate(it.aLong); 1019 for (int j = 0; j < is; j++) { 1020 ai64data[it.oIndex + j] = ox; 1021 } 1022 } 1023 } else { 1024 int ms = Math.min(is, as); 1025 while (it.hasNext()) { 1026 ai64data[it.oIndex] = op.longOperate(it.aLong); 1027 for (int j = 1; j < ms; j++) { 1028 ai64data[it.oIndex + j] = op.longOperate(da.getElementLongAbs(it.aIndex + j)); 1029 } 1030 } 1031 } 1032 } else { 1033 z = new double[2]; 1034 while (it.hasNext()) { 1035 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1036 long ox = toLong(z[0]); 1037 for (int j = 0; j < is; j++) { 1038 ai64data[it.oIndex + j] = ox; 1039 } 1040 } 1041 } 1042 break; 1043 case Dataset.FLOAT32: 1044 final float[] f32data = ((FloatDataset) result).getData(); 1045 1046 if (!da.isComplex()) { 1047 while (it.hasNext()) { 1048 f32data[it.oIndex] = (float) op.doubleOperate(it.aDouble); 1049 } 1050 } else { // only for complex input 1051 z = new double[2]; 1052 while (it.hasNext()) { 1053 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1054 f32data[it.oIndex] = (float) z[0]; 1055 } 1056 } 1057 break; 1058 case Dataset.FLOAT64: 1059 final double[] f64data = ((DoubleDataset) result).getData(); 1060 1061 if (!da.isComplex()) { 1062 while (it.hasNext()) { 1063 f64data[it.oIndex] = op.doubleOperate(it.aDouble); 1064 } 1065 } else { 1066 z = new double[2]; 1067 while (it.hasNext()) { 1068 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1069 f64data[it.oIndex] = z[0]; 1070 } 1071 } 1072 break; 1073 case Dataset.ARRAYFLOAT32: 1074 final float[] af32data = ((CompoundFloatDataset) result).getData(); 1075 1076 if (!da.isComplex()) { 1077 if (is == 1) { 1078 while (it.hasNext()) { 1079 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble); 1080 } 1081 } else if (as == 1) { 1082 while (it.hasNext()) { 1083 float ox = (float) op.doubleOperate(it.aDouble); 1084 for (int j = 0; j < is; j++) { 1085 af32data[it.oIndex + j] = ox; 1086 } 1087 } 1088 } else { 1089 int ms = Math.min(is, as); 1090 while (it.hasNext()) { 1091 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble); 1092 for (int j = 1; j < ms; j++) { 1093 af32data[it.oIndex + j] = (float) op.doubleOperate(da.getElementDoubleAbs(it.aIndex + j)); 1094 } 1095 } 1096 } 1097 } else { 1098 z = new double[2]; 1099 while (it.hasNext()) { 1100 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1101 float ox = (float) z[0]; 1102 for (int j = 0; j < is; j++) { 1103 af32data[it.oIndex + j] = ox; 1104 } 1105 } 1106 } 1107 break; 1108 case Dataset.ARRAYFLOAT64: 1109 final double[] af64data = ((CompoundDoubleDataset) result).getData(); 1110 1111 if (!da.isComplex()) { 1112 if (is == 1) { 1113 while (it.hasNext()) { 1114 af64data[it.oIndex] = op.doubleOperate(it.aDouble); 1115 } 1116 } else if (as == 1) { 1117 while (it.hasNext()) { 1118 final double ix = it.aDouble; 1119 double ox = op.doubleOperate(ix); 1120 for (int j = 0; j < is; j++) { 1121 af64data[it.oIndex + j] = ox; 1122 } 1123 } 1124 } else { 1125 int ms = Math.min(is, as); 1126 while (it.hasNext()) { 1127 af64data[it.oIndex] = op.doubleOperate(it.aDouble); 1128 for (int j = 1; j < ms; j++) { 1129 af64data[it.oIndex + j] = op.doubleOperate(da.getElementDoubleAbs(it.aIndex + j)); 1130 } 1131 } 1132 } 1133 } else { 1134 z = new double[2]; 1135 while (it.hasNext()) { 1136 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1137 double ox = z[0]; 1138 for (int j = 0; j < is; j++) { 1139 af64data[it.oIndex + j] = ox; 1140 } 1141 } 1142 } 1143 break; 1144 case Dataset.COMPLEX64: 1145 final float[] c64data = ((ComplexFloatDataset) result).getData(); 1146 z = new double[2]; 1147 1148 if (!da.isComplex()) { 1149 while (it.hasNext()) { 1150 op.complexOperate(z, it.aDouble, 0); 1151 c64data[it.oIndex] = (float) z[0]; 1152 } 1153 } else { 1154 while (it.hasNext()) { 1155 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1156 c64data[it.oIndex] = (float) z[0]; 1157 c64data[it.oIndex + 1] = (float) z[1]; 1158 } 1159 } 1160 break; 1161 case Dataset.COMPLEX128: 1162 final double[] c128data = ((ComplexDoubleDataset) result).getData(); 1163 z = new double[2]; 1164 1165 if (!da.isComplex()) { 1166 while (it.hasNext()) { 1167 op.complexOperate(z, it.aDouble, 0); 1168 c128data[it.oIndex] = z[0]; 1169 } 1170 } else { 1171 while (it.hasNext()) { 1172 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1)); 1173 c128data[it.oIndex] = z[0]; 1174 c128data[it.oIndex + 1] = z[1]; 1175 } 1176 } 1177 break; 1178 default: 1179 throw new UnsupportedOperationException("operate does not support this dataset type"); 1180 } 1181 1182 result.setName(op.toString(da.getName())); 1183 return result; 1184 } 1185 1186 /** 1187 * Operate on a dataset 1188 * 1189 * @param op 1190 * binary operator 1191 * @param a 1192 * @param b 1193 * @param o 1194 * output can be null - in which case, a new dataset is created 1195 * @return a op b, operation on a and b 1196 */ 1197 public static Dataset operate(final BinaryOperation op, final Object a, final Object b, final Dataset o) { 1198 final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a); 1199 final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 1200 1201 final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true); 1202 final Dataset result = it.getOutput(); 1203 it.setOutputDouble(result.hasFloatingPointElements() || da.isComplex() || db.isComplex()); 1204 final int is = result.getElementsPerItem(); 1205 int as = da.getElementsPerItem(); 1206 int bs = db.getElementsPerItem(); 1207 final double[] z; 1208 1209 switch (result.getDType()) { 1210 case Dataset.BOOL: 1211 boolean[] bdata = ((BooleanDataset) result).getData(); 1212 1213 if (!da.isComplex() && !db.isComplex()) { 1214 while (it.hasNext()) { 1215 bdata[it.oIndex] = op.booleanOperate(it.aLong, it.aLong); 1216 } 1217 } else { 1218 z = new double[2]; 1219 if (!db.isComplex()) { 1220 while (it.hasNext()) { 1221 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1222 bdata[it.oIndex] = z[0] != 0; 1223 } 1224 } else if (!da.isComplex()) { 1225 while (it.hasNext()) { 1226 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1227 bdata[it.oIndex] = z[0] != 0; 1228 } 1229 } else { 1230 while (it.hasNext()) { 1231 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1232 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1233 bdata[it.oIndex] = z[0] != 0; 1234 } 1235 } 1236 } 1237 break; 1238 case Dataset.INT8: 1239 byte[] i8data = ((ByteDataset) result).getData(); 1240 1241 if (!da.isComplex() && !db.isComplex()) { 1242 while (it.hasNext()) { 1243 i8data[it.oIndex] = (byte) op.longOperate(it.aLong, it.aLong); 1244 } 1245 } else { 1246 z = new double[2]; 1247 if (!db.isComplex()) { // only a complex 1248 while (it.hasNext()) { 1249 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1250 i8data[it.oIndex] = (byte) toLong(z[0]); 1251 } 1252 } else if (!da.isComplex()) { // only b complex 1253 while (it.hasNext()) { 1254 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1255 i8data[it.oIndex] = (byte) toLong(z[0]); 1256 } 1257 } else { 1258 while (it.hasNext()) { 1259 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1260 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1261 i8data[it.oIndex] = (byte) toLong(z[0]); 1262 } 1263 } 1264 } 1265 break; 1266 case Dataset.INT16: 1267 short[] i16data = ((ShortDataset) result).getData(); 1268 1269 if (!da.isComplex() && !db.isComplex()) { 1270 while (it.hasNext()) { 1271 i16data[it.oIndex] = (short) op.longOperate(it.aLong, it.aLong); 1272 } 1273 } else { 1274 z = new double[2]; 1275 if (!db.isComplex()) { // only a complex 1276 while (it.hasNext()) { 1277 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1278 i16data[it.oIndex] = (short) toLong(z[0]); 1279 } 1280 } else if (!da.isComplex()) { // only b complex 1281 while (it.hasNext()) { 1282 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1283 i16data[it.oIndex] = (short) toLong(z[0]); 1284 } 1285 } else { 1286 while (it.hasNext()) { 1287 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1288 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1289 i16data[it.oIndex] = (short) toLong(z[0]); 1290 } 1291 } 1292 } 1293 break; 1294 case Dataset.INT32: 1295 int[] i32data = ((IntegerDataset) result).getData(); 1296 1297 if (!da.isComplex() && !db.isComplex()) { 1298 while (it.hasNext()) { 1299 i32data[it.oIndex] = (int) op.longOperate(it.aLong, it.aLong); 1300 } 1301 } else { 1302 z = new double[2]; 1303 if (!db.isComplex()) { // only a complex 1304 while (it.hasNext()) { 1305 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1306 i32data[it.oIndex] = (int) toLong(z[0]); 1307 } 1308 } else if (!da.isComplex()) { // only b complex 1309 while (it.hasNext()) { 1310 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1311 i32data[it.oIndex] = (int) toLong(z[0]); 1312 } 1313 } else { 1314 while (it.hasNext()) { 1315 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1316 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1317 i32data[it.oIndex] = (int) toLong(z[0]); 1318 } 1319 } 1320 } 1321 break; 1322 case Dataset.INT64: 1323 long[] i64data = ((LongDataset) result).getData(); 1324 1325 if (!da.isComplex() && !db.isComplex()) { 1326 while (it.hasNext()) { 1327 i64data[it.oIndex] = op.longOperate(it.aLong, it.aLong); 1328 } 1329 } else { 1330 z = new double[2]; 1331 if (!db.isComplex()) { // only a complex 1332 while (it.hasNext()) { 1333 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1334 i64data[it.oIndex] = toLong(z[0]); 1335 } 1336 } else if (!da.isComplex()) { // only b complex 1337 while (it.hasNext()) { 1338 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1339 i64data[it.oIndex] = toLong(z[0]); 1340 } 1341 } else { 1342 while (it.hasNext()) { 1343 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1344 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1345 i64data[it.oIndex] = toLong(z[0]); 1346 } 1347 } 1348 } 1349 break; 1350 case Dataset.ARRAYINT8: 1351 byte[] ai8data = ((CompoundByteDataset) result).getData(); 1352 1353 if (!da.isComplex() && !db.isComplex()) { 1354 if (is == 1) { 1355 while (it.hasNext()) { 1356 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong, it.bLong); 1357 } 1358 } else { // broadcast to other elements of output if possible 1359 int ms; 1360 if (as == 1 && bs != 1) { 1361 ms = Math.min(is, bs); 1362 while (it.hasNext()) { 1363 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong, it.bLong); 1364 for (int j = 1; j < ms; j++) { 1365 ai8data[it.oIndex + j] = (byte) op.longOperate(it.aLong, 1366 db.getElementLongAbs(it.bIndex + j)); 1367 } 1368 } 1369 } else if (as != 1 && bs == 1) { 1370 ms = Math.min(is, as); 1371 while (it.hasNext()) { 1372 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong, it.bLong); 1373 for (int j = 1; j < ms; j++) { 1374 ai8data[it.oIndex + j] = (byte) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1375 it.bLong); 1376 } 1377 } 1378 } else { 1379 ms = Math.min(is, Math.min(as, bs)); 1380 while (it.hasNext()) { 1381 ai8data[it.oIndex] = (byte) op.longOperate(it.aLong, it.bLong); 1382 for (int j = 1; j < ms; j++) { 1383 ai8data[it.oIndex + j] = (byte) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1384 db.getElementLongAbs(it.bIndex + j)); 1385 } 1386 } 1387 } 1388 } 1389 } else { 1390 z = new double[2]; 1391 if (!db.isComplex()) { // only a complex 1392 while (it.hasNext()) { 1393 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1394 byte ox = (byte) toLong(z[0]); 1395 for (int j = 0; j < is; j++) { 1396 ai8data[it.oIndex + j] = ox; 1397 } 1398 } 1399 } else if (!da.isComplex()) { // only b complex 1400 while (it.hasNext()) { 1401 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1402 byte ox = (byte) toLong(z[0]); 1403 for (int j = 0; j < is; j++) { 1404 ai8data[it.oIndex + j] = ox; 1405 } 1406 } 1407 } else { 1408 while (it.hasNext()) { 1409 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1410 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1411 byte ox = (byte) toLong(z[0]); 1412 for (int j = 0; j < is; j++) { 1413 ai8data[it.oIndex + j] = ox; 1414 } 1415 } 1416 } 1417 } 1418 break; 1419 case Dataset.ARRAYINT16: 1420 short[] ai16data = ((CompoundShortDataset) result).getData(); 1421 1422 if (!da.isComplex() && !db.isComplex()) { 1423 if (is == 1) { 1424 while (it.hasNext()) { 1425 ai16data[it.oIndex] = (short) op.longOperate(it.aLong, it.bLong); 1426 } 1427 } else { 1428 int ms; 1429 if (as == 1 && bs != 1) { 1430 ms = Math.min(is, bs); 1431 while (it.hasNext()) { 1432 ai16data[it.oIndex] = (short) op.longOperate(it.aLong, it.bLong); 1433 for (int j = 1; j < ms; j++) { 1434 ai16data[it.oIndex + j] = (short) op.longOperate(it.aLong, 1435 db.getElementLongAbs(it.bIndex + j)); 1436 } 1437 } 1438 } else if (as != 1 && bs == 1) { 1439 ms = Math.min(is, as); 1440 while (it.hasNext()) { 1441 ai16data[it.oIndex] = (short) op.longOperate(it.aLong, it.bLong); 1442 for (int j = 1; j < ms; j++) { 1443 ai16data[it.oIndex + j] = (short) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1444 it.bLong); 1445 } 1446 } 1447 } else { 1448 ms = Math.min(is, Math.min(as, bs)); 1449 while (it.hasNext()) { 1450 ai16data[it.oIndex] = (short) op.longOperate(it.aLong, it.bLong); 1451 for (int j = 1; j < ms; j++) { 1452 ai16data[it.oIndex + j] = (short) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1453 db.getElementLongAbs(it.bIndex + j)); 1454 } 1455 } 1456 } 1457 } 1458 } else { 1459 z = new double[2]; 1460 if (!db.isComplex()) { // only a complex 1461 while (it.hasNext()) { 1462 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1463 short ox = (short) toLong(z[0]); 1464 for (int j = 0; j < is; j++) { 1465 ai16data[it.oIndex + j] = ox; 1466 } 1467 } 1468 } else if (!da.isComplex()) { // only b complex 1469 while (it.hasNext()) { 1470 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1471 short ox = (short) toLong(z[0]); 1472 for (int j = 0; j < is; j++) { 1473 ai16data[it.oIndex + j] = ox; 1474 } 1475 } 1476 } else { 1477 while (it.hasNext()) { 1478 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1479 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1480 short ox = (short) toLong(z[0]); 1481 for (int j = 0; j < is; j++) { 1482 ai16data[it.oIndex + j] = ox; 1483 } 1484 } 1485 } 1486 } 1487 break; 1488 case Dataset.ARRAYINT32: 1489 int[] ai32data = ((CompoundIntegerDataset) result).getData(); 1490 1491 if (!da.isComplex() && !db.isComplex()) { 1492 if (is == 1) { 1493 while (it.hasNext()) { 1494 ai32data[it.oIndex] = (int) op.longOperate(it.aLong, it.bLong); 1495 } 1496 } else { 1497 int ms; 1498 if (as == 1 && bs != 1) { 1499 ms = Math.min(is, bs); 1500 while (it.hasNext()) { 1501 ai32data[it.oIndex] = (int) op.longOperate(it.aLong, it.bLong); 1502 for (int j = 1; j < ms; j++) { 1503 ai32data[it.oIndex + j] = (int) op.longOperate(it.aLong, 1504 db.getElementLongAbs(it.bIndex + j)); 1505 } 1506 } 1507 } else if (as != 1 && bs == 1) { 1508 ms = Math.min(is, as); 1509 while (it.hasNext()) { 1510 ai32data[it.oIndex] = (int) op.longOperate(it.aLong, it.bLong); 1511 for (int j = 1; j < ms; j++) { 1512 ai32data[it.oIndex + j] = (int) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1513 it.bLong); 1514 } 1515 } 1516 } else { 1517 ms = Math.min(is, Math.min(as, bs)); 1518 while (it.hasNext()) { 1519 ai32data[it.oIndex] = (int) op.longOperate(it.aLong, it.bLong); 1520 for (int j = 1; j < ms; j++) { 1521 ai32data[it.oIndex + j] = (int) op.longOperate(da.getElementLongAbs(it.aIndex + j), 1522 db.getElementLongAbs(it.bIndex + j)); 1523 } 1524 } 1525 } 1526 } 1527 } else { 1528 z = new double[2]; 1529 if (!db.isComplex()) { // only a complex 1530 while (it.hasNext()) { 1531 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1532 short ox = (short) toLong(z[0]); 1533 for (int j = 0; j < is; j++) { 1534 ai32data[it.oIndex + j] = ox; 1535 } 1536 } 1537 } else if (!da.isComplex()) { // only b complex 1538 while (it.hasNext()) { 1539 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1540 short ox = (short) toLong(z[0]); 1541 for (int j = 0; j < is; j++) { 1542 ai32data[it.oIndex + j] = ox; 1543 } 1544 } 1545 } else { 1546 while (it.hasNext()) { 1547 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1548 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1549 short ox = (short) toLong(z[0]); 1550 for (int j = 0; j < is; j++) { 1551 ai32data[it.oIndex + j] = ox; 1552 } 1553 } 1554 } 1555 } 1556 break; 1557 case Dataset.ARRAYINT64: 1558 long[] ai64data = ((CompoundLongDataset) result).getData(); 1559 1560 if (!da.isComplex() && !db.isComplex()) { 1561 if (is == 1) { 1562 while (it.hasNext()) { 1563 ai64data[it.oIndex] = op.longOperate(it.aLong, it.bLong); 1564 } 1565 } else { 1566 int ms; 1567 if (as == 1 && bs != 1) { 1568 ms = Math.min(is, bs); 1569 while (it.hasNext()) { 1570 ai64data[it.oIndex] = op.longOperate(it.aLong, it.bLong); 1571 for (int j = 1; j < ms; j++) { 1572 ai64data[it.oIndex + j] = op.longOperate(it.aLong, db.getElementLongAbs(it.bIndex + j)); 1573 } 1574 } 1575 } else if (as != 1 && bs == 1) { 1576 ms = Math.min(is, as); 1577 while (it.hasNext()) { 1578 ai64data[it.oIndex] = op.longOperate(it.aLong, it.bLong); 1579 for (int j = 1; j < ms; j++) { 1580 ai64data[it.oIndex + j] = op.longOperate(da.getElementLongAbs(it.aIndex + j), it.bLong); 1581 } 1582 } 1583 } else { 1584 ms = Math.min(is, Math.min(as, bs)); 1585 while (it.hasNext()) { 1586 ai64data[it.oIndex] = op.longOperate(it.aLong, it.bLong); 1587 for (int j = 1; j < ms; j++) { 1588 ai64data[it.oIndex + j] = op.longOperate(da.getElementLongAbs(it.aIndex + j), 1589 db.getElementLongAbs(it.bIndex + j)); 1590 } 1591 } 1592 } 1593 } 1594 } else { 1595 z = new double[2]; 1596 if (!db.isComplex()) { // only a complex 1597 while (it.hasNext()) { 1598 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1599 long ox = toLong(z[0]); 1600 for (int j = 0; j < is; j++) { 1601 ai64data[it.oIndex + j] = ox; 1602 } 1603 } 1604 } else if (!da.isComplex()) { // only b complex 1605 while (it.hasNext()) { 1606 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1607 long ox = toLong(z[0]); 1608 for (int j = 0; j < is; j++) { 1609 ai64data[it.oIndex + j] = ox; 1610 } 1611 } 1612 } else { 1613 while (it.hasNext()) { 1614 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1615 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1616 long ox = toLong(z[0]); 1617 for (int j = 0; j < is; j++) { 1618 ai64data[it.oIndex + j] = ox; 1619 } 1620 } 1621 } 1622 } 1623 break; 1624 case Dataset.FLOAT32: 1625 float[] f32data = ((FloatDataset) result).getData(); 1626 1627 if (!da.isComplex() && !db.isComplex()) { 1628 while (it.hasNext()) { 1629 f32data[it.oIndex] = (float) op.doubleOperate(it.aDouble, it.bDouble); 1630 } 1631 } else { 1632 z = new double[2]; 1633 if (!db.isComplex()) { // only a complex 1634 while (it.hasNext()) { 1635 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1636 f32data[it.oIndex] = (float) z[0]; 1637 } 1638 } else if (!da.isComplex()) { // only b complex 1639 while (it.hasNext()) { 1640 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1641 f32data[it.oIndex] = (float) z[0]; 1642 } 1643 } else { 1644 while (it.hasNext()) { 1645 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1646 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1647 f32data[it.oIndex] = (float) z[0]; 1648 } 1649 } 1650 } 1651 break; 1652 case Dataset.FLOAT64: 1653 double[] f64data = ((DoubleDataset) result).getData(); 1654 1655 if (!da.isComplex() && !db.isComplex()) { 1656 while (it.hasNext()) { 1657 f64data[it.oIndex] = op.doubleOperate(it.aDouble, it.bDouble); 1658 } 1659 } else { 1660 z = new double[2]; 1661 if (!db.isComplex()) { // only a complex 1662 while (it.hasNext()) { 1663 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1664 f64data[it.oIndex] = z[0]; 1665 } 1666 } else if (!da.isComplex()) { // only b complex 1667 while (it.hasNext()) { 1668 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1669 f64data[it.oIndex] = z[0]; 1670 } 1671 } else { 1672 while (it.hasNext()) { 1673 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1674 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1675 f64data[it.oIndex] = z[0]; 1676 } 1677 } 1678 } 1679 break; 1680 case Dataset.ARRAYFLOAT32: 1681 float[] af32data = ((CompoundFloatDataset) result).getData(); 1682 1683 if (!da.isComplex() && !db.isComplex()) { 1684 if (is == 1) { 1685 while (it.hasNext()) { 1686 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble, it.bDouble); 1687 } 1688 } else { 1689 int ms; 1690 if (as == 1 && bs != 1) { 1691 ms = Math.min(is, bs); 1692 while (it.hasNext()) { 1693 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble, it.bDouble); 1694 for (int j = 1; j < ms; j++) { 1695 af32data[it.oIndex + j] = (float) op.doubleOperate(it.aDouble, 1696 db.getElementDoubleAbs(it.bIndex + j)); 1697 } 1698 } 1699 } else if (as != 1 && bs == 1) { 1700 ms = Math.min(is, as); 1701 while (it.hasNext()) { 1702 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble, it.bDouble); 1703 for (int j = 1; j < ms; j++) { 1704 af32data[it.oIndex + j] = (float) op 1705 .doubleOperate(da.getElementDoubleAbs(it.aIndex + j), it.bDouble); 1706 } 1707 } 1708 } else { 1709 ms = Math.min(is, Math.min(as, bs)); 1710 while (it.hasNext()) { 1711 af32data[it.oIndex] = (float) op.doubleOperate(it.aDouble, it.bDouble); 1712 for (int j = 1; j < ms; j++) { 1713 af32data[it.oIndex + j] = (float) op.doubleOperate( 1714 da.getElementDoubleAbs(it.aIndex + j), db.getElementDoubleAbs(it.bIndex + j)); 1715 } 1716 } 1717 } 1718 } 1719 } else { 1720 z = new double[2]; 1721 if (!db.isComplex()) { // only a complex 1722 while (it.hasNext()) { 1723 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1724 float ox = (float) z[0]; 1725 for (int j = 0; j < is; j++) { 1726 af32data[it.oIndex + j] = ox; 1727 } 1728 } 1729 } else if (!da.isComplex()) { // only b complex 1730 while (it.hasNext()) { 1731 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1732 float ox = (float) z[0]; 1733 for (int j = 0; j < is; j++) { 1734 af32data[it.oIndex + j] = ox; 1735 } 1736 } 1737 } else { 1738 while (it.hasNext()) { 1739 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1740 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1741 float ox = (float) z[0]; 1742 for (int j = 0; j < is; j++) { 1743 af32data[it.oIndex + j] = ox; 1744 } 1745 } 1746 } 1747 } 1748 break; 1749 case Dataset.ARRAYFLOAT64: 1750 double[] af64data = ((CompoundDoubleDataset) result).getData(); 1751 1752 if (!da.isComplex() && !db.isComplex()) { 1753 if (is == 1) { 1754 while (it.hasNext()) { 1755 af64data[it.oIndex] = op.doubleOperate(it.aDouble, it.bDouble); 1756 } 1757 } else { 1758 int ms; 1759 if (as == 1 && bs != 1) { 1760 ms = Math.min(is, bs); 1761 while (it.hasNext()) { 1762 af64data[it.oIndex] = op.doubleOperate(it.aDouble, it.bDouble); 1763 for (int j = 1; j < ms; j++) { 1764 af64data[it.oIndex + j] = op.doubleOperate(it.aDouble, 1765 db.getElementDoubleAbs(it.bIndex + j)); 1766 } 1767 } 1768 } else if (as != 1 && bs == 1) { 1769 ms = Math.min(is, as); 1770 while (it.hasNext()) { 1771 af64data[it.oIndex] = op.doubleOperate(it.aDouble, it.bDouble); 1772 for (int j = 1; j < ms; j++) { 1773 af64data[it.oIndex + j] = op.doubleOperate(da.getElementDoubleAbs(it.aIndex + j), 1774 it.bDouble); 1775 } 1776 } 1777 } else { 1778 ms = Math.min(is, Math.min(as, bs)); 1779 while (it.hasNext()) { 1780 af64data[it.oIndex] = op.doubleOperate(it.aDouble, it.bDouble); 1781 for (int j = 1; j < ms; j++) { 1782 af64data[it.oIndex + j] = op.doubleOperate(da.getElementDoubleAbs(it.aIndex + j), 1783 db.getElementDoubleAbs(it.bIndex + j)); 1784 } 1785 } 1786 } 1787 } 1788 } else { 1789 z = new double[2]; 1790 if (!db.isComplex()) { // only a complex 1791 while (it.hasNext()) { 1792 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1793 double ox = z[0]; 1794 for (int j = 0; j < is; j++) { 1795 af64data[it.oIndex + j] = ox; 1796 } 1797 } 1798 } else if (!da.isComplex()) { // only b complex 1799 while (it.hasNext()) { 1800 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1801 double ox = z[0]; 1802 for (int j = 0; j < is; j++) { 1803 af64data[it.oIndex + j] = ox; 1804 } 1805 } 1806 } else { 1807 while (it.hasNext()) { 1808 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), 1809 it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1810 double ox = z[0]; 1811 for (int j = 0; j < is; j++) { 1812 af64data[it.oIndex + j] = ox; 1813 } 1814 } 1815 } 1816 } 1817 break; 1818 case Dataset.COMPLEX64: 1819 float[] c64data = ((ComplexFloatDataset) result).getData(); 1820 z = new double[2]; 1821 1822 if (da.isComplex() || db.isComplex()) { 1823 if (!db.isComplex()) { // only a complex 1824 while (it.hasNext()) { 1825 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1826 c64data[it.oIndex] = (float) z[0]; 1827 c64data[it.oIndex + 1] = (float) z[1]; 1828 } 1829 } else if (!da.isComplex()) { // only b complex 1830 while (it.hasNext()) { 1831 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1832 c64data[it.oIndex] = (float) z[0]; 1833 c64data[it.oIndex + 1] = (float) z[1]; 1834 } 1835 } else { 1836 while (it.hasNext()) { 1837 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 1838 db.getElementDoubleAbs(it.bIndex + 1)); 1839 c64data[it.oIndex] = (float) z[0]; 1840 c64data[it.oIndex + 1] = (float) z[1]; 1841 } 1842 } 1843 } else { 1844 while (it.hasNext()) { 1845 op.complexOperate(z, it.aDouble, 0, it.bDouble, 0); 1846 c64data[it.oIndex] = (float) z[0]; 1847 c64data[it.oIndex + 1] = (float) z[1]; 1848 } 1849 } 1850 break; 1851 case Dataset.COMPLEX128: 1852 double[] c128data = ((ComplexDoubleDataset) result).getData(); 1853 z = new double[2]; 1854 1855 if (da.isComplex() || db.isComplex()) { 1856 if (!db.isComplex()) { // only a complex 1857 while (it.hasNext()) { 1858 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 0); 1859 c128data[it.oIndex] = z[0]; 1860 c128data[it.oIndex + 1] = z[1]; 1861 } 1862 } else if (!da.isComplex()) { // only b complex 1863 while (it.hasNext()) { 1864 op.complexOperate(z, it.aDouble, 0, it.bDouble, db.getElementDoubleAbs(it.bIndex + 1)); 1865 c128data[it.oIndex] = z[0]; 1866 c128data[it.oIndex + 1] = z[1]; 1867 } 1868 } else { 1869 while (it.hasNext()) { 1870 op.complexOperate(z, it.aDouble, da.getElementDoubleAbs(it.aIndex + 1), it.bDouble, 1871 db.getElementDoubleAbs(it.bIndex + 1)); 1872 c128data[it.oIndex] = z[0]; 1873 c128data[it.oIndex + 1] = z[1]; 1874 } 1875 } 1876 } else { 1877 while (it.hasNext()) { 1878 op.complexOperate(z, it.aDouble, 0, it.bDouble, 0); 1879 c128data[it.oIndex] = z[0]; 1880 c128data[it.oIndex + 1] = z[1]; 1881 } 1882 } 1883 break; 1884 default: 1885 throw new UnsupportedOperationException("operate does not support this dataset type"); 1886 } 1887 1888 // set the name based on the changes made 1889 result.setName(op.toString(da.getName(), db.getName())); 1890 1891 return result; 1892 } 1893}