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// GEN_COMMENT
014
015package org.eclipse.january.dataset;
016
017import java.util.ArrayList;
018import java.util.Arrays;
019import java.util.List;
020import java.util.Set;
021import java.util.TreeSet;
022
023import org.apache.commons.math3.complex.Complex; // NAN_OMIT
024import org.eclipse.january.metadata.StatisticsMetadata;
025
026
027/**
028 * Extend dataset for double values // PRIM_TYPE
029 */
030public class DoubleDataset extends AbstractDataset {
031        // pin UID to base class
032        private static final long serialVersionUID = Dataset.serialVersionUID;
033
034        protected double[] data; // subclass alias // PRIM_TYPE
035
036        @Override
037        protected void setData() {
038                data = (double[]) odata; // PRIM_TYPE
039        }
040
041        protected static double[] createArray(final int size) { // PRIM_TYPE
042                double[] array = null; // PRIM_TYPE
043
044                try {
045                        array = new double[size]; // PRIM_TYPE
046                } catch (OutOfMemoryError e) {
047                        logger.error("The size of the dataset ({}) that is being created is too large "
048                                        + "and there is not enough memory to hold it.", size);
049                        throw new OutOfMemoryError("The dimensions given are too large, and there is "
050                                        + "not enough memory available in the Java Virtual Machine");
051                }
052                return array;
053        }
054
055        @Override
056        public int getDType() {
057                return FLOAT64; // DATA_TYPE
058        }
059
060        /**
061         * Create a null dataset
062         */
063        DoubleDataset() {
064        }
065
066        /**
067         * Create a zero-filled dataset of given shape
068         * @param shape
069         */
070        DoubleDataset(final int... shape) {
071                if (shape != null) {
072                        size = ShapeUtils.calcSize(shape);
073                        this.shape = shape.clone();
074        
075                        try {
076                                odata = data = createArray(size);
077                        } catch (Throwable t) {
078                                logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
079                                throw new IllegalArgumentException(t);
080                        }
081                }
082        }
083
084        /**
085         * Create a dataset using given data
086         * @param data
087         * @param shape
088         *            (can be null to create 1D dataset)
089         */
090        DoubleDataset(final double[] data, int... shape) { // PRIM_TYPE
091                if (data == null) {
092                        throw new IllegalArgumentException("Data must not be null");
093                }
094                if (shape == null || shape.length == 0) {
095                        shape = new int[] { data.length };
096                }
097                size = ShapeUtils.calcSize(shape);
098                if (size != data.length) {
099                        throw new IllegalArgumentException(String.format("Shape %s is not compatible with size of data array, %d",
100                                        Arrays.toString(shape), data.length));
101                }
102                this.shape = size == 0 ? null : shape.clone();
103
104                odata = this.data = data;
105        }
106
107        /**
108         * Copy a dataset
109         * @param dataset
110         */
111        DoubleDataset(final DoubleDataset dataset) {
112                copyToView(dataset, this, true, true);
113
114                try {
115                        if (dataset.stride == null) {
116                                if (dataset.data != null) {
117                                        odata = data = dataset.data.clone();
118                                }
119                        } else {
120                                offset = 0;
121                                stride = null;
122                                base = null;
123                                odata = data = createArray(size);
124
125                                IndexIterator iter = dataset.getIterator();
126                                for (int i = 0; iter.hasNext(); i++) {
127                                        data[i] = dataset.data[iter.index];
128                                }
129                        }
130                } catch (Throwable t) {
131                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
132                        throw new IllegalArgumentException(t);
133                }
134        }
135
136        /**
137         * Copy and cast a dataset to this class type
138         * @param dataset
139         */
140        DoubleDataset(final Dataset dataset) {
141                copyToView(dataset, this, true, false);
142                offset = 0;
143                stride = null;
144                base = null;
145                try {
146                        odata = data = createArray(size);
147                } catch (Throwable t) {
148                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
149                        throw new IllegalArgumentException(t);
150                }
151                IndexIterator iter = dataset.getIterator();
152                for (int i = 0; iter.hasNext(); i++) {
153                        data[i] = dataset.getElementDoubleAbs(iter.index); // GET_ELEMENT_WITH_CAST
154                }
155        }
156
157        @Override
158        public boolean equals(Object obj) {
159                if (this == obj) {
160                        return true;
161                }
162
163                if (obj == null) {
164                        return false;
165                }
166
167                if (!getClass().equals(obj.getClass())) {
168                        if (getRank() == 0) { // for zero-rank datasets
169                                return obj.equals(getObjectAbs(offset));
170                        }
171                        return false;
172                }
173
174                DoubleDataset other = (DoubleDataset) obj;
175                if (size != other.size) {
176                        return false;
177                }
178                if (!Arrays.equals(shape, other.shape)) {
179                        return false;
180                }
181                if (data == other.data && stride == null && other.stride == null) {
182                        return true;
183                }
184
185                IndexIterator iter = getIterator();
186                IndexIterator oiter = other.getIterator();
187                while (iter.hasNext() && oiter.hasNext()) {
188                        if (data[iter.index] != other.data[oiter.index]) { // OBJECT_UNEQUAL
189                                return false;
190                        }
191                }
192                return true;
193        }
194
195        @Override
196        public int hashCode() {
197                return super.hashCode();
198        }
199
200        @Override
201        public DoubleDataset clone() {
202                return new DoubleDataset(this);
203        }
204
205        /**
206         * Create a dataset from an object which could be a Java list, array (of arrays...) or Number. Ragged
207         * sequences or arrays are padded with zeros.
208         * 
209         * @param obj
210         * @return dataset with contents given by input
211         */
212        static DoubleDataset createFromObject(final Object obj) {
213                DoubleDataset result = new DoubleDataset();
214
215                if (obj != null) {
216                        result.shape = ShapeUtils.getShapeFromObject(obj);
217                        result.size = ShapeUtils.calcSize(result.shape);
218        
219                        try {
220                                result.odata = result.data = createArray(result.size);
221                        } catch (Throwable t) {
222                                logger.error("Could not create a dataset of shape {}", Arrays.toString(result.shape), t);
223                                throw new IllegalArgumentException(t);
224                        }
225        
226                        int[] pos = new int[result.shape.length];
227                        result.fillData(obj, 0, pos);
228                }
229
230                return result;
231        }
232         // NAN_OMIT
233        /** // NAN_OMIT
234         * // NAN_OMIT
235         * @param stop // NAN_OMIT
236         * @return a new 1D dataset, filled with values determined by parameters // NAN_OMIT
237         */ // NAN_OMIT
238        static DoubleDataset createRange(final double stop) { // NAN_OMIT
239                return createRange(0, stop, 1); // NAN_OMIT
240        } // NAN_OMIT
241         // NAN_OMIT
242        /** // NAN_OMIT
243         * // NAN_OMIT
244         * @param start // NAN_OMIT
245         * @param stop // NAN_OMIT
246         * @param step // NAN_OMIT
247         * @return a new 1D dataset, filled with values determined by parameters // NAN_OMIT
248         */ // NAN_OMIT
249        static DoubleDataset createRange(final double start, final double stop, final double step) { // NAN_OMIT
250                int size = calcSteps(start, stop, step); // NAN_OMIT
251                DoubleDataset result = new DoubleDataset(size); // NAN_OMIT
252                for (int i = 0; i < size; i++) { // NAN_OMIT
253                        result.data[i] = (start + i * step); // PRIM_TYPE // NAN_OMIT // ADD_CAST
254                } // NAN_OMIT
255                return result; // NAN_OMIT
256        } // NAN_OMIT
257
258        /**
259         * @param shape
260         * @return a dataset filled with ones
261         */
262        static DoubleDataset ones(final int... shape) {
263                return new DoubleDataset(shape).fill(1);
264        }
265
266        @Override
267        public DoubleDataset fill(final Object obj) {
268                setDirty();
269                double dv = DTypeUtils.toReal(obj); // PRIM_TYPE // FROM_OBJECT
270                IndexIterator iter = getIterator();
271                while (iter.hasNext()) {
272                        data[iter.index] = dv;
273                }
274
275                return this;
276        }
277
278        /**
279         * This is a typed version of {@link #getBuffer()}
280         * @return data buffer as linear array
281         */
282        public double[] getData() { // PRIM_TYPE
283                return data;
284        }
285
286        @Override
287        protected int getBufferLength() {
288                if (data == null)
289                        return 0;
290                return data.length;
291        }
292
293        @Override
294        public DoubleDataset getView(boolean deepCopyMetadata) {
295                DoubleDataset view = new DoubleDataset();
296                copyToView(this, view, true, deepCopyMetadata);
297                view.setData();
298                return view;
299        }
300
301        /**
302         * Get a value from an absolute index of the internal array. This is an internal method with no checks so can be
303         * dangerous. Use with care or ideally with an iterator.
304         * 
305         * @param index
306         *            absolute index
307         * @return value
308         */
309        public double getAbs(final int index) { // PRIM_TYPE
310                return data[index];
311        }
312
313        @Override
314        public boolean getElementBooleanAbs(final int index) {
315                return data[index] != 0; // BOOLEAN_FALSE
316        }
317
318        @Override
319        public double getElementDoubleAbs(final int index) {
320                return data[index]; // BOOLEAN_ZERO
321        }
322
323        @Override
324        public long getElementLongAbs(final int index) {
325                return DTypeUtils.toLong(data[index]); // BOOLEAN_ZERO // OMIT_TOLONG_INT
326        }
327
328        @Override
329        public Object getObjectAbs(final int index) {
330                return data[index];
331        }
332
333        @Override
334        public String getStringAbs(final int index) {
335                return stringFormat == null ? String.format("%.8g", data[index]) : // FORMAT_STRING
336                        stringFormat.format(data[index]);
337        }
338
339        /**
340         * Set a value at absolute index in the internal array. This is an internal method with no checks so can be
341         * dangerous. Use with care or ideally with an iterator.
342         * 
343         * @param index
344         *            absolute index
345         * @param val
346         *            new value
347         */
348        public void setAbs(final int index, final double val) { // PRIM_TYPE
349                setDirty();
350                data[index] = val;
351        }
352
353        @Override
354        protected void setItemDirect(final int dindex, final int sindex, final Object src) {
355                setDirty();
356                double[] dsrc = (double[]) src; // PRIM_TYPE
357                data[dindex] = dsrc[sindex];
358        }
359
360        @Override
361        public void setObjectAbs(final int index, final Object obj) {
362                if (index < 0 || index > data.length) {
363                        throw new IndexOutOfBoundsException("Index given is outside dataset");
364                }
365
366                setAbs(index, DTypeUtils.toReal(obj)); // FROM_OBJECT
367        }
368
369        /**
370         * @return item in first position
371         * @since 2.0
372         */
373        public double get() { // PRIM_TYPE
374                return data[getFirst1DIndex()];
375        }
376
377        /**
378         * @param i
379         * @return item in given position
380         */
381        public double get(final int i) { // PRIM_TYPE
382                return data[get1DIndex(i)];
383        }
384
385        /**
386         * @param i
387         * @param j
388         * @return item in given position
389         */
390        public double get(final int i, final int j) { // PRIM_TYPE
391                return data[get1DIndex(i, j)];
392        }
393
394        /**
395         * @param pos
396         * @return item in given position
397         */
398        public double get(final int... pos) { // PRIM_TYPE
399                return data[get1DIndex(pos)];
400        }
401
402        @Override
403        public Object getObject() {
404                return Double.valueOf(get()); // CLASS_TYPE
405        }
406
407        @Override
408        public Object getObject(final int i) {
409                return Double.valueOf(get(i)); // CLASS_TYPE
410        }
411
412        @Override
413        public Object getObject(final int i, final int j) {
414                return Double.valueOf(get(i, j)); // CLASS_TYPE
415        }
416
417        @Override
418        public Object getObject(final int... pos) {
419                return Double.valueOf(get(pos)); // CLASS_TYPE
420        }
421
422        @Override
423        public String getString() {
424                return getStringAbs(getFirst1DIndex());
425        }
426
427        @Override
428        public String getString(final int i) {
429                return getStringAbs(get1DIndex(i));
430        }
431
432        @Override
433        public String getString(final int i, final int j) {
434                return getStringAbs(get1DIndex(i, j));
435        }
436
437        @Override
438        public String getString(final int... pos) {
439                return getStringAbs(get1DIndex(pos));
440        }
441
442        @Override
443        public double getDouble() {
444                return get(); // BOOLEAN_ZERO
445        }
446
447        @Override
448        public double getDouble(final int i) {
449                return get(i); // BOOLEAN_ZERO
450        }
451
452        @Override
453        public double getDouble(final int i, final int j) {
454                return get(i, j); // BOOLEAN_ZERO
455        }
456
457        @Override
458        public double getDouble(final int... pos) {
459                return get(pos); // BOOLEAN_ZERO
460        }
461
462        @Override
463        public float getFloat() {
464                return (float) get(); // BOOLEAN_ZERO // OMIT_REAL_CAST
465        }
466
467        @Override
468        public float getFloat(final int i) {
469                return (float) get(i); // BOOLEAN_ZERO // OMIT_REAL_CAST
470        }
471
472        @Override
473        public float getFloat(final int i, final int j) {
474                return (float) get(i, j); // BOOLEAN_ZERO // OMIT_REAL_CAST
475        }
476
477        @Override
478        public float getFloat(final int... pos) {
479                return (float) get(pos); // BOOLEAN_ZERO // OMIT_REAL_CAST
480        }
481
482        @Override
483        public long getLong() {
484                return (long) get(); // BOOLEAN_ZERO // OMIT_UPCAST
485        }
486
487        @Override
488        public long getLong(final int i) {
489                return (long) get(i); // BOOLEAN_ZERO // OMIT_UPCAST
490        }
491
492        @Override
493        public long getLong(final int i, final int j) {
494                return (long) get(i, j); // BOOLEAN_ZERO // OMIT_UPCAST
495        }
496
497        @Override
498        public long getLong(final int... pos) {
499                return (long) get(pos); // BOOLEAN_ZERO // OMIT_UPCAST
500        }
501
502        @Override
503        public int getInt() {
504                return (int) get(); // BOOLEAN_ZERO // OMIT_UPCAST
505        }
506
507        @Override
508        public int getInt(final int i) {
509                return (int) get(i); // BOOLEAN_ZERO // OMIT_UPCAST
510        }
511
512        @Override
513        public int getInt(final int i, final int j) {
514                return (int) get(i, j); // BOOLEAN_ZERO // OMIT_UPCAST
515        }
516
517        @Override
518        public int getInt(final int... pos) {
519                return (int) get(pos); // BOOLEAN_ZERO // OMIT_UPCAST
520        }
521
522        @Override
523        public short getShort() {
524                return (short) get(); // BOOLEAN_ZERO // OMIT_UPCAST
525        }
526
527        @Override
528        public short getShort(final int i) {
529                return (short) get(i); // BOOLEAN_ZERO // OMIT_UPCAST
530        }
531
532        @Override
533        public short getShort(final int i, final int j) {
534                return (short) get(i, j); // BOOLEAN_ZERO // OMIT_UPCAST
535        }
536
537        @Override
538        public short getShort(final int... pos) {
539                return (short) get(pos); // BOOLEAN_ZERO // OMIT_UPCAST
540        }
541
542        @Override
543        public byte getByte() {
544                return (byte) get(); // BOOLEAN_ZERO // OMIT_UPCAST
545        }
546
547        @Override
548        public byte getByte(final int i) {
549                return (byte) get(i); // BOOLEAN_ZERO // OMIT_UPCAST
550        }
551
552        @Override
553        public byte getByte(final int i, final int j) {
554                return (byte) get(i, j); // BOOLEAN_ZERO // OMIT_UPCAST
555        }
556
557        @Override
558        public byte getByte(final int... pos) {
559                return (byte) get(pos); // BOOLEAN_ZERO // OMIT_UPCAST
560        }
561
562        @Override
563        public boolean getBoolean() {
564                return get() != 0; // BOOLEAN_FALSE
565        }
566
567        @Override
568        public boolean getBoolean(final int i) {
569                return get(i) != 0; // BOOLEAN_FALSE
570        }
571
572        @Override
573        public boolean getBoolean(final int i, final int j) {
574                return get(i, j) != 0; // BOOLEAN_FALSE
575        }
576
577        @Override
578        public boolean getBoolean(final int... pos) {
579                return get(pos) != 0; // BOOLEAN_FALSE
580        }
581
582        /**
583         * Sets the value at first point to the passed value. The dataset must not be null
584         * 
585         * @param value
586         * @since 2.0
587         */
588        public void setItem(final double value) { // PRIM_TYPE
589                setAbs(getFirst1DIndex(), value);
590        }
591
592        /**
593         * Sets the value at a particular point to the passed value. The dataset must be 1D
594         * 
595         * @param value
596         * @param i
597         */
598        public void setItem(final double value, final int i) { // PRIM_TYPE
599                setAbs(get1DIndex(i), value);
600        }
601
602        /**
603         * Sets the value at a particular point to the passed value. The dataset must be 2D
604         * 
605         * @param value
606         * @param i
607         * @param j
608         */
609        public void setItem(final double value, final int i, final int j) { // PRIM_TYPE
610                setAbs(get1DIndex(i, j), value);
611        }
612
613        /**
614         * Sets the value at a particular point to the passed value
615         * 
616         * @param value
617         * @param pos
618         */
619        public void setItem(final double value, final int... pos) { // PRIM_TYPE
620                setAbs(get1DIndex(pos), value);
621        }
622
623        @Override
624        public void set(final Object obj) {
625                setItem(DTypeUtils.toReal(obj)); // FROM_OBJECT
626        }
627
628        @Override
629        public void set(final Object obj, final int i) {
630                setItem(DTypeUtils.toReal(obj), i); // FROM_OBJECT
631        }
632
633        @Override
634        public void set(final Object obj, final int i, final int j) {
635                setItem(DTypeUtils.toReal(obj), i, j); // FROM_OBJECT
636        }
637
638        @Override
639        public void set(final Object obj, int... pos) {
640                if (pos == null || (pos.length == 0 && shape.length > 0)) {
641                        pos = new int[shape.length];
642                }
643
644                setItem(DTypeUtils.toReal(obj), pos); // FROM_OBJECT
645        }
646
647        @Override
648        public void resize(int... newShape) {
649                setDirty();
650                final IndexIterator iter = getIterator();
651                final int nsize = ShapeUtils.calcSize(newShape);
652                final double[] ndata; // PRIM_TYPE
653                try {
654                        ndata = createArray(nsize);
655                } catch (Throwable t) {
656                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
657                        throw new IllegalArgumentException(t);
658                }
659                for (int i = 0; iter.hasNext() && i < nsize; i++) {
660                        ndata[i] = data[iter.index];
661                }
662
663                odata = data = ndata;
664                size = nsize;
665                shape = newShape;
666                stride = null;
667                offset = 0;
668                base = null;
669        }
670
671        @Override
672        public DoubleDataset sort(Integer axis) {
673                setDirty(); // BOOLEAN_OMIT
674                if (axis == null) { // BOOLEAN_OMIT
675                        if (stride == null) { // BOOLEAN_OMIT
676                                Arrays.sort(data); // BOOLEAN_OMIT
677                        } else { // BOOLEAN_OMIT
678                                DoubleDataset ads = clone().sort(null); // BOOLEAN_OMIT
679                                setSlicedView(getView(false), ads); // BOOLEAN_OMIT
680                        } // BOOLEAN_OMIT
681                } else { // BOOLEAN_OMIT
682                        axis = checkAxis(axis); // BOOLEAN_OMIT
683                         // BOOLEAN_OMIT 
684                        DoubleDataset ads = new DoubleDataset(shape[axis]); // BOOLEAN_OMIT
685                        PositionIterator pi = getPositionIterator(axis); // BOOLEAN_OMIT
686                        int[] pos = pi.getPos(); // BOOLEAN_OMIT
687                        boolean[] hit = pi.getOmit(); // BOOLEAN_OMIT
688                        while (pi.hasNext()) { // BOOLEAN_OMIT
689                                copyItemsFromAxes(pos, hit, ads); // BOOLEAN_OMIT
690                                Arrays.sort(ads.data); // BOOLEAN_OMIT
691                                setItemsOnAxes(pos, hit, ads.data); // BOOLEAN_OMIT
692                        } // BOOLEAN_OMIT
693                } // BOOLEAN_OMIT
694                return this; // BOOLEAN_OMIT
695                // throw new UnsupportedOperationException("Cannot sort dataset"); // BOOLEAN_USE
696        }
697
698        @Override
699        public DoubleDataset getUniqueItems() {
700                Set<Double> set = new TreeSet<Double>(); // CLASS_TYPE
701                IndexIterator it = getIterator();
702                while (it.hasNext()) {
703                        set.add(data[it.index]);
704                }
705
706                DoubleDataset u = new DoubleDataset(set.size()); // CLASS_TYPE
707                int i = 0;
708                double[] udata = u.getData(); // PRIM_TYPE
709                for (Double v : set) { // CLASS_TYPE
710                        udata[i++] = v;
711                }
712                return u;
713        }
714
715        @Override
716        public DoubleDataset getSlice(final SliceIterator siter) {
717                DoubleDataset result = new DoubleDataset(siter.getShape());
718                double[] rdata = result.data; // PRIM_TYPE
719
720                for (int i = 0; siter.hasNext(); i++)
721                        rdata[i] = data[siter.index];
722
723                result.setName(name + BLOCK_OPEN + Slice.createString(siter.shape, siter.start, siter.stop, siter.step) + BLOCK_CLOSE);
724                return result;
725        }
726
727        @Override
728        public void fillDataset(Dataset result, IndexIterator iter) {
729                IndexIterator riter = result.getIterator();
730                result.setDirty();
731
732                double[] rdata = ((DoubleDataset) result).data; // PRIM_TYPE
733
734                while (riter.hasNext() && iter.hasNext()) {
735                        rdata[riter.index] = data[iter.index];
736                }
737        }
738
739        @Override
740        public DoubleDataset setByBoolean(final Object obj, Dataset selection) {
741                setDirty();
742                if (obj instanceof Dataset) {
743                        final Dataset ds = (Dataset) obj;
744                        final int length = ((Number) selection.sum()).intValue();
745                        if (length != ds.getSize()) {
746                                throw new IllegalArgumentException(
747                                                "Number of true items in selection does not match number of items in dataset");
748                        }
749
750                        final IndexIterator oiter = ds.getIterator();
751                        final BooleanIterator biter = getBooleanIterator(selection);
752
753                        while (biter.hasNext() && oiter.hasNext()) {
754                                data[biter.index] = ds.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
755                        }
756                } else {
757                        final double dv = DTypeUtils.toReal(obj); // PRIM_TYPE // FROM_OBJECT
758                        final BooleanIterator biter = getBooleanIterator(selection);
759
760                        while (biter.hasNext()) {
761                                data[biter.index] = dv;
762                        }
763                }
764                return this;
765        }
766
767        @Override
768        public DoubleDataset setBy1DIndex(final Object obj, final Dataset index) {
769                setDirty();
770                if (obj instanceof Dataset) {
771                        final Dataset ds = (Dataset) obj;
772                        if (index.getSize() != ds.getSize()) {
773                                throw new IllegalArgumentException(
774                                                "Number of items in index dataset does not match number of items in dataset");
775                        }
776
777                        final IndexIterator oiter = ds.getIterator();
778                        final IntegerIterator iter = new IntegerIterator(index, size);
779
780                        while (iter.hasNext() && oiter.hasNext()) {
781                                data[iter.index] = ds.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
782                        }
783                } else {
784                        final double dv = DTypeUtils.toReal(obj); // PRIM_TYPE // FROM_OBJECT
785                        IntegerIterator iter = new IntegerIterator(index, size);
786
787                        while (iter.hasNext()) {
788                                data[iter.index] = dv;
789                        }
790                }
791                return this;
792        }
793
794        @Override
795        public DoubleDataset setByIndexes(final Object obj, final Object... indexes) {
796                setDirty();
797                final IntegersIterator iter = new IntegersIterator(shape, indexes);
798                final int[] pos = iter.getPos();
799
800                if (obj instanceof Dataset) {
801                        final Dataset ds = (Dataset) obj;
802                        if (ShapeUtils.calcSize(iter.getShape()) != ds.getSize()) {
803                                throw new IllegalArgumentException(
804                                                "Number of items in index datasets does not match number of items in dataset");
805                        }
806
807                        final IndexIterator oiter = ds.getIterator();
808
809                        while (iter.hasNext() && oiter.hasNext()) {
810                                setItem(ds.getElementDoubleAbs(oiter.index), pos); // GET_ELEMENT_WITH_CAST
811                        }
812                } else {
813                        final double dv = DTypeUtils.toReal(obj); // PRIM_TYPE // FROM_OBJECT
814
815                        while (iter.hasNext()) {
816                                setItem(dv, pos);
817                        }
818                }
819                return this;
820        }
821
822        @Override
823        DoubleDataset setSlicedView(Dataset view, Dataset d) {
824                setDirty();
825                final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(view, d);
826
827                while (it.hasNext()) {
828                        data[it.aIndex] = it.bDouble; // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex);
829                }
830                return this;
831        }
832
833        @Override
834        public DoubleDataset setSlice(final Object obj, final IndexIterator siter) {
835                setDirty();
836
837                if (obj instanceof IDataset) {
838                        final IDataset ds = (IDataset) obj;
839                        final int[] oshape = ds.getShape();
840
841                        if (!ShapeUtils.areShapesCompatible(siter.getShape(), oshape)) {
842                                throw new IllegalArgumentException(String.format(
843                                                "Input dataset is not compatible with slice: %s cf %s", Arrays.toString(oshape),
844                                                Arrays.toString(siter.getShape())));
845                        }
846
847                        if (ds instanceof Dataset) {
848                                final Dataset ads = (Dataset) ds;
849                                final IndexIterator oiter = ads.getIterator();
850
851                                while (siter.hasNext() && oiter.hasNext())
852                                        data[siter.index] = ads.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
853                        } else {
854                                final IndexIterator oiter = new PositionIterator(oshape);
855                                final int[] pos = oiter.getPos();
856
857                                while (siter.hasNext() && oiter.hasNext())
858                                        data[siter.index] = ds.getDouble(pos); // PRIM_TYPE
859                        }
860                } else {
861                        try {
862                                double v = DTypeUtils.toReal(obj); // PRIM_TYPE // FROM_OBJECT
863
864                                while (siter.hasNext())
865                                        data[siter.index] = v;
866                        } catch (IllegalArgumentException e) {
867                                throw new IllegalArgumentException("Object for setting slice is not a dataset or number");
868                        }
869                }
870                return this;
871        }
872
873        @Override
874        public void copyItemsFromAxes(final int[] pos, final boolean[] axes, final Dataset dest) {
875                double[] ddata = (double[]) dest.getBuffer(); // PRIM_TYPE
876
877                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
878                int[] sshape = ShapeUtils.squeezeShape(siter.getShape(), false);
879
880                IndexIterator diter = dest.getSliceIterator(null, sshape, null);
881
882                if (ddata.length < ShapeUtils.calcSize(sshape)) {
883                        throw new IllegalArgumentException("destination array is not large enough");
884                }
885
886                dest.setDirty();
887                while (siter.hasNext() && diter.hasNext()) {
888                        ddata[diter.index] = data[siter.index];
889                }
890        }
891
892        @Override
893        public void setItemsOnAxes(final int[] pos, final boolean[] axes, final Object src) {
894                setDirty();
895                double[] sdata = (double[]) src; // PRIM_TYPE
896
897                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
898
899                if (sdata.length < ShapeUtils.calcSize(siter.getShape())) {
900                        throw new IllegalArgumentException("destination array is not large enough");
901                }
902
903                for (int i = 0; siter.hasNext(); i++) {
904                        data[siter.index] = sdata[i];
905                }
906        }
907
908        private List<int[]> findPositions(final double value) { // PRIM_TYPE
909                IndexIterator iter = getIterator(true);
910                List<int[]> posns = new ArrayList<int[]>();
911                int[] pos = iter.getPos();
912
913                if (Double.isNaN(value)) { // CLASS_TYPE // REAL_ONLY
914                        while (iter.hasNext()) { // REAL_ONLY
915                                if (Double.isNaN(data[iter.index])) { // REAL_ONLY
916                                        posns.add(pos.clone()); // REAL_ONLY
917                                } // REAL_ONLY
918                        } // REAL_ONLY
919                } else // REAL_ONLY
920                {
921                        while (iter.hasNext()) {
922                                if (data[iter.index] == value) {
923                                        posns.add(pos.clone());
924                                }
925                        }
926                }
927                return posns;
928        }
929
930        @Override
931        public int[] maxPos(boolean... ignoreInvalids) {
932                StatisticsMetadata<Number> md = getStats(); // PRIM_TYPE // NAN_OMIT
933                // StatisticsMetadata<Number> md = getStats(); // BOOLEAN_USE
934                // StatisticsMetadata<String> md = getStringStats(); // OBJECT_USE
935                List<int[]> max = md.getMaximumPositions(ignoreInvalids);
936
937                if (max == null) {
938                        max = findPositions(md.getMaximum(ignoreInvalids).doubleValue()); // PRIM_TYPE // NAN_OMIT
939                        // max = findPositions(md.getMaximum(ignoreInvalids).intValue() != 0); // BOOLEAN_USE
940                        // max = findPositions(md.getMaximum(ignoreInvalids).toString()); // OBJECT_USE
941
942                        md.setMaximumPositions(max);
943                }
944
945                return max.get(0); // first maximum
946        }
947
948        @Override
949        public int[] minPos(boolean... ignoreInvalids) {
950                StatisticsMetadata<Number> md = getStats(); // PRIM_TYPE // NAN_OMIT
951                // StatisticsMetadata<Number> md = getStats(); // BOOLEAN_USE
952                // StatisticsMetadata<String> md = getStringStats(); // OBJECT_USE
953                List<int[]> min = md.getMinimumPositions(ignoreInvalids);
954
955                if (min == null) {
956                        min = findPositions(md.getMinimum(ignoreInvalids).doubleValue()); // PRIM_TYPE // NAN_OMIT
957                        // min = findPositions(md.getMinimum(ignoreInvalids).intValue() != 0); // BOOLEAN_USE
958                        // min = findPositions(md.getMinimum(ignoreInvalids).toString()); // OBJECT_USE
959
960                        md.setMinimumPositions(min);
961                }
962
963                return min.get(0); // first minimum
964        }
965
966        @Override
967        public boolean containsNans() {
968                IndexIterator iter = getIterator(); // REAL_ONLY
969                while (iter.hasNext()) { // REAL_ONLY
970                        if (Double.isNaN(data[iter.index])) // CLASS_TYPE // REAL_ONLY
971                                return true; // REAL_ONLY
972                } // REAL_ONLY
973                return false;
974        }
975
976        @Override
977        public boolean containsInfs() {
978                IndexIterator iter = getIterator(); // REAL_ONLY
979                while (iter.hasNext()) { // REAL_ONLY
980                        if (Double.isInfinite(data[iter.index])) // CLASS_TYPE // REAL_ONLY
981                                return true; // REAL_ONLY
982                } // REAL_ONLY
983                return false;
984        }
985
986        @Override
987        public boolean containsInvalidNumbers() {
988                IndexIterator iter = getIterator(); // REAL_ONLY
989                while (iter.hasNext()) { // REAL_ONLY
990                        double x = data[iter.index]; // PRIM_TYPE // REAL_ONLY
991                        if (Double.isNaN(x) || Double.isInfinite(x)) // CLASS_TYPE // REAL_ONLY
992                                return true; // REAL_ONLY
993                } // REAL_ONLY
994                return false;
995        }
996
997        @Override
998        public DoubleDataset iadd(final Object b) {
999                setDirty(); // NAN_OMIT
1000                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1001                boolean useLong = bds.getElementClass().equals(Long.class); // NAN_OMIT
1002                if (bds.getSize() == 1) { // NAN_OMIT
1003                        final IndexIterator it = getIterator(); // NAN_OMIT
1004                        final int bOffset = bds.getOffset(); // NAN_OMIT
1005                        if (useLong) { // NAN_OMIT
1006                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1007                                while (it.hasNext()) { // NAN_OMIT
1008                                        data[it.index] += lb; // NAN_OMIT
1009                                } // NAN_OMIT
1010                        } else { // NAN_OMIT
1011                                final double db = bds.getElementDoubleAbs(bOffset); // NAN_OMIT
1012                                while (it.hasNext()) { // NAN_OMIT
1013                                        data[it.index] += db; // NAN_OMIT
1014                                } // NAN_OMIT
1015                        } // NAN_OMIT
1016                } else { // NAN_OMIT
1017                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); // NAN_OMIT
1018                        it.setOutputDouble(!useLong); // NAN_OMIT
1019                        if (useLong) { // NAN_OMIT
1020                                while (it.hasNext()) { // NAN_OMIT
1021                                        data[it.aIndex] += it.bLong; // NAN_OMIT
1022                                } // NAN_OMIT
1023                        } else { // NAN_OMIT
1024                                while (it.hasNext()) { // NAN_OMIT
1025                                        data[it.aIndex] += it.bDouble; // NAN_OMIT
1026                                } // NAN_OMIT
1027                        } // NAN_OMIT
1028                } // NAN_OMIT
1029                return this;
1030        }
1031
1032        @Override
1033        public DoubleDataset isubtract(final Object b) {
1034                setDirty(); // NAN_OMIT
1035                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1036                boolean useLong = bds.getElementClass().equals(Long.class); // NAN_OMIT
1037                if (bds.getSize() == 1) { // NAN_OMIT
1038                        final IndexIterator it = getIterator(); // NAN_OMIT
1039                        final int bOffset = bds.getOffset(); // NAN_OMIT
1040                        if (useLong) { // NAN_OMIT
1041                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1042                                while (it.hasNext()) { // NAN_OMIT
1043                                        data[it.index] -= lb; // NAN_OMIT
1044                                } // NAN_OMIT
1045                        } else { // NAN_OMIT
1046                                final double db = bds.getElementDoubleAbs(bOffset); // NAN_OMIT
1047                                while (it.hasNext()) { // NAN_OMIT
1048                                        data[it.index] -= db; // NAN_OMIT
1049                                } // NAN_OMIT
1050                        } // NAN_OMIT
1051                } else { // NAN_OMIT
1052                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); // NAN_OMIT
1053                        if (useLong) { // NAN_OMIT
1054                                it.setOutputDouble(false); // NAN_OMIT
1055                                while (it.hasNext()) { // NAN_OMIT
1056                                        data[it.aIndex] -= it.bLong; // NAN_OMIT
1057                                } // NAN_OMIT
1058                        } else { // NAN_OMIT
1059                                it.setOutputDouble(true); // NAN_OMIT
1060                                while (it.hasNext()) { // NAN_OMIT
1061                                        data[it.aIndex] -= it.bDouble; // NAN_OMIT
1062                                } // NAN_OMIT
1063                        } // NAN_OMIT
1064                } // NAN_OMIT
1065                return this;
1066        }
1067
1068        @Override
1069        public DoubleDataset imultiply(final Object b) {
1070                setDirty(); // NAN_OMIT
1071                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1072                boolean useLong = bds.getElementClass().equals(Long.class); // NAN_OMIT
1073                if (bds.getSize() == 1) { // NAN_OMIT
1074                        final IndexIterator it = getIterator(); // NAN_OMIT
1075                        final int bOffset = bds.getOffset(); // NAN_OMIT
1076                        if (useLong) { // NAN_OMIT
1077                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1078                                while (it.hasNext()) { // NAN_OMIT
1079                                        data[it.index] *= lb; // NAN_OMIT
1080                                } // NAN_OMIT
1081                        } else { // NAN_OMIT
1082                                final double db = bds.getElementDoubleAbs(bOffset); // NAN_OMIT
1083                                while (it.hasNext()) { // NAN_OMIT
1084                                        data[it.index] *= db; // NAN_OMIT
1085                                } // NAN_OMIT
1086                        } // NAN_OMIT
1087                } else { // NAN_OMIT
1088                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); // NAN_OMIT
1089                        it.setOutputDouble(!useLong); // NAN_OMIT
1090                        if (useLong) { // NAN_OMIT
1091                                while (it.hasNext()) { // NAN_OMIT
1092                                        data[it.aIndex] *= it.bLong; // NAN_OMIT
1093                                } // NAN_OMIT
1094                        } else { // NAN_OMIT
1095                                while (it.hasNext()) { // NAN_OMIT
1096                                        data[it.aIndex] *= it.bDouble; // NAN_OMIT
1097                                } // NAN_OMIT
1098                        } // NAN_OMIT
1099                } // NAN_OMIT
1100                return this;
1101        }
1102
1103        @Override
1104        public DoubleDataset idivide(final Object b) {
1105                setDirty(); // NAN_OMIT
1106                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1107                boolean useLong = bds.getElementClass().equals(Long.class); // NAN_OMIT
1108                if (bds.getSize() == 1) { // NAN_OMIT
1109                        final int bOffset = bds.getOffset(); // NAN_OMIT
1110                        if (useLong) { // NAN_OMIT
1111                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1112                                // if (lb == 0) { // INT_USE // NAN_OMIT
1113                                //      fill(0); // INT_USE // NAN_OMIT
1114                                // } else { // INT_USE // NAN_OMIT
1115                                final IndexIterator it = getIterator(); // NAN_OMIT
1116                                while (it.hasNext()) { // NAN_OMIT
1117                                        data[it.index] /= lb; // NAN_OMIT
1118                                } // NAN_OMIT
1119                                // } // INT_USE // NAN_OMIT
1120                        } else { // NAN_OMIT
1121                                final double db = bds.getElementDoubleAbs(bOffset); // NAN_OMIT
1122                                // if (db == 0) { // INT_USE // NAN_OMIT
1123                                //      fill(0); // INT_USE // NAN_OMIT
1124                                // } else { // INT_USE // NAN_OMIT
1125                                final IndexIterator it = getIterator(); // NAN_OMIT
1126                                while (it.hasNext()) { // NAN_OMIT
1127                                        data[it.index] /= db; // NAN_OMIT
1128                                } // NAN_OMIT
1129                                // } // INT_USE // NAN_OMIT
1130                        } // NAN_OMIT
1131                } else { // NAN_OMIT
1132                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); // NAN_OMIT
1133                        it.setOutputDouble(!useLong); // NAN_OMIT
1134                        if (useLong) { // NAN_OMIT
1135                                while (it.hasNext()) { // NAN_OMIT
1136                                        // if (it.bLong == 0) { // INT_USE // NAN_OMIT
1137                                        //      data[it.aIndex] = 0; // INT_USE // NAN_OMIT
1138                                        // } else { // INT_USE // NAN_OMIT
1139                                        data[it.aIndex] /= it.bLong; // NAN_OMIT
1140                                        // } // INT_USE // NAN_OMIT
1141                                } // NAN_OMIT
1142                        } else { // NAN_OMIT
1143                                while (it.hasNext()) { // NAN_OMIT
1144                                        // if (it.bDouble == 0) { // INT_USE // NAN_OMIT
1145                                        //      data[it.aIndex] = 0; // INT_USE // NAN_OMIT
1146                                        // } else { // INT_USE // NAN_OMIT
1147                                        data[it.aIndex] /= it.bDouble; // NAN_OMIT
1148                                        // } // INT_USE // NAN_OMIT
1149                                } // NAN_OMIT
1150                        } // NAN_OMIT
1151                } // NAN_OMIT
1152                return this;
1153        }
1154
1155        @Override
1156        public DoubleDataset ifloor() {
1157                setDirty(); // REAL_ONLY
1158                IndexIterator it = getIterator(); // REAL_ONLY
1159                while (it.hasNext()) { // REAL_ONLY
1160                        data[it.index] = Math.floor(data[it.index]); // PRIM_TYPE // REAL_ONLY // ADD_CAST
1161                } // REAL_ONLY
1162                return this;
1163        }
1164
1165        @Override
1166        public DoubleDataset iremainder(final Object b) {
1167                setDirty(); // NAN_OMIT
1168                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1169                boolean useLong = bds.getElementClass().equals(Long.class); // NAN_OMIT
1170                if (bds.getSize() == 1) { // NAN_OMIT
1171                        final int bOffset = bds.getOffset(); // NAN_OMIT
1172                        if (useLong) { // NAN_OMIT
1173                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1174                                // if (lb == 0) { // INT_USE // NAN_OMIT
1175                                //      fill(0); // INT_USE // NAN_OMIT
1176                                // } else { // INT_USE // NAN_OMIT
1177                                final IndexIterator it = getIterator(); // NAN_OMIT
1178                                while (it.hasNext()) { // NAN_OMIT
1179                                        data[it.index] %= lb; // NAN_OMIT
1180                                } // NAN_OMIT
1181                                // } // INT_USE // NAN_OMIT
1182                        } else { // NAN_OMIT
1183                                final long lb = bds.getElementLongAbs(bOffset); // NAN_OMIT
1184                                // if (lb == 0) { // INT_USE // NAN_OMIT
1185                                //      fill(0); // INT_USE // NAN_OMIT
1186                                // } else { // INT_USE // NAN_OMIT
1187                                final IndexIterator it = getIterator(); // NAN_OMIT
1188                                while (it.hasNext()) { // NAN_OMIT
1189                                        data[it.index] %= lb; // NAN_OMIT
1190                                } // NAN_OMIT
1191                                // } // INT_USE // NAN_OMIT
1192                        } // NAN_OMIT
1193                } else { // NAN_OMIT
1194                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds); // NAN_OMIT
1195                        it.setOutputDouble(!useLong); // NAN_OMIT
1196                        if (useLong) { // NAN_OMIT
1197                                while (it.hasNext()) { // NAN_OMIT
1198                                        data[it.aIndex] %= it.bLong; // NAN_OMIT // INT_EXCEPTION
1199                                } // NAN_OMIT
1200                        } else { // NAN_OMIT
1201                                while (it.hasNext()) { // NAN_OMIT
1202                                        data[it.aIndex] %= it.bDouble; // NAN_OMIT
1203                                } // NAN_OMIT
1204                        } // NAN_OMIT
1205                } // NAN_OMIT
1206                return this;
1207        }
1208
1209        @Override
1210        public DoubleDataset ipower(final Object b) {
1211                setDirty(); // NAN_OMIT
1212                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1213                if (bds.getSize() == 1) { // NAN_OMIT
1214                        final int bOffset = bds.getOffset(); // NAN_OMIT
1215                        final double vr = bds.getElementDoubleAbs(bOffset); // NAN_OMIT
1216                        final IndexIterator it = getIterator(); // NAN_OMIT
1217                        if (bds.isComplex()) { // NAN_OMIT
1218                                final double vi = bds.getElementDoubleAbs(bOffset + 1); // NAN_OMIT
1219                                if (vi == 0) { // NAN_OMIT
1220                                        while (it.hasNext()) { // NAN_OMIT
1221                                                final double v = Math.pow(data[it.index], vr); // NAN_OMIT
1222                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE // NAN_OMIT
1223                                                //      data[it.index] = 0; // INT_USE // NAN_OMIT
1224                                                // } else { // INT_USE // NAN_OMIT
1225                                                data[it.index] = v; // PRIM_TYPE_LONG // NAN_OMIT // ADD_CAST
1226                                                // } // INT_USE // NAN_OMIT
1227                                        } // NAN_OMIT
1228                                } else { // NAN_OMIT
1229                                        final Complex zv = new Complex(vr, vi); // NAN_OMIT
1230                                        while (it.hasNext()) { // NAN_OMIT
1231                                                Complex zd = new Complex(data[it.index], 0); // NAN_OMIT
1232                                                final double v = zd.pow(zv).getReal(); // NAN_OMIT
1233                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE // NAN_OMIT
1234                                                //      data[it.index] = 0; // INT_USE // NAN_OMIT
1235                                                // } else { // INT_USE // NAN_OMIT
1236                                                data[it.index] = v; // PRIM_TYPE_LONG // NAN_OMIT // ADD_CAST
1237                                                // } // INT_USE // NAN_OMIT
1238                                        } // NAN_OMIT
1239                                } // NAN_OMIT
1240                        } else {// NAN_OMIT
1241                                while (it.hasNext()) { // NAN_OMIT
1242                                        final double v = Math.pow(data[it.index], vr); // NAN_OMIT
1243                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE // NAN_OMIT
1244                                        //      data[it.index] = 0; // INT_USE // NAN_OMIT
1245                                        // } else { // INT_USE // NAN_OMIT
1246                                        data[it.index] = v; // PRIM_TYPE_LONG // NAN_OMIT // ADD_CAST
1247                                        // } // INT_USE // NAN_OMIT
1248                                } // NAN_OMIT
1249                        } // NAN_OMIT
1250                } else { // NAN_OMIT
1251                        final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); // NAN_OMIT
1252                        it.setOutputDouble(true); // NAN_OMIT
1253                        if (bds.isComplex()) { // NAN_OMIT
1254                                while (it.hasNext()) { // NAN_OMIT
1255                                        final Complex zv = new Complex(it.bDouble, bds.getElementDoubleAbs(it.bIndex + 1)); // NAN_OMIT
1256                                        final double v = new Complex(it.aDouble, 0).pow(zv).getReal(); // NAN_OMIT
1257                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE // NAN_OMIT
1258                                        //      data[it.aIndex] = 0; // INT_USE // NAN_OMIT
1259                                        // } else { // INT_USE // NAN_OMIT
1260                                        data[it.aIndex] = v; // PRIM_TYPE_LONG // NAN_OMIT // ADD_CAST
1261                                        // } // INT_USE // NAN_OMIT
1262                                } // NAN_OMIT
1263                        } else {// NAN_OMIT
1264                                while (it.hasNext()) { // NAN_OMIT
1265                                        final double v = Math.pow(it.aDouble, it.bDouble); // NAN_OMIT
1266                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE // NAN_OMIT
1267                                        //      data[it.aIndex] = 0; // INT_USE // NAN_OMIT
1268                                        // } else { // INT_USE // NAN_OMIT
1269                                        data[it.aIndex] = v; // PRIM_TYPE_LONG // NAN_OMIT // ADD_CAST
1270                                        // } // INT_USE // NAN_OMIT
1271                                } // NAN_OMIT
1272                        } // NAN_OMIT
1273                } // NAN_OMIT
1274                return this;
1275        }
1276
1277        @Override
1278        public double residual(final Object b, final Dataset w, boolean ignoreNaNs) {
1279                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b); // NAN_OMIT
1280                final BroadcastIterator it = BroadcastIterator.createIterator(this, bds); // NAN_OMIT
1281                it.setOutputDouble(true); // NAN_OMIT
1282                double sum = 0;
1283                double comp = 0; // NAN_OMIT
1284                if (ignoreNaNs) { // REAL_ONLY // NAN_OMIT
1285                        if (w == null) { // REAL_ONLY // NAN_OMIT
1286                                while (it.hasNext()) { // REAL_ONLY // NAN_OMIT
1287                                        final double diff = it.aDouble - it.bDouble; // REAL_ONLY // NAN_OMIT
1288                                        if (Double.isNaN(diff)) // REAL_ONLY // NAN_OMIT
1289                                                continue; // REAL_ONLY // NAN_OMIT
1290                                        final double err = diff * diff - comp; // REAL_ONLY // NAN_OMIT
1291                                        final double temp = sum + err; // REAL_ONLY // NAN_OMIT
1292                                        comp = (temp - sum) - err; // REAL_ONLY // NAN_OMIT
1293                                        sum = temp; // REAL_ONLY // NAN_OMIT
1294                                } // REAL_ONLY // NAN_OMIT
1295                        } else { // REAL_ONLY // NAN_OMIT
1296                                IndexIterator itw = w.getIterator(); // REAL_ONLY // NAN_OMIT
1297                                while (it.hasNext() && itw.hasNext()) { // REAL_ONLY // NAN_OMIT
1298                                        final double diff = it.aDouble - it.bDouble; // REAL_ONLY // NAN_OMIT
1299                                        if (Double.isNaN(diff)) // REAL_ONLY // NAN_OMIT
1300                                                continue; // REAL_ONLY // NAN_OMIT
1301                                        final double err = diff * diff * w.getElementDoubleAbs(itw.index) - comp; // REAL_ONLY // NAN_OMIT
1302                                        final double temp = sum + err; // REAL_ONLY // NAN_OMIT
1303                                        comp = (temp - sum) - err; // REAL_ONLY // NAN_OMIT
1304                                        sum = temp; // REAL_ONLY // NAN_OMIT
1305                                } // REAL_ONLY // NAN_OMIT
1306                        } // REAL_ONLY // NAN_OMIT
1307                } else // REAL_ONLY // NAN_OMIT
1308                { // NAN_OMIT
1309                        if (w == null) { // NAN_OMIT
1310                                while (it.hasNext()) { // NAN_OMIT
1311                                        final double diff = it.aDouble - it.bDouble; // NAN_OMIT
1312                                        final double err = diff * diff - comp; // NAN_OMIT
1313                                        final double temp = sum + err; // NAN_OMIT
1314                                        comp = (temp - sum) - err; // NAN_OMIT
1315                                        sum = temp; // NAN_OMIT
1316                                } // NAN_OMIT
1317                        } else { // NAN_OMIT
1318                                IndexIterator itw = w.getIterator(); // NAN_OMIT
1319                                while (it.hasNext() && itw.hasNext()) { // NAN_OMIT
1320                                        final double diff = it.aDouble - it.bDouble; // NAN_OMIT
1321                                        final double err = diff * diff * w.getElementDoubleAbs(itw.index) - comp; // NAN_OMIT
1322                                        final double temp = sum + err; // NAN_OMIT
1323                                        comp = (temp - sum) - err; // NAN_OMIT
1324                                        sum = temp; // NAN_OMIT
1325                                } // NAN_OMIT
1326                        } // NAN_OMIT
1327                } // NAN_OMIT
1328                return sum;
1329        }
1330}