001/*-
002 *******************************************************************************
003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd.
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *    Peter Chang - initial API and implementation and/or initial documentation
011 *******************************************************************************/
012
013// This is generated from DoubleDataset.java by fromdouble.py
014
015package org.eclipse.january.dataset;
016
017import java.util.ArrayList;
018import java.util.Arrays;
019import java.util.List;
020import java.util.Set;
021import java.util.TreeSet;
022
023import org.eclipse.january.metadata.StatisticsMetadata;
024
025
026/**
027 * Extend dataset for String values // PRIM_TYPE
028 */
029public class StringDatasetBase extends AbstractDataset {
030        // pin UID to base class
031        private static final long serialVersionUID = Dataset.serialVersionUID;
032
033        protected String[] data; // subclass alias // PRIM_TYPE
034
035        @Override
036        protected void setData() {
037                data = (String[]) odata; // PRIM_TYPE
038        }
039
040        protected static String[] createArray(final int size) { // PRIM_TYPE
041                String[] array = null; // PRIM_TYPE
042
043                try {
044                        array = new String[size]; // PRIM_TYPE
045                } catch (OutOfMemoryError e) {
046                        logger.error("The size of the dataset ({}) that is being created is too large "
047                                        + "and there is not enough memory to hold it.", size);
048                        throw new OutOfMemoryError("The dimensions given are too large, and there is "
049                                        + "not enough memory available in the Java Virtual Machine");
050                }
051                return array;
052        }
053
054        @Override
055        public int getDType() {
056                return STRING; // DATA_TYPE
057        }
058
059        /**
060         * Create a null dataset
061         */
062        StringDatasetBase() {
063        }
064
065        /**
066         * Create a zero-filled dataset of given shape
067         * @param shape
068         */
069        StringDatasetBase(final int... shape) {
070                if (shape != null) {
071                        size = ShapeUtils.calcSize(shape);
072                        this.shape = shape.clone();
073
074                        try {
075                                odata = data = createArray(size);
076                        } catch (Throwable t) {
077                                logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
078                                throw new IllegalArgumentException(t);
079                        }
080                }
081        }
082
083        /**
084         * Create a dataset using given data
085         * @param data
086         * @param shape
087         *            (can be null to create 1D dataset)
088         */
089        StringDatasetBase(final String[] data, int... shape) { // PRIM_TYPE
090                if (data == null) {
091                        throw new IllegalArgumentException("Data must not be null");
092                }
093                if (shape == null || shape.length == 0) {
094                        shape = new int[] { data.length };
095                }
096                size = ShapeUtils.calcSize(shape);
097                if (size != data.length) {
098                        throw new IllegalArgumentException(String.format("Shape %s is not compatible with size of data array, %d",
099                                        Arrays.toString(shape), data.length));
100                }
101                this.shape = size == 0 ? null : shape.clone();
102
103                odata = this.data = data;
104        }
105
106        /**
107         * Copy a dataset
108         * @param dataset
109         */
110        StringDatasetBase(final StringDatasetBase dataset) {
111                copyToView(dataset, this, true, true);
112
113                try {
114                        if (dataset.stride == null) {
115                                odata = data = dataset.data.clone();
116                        } else {
117                                offset = 0;
118                                stride = null;
119                                base = null;
120                                odata = data = createArray(size);
121
122                                IndexIterator iter = dataset.getIterator();
123                                for (int i = 0; iter.hasNext(); i++) {
124                                        data[i] = dataset.data[iter.index];
125                                }
126                        }
127                } catch (Throwable t) {
128                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
129                        throw new IllegalArgumentException(t);
130                }
131        }
132
133        /**
134         * Copy and cast a dataset to this class type
135         * @param dataset
136         */
137        StringDatasetBase(final Dataset dataset) {
138                copyToView(dataset, this, true, false);
139                offset = 0;
140                stride = null;
141                base = null;
142                try {
143                        odata = data = createArray(size);
144                } catch (Throwable t) {
145                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
146                        throw new IllegalArgumentException(t);
147                }
148                IndexIterator iter = dataset.getIterator();
149                for (int i = 0; iter.hasNext(); i++) {
150                        data[i] = dataset.getStringAbs(iter.index); // GET_ELEMENT_WITH_CAST
151                }
152        }
153
154        @Override
155        public boolean equals(Object obj) {
156                if (!super.equals(obj)) {
157                        return false;
158                }
159
160                if (getRank() == 0 && !getClass().equals(obj.getClass())) // already true for zero-rank dataset
161                        return true;
162
163                StringDatasetBase other = (StringDatasetBase) obj;
164//              if (size == 1) // for zero-rank datasets
165//                      return getAbs(offset) == other.getAbs(other.offset);
166
167                IndexIterator iter = getIterator();
168                IndexIterator oiter = other.getIterator();
169                while (iter.hasNext() && oiter.hasNext()) {
170                        if (!data[iter.index].equals(other.data[oiter.index])) // OBJECT_UNEQUAL
171                                return false;
172                }
173                return true;
174        }
175
176        @Override
177        public int hashCode() {
178                return super.hashCode();
179        }
180
181        @Override
182        public StringDatasetBase clone() {
183                return new StringDatasetBase(this);
184        }
185
186        /**
187         * Create a dataset from an object which could be a Java list, array (of arrays...) or Number. Ragged
188         * sequences or arrays are padded with zeros.
189         *
190         * @param obj
191         * @return dataset with contents given by input
192         */
193        static StringDatasetBase createFromObject(final Object obj) {
194                StringDatasetBase result = new StringDatasetBase();
195
196                if (obj != null) {
197                        result.shape = ShapeUtils.getShapeFromObject(obj);
198                        result.size = ShapeUtils.calcSize(result.shape);
199
200                        try {
201                                result.odata = result.data = createArray(result.size);
202                        } catch (Throwable t) {
203                                logger.error("Could not create a dataset of shape {}", Arrays.toString(result.shape), t);
204                                throw new IllegalArgumentException(t);
205                        }
206
207                        int[] pos = new int[result.shape.length];
208                        result.fillData(obj, 0, pos);
209                }
210
211                return result;
212        }
213
214        /**
215         * @param shape
216         * @return a dataset filled with ones
217         */
218        static StringDatasetBase ones(final int... shape) {
219                return new StringDatasetBase(shape).fill(1);
220        }
221
222        @Override
223        public StringDatasetBase fill(final Object obj) {
224                setDirty();
225                String dv = obj.toString(); // PRIM_TYPE // FROM_OBJECT
226                IndexIterator iter = getIterator();
227                while (iter.hasNext()) {
228                        data[iter.index] = dv;
229                }
230
231                return this;
232        }
233
234        /**
235         * This is a typed version of {@link #getBuffer()}
236         * @return data buffer as linear array
237         */
238        public String[] getData() { // PRIM_TYPE
239                return data;
240        }
241
242        @Override
243        protected int getBufferLength() {
244                if (data == null)
245                        return 0;
246                return data.length;
247        }
248
249        @Override
250        public StringDatasetBase getView(boolean deepCopyMetadata) {
251                StringDatasetBase view = new StringDatasetBase();
252                copyToView(this, view, true, deepCopyMetadata);
253                view.setData();
254                return view;
255        }
256
257        /**
258         * Get a value from an absolute index of the internal array. This is an internal method with no checks so can be
259         * dangerous. Use with care or ideally with an iterator.
260         *
261         * @param index
262         *            absolute index
263         * @return value
264         */
265        public String getAbs(final int index) { // PRIM_TYPE
266                return data[index];
267        }
268
269        @Override
270        public boolean getElementBooleanAbs(final int index) {
271                return false;
272        }
273
274        @Override
275        public double getElementDoubleAbs(final int index) {
276                return 0;
277        }
278
279        @Override
280        public long getElementLongAbs(final int index) {
281                return 0;
282        }
283
284        @Override
285        public Object getObjectAbs(final int index) {
286                return data[index];
287        }
288
289        @Override
290        public String getStringAbs(final int index) {
291                return stringFormat == null ?  data[index] : // FORMAT_STRING
292                        stringFormat.format(data[index]);
293        }
294
295        /**
296         * Set a value at absolute index in the internal array. This is an internal method with no checks so can be
297         * dangerous. Use with care or ideally with an iterator.
298         *
299         * @param index
300         *            absolute index
301         * @param val
302         *            new value
303         */
304        public void setAbs(final int index, final String val) { // PRIM_TYPE
305                setDirty();
306                data[index] = val;
307        }
308
309        @Override
310        protected void setItemDirect(final int dindex, final int sindex, final Object src) {
311                setDirty();
312                String[] dsrc = (String[]) src; // PRIM_TYPE
313                data[dindex] = dsrc[sindex];
314        }
315
316        @Override
317        public void setObjectAbs(final int index, final Object obj) {
318                if (index < 0 || index > data.length) {
319                        throw new IndexOutOfBoundsException("Index given is outside dataset");
320                }
321
322                setAbs(index, obj.toString()); // FROM_OBJECT
323        }
324
325        /**
326         * @return item in first position
327         * @since 2.0
328         */
329        public String get() { // PRIM_TYPE
330                return data[getFirst1DIndex()];
331        }
332
333        /**
334         * @param i
335         * @return item in given position
336         */
337        public String get(final int i) { // PRIM_TYPE
338                return data[get1DIndex(i)];
339        }
340
341        /**
342         * @param i
343         * @param j
344         * @return item in given position
345         */
346        public String get(final int i, final int j) { // PRIM_TYPE
347                return data[get1DIndex(i, j)];
348        }
349
350        /**
351         * @param pos
352         * @return item in given position
353         */
354        public String get(final int... pos) { // PRIM_TYPE
355                return data[get1DIndex(pos)];
356        }
357
358        @Override
359        public Object getObject() {
360                return get(); // CLASS_TYPE
361        }
362
363        @Override
364        public Object getObject(final int i) {
365                return get(i); // CLASS_TYPE
366        }
367
368        @Override
369        public Object getObject(final int i, final int j) {
370                return get(i, j); // CLASS_TYPE
371        }
372
373        @Override
374        public Object getObject(final int... pos) {
375                return get(pos); // CLASS_TYPE
376        }
377
378        @Override
379        public String getString() {
380                return getStringAbs(getFirst1DIndex());
381        }
382
383        @Override
384        public String getString(final int i) {
385                return getStringAbs(get1DIndex(i));
386        }
387
388        @Override
389        public String getString(final int i, final int j) {
390                return getStringAbs(get1DIndex(i, j));
391        }
392
393        @Override
394        public String getString(final int... pos) {
395                return getStringAbs(get1DIndex(pos));
396        }
397
398        @Override
399        public double getDouble() {
400                return 0;
401        }
402
403        @Override
404        public double getDouble(final int i) {
405                return 0;
406        }
407
408        @Override
409        public double getDouble(final int i, final int j) {
410                return 0;
411        }
412
413        @Override
414        public double getDouble(final int... pos) {
415                return 0;
416        }
417
418        @Override
419        public float getFloat() {
420                return 0;
421        }
422
423        @Override
424        public float getFloat(final int i) {
425                return 0;
426        }
427
428        @Override
429        public float getFloat(final int i, final int j) {
430                return 0;
431        }
432
433        @Override
434        public float getFloat(final int... pos) {
435                return 0;
436        }
437
438        @Override
439        public long getLong() {
440                return 0;
441        }
442
443        @Override
444        public long getLong(final int i) {
445                return 0;
446        }
447
448        @Override
449        public long getLong(final int i, final int j) {
450                return 0;
451        }
452
453        @Override
454        public long getLong(final int... pos) {
455                return 0;
456        }
457
458        @Override
459        public int getInt() {
460                return 0;
461        }
462
463        @Override
464        public int getInt(final int i) {
465                return 0;
466        }
467
468        @Override
469        public int getInt(final int i, final int j) {
470                return 0;
471        }
472
473        @Override
474        public int getInt(final int... pos) {
475                return 0;
476        }
477
478        @Override
479        public short getShort() {
480                return 0;
481        }
482
483        @Override
484        public short getShort(final int i) {
485                return 0;
486        }
487
488        @Override
489        public short getShort(final int i, final int j) {
490                return 0;
491        }
492
493        @Override
494        public short getShort(final int... pos) {
495                return 0;
496        }
497
498        @Override
499        public byte getByte() {
500                return 0;
501        }
502
503        @Override
504        public byte getByte(final int i) {
505                return 0;
506        }
507
508        @Override
509        public byte getByte(final int i, final int j) {
510                return 0;
511        }
512
513        @Override
514        public byte getByte(final int... pos) {
515                return 0;
516        }
517
518        @Override
519        public boolean getBoolean() {
520                return false;
521        }
522
523        @Override
524        public boolean getBoolean(final int i) {
525                return false;
526        }
527
528        @Override
529        public boolean getBoolean(final int i, final int j) {
530                return false;
531        }
532
533        @Override
534        public boolean getBoolean(final int... pos) {
535                return false;
536        }
537
538        /**
539         * Sets the value at first point to the passed value. The dataset must not be null
540         *
541         * @param value
542         * @since 2.0
543         */
544        public void setItem(final String value) { // PRIM_TYPE
545                setAbs(getFirst1DIndex(), value);
546        }
547
548        /**
549         * Sets the value at a particular point to the passed value. The dataset must be 1D
550         *
551         * @param value
552         * @param i
553         */
554        public void setItem(final String value, final int i) { // PRIM_TYPE
555                setAbs(get1DIndex(i), value);
556        }
557
558        /**
559         * Sets the value at a particular point to the passed value. The dataset must be 2D
560         *
561         * @param value
562         * @param i
563         * @param j
564         */
565        public void setItem(final String value, final int i, final int j) { // PRIM_TYPE
566                setAbs(get1DIndex(i, j), value);
567        }
568
569        /**
570         * Sets the value at a particular point to the passed value
571         *
572         * @param value
573         * @param pos
574         */
575        public void setItem(final String value, final int... pos) { // PRIM_TYPE
576                setAbs(get1DIndex(pos), value);
577        }
578
579        @Override
580        public void set(final Object obj) {
581                setItem(obj.toString()); // FROM_OBJECT
582        }
583
584        @Override
585        public void set(final Object obj, final int i) {
586                setItem(obj.toString(), i); // FROM_OBJECT
587        }
588
589        @Override
590        public void set(final Object obj, final int i, final int j) {
591                setItem(obj.toString(), i, j); // FROM_OBJECT
592        }
593
594        @Override
595        public void set(final Object obj, int... pos) {
596                if (pos == null || (pos.length == 0 && shape.length > 0)) {
597                        pos = new int[shape.length];
598                }
599
600                setItem(obj.toString(), pos); // FROM_OBJECT
601        }
602
603
604        @Override
605        public void resize(int... newShape) {
606                setDirty();
607                final IndexIterator iter = getIterator();
608                final int nsize = ShapeUtils.calcSize(newShape);
609                final String[] ndata; // PRIM_TYPE
610                try {
611                        ndata = createArray(nsize);
612                } catch (Throwable t) {
613                        logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t);
614                        throw new IllegalArgumentException(t);
615                }
616                for (int i = 0; iter.hasNext() && i < nsize; i++) {
617                        ndata[i] = data[iter.index];
618                }
619
620                odata = data = ndata;
621                size = nsize;
622                shape = newShape;
623                stride = null;
624                offset = 0;
625                base = null;
626        }
627
628        @Override
629        public StringDatasetBase sort(Integer axis) {
630                setDirty();
631                if (axis == null) {
632                        if (stride == null) {
633                                Arrays.sort(data);
634                        } else {
635                                StringDatasetBase ads = clone().sort(null);
636                                setSlicedView(getView(false), ads);
637                        }
638                } else {
639                        axis = checkAxis(axis);
640                        
641                        StringDatasetBase ads = new StringDatasetBase(shape[axis]);
642                        PositionIterator pi = getPositionIterator(axis);
643                        int[] pos = pi.getPos();
644                        boolean[] hit = pi.getOmit();
645                        while (pi.hasNext()) {
646                                copyItemsFromAxes(pos, hit, ads);
647                                Arrays.sort(ads.data);
648                                setItemsOnAxes(pos, hit, ads.data);
649                        }
650                }
651                return this;
652                // throw new UnsupportedOperationException("Cannot sort dataset"); // BOOLEAN_USE
653        }
654
655        @Override
656        public StringDatasetBase getUniqueItems() {
657                Set<String> set = new TreeSet<String>(); // CLASS_TYPE
658                IndexIterator it = getIterator();
659                while (it.hasNext()) {
660                        set.add(data[it.index]);
661                }
662
663                StringDataset u = new StringDataset(set.size()); // CLASS_TYPE
664                int i = 0;
665                String[] udata = u.getData(); // PRIM_TYPE
666                for (String v : set) { // CLASS_TYPE
667                        udata[i++] = v;
668                }
669                return u;
670        }
671
672        @Override
673        public StringDatasetBase getSlice(final SliceIterator siter) {
674                StringDatasetBase result = new StringDatasetBase(siter.getShape());
675                String[] rdata = result.data; // PRIM_TYPE
676
677                for (int i = 0; siter.hasNext(); i++)
678                        rdata[i] = data[siter.index];
679
680                result.setName(name + BLOCK_OPEN + Slice.createString(siter.shape, siter.start, siter.stop, siter.step) + BLOCK_CLOSE);
681                return result;
682        }
683
684        @Override
685        public void fillDataset(Dataset result, IndexIterator iter) {
686                setDirty();
687                IndexIterator riter = result.getIterator();
688
689                String[] rdata = ((StringDatasetBase) result).data; // PRIM_TYPE
690
691                while (riter.hasNext() && iter.hasNext()) {
692                        rdata[riter.index] = data[iter.index];
693                }
694        }
695
696        @Override
697        public StringDatasetBase setByBoolean(final Object obj, Dataset selection) {
698                setDirty();
699                if (obj instanceof Dataset) {
700                        final Dataset ds = (Dataset) obj;
701                        final int length = ((Number) selection.sum()).intValue();
702                        if (length != ds.getSize()) {
703                                throw new IllegalArgumentException(
704                                                "Number of true items in selection does not match number of items in dataset");
705                        }
706
707                        final IndexIterator oiter = ds.getIterator();
708                        final BooleanIterator biter = getBooleanIterator(selection);
709
710                        while (biter.hasNext() && oiter.hasNext()) {
711                                data[biter.index] = ds.getStringAbs(oiter.index); // GET_ELEMENT_WITH_CAST
712                        }
713                } else {
714                        final String dv = obj.toString(); // PRIM_TYPE // FROM_OBJECT
715                        final BooleanIterator biter = getBooleanIterator(selection);
716
717                        while (biter.hasNext()) {
718                                data[biter.index] = dv;
719                        }
720                }
721                return this;
722        }
723
724        @Override
725        public StringDatasetBase setBy1DIndex(final Object obj, final Dataset index) {
726                setDirty();
727                if (obj instanceof Dataset) {
728                        final Dataset ds = (Dataset) obj;
729                        if (index.getSize() != ds.getSize()) {
730                                throw new IllegalArgumentException(
731                                                "Number of items in index dataset does not match number of items in dataset");
732                        }
733
734                        final IndexIterator oiter = ds.getIterator();
735                        final IntegerIterator iter = new IntegerIterator(index, size);
736
737                        while (iter.hasNext() && oiter.hasNext()) {
738                                data[iter.index] = ds.getStringAbs(oiter.index); // GET_ELEMENT_WITH_CAST
739                        }
740                } else {
741                        final String dv = obj.toString(); // PRIM_TYPE // FROM_OBJECT
742                        IntegerIterator iter = new IntegerIterator(index, size);
743
744                        while (iter.hasNext()) {
745                                data[iter.index] = dv;
746                        }
747                }
748                return this;
749        }
750
751        @Override
752        public StringDatasetBase setByIndexes(final Object obj, final Object... indexes) {
753                setDirty();
754                final IntegersIterator iter = new IntegersIterator(shape, indexes);
755                final int[] pos = iter.getPos();
756
757                if (obj instanceof Dataset) {
758                        final Dataset ds = (Dataset) obj;
759                        if (ShapeUtils.calcSize(iter.getShape()) != ds.getSize()) {
760                                throw new IllegalArgumentException(
761                                                "Number of items in index datasets does not match number of items in dataset");
762                        }
763
764                        final IndexIterator oiter = ds.getIterator();
765
766                        while (iter.hasNext() && oiter.hasNext()) {
767                                setItem(ds.getStringAbs(oiter.index), pos); // GET_ELEMENT_WITH_CAST
768                        }
769                } else {
770                        final String dv = obj.toString(); // PRIM_TYPE // FROM_OBJECT
771
772                        while (iter.hasNext()) {
773                                setItem(dv, pos);
774                        }
775                }
776                return this;
777        }
778
779        @Override
780        StringDatasetBase setSlicedView(Dataset view, Dataset d) {
781                setDirty();
782                final BroadcastSelfIterator it = BroadcastSelfIterator.createIterator(view, d);
783
784                while (it.hasNext()) {
785                        data[it.aIndex] = d.getStringAbs(it.bIndex);
786                }
787                return this;
788        }
789
790        @Override
791        public StringDatasetBase setSlice(final Object obj, final IndexIterator siter) {
792                setDirty();
793
794                if (obj instanceof IDataset) {
795                        final IDataset ds = (IDataset) obj;
796                        final int[] oshape = ds.getShape();
797
798                        if (!ShapeUtils.areShapesCompatible(siter.getShape(), oshape)) {
799                                throw new IllegalArgumentException(String.format(
800                                                "Input dataset is not compatible with slice: %s cf %s", Arrays.toString(oshape),
801                                                Arrays.toString(siter.getShape())));
802                        }
803
804                        if (ds instanceof Dataset) {
805                                final Dataset ads = (Dataset) ds;
806                                final IndexIterator oiter = ads.getIterator();
807
808                                while (siter.hasNext() && oiter.hasNext())
809                                        data[siter.index] = ads.getStringAbs(oiter.index); // GET_ELEMENT_WITH_CAST
810                        } else {
811                                final IndexIterator oiter = new PositionIterator(oshape);
812                                final int[] pos = oiter.getPos();
813
814                                while (siter.hasNext() && oiter.hasNext())
815                                        data[siter.index] = ds.getString(pos); // PRIM_TYPE
816                        }
817                } else {
818                        try {
819                                String v = obj.toString(); // PRIM_TYPE // FROM_OBJECT
820
821                                while (siter.hasNext())
822                                        data[siter.index] = v;
823                        } catch (IllegalArgumentException e) {
824                                throw new IllegalArgumentException("Object for setting slice is not a dataset or number");
825                        }
826                }
827                return this;
828        }
829
830        @Override
831        public void copyItemsFromAxes(final int[] pos, final boolean[] axes, final Dataset dest) {
832                String[] ddata = (String[]) dest.getBuffer(); // PRIM_TYPE
833
834                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
835                int[] sshape = ShapeUtils.squeezeShape(siter.getShape(), false);
836
837                IndexIterator diter = dest.getSliceIterator(null, sshape, null);
838
839                if (ddata.length < ShapeUtils.calcSize(sshape)) {
840                        throw new IllegalArgumentException("destination array is not large enough");
841                }
842
843                dest.setDirty();
844                while (siter.hasNext() && diter.hasNext()) {
845                        ddata[diter.index] = data[siter.index];
846                }
847        }
848
849        @Override
850        public void setItemsOnAxes(final int[] pos, final boolean[] axes, final Object src) {
851                setDirty();
852                String[] sdata = (String[]) src; // PRIM_TYPE
853
854                SliceIterator siter = getSliceIteratorFromAxes(pos, axes);
855
856                if (sdata.length < ShapeUtils.calcSize(siter.getShape())) {
857                        throw new IllegalArgumentException("destination array is not large enough");
858                }
859
860                for (int i = 0; siter.hasNext(); i++) {
861                        data[siter.index] = sdata[i];
862                }
863        }
864
865        private List<int[]> findPositions(final String value) { // PRIM_TYPE
866                IndexIterator iter = getIterator(true);
867                List<int[]> posns = new ArrayList<int[]>();
868                int[] pos = iter.getPos();
869
870                {
871                        while (iter.hasNext()) {
872                                if (data[iter.index] == value) {
873                                        posns.add(pos.clone());
874                                }
875                        }
876                }
877                return posns;
878        }
879
880        @Override
881        public int[] maxPos(boolean... ignoreInvalids) {
882                // StatisticsMetadata<Number> md = getStats(); // BOOLEAN_USE
883                StatisticsMetadata<String> md = getStringStats(); // OBJECT_USE
884                List<int[]> max = md.getMaximumPositions(ignoreInvalids);
885
886                if (max == null) {
887                        // max = findPositions(md.getMaximum(ignoreInvalids).intValue() != 0); // BOOLEAN_USE
888                        max = findPositions(md.getMaximum(ignoreInvalids).toString()); // OBJECT_USE
889
890                        md.setMaximumPositions(max);
891                }
892
893                return max.get(0); // first maximum
894        }
895
896        @Override
897        public int[] minPos(boolean... ignoreInvalids) {
898                // StatisticsMetadata<Number> md = getStats(); // BOOLEAN_USE
899                StatisticsMetadata<String> md = getStringStats(); // OBJECT_USE
900                List<int[]> min = md.getMinimumPositions(ignoreInvalids);
901
902                if (min == null) {
903                        // min = findPositions(md.getMinimum(ignoreInvalids).intValue() != 0); // BOOLEAN_USE
904                        min = findPositions(md.getMinimum(ignoreInvalids).toString()); // OBJECT_USE
905
906                        md.setMinimumPositions(min);
907                }
908
909                return min.get(0); // first minimum
910        }
911
912        @Override
913        public boolean containsNans() {
914                return false;
915        }
916
917        @Override
918        public boolean containsInfs() {
919                return false;
920        }
921
922        @Override
923        public boolean containsInvalidNumbers() {
924                return false;
925        }
926
927        @Override
928        public StringDatasetBase iadd(final Object b) {
929                return this;
930        }
931
932        @Override
933        public StringDatasetBase isubtract(final Object b) {
934                return this;
935        }
936
937        @Override
938        public StringDatasetBase imultiply(final Object b) {
939                return this;
940        }
941
942        @Override
943        public StringDatasetBase idivide(final Object b) {
944                return this;
945        }
946
947        @Override
948        public StringDatasetBase ifloor() {
949                return this;
950        }
951
952        @Override
953        public StringDatasetBase iremainder(final Object b) {
954                return this;
955        }
956
957        @Override
958        public StringDatasetBase ipower(final Object b) {
959                return this;
960        }
961
962        @Override
963        public double residual(final Object b, final Dataset w, boolean ignoreNaNs) {
964                double sum = 0;
965                return sum;
966        }
967}