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