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                        final int bOffset = bds.getOffset();
665                        if (useLong) { // note no complex longs
666                                final long lb = bds.getElementLongAbs(bOffset);
667                                while (it.hasNext()) {
668                                        data[it.index] += lb;
669                                }
670                        } else {
671                                final double db = bds.getElementDoubleAbs(bOffset);
672                                if (!bds.isComplex() || bds.getElementDoubleAbs(bOffset + 1) == 0) {
673                                        while (it.hasNext()) {
674                                                data[it.index] += db;
675                                        }
676                                } else {
677                                        final double vi = bds.getElementDoubleAbs(bOffset + 1);
678                                        while (it.hasNext()) {
679                                                data[it.index]     += db;
680                                                data[it.index + 1] += vi;
681                                        }
682                                }
683                        }
684                } else {
685                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
686                        it.setOutputDouble(!useLong);
687                        if (useLong) { // note no complex longs
688                                while (it.hasNext()) {
689                                        data[it.aIndex] += it.bLong;
690                                }
691                        } else {
692                                if (bds.isComplex()) {
693                                        while (it.hasNext()) {
694                                                data[it.aIndex]     += it.bDouble;
695                                                data[it.aIndex + 1] += bds.getElementDoubleAbs(it.bIndex + 1);
696                                        }
697                                } else {
698                                        while (it.hasNext()) {
699                                                data[it.aIndex] += it.bDouble;
700                                        }
701                                }
702                        }
703                }
704                return this;
705        }
706
707        @Override
708        public ComplexFloatDataset isubtract(final Object b) {
709                setDirty();
710                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
711                boolean useLong = bds.getElementClass().equals(Long.class);
712                if (bds.getSize() == 1) {
713                        final IndexIterator it = getIterator();
714                        final int bOffset = bds.getOffset();
715                        if (useLong) { // note no complex longs
716                                final long lb = bds.getElementLongAbs(bOffset);
717                                while (it.hasNext()) {
718                                        data[it.index] -= lb;
719                                }
720                        } else {
721                                final double db = bds.getElementDoubleAbs(bOffset);
722                                if (!bds.isComplex() || bds.getElementDoubleAbs(bOffset + 1) == 0) {
723                                        while (it.hasNext()) {
724                                                data[it.index] -= db;
725                                        }
726                                } else {
727                                        final double vi = bds.getElementDoubleAbs(bOffset + 1);
728                                        while (it.hasNext()) {
729                                                data[it.index]     -= db;
730                                                data[it.index + 1] -= vi;
731                                        }
732                                }
733                        }
734                } else {
735                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
736                        it.setOutputDouble(!useLong);
737                        if (useLong) { // note no complex longs
738                                while (it.hasNext()) {
739                                        data[it.aIndex] -= it.bLong;
740                                }
741                        } else {
742                                if (bds.isComplex()) {
743                                        while (it.hasNext()) {
744                                                data[it.aIndex]     -= it.bDouble;
745                                                data[it.aIndex + 1] -= bds.getElementDoubleAbs(it.bIndex + 1);
746                                        }
747                                } else {
748                                        while (it.hasNext()) {
749                                                data[it.aIndex] -= it.bDouble;
750                                        }
751                                }
752                        }
753                }
754                return this;
755        }
756
757        @Override
758        public ComplexFloatDataset imultiply(final Object b) {
759                setDirty();
760                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
761                boolean useLong = bds.getElementClass().equals(Long.class);
762                if (bds.getSize() == 1) {
763                        final IndexIterator it = getIterator();
764                        final int bOffset = bds.getOffset();
765                        if (useLong) { // note no complex longs
766                                final long r2 = bds.getElementLongAbs(bOffset);
767                                while (it.hasNext()) {
768                                        data[it.index]     *= r2;
769                                        data[it.index + 1] *= r2;
770                                }
771                        } else {
772                                final double r2 = bds.getElementDoubleAbs(bOffset);
773                                if (!bds.isComplex() || bds.getElementDoubleAbs(bOffset + 1) == 0) {
774                                        while (it.hasNext()) {
775                                                data[it.index]     *= r2;
776                                                data[it.index + 1] *= r2;
777                                        }
778                                } else {
779                                        final double i2 = bds.getElementDoubleAbs(bOffset + 1);
780                                        while (it.hasNext()) {
781                                                double r1 = data[it.index];
782                                                double i1 = data[it.index + 1];
783                                                data[it.index]     = (float) (r1*r2 - i1*i2); // ADD_CAST
784                                                data[it.index + 1] = (float) (r1*i2 + i1*r2); // ADD_CAST
785                                        }
786                                }
787                        }
788                } else {
789                        final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
790                        it.setOutputDouble(!useLong);
791                        if (useLong) { // note no complex longs
792                                while (it.hasNext()) {
793                                        data[it.aIndex]     *= it.bDouble;
794                                        data[it.aIndex + 1] *= it.bDouble;
795                                }
796                        } else {
797                                if (bds.isComplex()) {
798                                        while (it.hasNext()) {
799                                                double r1 = it.aDouble;
800                                                double r2 = it.bDouble;
801                                                double i1 = data[it.aIndex + 1];
802                                                double i2 = bds.getElementDoubleAbs(it.bIndex + 1);
803                                                data[it.aIndex]     = (float) (r1*r2 - i1*i2); // ADD_CAST
804                                                data[it.aIndex + 1] = (float) (r1*i2 + i1*r2); // ADD_CAST
805                                        }
806                                } else {
807                                        while (it.hasNext()) {
808                                                data[it.aIndex]     *= it.bDouble;
809                                                data[it.aIndex + 1] *= it.bDouble;
810                                        }
811                                }
812                        }
813                }
814                return this;
815        }
816
817        @Override
818        public ComplexFloatDataset idivide(final Object b) {
819                setDirty();
820                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
821                boolean useLong = bds.getElementClass().equals(Long.class);
822                if (bds.getSize() == 1) {
823                        final IndexIterator it = getIterator();
824                        final int bOffset = bds.getOffset();
825                        if (useLong) { // note no complex longs
826                                final long r2 = bds.getElementLongAbs(bOffset);
827                                while (it.hasNext()) {
828                                        data[it.index]     /= r2;
829                                        data[it.index + 1] /= r2;
830                                }
831                        } else {
832                                final double r2 = bds.getElementDoubleAbs(bOffset);
833                                if (!bds.isComplex() || bds.getElementDoubleAbs(bOffset + 1) == 0) {
834                                        while (it.hasNext()) {
835                                                data[it.index]     /= r2;
836                                                data[it.index + 1] /= r2;
837                                        }
838                                } else {
839                                        final double i2 = bds.getElementDoubleAbs(bOffset + 1);
840                                        if (Math.abs(r2) < Math.abs(i2)) {
841                                                double q = r2/i2;
842                                                double den = r2*q + i2;
843                                                while (it.hasNext()) {
844                                                        double r1 = data[it.index];
845                                                        double i1 = data[it.index + 1];
846                                                        data[it.index]     = (float) ((r1*q + i1) / den); // ADD_CAST
847                                                        data[it.index + 1] = (float) ((i1*q - r1) / den); // ADD_CAST
848                                                }
849                                        } else {
850                                                double q = i2/r2;
851                                                double den = i2*q + r2;
852                                                if (den == 0) {
853                                                        while (it.hasNext()) {
854                                                                data[it.index]     = Float.NaN; // CLASS_TYPE
855                                                                data[it.index + 1] = Float.NaN; // CLASS_TYPE
856                                                        }
857                                                } else {
858                                                        while (it.hasNext()) {
859                                                                double r1 = data[it.index];
860                                                                double i1 = data[it.index + 1];
861                                                                data[it.index]     = (float) ((i1 * q + r1) / den); // ADD_CAST
862                                                                data[it.index + 1] = (float) ((i1 - r1 * q) / den); // ADD_CAST
863                                                        }
864                                                }
865                                        }
866                                }
867                        }
868                } else {
869                        final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
870                        it.setOutputDouble(!useLong);
871                        if (useLong) {
872                                while (it.hasNext()) {
873                                        data[it.aIndex]     /= it.bLong;
874                                        data[it.aIndex + 1] /= it.bLong;
875                                }
876                        } else {
877                                if (bds.isComplex()) {
878                                        while (it.hasNext()) {
879                                                double r1 = it.aDouble;
880                                                double r2 = it.bDouble;
881                                                double i1 = data[it.aIndex + 1];
882                                                double i2 = bds.getElementDoubleAbs(it.bIndex + 1);
883                                                if (Math.abs(r2) < Math.abs(i2)) {
884                                                        double q = r2/i2;
885                                                        double den = r2*q + i2;
886                                                        data[it.aIndex]     = (float) ((r1*q + i1) / den); // ADD_CAST
887                                                        data[it.aIndex + 1] = (float) ((i1*q - r1) / den); // ADD_CAST
888                                                } else {
889                                                        double q = i2/r2;
890                                                        double den = i2*q + r2;
891                                                        if (den == 0) {
892                                                                data[it.aIndex]     = Float.NaN; // CLASS_TYPE
893                                                                data[it.aIndex + 1] = Float.NaN; // CLASS_TYPE
894                                                        } else {
895                                                                data[it.aIndex]     = (float) ((i1 * q + r1) / den); // ADD_CAST
896                                                                data[it.aIndex + 1] = (float) ((i1 - r1 * q) / den); // ADD_CAST
897                                                        }
898                                                }
899                                        }
900                                } else {
901                                        while (it.hasNext()) {
902                                                data[it.aIndex]     /= it.bDouble;
903                                                data[it.aIndex + 1] /= it.bDouble;
904                                        }
905                                }
906                        }
907                }
908                return this;
909        }
910
911        @Override
912        public ComplexFloatDataset iremainder(final Object b) {
913                throw new UnsupportedOperationException("Unsupported method for class");
914        }
915
916        @Override
917        public ComplexFloatDataset ipower(final Object b) {
918                setDirty();
919                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
920                if (bds.getSize() == 1) {
921                        final IndexIterator it = getIterator();
922                        final int bOffset = bds.getOffset();
923                        final double r2 = bds.getElementDoubleAbs(bOffset);
924                        if (!bds.isComplex() || bds.getElementDoubleAbs(bOffset + 1) == 0) {
925                                while (it.hasNext()) {
926                                        final Complex zd = new Complex(data[it.index], data[it.index + 1]).pow(r2);
927                                        data[it.index]     = (float) zd.getReal(); // ADD_CAST
928                                        data[it.index + 1] = (float) zd.getImaginary(); // ADD_CAST
929                                }
930                        } else {
931                                final Complex zv = new Complex(r2, bds.getElementDoubleAbs(bOffset + 1));
932                                while (it.hasNext()) {
933                                        final Complex zd = new Complex(data[it.index], data[it.index + 1]).pow(zv);
934                                        data[it.index]     = (float) zd.getReal(); // ADD_CAST
935                                        data[it.index + 1] = (float) zd.getImaginary(); // ADD_CAST
936                                }
937                        }
938                } else {
939                        final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
940                        it.setOutputDouble(true);
941                        if (bds.isComplex()) {
942                                while (it.hasNext()) {
943                                        final Complex zv = new Complex(it.bDouble, bds.getElementDoubleAbs(it.bIndex + 1));
944                                        final Complex zd = new Complex(it.aDouble, data[it.aIndex + 1]).pow(zv);
945                                        data[it.aIndex]     = (float) zd.getReal(); // ADD_CAST
946                                        data[it.aIndex + 1] = (float) zd.getImaginary(); // ADD_CAST
947                                }
948                        } else {
949                                while (it.hasNext()) {
950                                        final Complex zd = new Complex(it.aDouble, data[it.aIndex + 1]).pow(it.bDouble);
951                                        data[it.aIndex]     = (float) zd.getReal(); // ADD_CAST
952                                        data[it.aIndex + 1] = (float) zd.getImaginary(); // ADD_CAST
953                                }
954                        }
955                }
956                return this;
957        }
958
959        @Override
960        public double residual(final Object b, Dataset w, boolean ignoreNaNs) {
961                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
962                final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
963                it.setOutputDouble(true);
964                double sum = 0;
965                double comp = 0;
966                final int bis = bds.getElementsPerItem();
967
968                if (bis == 1) {
969                        if (w == null) {
970                                while (it.hasNext()) {
971                                        double diffr = it.aDouble - it.bDouble;
972                                        double diffi = data[it.aIndex + 1];
973                                        if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) {
974                                                continue;
975                                        }
976                                        double err = diffr * diffr - comp;
977                                        double temp = sum + err;
978                                        comp = (temp - sum) - err;
979                                        sum = temp;
980
981                                        err = diffi * diffi - comp;
982                                        temp = sum + err;
983                                        comp = (temp - sum) - err;
984                                        sum = temp;
985                                }
986                        } else {
987                                IndexIterator itw = w.getIterator();
988                                while (it.hasNext() && itw.hasNext()) {
989                                        final double dw = w.getElementDoubleAbs(itw.index);
990                                        double diffr = it.aDouble - it.bDouble;
991                                        double diffi = data[it.aIndex + 1];
992                                        if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) {
993                                                continue;
994                                        }
995                                        double err = diffr * diffr * dw - comp;
996                                        double temp = sum + err;
997                                        comp = (temp - sum) - err;
998                                        sum = temp;
999
1000                                        err = diffi * diffi * dw - comp;
1001                                        temp = sum + err;
1002                                        comp = (temp - sum) - err;
1003                                        sum = temp;
1004                                }
1005                        }
1006                } else {
1007                        if (w == null) {
1008                                while (it.hasNext()) {
1009                                        double diffr = it.aDouble - it.bDouble;
1010                                        double diffi = data[it.aIndex] - bds.getElementDoubleAbs(it.bIndex + 1);
1011                                        if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) {
1012                                                continue;
1013                                        }
1014                                        double err = diffr * diffr - comp;
1015                                        double temp = sum + err;
1016                                        comp = (temp - sum) - err;
1017                                        sum = temp;
1018
1019                                        err = diffi * diffi - comp;
1020                                        temp = sum + err;
1021                                        comp = (temp - sum) - err;
1022                                        sum = temp;
1023                                }
1024                        } else {
1025                                IndexIterator itw = w.getIterator();
1026                                while (it.hasNext() && itw.hasNext()) {
1027                                        final double dw = w.getElementDoubleAbs(itw.index);
1028                                        double diffr = it.aDouble - it.bDouble;
1029                                        double diffi = data[it.aIndex] - bds.getElementDoubleAbs(it.bIndex + 1);
1030                                        if (ignoreNaNs && (Double.isNaN(diffr) || Double.isNaN(diffi))) {
1031                                                continue;
1032                                        }
1033                                        double err = diffr * diffr * dw - comp;
1034                                        double temp = sum + err;
1035                                        comp = (temp - sum) - err;
1036                                        sum = temp;
1037
1038                                        err = diffi * diffi * dw - comp;
1039                                        temp = sum + err;
1040                                        comp = (temp - sum) - err;
1041                                        sum = temp;
1042                                }
1043                        }
1044                }
1045                return sum;
1046        }
1047}