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