001/*- 002 ******************************************************************************* 003 * Copyright (c) 2011, 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 *******************************************************************************/ 012 013// This is generated from ComplexDoubleDataset.java by fromcpxdouble.py 014 015package org.eclipse.january.dataset; 016 017 018import java.util.Arrays; 019 020import org.apache.commons.math3.complex.Complex; 021 022 023/** 024 * Extend compound dataset to hold complex float values // PRIM_TYPE 025 */ 026public class ComplexFloatDataset extends CompoundFloatDataset { // CLASS_TYPE 027 // pin UID to base class 028 private static final long serialVersionUID = Dataset.serialVersionUID; 029 030 private static final int ISIZE = 2; // number of elements per item 031 032 @Override 033 public int getDType() { 034 return Dataset.COMPLEX64; // DATA_TYPE 035 } 036 037 /** 038 * Create a null dataset 039 */ 040 ComplexFloatDataset() { 041 super(ISIZE); 042 } 043 044 /** 045 * Create a zero-filled dataset of given shape 046 * @param shape 047 */ 048 ComplexFloatDataset(final int... shape) { 049 super(ISIZE, shape); 050 } 051 052 /** 053 * Create a dataset using given data (real and imaginary parts are grouped in pairs) 054 * @param data 055 * @param shape (can be null to create 1D dataset) 056 */ 057 ComplexFloatDataset(final float[] data, final int... shape) { // PRIM_TYPE 058 super(ISIZE, data, shape); 059 } 060 061 /** 062 * Copy a dataset 063 * @param dataset 064 */ 065 ComplexFloatDataset(final ComplexFloatDataset dataset) { 066 super(dataset); 067 } 068 069 /** 070 * Create a dataset using given data (real and imaginary parts are given separately) 071 * @param realData 072 * @param imagData 073 * @param shape (can be null or zero-length to create 1D dataset) 074 */ 075 ComplexFloatDataset(final float[] realData, final float[] imagData, int... shape) { // PRIM_TYPE 076 if (realData == null || imagData == null) { 077 throw new IllegalArgumentException("Data must not be null"); 078 } 079 int dsize = realData.length > imagData.length ? imagData.length : realData.length; 080 if (shape == null || shape.length == 0) { 081 shape = new int[] {dsize}; 082 } 083 isize = ISIZE; 084 size = ShapeUtils.calcSize(shape); 085 if (size != dsize) { 086 throw new IllegalArgumentException(String.format("Shape %s is not compatible with size of data array, %d", 087 Arrays.toString(shape), dsize)); 088 } 089 this.shape = size == 0 ? null : shape.clone(); 090 091 try { 092 odata = data = createArray(size); 093 } catch (Throwable t) { 094 logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t); 095 throw new IllegalArgumentException(t); 096 } 097 098 for (int i = 0, n = 0; i < size; i++) { 099 data[n++] = realData[i]; 100 data[n++] = imagData[i]; 101 } 102 } 103 104 /** 105 * Create a dataset using given data (real and imaginary parts are given separately) 106 * @param real 107 * @param imag 108 */ 109 ComplexFloatDataset(final Dataset real, final Dataset imag) { 110 super(ISIZE, real.getShapeRef()); 111 real.checkCompatibility(imag); 112 113 IndexIterator riter = real.getIterator(); 114 IndexIterator iiter = imag.getIterator(); 115 116 for (int i = 0; riter.hasNext() && iiter.hasNext();) { 117 data[i++] = (float) real.getElementDoubleAbs(riter.index); // ADD_CAST 118 data[i++] = (float) imag.getElementDoubleAbs(iiter.index); // ADD_CAST 119 } 120 } 121 122 /** 123 * Copy and cast a dataset to this complex type 124 * @param dataset 125 */ 126 ComplexFloatDataset(final Dataset dataset) { 127 super(ISIZE, dataset.getShapeRef()); 128 copyToView(dataset, this, true, false); 129 offset = 0; 130 stride = null; 131 base = null; 132 133 IndexIterator iter = dataset.getIterator(); 134 int disize = dataset.getElementsPerItem(); 135 if (disize == 1) { 136 for (int i = 0; iter.hasNext(); i += isize) { 137 data[i] = (float) dataset.getElementDoubleAbs(iter.index); // ADD_CAST 138 } 139 } else { 140 for (int i = 0; iter.hasNext(); i += isize) { 141 data[i] = (float) dataset.getElementDoubleAbs(iter.index); // ADD_CAST 142 data[i+1] = (float) dataset.getElementDoubleAbs(iter.index+1); // ADD_CAST 143 } 144 } 145 } 146 147 @Override 148 public ComplexFloatDataset clone() { 149 return new ComplexFloatDataset(this); 150 } 151 152 /** 153 * Create a dataset from an object which could be a Java list, array (of arrays...) 154 * or Number. Ragged sequences or arrays are padded with zeros. 155 * 156 * @param obj 157 * @return dataset with contents given by input 158 */ 159 static ComplexFloatDataset createFromObject(final Object obj) { 160 ComplexFloatDataset result = new ComplexFloatDataset(); 161 162 result.shape = ShapeUtils.getShapeFromObject(obj); 163 result.size = ShapeUtils.calcSize(result.shape); 164 165 try { 166 result.odata = result.data = result.createArray(result.size); 167 } catch (Throwable t) { 168 logger.error("Could not create a dataset of shape {}", Arrays.toString(result.shape), t); 169 throw new IllegalArgumentException(t); 170 } 171 172 int[] pos = new int[result.shape.length]; 173 result.fillData(obj, 0, pos); 174 return result; 175 } 176 177 /** 178 * @param stop 179 * @return a new 1D dataset, filled with values determined by parameters 180 */ 181 static ComplexFloatDataset createRange(final double stop) { 182 return createRange(0, stop, 1); 183 } 184 185 /** 186 * @param start 187 * @param stop 188 * @param step 189 * @return a new 1D dataset, filled with values determined by parameters 190 */ 191 static ComplexFloatDataset createRange(final double start, final double stop, final double step) { 192 int size = calcSteps(start, stop, step); 193 ComplexFloatDataset result = new ComplexFloatDataset(size); 194 for (int i = 0; i < size; i ++) { 195 result.data[i*ISIZE] = (float) (start + i*step); // ADD_CAST 196 } 197 return result; 198 } 199 200 /** 201 * @param shape 202 * @return a dataset filled with ones 203 */ 204 static ComplexFloatDataset ones(final int... shape) { 205 return new ComplexFloatDataset(shape).fill(1); 206 } 207 208 @Override 209 public ComplexFloatDataset fill(final Object obj) { 210 setDirty(); 211 float vr = (float) DTypeUtils.toReal(obj); // PRIM_TYPE // ADD_CAST 212 float vi = (float) DTypeUtils.toImag(obj); // PRIM_TYPE // ADD_CAST 213 IndexIterator iter = getIterator(); 214 215 while (iter.hasNext()) { 216 data[iter.index] = vr; 217 data[iter.index+1] = vi; 218 } 219 220 return this; 221 } 222 223 @Override 224 public ComplexFloatDataset getView(boolean deepCopyMetadata) { 225 ComplexFloatDataset view = new ComplexFloatDataset(); 226 copyToView(this, view, true, deepCopyMetadata); 227 view.data = data; 228 return view; 229 } 230 231 /** 232 * Get complex value at absolute index in the internal array. 233 * 234 * This is an internal method with no checks so can be dangerous. Use with care or ideally with an iterator. 235 * 236 * @param index absolute index 237 * @return value 238 */ 239 public Complex getComplexAbs(final int index) { 240 return new Complex(data[index], data[index+1]); 241 } 242 243 @Override 244 public Object getObjectAbs(final int index) { 245 return new Complex(data[index], data[index+1]); 246 } 247 248 @Override 249 public String getStringAbs(final int index) { 250 float di = data[index + 1]; // PRIM_TYPE 251 if (stringFormat == null) { 252 return di >= 0 ? String.format("%.8g + %.8gj", data[index], di) : // FORMAT_STRING 253 String.format("%.8g - %.8gj", data[index], -di); // FORMAT_STRING 254 } 255 StringBuilder s = new StringBuilder(); 256 s.append(stringFormat.format(data[index])); 257 if (di >= 0) { 258 s.append(" + "); 259 s.append(stringFormat.format(di)); 260 } else { 261 s.append(" - "); 262 s.append(stringFormat.format(-di)); 263 } 264 s.append('j'); 265 return s.toString(); 266 } 267 268 /** 269 * Set values at absolute index in the internal array. 270 * 271 * This is an internal method with no checks so can be dangerous. Use with care or ideally with an iterator. 272 * @param index absolute index 273 * @param val new values 274 */ 275 public void setAbs(final int index, final Complex val) { 276 setAbs(index, (float) val.getReal(), (float) val.getImaginary()); // PRIM_TYPE 277 } 278 279 @Override 280 public void setObjectAbs(final int index, final Object obj) { 281 setAbs(index, (float) DTypeUtils.toReal(obj), (float) DTypeUtils.toImag(obj)); // PRIM_TYPE 282 } 283 284 /** 285 * Set item at index to complex value given by real and imaginary parts 286 * @param index absolute index 287 * @param real 288 * @param imag 289 */ 290 public void setAbs(final int index, final float real, final float imag) { // PRIM_TYPE 291 setDirty(); 292 data[index] = real; 293 data[index+1] = imag; 294 } 295 296 /** 297 * @return item in first position 298 * @since 2.0 299 */ 300 public Complex get() { 301 int n = getFirst1DIndex(); 302 Complex z = new Complex(data[n], data[n+1]); 303 return z; 304 } 305 306 /** 307 * @param i 308 * @return item in given position 309 */ 310 public Complex get(final int i) { 311 int n = get1DIndex(i); 312 Complex z = new Complex(data[n], data[n+1]); 313 return z; 314 } 315 316 /** 317 * @param i 318 * @param j 319 * @return item in given position 320 */ 321 public Complex get(final int i, final int j) { 322 int n = get1DIndex(i, j); 323 Complex z = new Complex(data[n], data[n+1]); 324 return z; 325 } 326 327 /** 328 * @param pos 329 * @return item in given position 330 */ 331 public Complex get(final int... pos) { 332 int n = get1DIndex(pos); 333 Complex z = new Complex(data[n], data[n+1]); 334 return z; 335 } 336 337 @Override 338 public Object getObject() { 339 return get(); 340 } 341 342 @Override 343 public Object getObject(final int i) { 344 return get(i); 345 } 346 347 @Override 348 public Object getObject(final int i, final int j) { 349 return get(i, j); 350 } 351 352 @Override 353 public Object getObject(final int... pos) { 354 return getComplex(pos); 355 } 356 357 /** 358 * @return item in first position 359 * @since 2.0 360 */ 361 public float getReal() { // PRIM_TYPE 362 return (float) getFirstValue(); // PRIM_TYPE 363 } 364 365 /** 366 * @param i 367 * @return item in given position 368 */ 369 public float getReal(final int i) { // PRIM_TYPE 370 return (float) getFirstValue(i); // PRIM_TYPE 371 } 372 373 /** 374 * @param i 375 * @param j 376 * @return item in given position 377 */ 378 public float getReal(final int i, final int j) { // PRIM_TYPE 379 return (float) getFirstValue(i, j); // PRIM_TYPE 380 } 381 382 /** 383 * @param pos 384 * @return item in given position 385 */ 386 public float getReal(final int... pos) { // PRIM_TYPE 387 return (float) getFirstValue(pos); // PRIM_TYPE 388 } 389 390 /** 391 * @return item in first position 392 * @since 2.0 393 */ 394 public float getImag() { // PRIM_TYPE 395 return data[getFirst1DIndex() + 1]; 396 } 397 398 /** 399 * @param i 400 * @return item in given position 401 */ 402 public float getImag(final int i) { // PRIM_TYPE 403 return data[get1DIndex(i) + 1]; 404 } 405 406 /** 407 * @param i 408 * @param j 409 * @return item in given position 410 */ 411 public float getImag(final int i, final int j) { // PRIM_TYPE 412 return data[get1DIndex(i, j) + 1]; 413 } 414 415 /** 416 * @param pos 417 * @return item in given position 418 */ 419 public float getImag(final int... pos) { // PRIM_TYPE 420 return data[get1DIndex(pos) + 1]; 421 } 422 423 /** 424 * @return item in first position 425 * @since 2.0 426 */ 427 public Complex getComplex() { 428 return get(); 429 } 430 431 /** 432 * @param i 433 * @return item in given position 434 */ 435 public Complex getComplex(final int i) { 436 return get(i); 437 } 438 439 /** 440 * @param i 441 * @param j 442 * @return item in given position 443 */ 444 public Complex getComplex(final int i, final int j) { 445 return get(i, j); 446 } 447 448 /** 449 * @param pos 450 * @return item in given position 451 */ 452 public Complex getComplex(final int... pos) { 453 return get(pos); 454 } 455 456 @Override 457 public void set(final Object obj, final int i) { 458 setItem(new float[] {(float) DTypeUtils.toReal(obj), (float) DTypeUtils.toImag(obj)}, i); // PRIM_TYPE 459 } 460 461 @Override 462 public void set(final Object obj, final int i, final int j) { 463 setItem(new float[] {(float) DTypeUtils.toReal(obj), (float) DTypeUtils.toImag(obj)}, i, j); // PRIM_TYPE 464 } 465 466 @Override 467 public void set(final Object obj, int... pos) { 468 if (pos == null || (pos.length == 0 && shape.length > 0)) { 469 pos = new int[shape.length]; 470 } 471 472 setItem(new float[] {(float) DTypeUtils.toReal(obj), (float) DTypeUtils.toImag(obj)}, pos); // PRIM_TYPE 473 } 474 475 /** 476 * Set real and imaginary values at given position 477 * @param dr 478 * @param di 479 * @param i 480 */ 481 public void set(final float dr, final float di, final int i) { // PRIM_TYPE 482 setItem(new float[] {dr, di}, i); // PRIM_TYPE 483 } 484 485 /** 486 * Set real and imaginary values at given position 487 * @param dr 488 * @param di 489 * @param i 490 * @param j 491 */ 492 public void set(final float dr, final float di, final int i, final int j) { // PRIM_TYPE 493 setItem(new float[] {dr, di}, i, j); // PRIM_TYPE 494 } 495 496 /** 497 * Set real and imaginary values at given position 498 * @param dr 499 * @param di 500 * @param pos 501 * @since 2.0 502 */ 503 public void set(final float dr, final float di, final int... pos) { // PRIM_TYPE 504 setItem(new float[] {dr, di}, pos); // PRIM_TYPE 505 } 506 507 /** 508 * @since 2.0 509 */ 510 @Override 511 public FloatDataset getRealPart() { // CLASS_TYPE 512 return getElements(0); 513 } 514 515 /** 516 * @since 2.0 517 */ 518 @Override 519 public FloatDataset getRealView() { // CLASS_TYPE 520 return getElementsView(0); 521 } 522 523 /** 524 * @return imaginary part of dataset as new dataset 525 * @since 2.0 526 */ 527 public FloatDataset getImaginaryPart() { // CLASS_TYPE 528 return getElements(1); 529 } 530 531 /** 532 * @return view of imaginary values 533 */ 534 public FloatDataset getImaginaryView() { // CLASS_TYPE 535 return getElementsView(1); 536 } 537 538 @Override 539 public Number max(boolean... switches) { 540 throw new UnsupportedOperationException("Cannot compare complex numbers"); 541 } 542 543 @Override 544 public Number min(boolean... switches) { 545 throw new UnsupportedOperationException("Cannot compare complex numbers"); 546 } 547 548 @Override 549 public Object sum(boolean... switches) { // FIXME 550 double[] sum = (double[]) super.sum(switches); 551 return new Complex(sum[0], sum[1]); 552 } 553 554 @Override 555 public Object mean(boolean... switches) { 556 double[] mean = (double[]) super.mean(switches); 557 return new Complex(mean[0], mean[1]); 558 } 559 560 @Override 561 public int[] maxPos(boolean... switches) { 562 throw new UnsupportedOperationException("Cannot compare complex numbers"); 563 } 564 565 @Override 566 public int[] minPos(boolean... switches) { 567 throw new UnsupportedOperationException("Cannot compare complex numbers"); 568 } 569 570 @Override 571 public ComplexFloatDataset getSlice(final SliceIterator siter) { 572 ComplexFloatDataset result = new ComplexFloatDataset(siter.getShape()); 573 float[] rdata = result.data; // PRIM_TYPE 574 IndexIterator riter = result.getIterator(); 575 576 while (siter.hasNext() && riter.hasNext()) { 577 rdata[riter.index] = data[siter.index]; 578 rdata[riter.index+1] = data[siter.index+1]; 579 } 580 581 result.setName(name + BLOCK_OPEN + Slice.createString(siter.shape, siter.start, siter.stop, siter.step) + BLOCK_CLOSE); 582 return result; 583 } 584 585 @Override 586 ComplexFloatDataset setSlicedView(Dataset view, Dataset d) { 587 setDirty(); 588 final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(view, d); 589 590 if (d instanceof ComplexFloatDataset || d instanceof ComplexFloatDataset) { 591 while (it.hasNext()) { 592 data[it.aIndex] = (float) it.bDouble; // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex); 593 data[it.aIndex + 1] = (float) d.getElementDoubleAbs(it.bIndex + 1); // GET_ELEMENT_WITH_CAST 594 } 595 } else { 596 while (it.hasNext()) { 597 data[it.aIndex] = (float) it.bDouble; // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex); 598 data[it.aIndex + 1] = 0; 599 } 600 } 601 return this; 602 } 603 604 @Override 605 public ComplexFloatDataset setSlice(final Object o, final IndexIterator siter) { 606 setDirty(); 607 if (o instanceof ComplexFloatDataset) { 608 ComplexFloatDataset zds = (ComplexFloatDataset) o; 609 610 if (!ShapeUtils.areShapesCompatible(siter.getShape(), zds.shape)) { 611 throw new IllegalArgumentException(String.format( 612 "Input dataset is not compatible with slice: %s cf %s", Arrays.toString(zds.shape), 613 Arrays.toString(siter.getShape()))); 614 } 615 616 IndexIterator oiter = zds.getIterator(); 617 float[] odata = zds.data; 618 619 while (siter.hasNext() && oiter.hasNext()) { 620 data[siter.index] = odata[oiter.index]; 621 data[siter.index+1] = odata[oiter.index+1]; 622 } 623 } else if (o instanceof ComplexDoubleDataset) { // IGNORE_CLASS 624 ComplexDoubleDataset zds = (ComplexDoubleDataset) o; // IGNORE_CLASS 625 626 if (!ShapeUtils.areShapesCompatible(siter.getShape(), zds.shape)) { 627 throw new IllegalArgumentException(String.format( 628 "Input dataset is not compatible with slice: %s cf %s", Arrays.toString(zds.shape), 629 Arrays.toString(siter.getShape()))); 630 } 631 632 IndexIterator oiter = zds.getIterator(); 633 double[] odata = zds.data; 634 635 while (siter.hasNext() && oiter.hasNext()) { 636 data[siter.index] = (float) odata[oiter.index]; // PRIM_TYPE // ADD_CAST 637 data[siter.index+1] = (float) odata[oiter.index+1]; // PRIM_TYPE // ADD_CAST 638 } 639 } else if (o instanceof IDataset) { 640 super.setSlice(o, siter); 641 } else { 642 try { 643 float vr = (float) DTypeUtils.toReal(o); // PRIM_TYPE // ADD_CAST 644 float vi = (float) DTypeUtils.toImag(o); // PRIM_TYPE // ADD_CAST 645 646 while (siter.hasNext()) { 647 data[siter.index] = vr; 648 data[siter.index + 1] = vi; 649 } 650 } catch (IllegalArgumentException e) { 651 throw new IllegalArgumentException("Object for setting slice is not a dataset or number"); 652 } 653 } 654 return this; 655 } 656 657 @Override 658 public ComplexFloatDataset iadd(final Object b) { 659 setDirty(); 660 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 661 boolean useLong = bds.getElementClass().equals(Long.class); 662 if (bds.getSize() == 1) { 663 final IndexIterator it = getIterator(); 664 if (useLong) { // note no complex longs 665 final long lb = bds.getElementLongAbs(0); 666 while (it.hasNext()) { 667 data[it.index] += lb; 668 } 669 } else { 670 final double db = bds.getElementDoubleAbs(0); 671 if (!bds.isComplex() || bds.getElementDoubleAbs(1) == 0) { 672 while (it.hasNext()) { 673 data[it.index] += db; 674 } 675 } else { 676 final double vi = bds.getElementDoubleAbs(1); 677 while (it.hasNext()) { 678 data[it.index] += db; 679 data[it.index + 1] += vi; 680 } 681 } 682 } 683 } else { 684 final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); 685 it.setOutputDouble(!useLong); 686 if (useLong) { // note no complex longs 687 while (it.hasNext()) { 688 data[it.aIndex] += it.bLong; 689 } 690 } else { 691 if (bds.isComplex()) { 692 while (it.hasNext()) { 693 data[it.aIndex] += it.bDouble; 694 data[it.aIndex + 1] += bds.getElementDoubleAbs(it.bIndex + 1); 695 } 696 } else { 697 while (it.hasNext()) { 698 data[it.aIndex] += it.bDouble; 699 } 700 } 701 } 702 } 703 return this; 704 } 705 706 @Override 707 public ComplexFloatDataset isubtract(final Object b) { 708 setDirty(); 709 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 710 boolean useLong = bds.getElementClass().equals(Long.class); 711 if (bds.getSize() == 1) { 712 final IndexIterator it = getIterator(); 713 if (useLong) { // note no complex longs 714 final long lb = bds.getElementLongAbs(0); 715 while (it.hasNext()) { 716 data[it.index] -= lb; 717 } 718 } else { 719 final double db = bds.getElementDoubleAbs(0); 720 if (!bds.isComplex() || bds.getElementDoubleAbs(1) == 0) { 721 while (it.hasNext()) { 722 data[it.index] -= db; 723 } 724 } else { 725 final double vi = bds.getElementDoubleAbs(1); 726 while (it.hasNext()) { 727 data[it.index] -= db; 728 data[it.index + 1] -= vi; 729 } 730 } 731 } 732 } else { 733 final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); 734 it.setOutputDouble(!useLong); 735 if (useLong) { // note no complex longs 736 while (it.hasNext()) { 737 data[it.aIndex] -= it.bLong; 738 } 739 } else { 740 if (bds.isComplex()) { 741 while (it.hasNext()) { 742 data[it.aIndex] -= it.bDouble; 743 data[it.aIndex + 1] -= bds.getElementDoubleAbs(it.bIndex + 1); 744 } 745 } else { 746 while (it.hasNext()) { 747 data[it.aIndex] -= it.bDouble; 748 } 749 } 750 } 751 } 752 return this; 753 } 754 755 @Override 756 public ComplexFloatDataset imultiply(final Object b) { 757 setDirty(); 758 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 759 boolean useLong = bds.getElementClass().equals(Long.class); 760 if (bds.getSize() == 1) { 761 final IndexIterator it = getIterator(); 762 if (useLong) { // note no complex longs 763 final long r2 = bds.getElementLongAbs(0); 764 while (it.hasNext()) { 765 data[it.index] *= r2; 766 data[it.index + 1] *= r2; 767 } 768 } else { 769 final double r2 = bds.getElementDoubleAbs(0); 770 if (!bds.isComplex() || bds.getElementDoubleAbs(1) == 0) { 771 while (it.hasNext()) { 772 data[it.index] *= r2; 773 data[it.index + 1] *= r2; 774 } 775 } else { 776 final double i2 = bds.getElementDoubleAbs(1); 777 while (it.hasNext()) { 778 double r1 = data[it.index]; 779 double i1 = data[it.index + 1]; 780 data[it.index] = (float) (r1*r2 - i1*i2); // ADD_CAST 781 data[it.index + 1] = (float) (r1*i2 + i1*r2); // ADD_CAST 782 } 783 } 784 } 785 } else { 786 final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); 787 it.setOutputDouble(!useLong); 788 if (useLong) { // note no complex longs 789 while (it.hasNext()) { 790 data[it.aIndex] *= it.bDouble; 791 data[it.aIndex + 1] *= it.bDouble; 792 } 793 } else { 794 if (bds.isComplex()) { 795 while (it.hasNext()) { 796 double r1 = it.aDouble; 797 double r2 = it.bDouble; 798 double i1 = data[it.aIndex + 1]; 799 double i2 = bds.getElementDoubleAbs(it.bIndex + 1); 800 data[it.aIndex] = (float) (r1*r2 - i1*i2); // ADD_CAST 801 data[it.aIndex + 1] = (float) (r1*i2 + i1*r2); // ADD_CAST 802 } 803 } else { 804 while (it.hasNext()) { 805 data[it.aIndex] *= it.bDouble; 806 data[it.aIndex + 1] *= it.bDouble; 807 } 808 } 809 } 810 } 811 return this; 812 } 813 814 @Override 815 public ComplexFloatDataset idivide(final Object b) { 816 setDirty(); 817 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 818 boolean useLong = bds.getElementClass().equals(Long.class); 819 if (bds.getSize() == 1) { 820 final IndexIterator it = getIterator(); 821 if (useLong) { // note no complex longs 822 final long r2 = bds.getElementLongAbs(0); 823 while (it.hasNext()) { 824 data[it.index] /= r2; 825 data[it.index + 1] /= r2; 826 } 827 } else { 828 final double r2 = bds.getElementDoubleAbs(0); 829 if (!bds.isComplex() || bds.getElementDoubleAbs(1) == 0) { 830 while (it.hasNext()) { 831 data[it.index] /= r2; 832 data[it.index + 1] /= r2; 833 } 834 } else { 835 final double i2 = bds.getElementDoubleAbs(1); 836 if (Math.abs(r2) < Math.abs(i2)) { 837 double q = r2/i2; 838 double den = r2*q + i2; 839 while (it.hasNext()) { 840 double r1 = data[it.index]; 841 double i1 = data[it.index + 1]; 842 data[it.index] = (float) ((r1*q + i1) / den); // ADD_CAST 843 data[it.index + 1] = (float) ((i1*q - r1) / den); // ADD_CAST 844 } 845 } else { 846 double q = i2/r2; 847 double den = i2*q + r2; 848 if (den == 0) { 849 while (it.hasNext()) { 850 data[it.index] = Float.NaN; // CLASS_TYPE 851 data[it.index + 1] = Float.NaN; // CLASS_TYPE 852 } 853 } else { 854 while (it.hasNext()) { 855 double r1 = data[it.index]; 856 double i1 = data[it.index + 1]; 857 data[it.index] = (float) ((i1 * q + r1) / den); // ADD_CAST 858 data[it.index + 1] = (float) ((i1 - r1 * q) / den); // ADD_CAST 859 } 860 } 861 } 862 } 863 } 864 } else { 865 final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); 866 it.setOutputDouble(!useLong); 867 if (useLong) { 868 while (it.hasNext()) { 869 data[it.aIndex] /= it.bLong; 870 data[it.aIndex + 1] /= it.bLong; 871 } 872 } else { 873 if (bds.isComplex()) { 874 while (it.hasNext()) { 875 double r1 = it.aDouble; 876 double r2 = it.bDouble; 877 double i1 = data[it.aIndex + 1]; 878 double i2 = bds.getElementDoubleAbs(it.bIndex + 1); 879 if (Math.abs(r2) < Math.abs(i2)) { 880 double q = r2/i2; 881 double den = r2*q + i2; 882 data[it.aIndex] = (float) ((r1*q + i1) / den); // ADD_CAST 883 data[it.aIndex + 1] = (float) ((i1*q - r1) / den); // ADD_CAST 884 } else { 885 double q = i2/r2; 886 double den = i2*q + r2; 887 if (den == 0) { 888 data[it.aIndex] = Float.NaN; // CLASS_TYPE 889 data[it.aIndex + 1] = Float.NaN; // CLASS_TYPE 890 } else { 891 data[it.aIndex] = (float) ((i1 * q + r1) / den); // ADD_CAST 892 data[it.aIndex + 1] = (float) ((i1 - r1 * q) / den); // ADD_CAST 893 } 894 } 895 } 896 } else { 897 while (it.hasNext()) { 898 data[it.aIndex] /= it.bDouble; 899 data[it.aIndex + 1] /= it.bDouble; 900 } 901 } 902 } 903 } 904 return this; 905 } 906 907 @Override 908 public ComplexFloatDataset iremainder(final Object b) { 909 throw new UnsupportedOperationException("Unsupported method for class"); 910 } 911 912 @Override 913 public ComplexFloatDataset ipower(final Object b) { 914 setDirty(); 915 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 916 if (bds.getSize() == 1) { 917 final IndexIterator it = getIterator(); 918 final double r2 = bds.getElementDoubleAbs(0); 919 if (!bds.isComplex() || bds.getElementDoubleAbs(1) == 0) { 920 while (it.hasNext()) { 921 final Complex zd = new Complex(data[it.index], data[it.index + 1]).pow(r2); 922 data[it.index] = (float) zd.getReal(); // ADD_CAST 923 data[it.index + 1] = (float) zd.getImaginary(); // ADD_CAST 924 } 925 } else { 926 final Complex zv = new Complex(r2, bds.getElementDoubleAbs(1)); 927 while (it.hasNext()) { 928 final Complex zd = new Complex(data[it.index], data[it.index + 1]).pow(zv); 929 data[it.index] = (float) zd.getReal(); // ADD_CAST 930 data[it.index + 1] = (float) zd.getImaginary(); // ADD_CAST 931 } 932 } 933 } else { 934 final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); 935 it.setOutputDouble(true); 936 if (bds.isComplex()) { 937 while (it.hasNext()) { 938 final Complex zv = new Complex(it.bDouble, bds.getElementDoubleAbs(it.bIndex + 1)); 939 final Complex zd = new Complex(it.aDouble, data[it.aIndex + 1]).pow(zv); 940 data[it.aIndex] = (float) zd.getReal(); // ADD_CAST 941 data[it.aIndex + 1] = (float) zd.getImaginary(); // ADD_CAST 942 } 943 } else { 944 while (it.hasNext()) { 945 final Complex zd = new Complex(it.aDouble, data[it.aIndex + 1]).pow(it.bDouble); 946 data[it.aIndex] = (float) zd.getReal(); // ADD_CAST 947 data[it.aIndex + 1] = (float) zd.getImaginary(); // ADD_CAST 948 } 949 } 950 } 951 return this; 952 } 953 954 @Override 955 public double residual(final Object b, Dataset w, boolean ignoreNaNs) { 956 Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); 957 final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); 958 it.setOutputDouble(true); 959 double sum = 0; 960 double comp = 0; 961 final int bis = bds.getElementsPerItem(); 962 963 if (bis == 1) { 964 if (w == null) { 965 while (it.hasNext()) { 966 double diffr = it.aDouble - it.bDouble; 967 double diffi = data[it.aIndex + 1]; 968 if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) { 969 continue; 970 } 971 double err = diffr * diffr - comp; 972 double temp = sum + err; 973 comp = (temp - sum) - err; 974 sum = temp; 975 976 err = diffi * diffi - comp; 977 temp = sum + err; 978 comp = (temp - sum) - err; 979 sum = temp; 980 } 981 } else { 982 IndexIterator itw = w.getIterator(); 983 while (it.hasNext() && itw.hasNext()) { 984 final double dw = w.getElementDoubleAbs(itw.index); 985 double diffr = it.aDouble - it.bDouble; 986 double diffi = data[it.aIndex + 1]; 987 if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) { 988 continue; 989 } 990 double err = diffr * diffr * dw - comp; 991 double temp = sum + err; 992 comp = (temp - sum) - err; 993 sum = temp; 994 995 err = diffi * diffi * dw - comp; 996 temp = sum + err; 997 comp = (temp - sum) - err; 998 sum = temp; 999 } 1000 } 1001 } else { 1002 if (w == null) { 1003 while (it.hasNext()) { 1004 double diffr = it.aDouble - it.bDouble; 1005 double diffi = data[it.aIndex] - bds.getElementDoubleAbs(it.bIndex + 1); 1006 if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) { 1007 continue; 1008 } 1009 double err = diffr * diffr - comp; 1010 double temp = sum + err; 1011 comp = (temp - sum) - err; 1012 sum = temp; 1013 1014 err = diffi * diffi - comp; 1015 temp = sum + err; 1016 comp = (temp - sum) - err; 1017 sum = temp; 1018 } 1019 } else { 1020 IndexIterator itw = w.getIterator(); 1021 while (it.hasNext() && itw.hasNext()) { 1022 final double dw = w.getElementDoubleAbs(itw.index); 1023 double diffr = it.aDouble - it.bDouble; 1024 double diffi = data[it.aIndex] - bds.getElementDoubleAbs(it.bIndex + 1); 1025 if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) { 1026 continue; 1027 } 1028 double err = diffr * diffr * dw - comp; 1029 double temp = sum + err; 1030 comp = (temp - sum) - err; 1031 sum = temp; 1032 1033 err = diffi * diffi * dw - comp; 1034 temp = sum + err; 1035 comp = (temp - sum) - err; 1036 sum = temp; 1037 } 1038 } 1039 } 1040 return sum; 1041 } 1042}