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.Arrays;
018
019import org.apache.commons.math3.complex.Complex;
020import org.slf4j.Logger;
021import org.slf4j.LoggerFactory;
022
023/**
024 * Extend compound dataset for double values // PRIM_TYPE
025 */
026public class CompoundDoubleDataset extends AbstractCompoundDataset {
027        // pin UID to base class
028        private static final long serialVersionUID = Dataset.serialVersionUID;
029
030        private static final Logger logger = LoggerFactory.getLogger(CompoundDoubleDataset.class);
031
032        protected double[] data; // subclass alias // PRIM_TYPE
033
034        @Override
035        protected void setData() {
036                data = (double[]) odata; // PRIM_TYPE
037        }
038
039        protected double[] createArray(final int size) { // PRIM_TYPE
040                double[] array = null; // PRIM_TYPE
041
042                try {
043                        array = new double[isize * size]; // PRIM_TYPE
044                } catch (OutOfMemoryError e) {
045                        logger.error("The size of the dataset ({}) that is being created is too large "
046                                        + "and there is not enough memory to hold it.", size);
047                        throw new OutOfMemoryError("The dimensions given are too large, and there is "
048                                        + "not enough memory available in the Java Virtual Machine");
049                }
050                return array;
051        }
052
053        /**
054         * Create a null dataset
055         */
056        CompoundDoubleDataset() {
057        }
058
059        /**
060         * Create a null dataset
061         * @param itemSize
062         */
063        CompoundDoubleDataset(final int itemSize) {
064                isize = itemSize;
065        }
066
067        /**
068         * Create a zero-filled dataset of given item size and shape
069         * @param itemSize
070         * @param shape
071         */
072        CompoundDoubleDataset(final int itemSize, final int[] shape) {
073                isize = itemSize;
074                if (shape != null) {
075                        size = ShapeUtils.calcSize(shape);
076                        this.shape = shape.clone();
077        
078                        try {
079                                odata = data = createArray(size);
080                        } catch (Throwable t) {
081                                logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
082                                throw new IllegalArgumentException(t);
083                        }
084                }
085        }
086
087        /**
088         * Copy a dataset
089         * @param dataset
090         */
091        CompoundDoubleDataset(final CompoundDoubleDataset dataset) {
092                isize = dataset.isize;
093
094                copyToView(dataset, this, true, true);
095                try {
096                        if (dataset.stride == null) {
097                                if (dataset.data != null) {
098                                        odata = data = dataset.data.clone();
099                                }
100                        } else {
101                                offset = 0;
102                                stride = null;
103                                base = null;
104                                odata = data = createArray(size);
105                                IndexIterator iter = dataset.getIterator();
106                                for (int j = 0; iter.hasNext();) {
107                                        for (int i = 0; i < isize; i++) {
108                                                data[j++] = dataset.data[iter.index + i];
109                                        }
110                                }
111                        }
112                } catch (Throwable t) {
113                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
114                        throw new IllegalArgumentException(t);
115                }
116        }
117
118        /**
119         * Create a dataset using given dataset
120         * @param dataset
121         */
122        CompoundDoubleDataset(final CompoundDataset dataset) {
123                copyToView(dataset, this, true, false);
124                offset = 0;
125                stride = null;
126                base = null;
127                isize = dataset.getElementsPerItem();
128                try {
129                        odata = data = createArray(size);
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                IndexIterator iter = dataset.getIterator();
136                for (int j = 0; iter.hasNext();) {
137                        for (int i = 0; i < isize; i++) {
138                                data[j++] = dataset.getElementDoubleAbs(iter.index + i); // GET_ELEMENT_WITH_CAST
139                        }
140                }
141        }
142
143        /**
144         * Create a dataset using given data (elements are grouped together)
145         * @param itemSize
146         * @param data
147         * @param shape
148         *            (can be null to create 1D dataset)
149         */
150        CompoundDoubleDataset(final int itemSize, final double[] data, int... shape) { // PRIM_TYPE
151                isize = itemSize;
152                if (data != null) {
153                        if (shape == null || (shape.length == 0 && data.length > isize)) {
154                                shape = new int[] { data.length / isize };
155                        }
156                        size = ShapeUtils.calcSize(shape);
157                        if (size * isize != data.length) {
158                                throw new IllegalArgumentException(String.format("Shape %s is not compatible with size of data array, %d",
159                                                Arrays.toString(shape), data.length / isize));
160                        }
161                        this.shape = size == 0 ? null : shape.clone();
162        
163                        odata = this.data = data;
164                }
165        }
166
167        /**
168         * Create a dataset using given datasets
169         * @param datasets
170         */
171        CompoundDoubleDataset(final Dataset... datasets) {
172                if (datasets.length < 1) {
173                        throw new IllegalArgumentException("Array of datasets must have length greater than zero");
174                }
175
176                for (int i = 1; i < datasets.length; i++) {
177                        datasets[0].checkCompatibility(datasets[i]);
178                }
179
180                isize = datasets.length;
181                size = ShapeUtils.calcSize(datasets[0].getShapeRef());
182                shape = datasets[0].getShape();
183
184                try {
185                        odata = data = createArray(size);
186                } catch (Throwable t) {
187                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
188                        throw new IllegalArgumentException(t);
189                }
190
191                IndexIterator[] iters = new IndexIterator[isize];
192                for (int i = 0; i < datasets.length; i++) {
193                        iters[i] = datasets[i].getIterator();
194                }
195
196                for (int j = 0; iters[0].hasNext();) {
197                        data[j++] = datasets[0].getElementDoubleAbs(iters[0].index); // GET_ELEMENT_WITH_CAST
198                        for (int i = 1; i < datasets.length; i++) {
199                                iters[i].hasNext();
200                                data[j++] = datasets[i].getElementDoubleAbs(iters[i].index); // GET_ELEMENT_WITH_CAST
201                        }
202                }
203        }
204
205        /**
206         * Cast a dataset to this compound type. If repeat is set, the first element of each item in the given dataset is
207         * repeated across all elements of an item. Otherwise, each item comprises a truncated or zero-padded copy of
208         * elements from the given dataset.
209         * @param itemSize
210         * @param repeat
211         *            repeat first element
212         * @param dataset
213         */
214        CompoundDoubleDataset(final int itemSize, final boolean repeat, final Dataset dataset) {
215                isize = itemSize;
216                size = dataset.getSize();
217                shape = dataset.getShape();
218                name = new String(dataset.getName());
219
220                try {
221                        odata = data = createArray(size);
222                } catch (Throwable t) {
223                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
224                        throw new IllegalArgumentException(t);
225                }
226                final int os = dataset.getElementsPerItem();
227
228                IndexIterator iter = dataset.getIterator();
229                if (repeat) {
230                        int i = 0;
231                        while (iter.hasNext()) {
232                                final double v = dataset.getElementDoubleAbs(iter.index); // PRIM_TYPE // GET_ELEMENT_WITH_CAST
233                                for (int k = 0; k < isize; k++) {
234                                        data[i++] = v;
235                                }
236                        }
237                } else {
238                        final int kmax = Math.min(isize, os);
239                        int i = 0;
240                        while (iter.hasNext()) {
241                                for (int k = 0; k < kmax; k++) {
242                                        data[i + k] = dataset.getElementDoubleAbs(iter.index + k); // GET_ELEMENT_WITH_CAST
243                                }
244                                i += isize;
245                        }
246                }
247        }
248
249        @Override
250        public boolean equals(Object obj) {
251                if (this == obj) {
252                        return true;
253                }
254
255                if (obj == null) {
256                        return false;
257                }
258
259                if (!getClass().equals(obj.getClass())) {
260                        if (getRank() == 0) { // for zero-rank datasets
261                                return obj.equals(getObjectAbs(offset));
262                        }
263                        return false;
264                }
265
266                CompoundDoubleDataset other = (CompoundDoubleDataset) obj;
267                if (isize != other.isize) {
268                        return false;
269                }
270                if (size != other.size) {
271                        return false;
272                }
273                if (!Arrays.equals(shape, other.shape)) {
274                        return false;
275                }
276                if (data == other.data && stride == null && other.stride == null) {
277                        return true;
278                }
279
280                IndexIterator iter = getIterator();
281                IndexIterator oiter = other.getIterator();
282                while (iter.hasNext() && oiter.hasNext()) {
283                        for (int j = 0; j < isize; j++) {
284                                if (data[iter.index+j] != other.data[oiter.index+j]) {
285                                        return false;
286                                }
287                        }
288                }
289                return true;
290        }
291
292        @Override
293        public int hashCode() {
294                return super.hashCode();
295        }
296
297        @Override
298        public CompoundDoubleDataset clone() {
299                return new CompoundDoubleDataset(this);
300        }
301
302        /**
303         * Create a dataset from an object which could be a Java list, array (of arrays...) or Number. Ragged
304         * sequences or arrays are padded with zeros. The item size is the last dimension of the corresponding
305         * elemental dataset
306         * 
307         * @param obj
308         * @return dataset with contents given by input
309         */
310        static CompoundDoubleDataset createFromObject(final Object obj) {
311                DoubleDataset result = DoubleDataset.createFromObject(obj); // CLASS_TYPE
312                return createCompoundDatasetWithLastDimension(result, true);
313        }
314
315        /**
316         * Create a 1D dataset from an object which could be a Java list, array (of arrays...) or Number. Ragged
317         * sequences or arrays are padded with zeros.
318         * 
319         * @param itemSize item size
320         * @param obj object
321         * @return dataset with contents given by input
322         */
323        public static CompoundDoubleDataset createFromObject(final int itemSize, final Object obj) {
324                DoubleDataset result = DoubleDataset.createFromObject(obj); // CLASS_TYPE
325                boolean zeroRank = result.shape == null ? false : result.shape.length == 0;
326                if (zeroRank) {
327                        result.resize(itemSize); // special case of single item
328                        result.fill(obj);
329                }
330                CompoundDoubleDataset ds = new CompoundDoubleDataset(itemSize, result.getData(), null);
331                if (zeroRank) {
332                        ds.setShape(new int[0]);
333                }
334                return ds;
335        }
336
337        /**
338         * @param stop
339         * @return a new 1D dataset, filled with values determined by parameters
340         */
341        static CompoundDoubleDataset createRange(final int itemSize, final double stop) {
342                return createRange(itemSize, 0., stop, 1.);
343        }
344
345        /**
346         * @param start
347         * @param stop
348         * @param step
349         * @return a new 1D dataset, filled with values determined by parameters
350         */
351        static CompoundDoubleDataset createRange(final int itemSize, final double start, final double stop,
352                        final double step) {
353                int size = calcSteps(start, stop, step);
354                CompoundDoubleDataset result = new CompoundDoubleDataset(itemSize, new int[] { size });
355                for (int i = 0; i < size; i++) {
356                        result.data[i * result.isize] = (start + i * step); // PRIM_TYPE // ADD_CAST
357                }
358                return result;
359        }
360
361        /**
362         * @param shape
363         * @return a dataset filled with ones
364         */
365        static CompoundDoubleDataset ones(final int itemSize, final int... shape) {
366                return new CompoundDoubleDataset(itemSize, shape).fill(1);
367        }
368
369        /**
370         * Create a compound dataset using last dimension of given dataset
371         * @param a dataset
372         * @param shareData if true, then share data when possible otherwise copy it
373         * @return compound dataset
374         */
375        public static CompoundDoubleDataset createCompoundDatasetWithLastDimension(final Dataset a, final boolean shareData) {
376                if (a.getElementsPerItem() != 1) {
377                        logger.error("Need a single-element dataset");
378                        throw new IllegalArgumentException("Need a single-element dataset");
379                }
380                if (!DoubleDataset.class.isAssignableFrom(a.getClass())) { // CLASS_TYPE
381                        logger.error("Dataset type must be double"); // PRIM_TYPE 
382                        throw new IllegalArgumentException("Dataset type must be double"); // PRIM_TYPE 
383                }
384
385                final int[] shape = a.getShapeRef();
386                if (shape == null) {
387                        return new CompoundDoubleDataset(0);
388                }
389
390                final int rank = shape.length - 1;
391                final int is = rank < 0 ? 1 : shape[rank];
392
393                CompoundDoubleDataset result = new CompoundDoubleDataset(is);
394
395                result.shape = rank > 0 ? Arrays.copyOf(shape, rank) : (rank < 0 ? new int[0] : new int[] {1});
396                result.size = ShapeUtils.calcSize(result.shape);
397                result.odata = shareData ? a.flatten().getBuffer() : a.clone().getBuffer();
398                result.setName(a.getName());
399                result.setData();
400                return result;
401        }
402
403        @Override
404        public DoubleDataset asNonCompoundDataset(final boolean shareData) { // CLASS_TYPE
405                DoubleDataset result = new DoubleDataset(); // CLASS_TYPE
406                final int is = getElementsPerItem();
407                final int rank = is == 1 ? shape.length : shape.length + 1;
408                final int[] nshape = Arrays.copyOf(shape, rank);
409                if (is != 1)
410                        nshape[rank-1] = is;
411
412                result.shape = nshape;
413                result.size = ShapeUtils.calcSize(nshape);
414                result.odata = shareData && isContiguous() ? data : clone().getBuffer();
415                result.setName(name);
416                result.setData();
417                return result;
418        }
419
420        @Override
421        public CompoundDoubleDataset fill(Object obj) {
422                setDirty();
423                if (obj instanceof Complex) {
424                        obj = new Complex(((Complex) obj).getReal(), 0);
425                }
426                double[] vr = DTypeUtils.toDoubleArray(obj, isize); // PRIM_TYPE // CLASS_TYPE
427                IndexIterator iter = getIterator();
428
429                while (iter.hasNext()) {
430                        for (int i = 0; i < isize; i++) {
431                                data[iter.index + i] = vr[i]; // PRIM_TYPE
432                        }
433                }
434
435                return this;
436        }
437
438        /**
439         * This is a typed version of {@link #getBuffer()}
440         * @return data buffer as linear array
441         */
442        public double[] getData() { // PRIM_TYPE
443                return data;
444        }
445
446        @Override
447        protected int getBufferLength() {
448                if (data == null)
449                        return 0;
450                return data.length;
451        }
452
453        @Override
454        public CompoundDoubleDataset getView(boolean deepCopyMetadata) {
455                CompoundDoubleDataset view = new CompoundDoubleDataset(isize);
456                copyToView(this, view, true, deepCopyMetadata);
457                view.setData();
458                return view;
459        }
460
461        /**
462         * Get values at absolute index in the internal array. This is an internal method with no checks so can be
463         * dangerous. Use with care or ideally with an iterator.
464         * 
465         * @param index
466         *            absolute index
467         * @return values
468         */
469        public double[] getAbs(final int index) { // PRIM_TYPE
470                double[] result = new double[isize]; // PRIM_TYPE
471                for (int i = 0; i < isize; i++) {
472                        result[i] = data[index + i];
473                }
474                return result;
475        }
476
477        /**
478         * Get values at absolute index in the internal array. This is an internal method with no checks so can be
479         * dangerous. Use with care or ideally with an iterator.
480         *
481         * @param index
482         *            absolute index
483         * @param values output destination
484         */
485        public void getAbs(final int index, final double[] values) { // PRIM_TYPE
486                for (int i = 0; i < isize; i++) {
487                        values[i] = data[index + i];
488                }
489        }
490
491        @Override
492        public boolean getElementBooleanAbs(final int index) {
493                return data[index] != 0;
494        }
495
496        @Override
497        public double getElementDoubleAbs(final int index) {
498                return data[index];
499        }
500
501        @Override
502        public long getElementLongAbs(final int index) {
503                return DTypeUtils.toLong(data[index]); // OMIT_TOLONG_INT
504        }
505
506        @Override
507        protected void setItemDirect(final int dindex, final int sindex, final Object src) {
508                setDirty();
509                double[] dsrc = (double[]) src; // PRIM_TYPE
510                for (int i = 0; i < isize; i++) {
511                        data[dindex + i] = dsrc[sindex + i];
512                }
513        }
514
515        /**
516         * Set values at absolute index in the internal array. This is an internal method with no checks so can be
517         * dangerous. Use with care or ideally with an iterator.
518         *
519         * @param index
520         *            absolute index
521         * @param val
522         *            new values
523         */
524        public void setAbs(final int index, final double[] val) { // PRIM_TYPE
525                setDirty();
526                for (int i = 0; i < isize; i++) {
527                        data[index + i] = val[i];
528                }
529        }
530
531        /**
532         * Set element value at absolute index in the internal array. This is an internal method with no checks so can be
533         * dangerous. Use with care or ideally with an iterator.
534         *
535         * @param index
536         *            absolute index
537         * @param val
538         *            new value
539         */
540        public void setAbs(final int index, final double val) { // PRIM_TYPE
541                setDirty();
542                data[index] = val;
543        }
544
545        @Override
546        public Object getObject() {
547                return getDoubleArray(); // PRIM_TYPE
548        }
549
550        @Override
551        public Object getObject(final int i) {
552                return getDoubleArray(i); // PRIM_TYPE
553        }
554
555        @Override
556        public Object getObject(final int i, final int j) {
557                return getDoubleArray(i, j); // PRIM_TYPE
558        }
559
560        @Override
561        public Object getObject(final int... pos) {
562                return getDoubleArray(pos); // PRIM_TYPE
563        }
564
565        @Override
566        public byte[] getByteArray() {
567                byte[] result = new byte[isize];
568                int index = getFirst1DIndex();
569                for (int k = 0; k < isize; k++) {
570                        result[k] = (byte) data[index + k]; // OMIT_UPCAST
571                }
572                return result;
573        }
574
575        @Override
576        public byte[] getByteArray(final int i) {
577                byte[] result = new byte[isize];
578                int index = get1DIndex(i);
579                for (int k = 0; k < isize; k++) {
580                        result[k] = (byte) data[index + k]; // OMIT_UPCAST
581                }
582                return result;
583        }
584
585        @Override
586        public byte[] getByteArray(final int i, final int j) {
587                byte[] result = new byte[isize];
588                int index = get1DIndex(i, j);
589                for (int k = 0; k < isize; k++) {
590                        result[k] = (byte) data[index + k]; // OMIT_UPCAST
591                }
592                return result;
593        }
594
595        @Override
596        public byte[] getByteArray(final int... pos) {
597                byte[] result = new byte[isize];
598                int index = get1DIndex(pos);
599                for (int k = 0; k < isize; k++) {
600                        result[k] = (byte) data[index + k]; // OMIT_UPCAST
601                }
602                return result;
603        }
604
605        @Override
606        public short[] getShortArray() {
607                short[] result = new short[isize];
608                int index = getFirst1DIndex();
609                for (int k = 0; k < isize; k++) {
610                        result[k] = (short) data[index + k]; // OMIT_UPCAST
611                }
612                return result;
613        }
614
615        @Override
616        public short[] getShortArray(final int i) {
617                short[] result = new short[isize];
618                int index = get1DIndex(i);
619                for (int k = 0; k < isize; k++) {
620                        result[k] = (short) data[index + k]; // OMIT_UPCAST
621                }
622                return result;
623        }
624
625        @Override
626        public short[] getShortArray(final int i, final int j) {
627                short[] result = new short[isize];
628                int index = get1DIndex(i, j);
629                for (int k = 0; k < isize; k++) {
630                        result[k] = (short) data[index + k]; // OMIT_UPCAST
631                }
632                return result;
633        }
634
635        @Override
636        public short[] getShortArray(final int... pos) {
637                short[] result = new short[isize];
638                int index = get1DIndex(pos);
639                for (int k = 0; k < isize; k++) {
640                        result[k] = (short) data[index + k]; // OMIT_UPCAST
641                }
642                return result;
643        }
644
645        @Override
646        public int[] getIntArray() {
647                int[] result = new int[isize];
648                int index = getFirst1DIndex();
649                for (int k = 0; k < isize; k++) {
650                        result[k] = (int) data[index + k]; // OMIT_UPCAST
651                }
652                return result;
653        }
654
655        @Override
656        public int[] getIntArray(final int i) {
657                int[] result = new int[isize];
658                int index = get1DIndex(i);
659                for (int k = 0; k < isize; k++) {
660                        result[k] = (int) data[index + k]; // OMIT_UPCAST
661                }
662                return result;
663        }
664
665        @Override
666        public int[] getIntArray(final int i, final int j) {
667                int[] result = new int[isize];
668                int index = get1DIndex(i, j);
669                for (int k = 0; k < isize; k++) {
670                        result[k] = (int) data[index + k]; // OMIT_UPCAST
671                }
672                return result;
673        }
674
675        @Override
676        public int[] getIntArray(final int... pos) {
677                int[] result = new int[isize];
678                int index = get1DIndex(pos);
679                for (int k = 0; k < isize; k++) {
680                        result[k] = (int) data[index + k]; // OMIT_UPCAST
681                }
682                return result;
683        }
684
685        @Override
686        public long[] getLongArray() {
687                long[] result = new long[isize];
688                int index = getFirst1DIndex();
689                for (int k = 0; k < isize; k++) {
690                        result[k] = (long) data[index + k]; // OMIT_UPCAST
691                }
692                return result;
693        }
694
695        @Override
696        public long[] getLongArray(final int i) {
697                long[] result = new long[isize];
698                int index = get1DIndex(i);
699                for (int k = 0; k < isize; k++) {
700                        result[k] = (long) data[index + k]; // OMIT_UPCAST
701                }
702                return result;
703        }
704
705        @Override
706        public long[] getLongArray(final int i, final int j) {
707                long[] result = new long[isize];
708                int index = get1DIndex(i, j);
709                for (int k = 0; k < isize; k++) {
710                        result[k] = (long) data[index + k]; // OMIT_UPCAST
711                }
712                return result;
713        }
714
715        @Override
716        public long[] getLongArray(final int... pos) {
717                long[] result = new long[isize];
718                int index = get1DIndex(pos);
719                for (int k = 0; k < isize; k++) {
720                        result[k] = (long) data[index + k]; // OMIT_UPCAST
721                }
722                return result;
723        }
724
725        @Override
726        public float[] getFloatArray() {
727                float[] result = new float[isize];
728                int index = getFirst1DIndex();
729                for (int k = 0; k < isize; k++) {
730                        result[k] = (float) data[index + k]; // OMIT_REAL_CAST
731                }
732                return result;
733        }
734
735        @Override
736        public float[] getFloatArray(final int i) {
737                float[] result = new float[isize];
738                int index = get1DIndex(i);
739                for (int k = 0; k < isize; k++) {
740                        result[k] = (float) data[index + k]; // OMIT_REAL_CAST
741                }
742                return result;
743        }
744
745        @Override
746        public float[] getFloatArray(final int i, final int j) {
747                float[] result = new float[isize];
748                int index = get1DIndex(i, j);
749                for (int k = 0; k < isize; k++) {
750                        result[k] = (float) data[index + k]; // OMIT_REAL_CAST
751                }
752                return result;
753        }
754
755        @Override
756        public float[] getFloatArray(final int... pos) {
757                float[] result = new float[isize];
758                int index = get1DIndex(pos);
759                for (int k = 0; k < isize; k++) {
760                        result[k] = (float) data[index + k]; // OMIT_REAL_CAST
761                }
762                return result;
763        }
764
765        @Override
766        public double[] getDoubleArray() {
767                double[] result = new double[isize];
768                int index = getFirst1DIndex();
769                for (int k = 0; k < isize; k++) {
770                        result[k] = data[index + k]; // OMIT_REAL_CAST
771                }
772                return result;
773        }
774
775        @Override
776        public double[] getDoubleArray(final int i) {
777                double[] result = new double[isize];
778                int index = get1DIndex(i);
779                for (int k = 0; k < isize; k++) {
780                        result[k] = data[index + k]; // OMIT_REAL_CAST
781                }
782                return result;
783        }
784
785        @Override
786        public double[] getDoubleArray(final int i, final int j) {
787                double[] result = new double[isize];
788                int index = get1DIndex(i, j);
789                for (int k = 0; k < isize; k++) {
790                        result[k] = data[index + k]; // OMIT_REAL_CAST
791                }
792                return result;
793        }
794
795        @Override
796        public double[] getDoubleArray(final int... pos) {
797                double[] result = new double[isize];
798                int index = get1DIndex(pos);
799                for (int k = 0; k < isize; k++) {
800                        result[k] = data[index + k]; // OMIT_REAL_CAST
801                }
802                return result;
803        }
804
805        @Override
806        public void getDoubleArrayAbs(final int index, final double[] darray) {
807                for (int i = 0; i < isize; i++) {
808                        darray[i] = data[index + i];
809                }
810        }
811
812        @Override
813        public String getString() {
814                return getStringAbs(getFirst1DIndex());
815        }
816
817        @Override
818        public String getString(final int i) {
819                return getStringAbs(get1DIndex(i));
820        }
821
822        @Override
823        public String getString(final int i, final int j) {
824                return getStringAbs(get1DIndex(i, j));
825        }
826
827        @Override
828        public String getString(final int... pos) {
829                return getStringAbs(get1DIndex(pos));
830        }
831
832        @Override
833        protected double getFirstValue() {
834                return data[getFirst1DIndex()];
835        }
836
837        @Override
838        protected double getFirstValue(int i) {
839                return data[get1DIndex(i)];
840        }
841
842        @Override
843        protected double getFirstValue(int i, int j) {
844                return data[get1DIndex(i, j)];
845        }
846
847        @Override
848        protected double getFirstValue(final int... pos) {
849                return data[get1DIndex(pos)];
850        }
851
852        @Override
853        public Object getObjectAbs(final int index) {
854                double[] result = new double[isize]; // PRIM_TYPE
855                for (int i = 0; i < isize; i++) {
856                        result[i] = data[index + i];
857                }
858                return result;
859        }
860
861        @Override
862        public String getStringAbs(final int index) {
863                StringBuilder s = new StringBuilder();
864                s.append('(');
865                s.append(stringFormat == null ? String.format("%.8g", data[index]) : // FORMAT_STRING
866                        stringFormat.format(data[index]));
867                for (int i = 1; i < isize; i++) {
868                        s.append(' ');
869                        s.append(stringFormat == null ? String.format("%.8g", data[index + i]) : // FORMAT_STRING
870                                stringFormat.format(data[index + i]));
871                }
872                s.append(')');
873                return s.toString();
874        }
875
876        @Override
877        public void setObjectAbs(final int index, Object obj) {
878                if (obj instanceof Complex) {
879                        obj = new Complex(((Complex) obj).getReal(), 0);
880                }
881                double[] oa = DTypeUtils.toDoubleArray(obj, isize); // PRIM_TYPE // CLASS_TYPE
882                setAbs(index, oa);
883        }
884
885        @Override
886        public void set(final Object obj) {
887                setItem(DTypeUtils.toDoubleArray(obj, isize)); // CLASS_TYPE
888        }
889
890        @Override
891        public void set(final Object obj, final int i) {
892                setItem(DTypeUtils.toDoubleArray(obj, isize), i); // CLASS_TYPE
893        }
894
895        @Override
896        public void set(final Object obj, final int i, final int j) {
897                setItem(DTypeUtils.toDoubleArray(obj, isize), i, j); // CLASS_TYPE
898        }
899
900        @Override
901        public void set(final Object obj, int... pos) {
902                if (pos == null || (pos.length == 0 && shape.length > 0)) {
903                        pos = new int[shape.length];
904                }
905
906                setItem(DTypeUtils.toDoubleArray(obj, isize), pos); // CLASS_TYPE
907        }
908
909        /**
910         * Set values at first position. The dataset must not be null
911         * 
912         * @param d input source
913         * @since 2.0
914         */
915        public void setItem(final double[] d) { // PRIM_TYPE
916                if (d.length > isize) {
917                        throw new IllegalArgumentException("Array is larger than number of elements in an item");
918                }
919                setAbs(getFirst1DIndex(), d);
920        }
921
922        /**
923         * Set values at given position. The dataset must be 1D
924         * 
925         * @param d input source
926         * @param i position in first dimension
927         */
928        public void setItem(final double[] d, final int i) { // PRIM_TYPE
929                if (d.length > isize) {
930                        throw new IllegalArgumentException("Array is larger than number of elements in an item");
931                }
932                setAbs(get1DIndex(i), d);
933        }
934
935        /**
936         * Set values at given position. The dataset must be 1D
937         * 
938         * @param d input source
939         * @param i position in first dimension
940         * @param j position in second dimension
941         */
942        public void setItem(final double[] d, final int i, final int j) { // PRIM_TYPE
943                if (d.length > isize) {
944                        throw new IllegalArgumentException("Array is larger than number of elements in an item");
945                }
946                setAbs(get1DIndex(i, j), d);
947        }
948
949        /**
950         * Set values at given position
951         * 
952         * @param d input source
953         * @param pos position
954         */
955        public void setItem(final double[] d, final int... pos) { // PRIM_TYPE
956                if (d.length > isize) {
957                        throw new IllegalArgumentException("Array is larger than number of elements in an item");
958                }
959                setAbs(get1DIndex(pos), d);
960        }
961
962        private void setDoubleArrayAbs(final int index, final double[] d) {
963                for (int i = 0; i < isize; i++)
964                        data[index + i] = d[i]; // ADD_CAST
965        }
966
967        @Override
968        public void resize(int... newShape) {
969                setDirty();
970                IndexIterator iter = getIterator();
971                int nsize = ShapeUtils.calcSize(newShape);
972                double[] ndata; // PRIM_TYPE
973                try {
974                        ndata = createArray(nsize);
975                } catch (Throwable t) {
976                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
977                        throw new IllegalArgumentException(t);
978                }
979
980                int i = 0;
981                while (iter.hasNext() && i < nsize) {
982                        for (int j = 0; j < isize; j++) {
983                                ndata[i++] = data[iter.index + j];
984                        }
985                }
986
987                odata = data = ndata;
988                size = nsize;
989                shape = newShape;
990                stride = null;
991                offset = 0;
992                base = null;
993        }
994
995        @Override
996        public CompoundDoubleDataset getSlice(final SliceIterator siter) {
997                CompoundDoubleDataset result = new CompoundDoubleDataset(isize, siter.getShape());
998                double[] rdata = result.data; // PRIM_TYPE
999                IndexIterator riter = result.getIterator();
1000
1001                while (siter.hasNext() && riter.hasNext()) {
1002                        for (int i = 0; i < isize; i++)
1003                                rdata[riter.index + i] = data[siter.index + i];
1004                }
1005
1006                result.setName(name + BLOCK_OPEN + Slice.createString(siter.shape, siter.start, siter.stop, siter.step) + BLOCK_CLOSE);
1007                return result;
1008        }
1009
1010        @Override
1011        public DoubleDataset getElementsView(int element) { // CLASS_TYPE
1012                if (element < 0)
1013                        element += isize;
1014                if (element < 0 || element > isize) {
1015                        throw new IllegalArgumentException(String.format("Invalid choice of element: %d/%d", element, isize));
1016                }
1017
1018                DoubleDataset view = new DoubleDataset(shape); // CLASS_TYPE
1019
1020                copyToView(this, view, true, true);
1021                view.setData();
1022                if (view.stride == null) {
1023                        int[] offset = new int[1];
1024                        view.stride = createStrides(this, offset);
1025                        view.offset = offset[0] + element;
1026                        view.base = base == null ? this : base;
1027                } else {
1028                        view.offset += element;
1029                }
1030
1031                return view;
1032        }
1033
1034        @Override
1035        public DoubleDataset getElements(int element) { // CLASS_TYPE
1036                final DoubleDataset elements = new DoubleDataset(shape); // CLASS_TYPE
1037
1038                copyElements(elements, element);
1039                return elements;
1040        }
1041
1042        @Override
1043        public void copyElements(Dataset destination, int element) {
1044                if (element < 0)
1045                        element += isize;
1046                if (element < 0 || element > isize) {
1047                        throw new IllegalArgumentException(String.format("Invalid choice of element: %d/%d", element, isize));
1048                }
1049                if (getElementClass() != destination.getElementClass()) {
1050                        throw new IllegalArgumentException("Element class of destination does not match this dataset");
1051                }
1052
1053                final IndexIterator it = getIterator(element);
1054                final double[] elements = ((DoubleDataset) destination).data; // CLASS_TYPE // PRIM_TYPE
1055                destination.setDirty();
1056
1057                int n = 0;
1058                while (it.hasNext()) {
1059                        elements[n] = data[it.index];
1060                        n++;
1061                }
1062        }
1063
1064        @Override
1065        public void setElements(Dataset source, int element) {
1066                setDirty();
1067                if (element < 0)
1068                        element += isize;
1069                if (element < 0 || element > isize) {
1070                        throw new IllegalArgumentException(String.format("Invalid choice of element: %d/%d", element, isize));
1071                }
1072                if (getElementClass() != source.getElementClass()) {
1073                        throw new IllegalArgumentException("Element class of destination does not match this dataset");
1074                }
1075
1076                final IndexIterator it = getIterator(element);
1077                final double[] elements = ((DoubleDataset) source).data; // CLASS_TYPE // PRIM_TYPE
1078
1079                int n = 0;
1080                while (it.hasNext()) {
1081                        data[it.index] = elements[n];
1082                        n++;
1083                }
1084        }
1085
1086        @Override
1087        public void fillDataset(Dataset result, IndexIterator iter) {
1088                IndexIterator riter = result.getIterator();
1089                result.setDirty();
1090
1091                double[] rdata = ((CompoundDoubleDataset) result).data; // PRIM_TYPE
1092
1093                while (riter.hasNext() && iter.hasNext()) {
1094                        for (int i = 0; i < isize; i++) {
1095                                rdata[riter.index + i] = data[iter.index + i];
1096                        }
1097                }
1098        }
1099
1100        @Override
1101        public CompoundDoubleDataset setByBoolean(final Object o, Dataset selection) {
1102                setDirty();
1103                if (o instanceof Dataset) {
1104                        Dataset ds = (Dataset) o;
1105                        final int length = ((Number) selection.sum()).intValue();
1106                        if (length != ds.getSize()) {
1107                                throw new IllegalArgumentException(
1108                                                "Number of true items in selection does not match number of items in dataset");
1109                        }
1110
1111                        IndexIterator iter = ds.getIterator();
1112                        BooleanIterator biter = getBooleanIterator(selection);
1113
1114                        if (ds instanceof AbstractCompoundDataset) {
1115                                if (isize != ds.getElementsPerItem()) {
1116                                        throw new IllegalArgumentException("Input dataset is not compatible with slice");
1117                                }
1118
1119                                while (biter.hasNext() && iter.hasNext()) {
1120                                        for (int i = 0; i < isize; i++) {
1121                                                data[biter.index + i] = ds.getElementDoubleAbs(iter.index + i); // GET_ELEMENT_WITH_CAST
1122                                        }
1123                                }
1124                        } else {
1125                                while (biter.hasNext() && iter.hasNext()) {
1126                                        data[biter.index] = ds.getElementDoubleAbs(iter.index); // GET_ELEMENT_WITH_CAST
1127                                        for (int i = 1; i < isize; i++) {
1128                                                data[biter.index + i] = 0;
1129                                        }
1130                                }
1131                        }
1132                } else {
1133                        try {
1134                                final double[] vr = DTypeUtils.toDoubleArray(o, isize); // PRIM_TYPE // CLASS_TYPE
1135
1136                                final BooleanIterator biter = getBooleanIterator(selection);
1137
1138                                while (biter.hasNext()) {
1139                                        for (int i = 0; i < isize; i++) {
1140                                                data[biter.index + i] = vr[i];
1141                                        }
1142                                }
1143                        } catch (IllegalArgumentException e) {
1144                                throw new IllegalArgumentException("Object for setting is not a dataset or number");
1145                        }
1146                }
1147                return this;
1148        }
1149
1150        @Override
1151        public CompoundDoubleDataset setBy1DIndex(final Object o, Dataset index) {
1152                setDirty();
1153                if (o instanceof Dataset) {
1154                        Dataset ds = (Dataset) o;
1155                        if (index.getSize() != ds.getSize()) {
1156                                throw new IllegalArgumentException(
1157                                                "Number of items in selection does not match number of items in dataset");
1158                        }
1159
1160                        IndexIterator oiter = ds.getIterator();
1161                        final IntegerIterator iter = new IntegerIterator(index, size, isize);
1162
1163                        if (ds instanceof AbstractCompoundDataset) {
1164                                if (isize != ds.getElementsPerItem()) {
1165                                        throw new IllegalArgumentException("Input dataset is not compatible with slice");
1166                                }
1167
1168                                double[] temp = new double[isize];
1169                                while (iter.hasNext() && oiter.hasNext()) {
1170                                        ((AbstractCompoundDataset) ds).getDoubleArrayAbs(oiter.index, temp);
1171                                        setDoubleArrayAbs(iter.index, temp);
1172                                }
1173                                while (iter.hasNext() && oiter.hasNext()) {
1174                                        for (int i = 0; i < isize; i++) {
1175                                                data[iter.index + i] = ds.getElementDoubleAbs(oiter.index + i); // GET_ELEMENT_WITH_CAST
1176                                        }
1177                                }
1178                        } else {
1179                                while (iter.hasNext() && oiter.hasNext()) {
1180                                        data[iter.index] = ds.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
1181                                        for (int i = 1; i < isize; i++) {
1182                                                data[iter.index + i] = 0;
1183                                        }
1184                                }
1185                        }
1186                } else {
1187                        try {
1188                                final double[] vr = DTypeUtils.toDoubleArray(o, isize); // PRIM_TYPE // CLASS_TYPE
1189
1190                                final IntegerIterator iter = new IntegerIterator(index, size, isize);
1191
1192                                while (iter.hasNext()) {
1193                                        setAbs(iter.index, vr);
1194                                }
1195                        } catch (IllegalArgumentException e) {
1196                                throw new IllegalArgumentException("Object for setting is not a dataset or number");
1197                        }
1198                }
1199                return this;
1200        }
1201
1202        @Override
1203        public CompoundDoubleDataset setByIndexes(final Object o, final Object... indexes) {
1204                setDirty();
1205                final IntegersIterator iter = new IntegersIterator(shape, indexes);
1206                final int[] pos = iter.getPos();
1207
1208                if (o instanceof Dataset) {
1209                        Dataset ds = (Dataset) o;
1210                        if (ShapeUtils.calcSize(iter.getShape()) != ds.getSize()) {
1211                                throw new IllegalArgumentException(
1212                                                "Number of items in selection does not match number of items in dataset");
1213                        }
1214
1215                        IndexIterator oiter = ds.getIterator();
1216
1217                        if (ds instanceof AbstractCompoundDataset) {
1218                                if (isize != ds.getElementsPerItem()) {
1219                                        throw new IllegalArgumentException("Input dataset is not compatible with slice");
1220                                }
1221
1222                                double[] temp = new double[isize];
1223                                while (iter.hasNext() && oiter.hasNext()) {
1224                                        ((AbstractCompoundDataset) ds).getDoubleArray(temp, pos);
1225                                        setDoubleArrayAbs(get1DIndex(pos), temp);
1226                                }
1227                        } else {
1228                                while (iter.hasNext() && oiter.hasNext()) {
1229                                        int n = get1DIndex(pos);
1230                                        data[n] = ds.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
1231                                        for (int i = 1; i < isize; i++) {
1232                                                data[n + i] = 0;
1233                                        }
1234                                }
1235                        }
1236                } else {
1237                        try {
1238                                final double[] vr = DTypeUtils.toDoubleArray(o, isize); // PRIM_TYPE // CLASS_TYPE
1239
1240                                while (iter.hasNext()) {
1241                                        setAbs(get1DIndex(pos), vr);
1242                                }
1243                        } catch (IllegalArgumentException e) {
1244                                throw new IllegalArgumentException("Object for setting is not a dataset or number");
1245                        }
1246                }
1247                return this;
1248        }
1249
1250        @Override
1251        CompoundDoubleDataset setSlicedView(Dataset view, Dataset d) {
1252                setDirty();
1253                final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(view, d);
1254
1255                final int is = view.getElementsPerItem();
1256
1257                if (is > 1) {
1258                        if (d.getElementsPerItem() == 1) {
1259                                while (it.hasNext()) {
1260                                        final double bv = it.bDouble; // PRIM_TYPE // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex);
1261                                        data[it.aIndex] = bv;
1262                                        for (int j = 1; j < is; j++) {
1263                                                data[it.aIndex + j] = bv;
1264                                        }
1265                                }
1266                        } else {
1267                                while (it.hasNext()) {
1268                                        data[it.aIndex] = it.bDouble; // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex);
1269                                        for (int j = 1; j < is; j++) {
1270                                                data[it.aIndex + j] = d.getElementDoubleAbs(it.bIndex + j); // GET_ELEMENT_WITH_CAST
1271                                        }
1272                                }
1273                        }
1274                } else {
1275                        while (it.hasNext()) {
1276                                data[it.aIndex] = it.bDouble; // BCAST_WITH_CAST d.getElementDoubleAbs(it.bIndex);
1277                        }
1278                }
1279                return this;
1280        }
1281
1282        @Override
1283        public CompoundDoubleDataset setSlice(final Object o, final IndexIterator siter) {
1284                setDirty();
1285                if (o instanceof IDataset) {
1286                        final IDataset ds = (IDataset) o;
1287                        final int[] oshape = ds.getShape();
1288
1289                        if (!ShapeUtils.areShapesCompatible(siter.getShape(), oshape)) {
1290                                throw new IllegalArgumentException(String.format(
1291                                                "Input dataset is not compatible with slice: %s cf %s", Arrays.toString(oshape),
1292                                                Arrays.toString(siter.getShape())));
1293                        }
1294
1295                        if (ds instanceof Dataset) {
1296                                final Dataset ads = (Dataset) ds;
1297                                IndexIterator oiter = ads.getIterator();
1298
1299                                if (ds instanceof AbstractCompoundDataset) {
1300                                        if (isize != ads.getElementsPerItem()) {
1301                                                throw new IllegalArgumentException("Input dataset is not compatible with slice");
1302                                        }
1303
1304                                        while (siter.hasNext() && oiter.hasNext()) {
1305                                                for (int i = 0; i < isize; i++) {
1306                                                        data[siter.index + i] = ads.getElementDoubleAbs(oiter.index + i); // GET_ELEMENT_WITH_CAST
1307                                                }
1308                                        }
1309                                } else {
1310                                        while (siter.hasNext() && oiter.hasNext()) {
1311                                                data[siter.index] = ads.getElementDoubleAbs(oiter.index); // GET_ELEMENT_WITH_CAST
1312                                                for (int i = 1; i < isize; i++) {
1313                                                        data[siter.index + i] = 0;
1314                                                }
1315                                        }
1316                                }
1317                        } else {
1318                                final IndexIterator oiter = new PositionIterator(oshape);
1319                                final int[] pos = oiter.getPos();
1320
1321                                if (ds.getElementsPerItem() == 1) {
1322                                        while (siter.hasNext() && oiter.hasNext()) {
1323                                                data[siter.index] = ds.getDouble(pos); // PRIM_TYPE
1324                                                for (int i = 1; i < isize; i++) {
1325                                                        data[siter.index + i] = 0;
1326                                                }
1327                                        }
1328                                } else {
1329                                        while (siter.hasNext() && oiter.hasNext()) {
1330                                                final double[] val = DTypeUtils.toDoubleArray(ds.getObject(pos), isize); // PRIM_TYPE // CLASS_TYPE
1331                                                for (int i = 0; i < isize; i++) {
1332                                                        data[siter.index + i] = val[i];
1333                                                }
1334                                        }
1335                                }
1336                        }
1337                } else {
1338                        try {
1339                                final double[] vr = DTypeUtils.toDoubleArray(o, isize); // PRIM_TYPE // CLASS_TYPE
1340
1341                                while (siter.hasNext()) {
1342                                        for (int i = 0; i < isize; i++) {
1343                                                data[siter.index + i] = vr[i];
1344                                        }
1345                                }
1346                        } catch (IllegalArgumentException e) {
1347                                throw new IllegalArgumentException("Object for setting slice is not a dataset or number");
1348                        }
1349                }
1350                return this;
1351        }
1352
1353        @Override
1354        public void copyItemsFromAxes(final int[] pos, final boolean[] axes, final Dataset dest) {
1355                double[] ddata = (double[]) dest.getBuffer(); // PRIM_TYPE
1356
1357                if (dest.getElementsPerItem() != isize) {
1358                        throw new IllegalArgumentException(String.format(
1359                                        "Destination dataset is incompatible as it has %d elements per item not %d",
1360                                        dest.getElementsPerItem(), isize));
1361                }
1362
1363                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
1364                int[] sshape = ShapeUtils.squeezeShape(siter.getShape(), false);
1365
1366                IndexIterator diter = dest.getSliceIterator(null, sshape, null);
1367
1368                if (ddata.length < ShapeUtils.calcSize(sshape)) {
1369                        throw new IllegalArgumentException("destination array is not large enough");
1370                }
1371
1372                dest.setDirty();
1373                while (siter.hasNext() && diter.hasNext()) {
1374                        for (int i = 0; i < isize; i++) {
1375                                ddata[diter.index + i] = data[siter.index + i];
1376                        }
1377                }
1378        }
1379
1380        @Override
1381        public void setItemsOnAxes(final int[] pos, final boolean[] axes, final Object src) {
1382                setDirty();
1383                double[] sdata = (double[]) src; // PRIM_TYPE
1384
1385                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
1386
1387                if (sdata.length < ShapeUtils.calcSize(siter.getShape())) {
1388                        throw new IllegalArgumentException("source array is not large enough");
1389                }
1390
1391                for (int i = 0; siter.hasNext(); i++) {
1392                        for (int j = 0; j < isize; j++) {
1393                                data[siter.index + j] = sdata[isize * i + j];
1394                        }
1395                }
1396        }
1397
1398        @Override
1399        public boolean containsNans() {
1400                final IndexIterator iter = getIterator(); // REAL_ONLY
1401                while (iter.hasNext()) { // REAL_ONLY
1402                        for (int i = 0; i < isize; i++) { // REAL_ONLY
1403                                if (Double.isNaN(data[iter.index + i])) // CLASS_TYPE // REAL_ONLY
1404                                        return true; // REAL_ONLY
1405                        } // REAL_ONLY
1406                } // REAL_ONLY
1407                return false;
1408        }
1409
1410        @Override
1411        public boolean containsInfs() {
1412                final IndexIterator iter = getIterator(); // REAL_ONLY
1413                while (iter.hasNext()) { // REAL_ONLY
1414                        for (int i = 0; i < isize; i++) { // REAL_ONLY
1415                                if (Double.isInfinite(data[iter.index + i])) // CLASS_TYPE // REAL_ONLY
1416                                        return true; // REAL_ONLY
1417                        } // REAL_ONLY
1418                } // REAL_ONLY
1419                return false;
1420        }
1421
1422        @Override
1423        public boolean containsInvalidNumbers() {
1424                IndexIterator iter = getIterator(); // REAL_ONLY
1425                while (iter.hasNext()) { // REAL_ONLY
1426                        for (int i = 0; i < isize; i++) { // REAL_ONLY
1427                                double x = data[iter.index + i]; // PRIM_TYPE // REAL_ONLY
1428                                if (Double.isNaN(x) || Double.isInfinite(x)) // CLASS_TYPE // REAL_ONLY
1429                                        return true; // REAL_ONLY
1430                        } // REAL_ONLY
1431                } // REAL_ONLY
1432                return false;
1433        }
1434
1435        @Override
1436        public CompoundDoubleDataset iadd(final Object b) {
1437                setDirty();
1438                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1439                boolean useLong = bds.getElementClass().equals(Long.class);
1440                int is = bds.getElementsPerItem();
1441                if (bds.getSize() == 1) {
1442                        final IndexIterator it = getIterator();
1443                        final int bOffset = bds.getOffset();
1444                        if (is == 1) {
1445                                if (useLong) {
1446                                        final long lb = bds.getElementLongAbs(bOffset);
1447                                        while (it.hasNext()) {
1448                                                for (int i = 0; i < isize; i++) {
1449                                                        data[it.index + i] += lb;
1450                                                }
1451                                        }
1452                                } else {
1453                                        final double db = bds.getElementDoubleAbs(bOffset);
1454                                        while (it.hasNext()) {
1455                                                for (int i = 0; i < isize; i++) {
1456                                                        data[it.index + i] += db;
1457                                                }
1458                                        }
1459                                }
1460                        } else if (is == isize) {
1461                                if (useLong) {
1462                                        while (it.hasNext()) {
1463                                                for (int i = 0; i < isize; i++) {
1464                                                        data[it.index + i] += bds.getElementLongAbs(i);
1465                                                }
1466                                        }
1467                                } else {
1468                                        while (it.hasNext()) {
1469                                                for (int i = 0; i < isize; i++) {
1470                                                        data[it.index + i] += bds.getElementDoubleAbs(i);
1471                                                }
1472                                        }
1473                                }
1474                        } else {
1475                                throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1476                        }
1477                } else {
1478                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
1479                        it.setOutputDouble(!useLong);
1480                        if (is == 1) {
1481                                if (useLong) {
1482                                        while (it.hasNext()) {
1483                                                final long lb = it.bLong;
1484                                                data[it.aIndex] += lb;
1485                                                for (int i = 1; i < isize; i++) {
1486                                                        data[it.aIndex + i] += lb;
1487                                                }
1488                                        }
1489                                } else {
1490                                        while (it.hasNext()) {
1491                                                final double db = it.bDouble;
1492                                                data[it.aIndex] += db;
1493                                                for (int i = 1; i < isize; i++) {
1494                                                        data[it.aIndex + i] += db;
1495                                                }
1496                                        }
1497                                }
1498                        } else if (is == isize) {
1499                                if (useLong) {
1500                                        while (it.hasNext()) {
1501                                                data[it.aIndex] += it.bLong;
1502                                                for (int i = 1; i < isize; i++) {
1503                                                        data[it.aIndex + i] += bds.getElementLongAbs(it.bIndex + i);
1504                                                }
1505                                        }
1506                                } else {
1507                                        while (it.hasNext()) {
1508                                                data[it.aIndex] += it.bDouble;
1509                                                for (int i = 1; i < isize; i++) {
1510                                                        data[it.aIndex + i] += bds.getElementDoubleAbs(it.bIndex + i);
1511                                                }
1512                                        }
1513                                }
1514                        } else {
1515                                throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1516                        }
1517                }
1518                return this;
1519        }
1520
1521        @Override
1522        public CompoundDoubleDataset isubtract(final Object b) {
1523                setDirty();
1524                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1525                boolean useLong = bds.getElementClass().equals(Long.class);
1526                int is = bds.getElementsPerItem();
1527                if (bds.getSize() == 1) {
1528                        final IndexIterator it = getIterator();
1529                        final int bOffset = bds.getOffset();
1530                        if (is == 1) {
1531                                if (useLong) {
1532                                        final long lb = bds.getElementLongAbs(bOffset);
1533                                        while (it.hasNext()) {
1534                                                for (int i = 0; i < isize; i++) {
1535                                                        data[it.index + i] -= lb;
1536                                                }
1537                                        }
1538                                } else {
1539                                        final double db = bds.getElementDoubleAbs(bOffset);
1540                                        while (it.hasNext()) {
1541                                                for (int i = 0; i < isize; i++) {
1542                                                        data[it.index + i] -= db;
1543                                                }
1544                                        }
1545                                }
1546                        } else if (is == isize) {
1547                                if (useLong) {
1548                                        while (it.hasNext()) {
1549                                                for (int i = 0; i < isize; i++) {
1550                                                        data[it.index + i] -= bds.getElementLongAbs(i);
1551                                                }
1552                                        }
1553                                } else {
1554                                        while (it.hasNext()) {
1555                                                for (int i = 0; i < isize; i++) {
1556                                                        data[it.index + i] -= bds.getElementDoubleAbs(i);
1557                                                }
1558                                        }
1559                                }
1560                        } else {
1561                                throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1562                        }
1563                } else {
1564                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
1565                        it.setOutputDouble(!useLong);
1566                        if (is == 1) {
1567                                if (useLong) {
1568                                        while (it.hasNext()) {
1569                                                final long lb = it.bLong;
1570                                                data[it.aIndex] += lb;
1571                                                for (int i = 1; i < isize; i++) {
1572                                                        data[it.aIndex + i] -= lb;
1573                                                }
1574                                        }
1575                                } else {
1576                                        while (it.hasNext()) {
1577                                                final double db = it.bDouble;
1578                                                data[it.aIndex] += db;
1579                                                for (int i = 1; i < isize; i++) {
1580                                                        data[it.aIndex + i] -= db;
1581                                                }
1582                                        }
1583                                }
1584                        } else if (is == isize) {
1585                                if (useLong) {
1586                                        while (it.hasNext()) {
1587                                                data[it.aIndex] += it.bLong;
1588                                                for (int i = 1; i < isize; i++) {
1589                                                        data[it.aIndex + i] -= bds.getElementLongAbs(it.bIndex + i);
1590                                                }
1591                                        }
1592                                } else {
1593                                        while (it.hasNext()) {
1594                                                data[it.aIndex] += it.bDouble;
1595                                                for (int i = 1; i < isize; i++) {
1596                                                        data[it.aIndex + i] -= bds.getElementDoubleAbs(it.bIndex + i);
1597                                                }
1598                                        }
1599                                }
1600                        } else {
1601                                throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1602                        }
1603                }
1604                return this;
1605        }
1606
1607        @Override
1608        public CompoundDoubleDataset imultiply(final Object b) {
1609                setDirty();
1610                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1611                boolean useLong = bds.getElementClass().equals(Long.class);
1612                int is = bds.getElementsPerItem();
1613                if (bds.getSize() == 1) {
1614                        final IndexIterator it = getIterator();
1615                        final int bOffset = bds.getOffset();
1616                        if (useLong) {
1617                                if (is == 1) {
1618                                        final long lb = bds.getElementLongAbs(bOffset);
1619                                        while (it.hasNext()) {
1620                                                for (int i = 0; i < isize; i++) {
1621                                                        data[it.index + i] *= lb;
1622                                                }
1623                                        }
1624                                } else if (is == isize) {
1625                                        while (it.hasNext()) {
1626                                                for (int i = 0; i < isize; i++) {
1627                                                        data[it.index + i] *= bds.getElementLongAbs(i);
1628                                                }
1629                                        }
1630                                } else {
1631                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1632                                }
1633                        } else {
1634                                if (is == 1) {
1635                                        final double db = bds.getElementDoubleAbs(bOffset);
1636                                        while (it.hasNext()) {
1637                                                for (int i = 0; i < isize; i++) {
1638                                                        data[it.index + i] *= db;
1639                                                }
1640                                        }
1641                                } else if (is == isize) {
1642                                        while (it.hasNext()) {
1643                                                for (int i = 0; i < isize; i++) {
1644                                                        data[it.index + i] *= bds.getElementDoubleAbs(i);
1645                                                }
1646                                        }
1647                                } else {
1648                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1649                                }
1650                        }
1651                } else {
1652                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
1653                        it.setOutputDouble(!useLong);
1654                        if (useLong) {
1655                                if (is == 1) {
1656                                        while (it.hasNext()) {
1657                                                final double lb = it.bLong;
1658                                                for (int i = 0; i < isize; i++) {
1659                                                        data[it.aIndex + i] *= lb;
1660                                                }
1661                                        }
1662                                } else if (is == isize) {
1663                                        while (it.hasNext()) {
1664                                                data[it.aIndex] *= it.bLong;
1665                                                for (int i = 1; i < isize; i++) {
1666                                                        data[it.aIndex + i] *= bds.getElementLongAbs(it.bIndex + i);
1667                                                }
1668                                        }
1669                                } else {
1670                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1671                                }
1672                        } else {
1673                                if (is == 1) {
1674                                        while (it.hasNext()) {
1675                                                final double db = it.bDouble;
1676                                                for (int i = 0; i < isize; i++) {
1677                                                        data[it.aIndex + i] *= db;
1678                                                }
1679                                        }
1680                                } else if (is == isize) {
1681                                        while (it.hasNext()) {
1682                                                data[it.aIndex] *= it.bDouble;
1683                                                for (int i = 1; i < isize; i++) {
1684                                                        data[it.aIndex + i] *= bds.getElementDoubleAbs(it.bIndex + i);
1685                                                }
1686                                        }
1687                                } else {
1688                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1689                                }
1690                        }
1691                }
1692                return this;
1693        }
1694
1695        @Override
1696        public CompoundDoubleDataset idivide(final Object b) {
1697                setDirty();
1698                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1699                boolean useLong = bds.getElementClass().equals(Long.class);
1700                int is = bds.getElementsPerItem();
1701                if (bds.getSize() == 1) {
1702                        final IndexIterator it = getIterator();
1703                        final int bOffset = bds.getOffset();
1704                        if (useLong) {
1705                                if (is == 1) {
1706                                        final long lb = bds.getElementLongAbs(bOffset);
1707                                        // if (lb == 0) { // INT_USE
1708                                        //      fill(0); // INT_USE
1709                                        // } else { // INT_USE
1710                                        while (it.hasNext()) {
1711                                                for (int i = 0; i < isize; i++) {
1712                                                        data[it.index + i] /= lb;
1713                                                }
1714                                        }
1715                                        // } // INT_USE
1716                                } else if (is == isize) {
1717                                        while (it.hasNext()) {
1718                                                for (int i = 0; i < isize; i++) {
1719                                                        final long lb = bds.getElementLongAbs(i);
1720                                                        data[it.index + i] /= lb; // INT_EXCEPTION
1721                                                }
1722                                        }
1723                                } else {
1724                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1725                                }
1726                        } else {
1727                                if (is == 1) {
1728                                        final double db = bds.getElementDoubleAbs(bOffset);
1729                                        // if (db == 0) { // INT_USE
1730                                        //      fill(0); // INT_USE
1731                                        // } else { // INT_USE
1732                                        while (it.hasNext()) {
1733                                                for (int i = 0; i < isize; i++) {
1734                                                        data[it.index + i] /= db;
1735                                                }
1736                                        }
1737                                        // } // INT_USE
1738                                } else if (is == isize) {
1739                                        while (it.hasNext()) {
1740                                                for (int i = 0; i < isize; i++) {
1741                                                        final double db = bds.getElementDoubleAbs(i);
1742                                                        data[it.index + i] /= db; // INT_EXCEPTION
1743                                                }
1744                                        }
1745                                } else {
1746                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1747                                }
1748                        }
1749                } else {
1750                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
1751                        it.setOutputDouble(!useLong);
1752                        if (useLong) {
1753                                if (is == 1) {
1754                                        while (it.hasNext()) {
1755                                                final long lb = it.bLong;
1756                                                // if (lb == 0) { // INT_USE
1757                                                //      for (int i = 0; i < isize; i++) { // INT_USE
1758                                                //              data[it.aIndex + i] = 0; // INT_USE
1759                                                //      }// INT_USE
1760                                                // } else { // INT_USE
1761                                                for (int i = 0; i < isize; i++) {
1762                                                        data[it.aIndex + i] /= lb;
1763                                                }
1764                                                // } // INT_USE
1765                                        }
1766                                } else if (is == isize) {
1767                                        while (it.hasNext()) {
1768                                                for (int i = 0; i < isize; i++) {
1769                                                        final long lb = bds.getElementLongAbs(it.bIndex + i);
1770                                                        data[it.aIndex + i] /= lb; // INT_EXCEPTION
1771                                                }
1772                                        }
1773                                } else {
1774                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1775                                }
1776                        } else {
1777                                if (is == 1) {
1778                                        while (it.hasNext()) {
1779                                                final double db = it.bDouble;
1780                                                // if (db == 0) { // INT_USE
1781                                                //      for (int i = 0; i < isize; i++) { // INT_USE
1782                                                //              data[it.aIndex + i] = 0; // INT_USE
1783                                                //      }// INT_USE
1784                                                // } else { // INT_USE
1785                                                for (int i = 0; i < isize; i++) {
1786                                                        data[it.aIndex + i] /= db;
1787                                                }
1788                                                // } // INT_USE
1789                                        }
1790                                } else if (is == isize) {
1791                                        while (it.hasNext()) {
1792                                                for (int i = 0; i < isize; i++) {
1793                                                        final double db = bds.getElementDoubleAbs(it.bIndex + i);
1794                                                        data[it.aIndex + i] /= db; // INT_EXCEPTION
1795                                                }
1796                                        }
1797                                } else {
1798                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1799                                }
1800                        }
1801                }
1802                return this;
1803        }
1804
1805        @Override
1806        public CompoundDoubleDataset ifloor() {
1807                setDirty(); // REAL_ONLY
1808                final IndexIterator it = getIterator(); // REAL_ONLY
1809                while (it.hasNext()) { // REAL_ONLY
1810                        for (int i = 0; i < isize; i++) { // REAL_ONLY
1811                                data[it.index + i] = Math.floor(data[it.index] + i); // REAL_ONLY // ADD_CAST
1812                        } // REAL_ONLY
1813                } // REAL_ONLY
1814                return this;
1815        }
1816
1817        @Override
1818        public CompoundDoubleDataset iremainder(final Object b) {
1819                setDirty();
1820                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1821                boolean useLong = bds.getElementClass().equals(Long.class);
1822                int is = bds.getElementsPerItem();
1823                if (bds.getSize() == 1) {
1824                        final IndexIterator it = getIterator();
1825                        final int bOffset = bds.getOffset();
1826                        if (useLong) {
1827                                if (is == 1) {
1828                                        final long lb = bds.getElementLongAbs(bOffset);
1829                                        // if (lb == 0) { // INT_USE
1830                                        //      fill(0); // INT_USE
1831                                        // } else { // INT_USE
1832                                        while (it.hasNext()) {
1833                                                for (int i = 0; i < isize; i++) {
1834                                                        data[it.index + i] %= lb;
1835                                                }
1836                                        }
1837                                        // } // INT_USE
1838                                } else if (is == isize) {
1839                                        while (it.hasNext()) {
1840                                                for (int i = 0; i < isize; i++) {
1841                                                        data[it.index + i] %= bds.getElementLongAbs(i); // INT_EXCEPTION
1842                                                }
1843                                        }
1844                                } else {
1845                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1846                                }
1847                        } else {
1848                                if (is == 1) {
1849                                        final double db = bds.getElementDoubleAbs(bOffset);
1850                                        // if (db == 0) { // INT_USE
1851                                        //      fill(0); // INT_USE
1852                                        // } else { // INT_USE
1853                                        while (it.hasNext()) {
1854                                                for (int i = 0; i < isize; i++) {
1855                                                        data[it.index + i] %= db;
1856                                                }
1857                                        }
1858                                        // } // INT_USE
1859                                } else if (is == isize) {
1860                                        while (it.hasNext()) {
1861                                                for (int i = 0; i < isize; i++) {
1862                                                        data[it.index + i] %= bds.getElementDoubleAbs(i); // INT_EXCEPTION
1863                                                }
1864                                        }
1865                                } else {
1866                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1867                                }
1868                        }
1869                } else {
1870                        final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(this, bds);
1871                        it.setOutputDouble(!useLong);
1872                        if (useLong) {
1873                                if (is == 1) {
1874                                        while (it.hasNext()) {
1875                                                final long lb = it.bLong;
1876                                                // if (lb == 0) { // INT_USE
1877                                                //      for (int i = 0; i < isize; i++) // INT_USE
1878                                                //              data[it.aIndex + i] = 0; // INT_USE
1879                                                // } else { // INT_USE
1880                                                for (int i = 0; i < isize; i++)
1881                                                        data[it.aIndex + i] %= lb;
1882                                                // } // INT_USE
1883                                        }
1884                                } else if (is == isize) {
1885                                        while (it.hasNext()) {
1886                                                for (int i = 0; i < isize; i++) {
1887                                                        final long lb = bds.getElementLongAbs(it.bIndex + i);
1888                                                        data[it.aIndex + i] %= lb; // INT_EXCEPTION
1889                                                }
1890                                        }
1891                                } else {
1892                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1893                                }
1894                        } else {
1895                                if (is == 1) {
1896                                        while (it.hasNext()) {
1897                                                final double db = it.bDouble;
1898                                                // if (db == 0) { // INT_USE
1899                                                //      for (int i = 0; i < isize; i++) // INT_USE
1900                                                //              data[it.aIndex + i] = 0; // INT_USE
1901                                                // } else { // INT_USE
1902                                                for (int i = 0; i < isize; i++) {
1903                                                        data[it.aIndex + i] %= db;
1904                                                }
1905                                                // } // INT_USE
1906                                        }
1907                                } else if (is == isize) {
1908                                        while (it.hasNext()) {
1909                                                for (int i = 0; i < isize; i++) {
1910                                                        final double db = bds.getElementDoubleAbs(it.bIndex + i);
1911                                                        data[it.aIndex + i] %= db; // INT_EXCEPTION
1912                                                }
1913                                        }
1914                                } else {
1915                                        throw new IllegalArgumentException("Argument does not have same number of elements per item or is not a non-compound dataset");
1916                                }
1917                        }
1918                }
1919                return this;
1920        }
1921
1922        @Override
1923        public CompoundDoubleDataset ipower(final Object b) {
1924                setDirty();
1925                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
1926                final int is = bds.getElementsPerItem();
1927                if (bds.getSize() == 1) {
1928                        final int bOffset = bds.getOffset();
1929                        final double vr = bds.getElementDoubleAbs(bOffset);
1930                        final IndexIterator it = getIterator();
1931                        if (bds.isComplex()) {
1932                                final double vi = bds.getElementDoubleAbs(bOffset + 1);
1933                                if (vi == 0) {
1934                                        while (it.hasNext()) {
1935                                                for (int i = 0; i < isize; i++) {
1936                                                        final double v = Math.pow(data[it.index + i], vr);
1937                                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1938                                                        //      data[it.index + i] = 0; // INT_USE
1939                                                        // } else { // INT_USE
1940                                                        data[it.index + i] = v; // PRIM_TYPE_LONG // ADD_CAST
1941                                                        // } // INT_USE
1942                                                }
1943                                        }
1944                                } else {
1945                                        final Complex zv = new Complex(vr, vi);
1946                                        while (it.hasNext()) {
1947                                                for (int i = 0; i < isize; i++) {
1948                                                        Complex zd = new Complex(data[it.index + i], 0);
1949                                                        final double v = zd.pow(zv).getReal();
1950                                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1951                                                        //      data[it.index + i] = 0; // INT_USE
1952                                                        // } else { // INT_USE
1953                                                        data[it.index + i] = v; // PRIM_TYPE_LONG // ADD_CAST
1954                                                        // } // INT_USE
1955                                                }
1956                                        }
1957                                }
1958                        } else if (is == 1) {
1959                                while (it.hasNext()) {
1960                                        for (int i = 0; i < isize; i++) {
1961                                                final double v = Math.pow(data[it.index + i], vr);
1962                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1963                                                //      data[it.index + i] = 0; // INT_USE
1964                                                // } else { // INT_USE
1965                                                data[it.index + i] = v; // PRIM_TYPE_LONG // ADD_CAST
1966                                                // } // INT_USE
1967                                        }
1968                                }
1969                        } else if (is == isize) {
1970                                while (it.hasNext()) {
1971                                        for (int i = 0; i < isize; i++) {
1972                                                final double v = Math.pow(data[it.index + i], bds.getElementDoubleAbs(i));
1973                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1974                                                //      data[it.index + i] = 0; // INT_USE
1975                                                // } else { // INT_USE
1976                                                data[it.index + i] = v; // PRIM_TYPE_LONG // ADD_CAST
1977                                                // } // INT_USE
1978                                        }
1979                                }
1980                        }
1981                } else {
1982                        final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
1983                        it.setOutputDouble(true);
1984                        if (bds.isComplex()) {
1985                                while (it.hasNext()) {
1986                                        final Complex zv = new Complex(it.bDouble, bds.getElementDoubleAbs(it.bIndex + 1));
1987                                        double v = new Complex(it.aDouble, 0).pow(zv).getReal();
1988                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1989                                        //      data[it.aIndex] = 0; // INT_USE
1990                                        // } else { // INT_USE
1991                                        data[it.aIndex] = v; // PRIM_TYPE_LONG // ADD_CAST
1992                                        // } // INT_USE
1993                                        for (int i = 1; i < isize; i++) {
1994                                                v = new Complex(data[it.aIndex + i], 0).pow(zv).getReal();
1995                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
1996                                                //      data[it.aIndex + i] = 0; // INT_USE
1997                                                // } else { // INT_USE
1998                                                data[it.aIndex + i] = v; // PRIM_TYPE_LONG // ADD_CAST
1999                                                // } // INT_USE
2000                                        }
2001                                }
2002                        } else {
2003                                while (it.hasNext()) {
2004                                        double v = Math.pow(it.aDouble, it.bDouble);
2005                                        // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
2006                                        //      data[it.aIndex] = 0; // INT_USE
2007                                        // } else { // INT_USE
2008                                        data[it.aIndex] = v; // PRIM_TYPE_LONG // ADD_CAST
2009                                        // } // INT_USE
2010                                        for (int i = 1; i < isize; i++) {
2011                                                v = Math.pow(data[it.aIndex + i], bds.getElementDoubleAbs(it.bIndex + i));
2012                                                // if (Double.isInfinite(v) || Double.isNaN(v)) { // INT_USE
2013                                                //      data[it.aIndex + i] = 0; // INT_USE
2014                                                // } else { // INT_USE
2015                                                data[it.aIndex + i] = v; // PRIM_TYPE_LONG // ADD_CAST
2016                                                // } // INT_USE
2017                                        }
2018                                }
2019                        }
2020                }
2021                return this;
2022        }
2023
2024        @Override
2025        public double residual(final Object b, final Dataset w, boolean ignoreNaNs) {
2026                Dataset bds = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
2027                final BroadcastIterator it = BroadcastIterator.createIterator(this, bds);
2028                it.setOutputDouble(true);
2029                double sum = 0;
2030                double comp = 0;
2031                final int bis = bds.getElementsPerItem();
2032
2033                if (bis == 1) {
2034                        if (w == null) {
2035                                while (it.hasNext()) {
2036                                        final double db = it.bDouble;
2037                                        double diff = it.aDouble - db;
2038                                        if (ignoreNaNs) { // REAL_ONLY
2039                                                if (Double.isNaN(diff)) // REAL_ONLY
2040                                                        continue; // REAL_ONLY
2041                                                boolean skip = false; // REAL_ONLY
2042                                                for (int i = 1; i < isize; i++) { // REAL_ONLY
2043                                                        if (Double.isNaN(data[it.aIndex + i])) { // REAL_ONLY
2044                                                                skip = true; // REAL_ONLY
2045                                                                break; // REAL_ONLY
2046                                                        } // REAL_ONLY
2047                                                } // REAL_ONLY
2048                                                if (skip) { // REAL_ONLY
2049                                                        continue; // REAL_ONLY
2050                                                } // REAL_ONLY
2051                                        } // REAL_ONLY
2052                                        double err = diff * diff - comp;
2053                                        double temp = sum + err;
2054                                        comp = (temp - sum) - err;
2055                                        sum = temp;
2056                                        for (int i = 1; i < isize; i++) {
2057                                                diff = data[it.aIndex + i] - db;
2058                                                err = diff * diff - comp;
2059                                                temp = sum + err;
2060                                                comp = (temp - sum) - err;
2061                                                sum = temp;
2062                                        }
2063                                }
2064                        } else {
2065                                IndexIterator itw = w.getIterator();
2066                                while (it.hasNext() && itw.hasNext()) {
2067                                        final double db = it.bDouble;
2068                                        double diff = it.aDouble - db;
2069                                        if (ignoreNaNs) { // REAL_ONLY
2070                                                if (Double.isNaN(diff)) // REAL_ONLY
2071                                                        continue; // REAL_ONLY
2072                                                boolean skip = false; // REAL_ONLY
2073                                                for (int i = 1; i < isize; i++) { // REAL_ONLY
2074                                                        if (Double.isNaN(data[it.aIndex + i])) { // REAL_ONLY
2075                                                                skip = true; // REAL_ONLY
2076                                                                break; // REAL_ONLY
2077                                                        } // REAL_ONLY
2078                                                } // REAL_ONLY
2079                                                if (skip) { // REAL_ONLY
2080                                                        continue; // REAL_ONLY
2081                                                } // REAL_ONLY
2082                                        } // REAL_ONLY
2083                                        final double dw = w.getElementDoubleAbs(itw.index);
2084                                        double err = diff * diff * dw - comp;
2085                                        double temp = sum + err;
2086                                        comp = (temp - sum) - err;
2087                                        sum = temp;
2088                                        for (int i = 1; i < isize; i++) {
2089                                                diff = data[it.aIndex + i] - db;
2090                                                err = diff * diff * dw - comp;
2091                                                temp = sum + err;
2092                                                comp = (temp - sum) - err;
2093                                                sum = temp;
2094                                        }
2095                                }
2096                        }
2097                } else {
2098                        if (w == null) {
2099                                while (it.hasNext()) {
2100                                        double diff = it.aDouble - it.bDouble;
2101                                        if (ignoreNaNs) { // REAL_ONLY
2102                                                if (Double.isNaN(diff)) // REAL_ONLY
2103                                                        continue; // REAL_ONLY
2104                                                boolean skip = false; // REAL_ONLY
2105                                                for (int i = 1; i < isize; i++) { // REAL_ONLY
2106                                                        if (Double.isNaN(data[it.aIndex + i]) || Double.isNaN(bds.getElementDoubleAbs(it.bIndex + i))) { // REAL_ONLY
2107                                                                skip = true; // REAL_ONLY
2108                                                                break; // REAL_ONLY
2109                                                        } // REAL_ONLY
2110                                                } // REAL_ONLY
2111                                                if (skip) { // REAL_ONLY
2112                                                        continue; // REAL_ONLY
2113                                                } // REAL_ONLY
2114                                        } // REAL_ONLY
2115                                        double err = diff * diff - comp;
2116                                        double temp = sum + err;
2117                                        comp = (temp - sum) - err;
2118                                        sum = temp;
2119                                        for (int i = 1; i < isize; i++) {
2120                                                diff = data[it.aIndex + i] - bds.getElementDoubleAbs(it.bIndex + i);
2121                                                err = diff * diff - comp;
2122                                                temp = sum + err;
2123                                                comp = (temp - sum) - err;
2124                                                sum = temp;
2125                                        }
2126                                }
2127                        } else {
2128                                IndexIterator itw = w.getIterator();
2129                                while (it.hasNext() && itw.hasNext()) {
2130                                        double diff = it.aDouble - it.bDouble;
2131                                        if (ignoreNaNs) { // REAL_ONLY
2132                                                if (Double.isNaN(diff)) // REAL_ONLY
2133                                                        continue; // REAL_ONLY
2134                                                boolean skip = false; // REAL_ONLY
2135                                                for (int i = 1; i < isize; i++) { // REAL_ONLY
2136                                                        if (Double.isNaN(data[it.aIndex + i]) || Double.isNaN(bds.getElementDoubleAbs(it.bIndex + i))) { // REAL_ONLY
2137                                                                skip = true; // REAL_ONLY
2138                                                                break; // REAL_ONLY
2139                                                        } // REAL_ONLY
2140                                                } // REAL_ONLY
2141                                                if (skip) { // REAL_ONLY
2142                                                        continue; // REAL_ONLY
2143                                                } // REAL_ONLY
2144                                        } // REAL_ONLY
2145                                        final double dw = w.getElementDoubleAbs(itw.index);
2146                                        double err = diff * diff * dw - comp;
2147                                        double temp = sum + err;
2148                                        comp = (temp - sum) - err;
2149                                        sum = temp;
2150                                        for (int i = 1; i < isize; i++) {
2151                                                diff = data[it.aIndex + i] - bds.getElementDoubleAbs(it.bIndex + i);
2152                                                err = diff * diff * dw - comp;
2153                                                temp = sum + err;
2154                                                comp = (temp - sum) - err;
2155                                                sum = temp;
2156                                        }
2157                                }
2158                        }
2159                }
2160                return sum;
2161        }
2162}