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