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}