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