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