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