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