    001/*-
    002 * Copyright (c) 2016 Diamond Light Source Ltd.
    003 *
    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
    010package org.eclipse.january.dataset;
    011
    012import java.lang.reflect.Array;
    013import java.util.Date;
    014import java.util.HashMap;
    015import java.util.List;
    016import java.util.Map;
    017
    018import org.apache.commons.math3.complex.Complex;
    019import org.slf4j.Logger;
    020import org.slf4j.LoggerFactory;
    021
    022public class DTypeUtils {
    023        protected static final Logger logger = LoggerFactory.getLogger(DTypeUtils.class);
    024
    025        private static final Map<Class<? extends Dataset>, Integer> interface2DTypes = createInterfaceMap(); // map interface to dataset type
    026
    027        private static Map<Class<? extends Dataset>, Integer> createInterfaceMap() {
    028                Map<Class<? extends Dataset>, Integer> map = new HashMap<Class<? extends Dataset>, Integer>();
    029                map.put(BooleanDataset.class, Dataset.BOOL);
    030                map.put(ByteDataset.class, Dataset.INT8);
    031                map.put(ShortDataset.class, Dataset.INT16);
    032                map.put(IntegerDataset.class, Dataset.INT32);
    033                map.put(LongDataset.class, Dataset.INT64);
    034                map.put(FloatDataset.class, Dataset.FLOAT32);
    035                map.put(DoubleDataset.class, Dataset.FLOAT64);
    036                map.put(CompoundByteDataset.class, Dataset.ARRAYINT8);
    037                map.put(CompoundShortDataset.class, Dataset.ARRAYINT16);
    038                map.put(CompoundIntegerDataset.class, Dataset.ARRAYINT32);
    039                map.put(CompoundLongDataset.class, Dataset.ARRAYINT64);
    040                map.put(CompoundFloatDataset.class, Dataset.ARRAYFLOAT32);
    041                map.put(CompoundDoubleDataset.class, Dataset.ARRAYFLOAT64);
    042                map.put(ComplexFloatDataset.class, Dataset.COMPLEX64);
    043                map.put(ComplexDoubleDataset.class, Dataset.COMPLEX128);
    044                map.put(ObjectDataset.class, Dataset.OBJECT);
    045                map.put(StringDataset.class, Dataset.STRING);
    046                map.put(DateDataset.class, Dataset.DATE);
    047                map.put(RGBDataset.class, Dataset.RGB);
    048                map.put(ObjectDataset.class, Dataset.OBJECT);
    049                return map;
    050        }
    051
    052        transient private static final Map<Class<?>, Integer> class2DType = createElementClassMap();
    053
    054        private static Map<Class<?>, Integer> createElementClassMap() {
    055                Map<Class<?>, Integer> result = new HashMap<Class<?>, Integer>();
    056                result.put(Boolean.class, Dataset.BOOL);
    057                result.put(Byte.class, Dataset.INT8);
    058                result.put(Short.class, Dataset.INT16);
    059                result.put(Integer.class, Dataset.INT32);
    060                result.put(Long.class, Dataset.INT64);
    061                result.put(Float.class, Dataset.FLOAT32);
    062                result.put(Double.class, Dataset.FLOAT64);
    063                result.put(boolean.class, Dataset.BOOL);
    064                result.put(byte.class, Dataset.INT8);
    065                result.put(short.class, Dataset.INT16);
    066                result.put(int.class, Dataset.INT32);
    067                result.put(long.class, Dataset.INT64);
    068                result.put(float.class, Dataset.FLOAT32);
    069                result.put(double.class, Dataset.FLOAT64);
    070                result.put(Complex.class, Dataset.COMPLEX128);
    071                result.put(String.class, Dataset.STRING);
    072                result.put(Date.class, Dataset.DATE);
    073                result.put(Object.class, Dataset.OBJECT);
    074                return result;
    075        }
    076
    077        /**
    078         * @param a
    079         * @return name of dataset type
    080         */
    081        public static String getDTypeName(Dataset a) {
    082                return getDTypeName(a.getDType(), a.getElementsPerItem());
    083        }
    084
    085        /**
    086         * @param a
    087         * @return name of dataset type
    088         */
    089        public static String getDTypeName(ILazyDataset a) {
    090                return getDTypeName(getDTypeFromClass(a.getElementClass()), a.getElementsPerItem());
    091        }
    092
    093        /**
    094         * @param dtype
    095         * @param itemSize
    096         * @return name of dataset type
    097         */
    098        public static String getDTypeName(int dtype, int itemSize) {
    099                int bytes = getItemBytes(dtype, 1);
    100                if (isDTypeComplex(dtype)) {
    101                        return "COMPLEX" + bytes*16;
    102                } else if (dtype == Dataset.RGB) {
    103                        return "RGB";
    104                }
    105
    106                String prefix = itemSize > 1 ? ("ARRAY of " + itemSize + " ") : "";
    107                if (isDTypeFloating(dtype)) {
    108                        return prefix + "FLOAT" + bytes*8;
    109                }
    110                switch (dtype) {
    111                case Dataset.BOOL:
    112                        return prefix + "BOOLEAN";
    113                case Dataset.STRING:
    114                        return prefix + "STRING";
    115                case Dataset.DATE:
    116                        return prefix + "DATE";
    117                case Dataset.OBJECT:
    118                        return prefix + "OBJECT";
    119                }
    120
    121                return prefix + "INT" + bytes*8;
    122        }
    123
    124        /**
    125         * @param clazz dataset class
    126         * @return dataset type for dataset class
    127         */
    128        public static int getDType(Class<? extends Dataset> clazz) {
    129                if (!interface2DTypes.containsKey(clazz)) {
    130                        throw new IllegalArgumentException("Interface class not allowed or supported");
    131                }
    132                return interface2DTypes.get(clazz);
    133        }
    134
    135        public static boolean isDTypeElemental(int dtype) {
    136                return dtype <= Dataset.DATE;
    137        }
    138
    139        public static boolean isDTypeInteger(int dtype) {
    140                return dtype == Dataset.INT8 || dtype == Dataset.INT16 || dtype == Dataset.INT32 || dtype == Dataset.INT64 ||
    141                                dtype == Dataset.ARRAYINT8 || dtype == Dataset.ARRAYINT16 || dtype == Dataset.ARRAYINT32 || dtype == Dataset.ARRAYINT64 || dtype == Dataset.RGB;
    142        }
    143
    144        public static boolean isDTypeFloating(int dtype) {
    145                return dtype == Dataset.FLOAT32 || dtype == Dataset.FLOAT64 || dtype == Dataset.COMPLEX64 || dtype == Dataset.COMPLEX128 ||
    146                                dtype == Dataset.ARRAYFLOAT32 || dtype == Dataset.ARRAYFLOAT64;
    147        }
    148
    149        public static boolean isDTypeComplex(int dtype) {
    150                return dtype == Dataset.COMPLEX64 || dtype == Dataset.COMPLEX128;
    151        }
    152
    153        /**
    154         * @param dtype
    155         * @return true if dataset type is numerical, i.e. a dataset contains numbers
    156         */
    157        public static boolean isDTypeNumerical(int dtype) {
    158                return isDTypeInteger(dtype) || isDTypeFloating(dtype) || dtype == Dataset.BOOL;
    159        }
    160
    161        /**
    162         * Find dataset type that best fits given types The best type takes into account complex and array datasets
    163         *
    164         * @param atype
    165         *            first dataset type
    166         * @param btype
    167         *            second dataset type
    168         * @return best dataset type
    169         */
    170        public static int getBestDType(final int atype, final int btype) {
    171                int besttype;
    172
    173                int a = atype >= Dataset.ARRAYINT8 ? atype / Dataset.ARRAYMUL : atype;
    174                int b = btype >= Dataset.ARRAYINT8 ? btype / Dataset.ARRAYMUL : btype;
    175
    176                if (isDTypeFloating(a)) {
    177                        if (!isDTypeFloating(b)) {
    178                                b = getBestFloatDType(b);
    179                                if (isDTypeComplex(a)) {
    180                                        b += Dataset.COMPLEX64 - Dataset.FLOAT32;
    181                                }
    182                        }
    183                } else if (isDTypeFloating(b)) {
    184                        a = getBestFloatDType(a);
    185                        if (isDTypeComplex(b)) {
    186                                a += Dataset.COMPLEX64 - Dataset.FLOAT32;
    187                        }
    188                }
    189                besttype = a > b ? a : b;
    190
    191                if (atype >= Dataset.ARRAYINT8 || btype >= Dataset.ARRAYINT8) {
    192                        if (besttype >= Dataset.COMPLEX64) {
    193                                throw new IllegalArgumentException("Complex type cannot be promoted to compound type");
    194                        }
    195                        besttype *= Dataset.ARRAYMUL;
    196                }
    197
    198                return besttype;
    199        }
    200
    201        /**
    202         * Find floating point dataset type that best fits given types. The best type takes into account complex and array
    203         * datasets
    204         *
    205         * @param otype
    206         *            old dataset type
    207         * @return best dataset type
    208         */
    209        public static int getBestFloatDType(final int otype) {
    210                int btype;
    211                switch (otype) {
    212                case Dataset.BOOL:
    213                case Dataset.INT8:
    214                case Dataset.INT16:
    215                case Dataset.ARRAYINT8:
    216                case Dataset.ARRAYINT16:
    217                case Dataset.FLOAT32:
    218                case Dataset.ARRAYFLOAT32:
    219                case Dataset.COMPLEX64:
    220                case Dataset.RGB:
    221                        btype = Dataset.FLOAT32; // demote, if necessary
    222                        break;
    223                case Dataset.INT32:
    224                case Dataset.INT64:
    225                case Dataset.ARRAYINT32:
    226                case Dataset.ARRAYINT64:
    227                case Dataset.FLOAT64:
    228                case Dataset.ARRAYFLOAT64:
    229                case Dataset.COMPLEX128:
    230                        btype = Dataset.FLOAT64; // promote, if necessary
    231                        break;
    232                default:
    233                        btype = otype; // for non-numeric datasets, preserve type
    234                        break;
    235                }
    236
    237                return btype;
    238        }
    239
    240        /**
    241         * Find floating point dataset type that best fits given class The best type takes into account complex and array
    242         * datasets
    243         *
    244         * @param cls
    245         *            of an item or element
    246         * @return best dataset type
    247         */
    248        public static int getBestFloatDType(Class<? extends Object> cls) {
    249                return getBestFloatDType(getDTypeFromClass(cls));
    250        }
    251
    252        /**
    253         * Get dataset type from an element class
    254         *
    255         * @param cls element class
    256         * @return dataset type
    257         */
    258        public static int getDTypeFromClass(Class<? extends Object> cls) {
    259                return getDTypeFromClass(cls, 1);
    260        }
    261
    262        /**
    263         * Get dataset type from an element class
    264         *
    265         * @param cls element class
    266         * @return dataset type
    267         */
    268        public static int getDTypeFromClass(Class<? extends Object> cls, int isize) {
    269                Integer dtype = class2DType.get(cls);
    270                if (dtype == null) {
    271                        throw new IllegalArgumentException("Class of object not supported");
    272                }
    273                if (isize != 1) {
    274                        if (dtype < Dataset.FLOAT64)
    275                                dtype *= Dataset.ARRAYMUL;
    276                }
    277                return dtype;
    278        }
    279
    280        /**
    281         * Get dataset type from an object. The following are supported: Java Number objects, Apache common math Complex
    282         * objects, Java arrays and lists
    283         *
    284         * @param obj
    285         * @return dataset type
    286         */
    287        public static int getDTypeFromObject(Object obj) {
    288                int dtype = -1;
    289
    290                if (obj == null) {
    291                        return dtype;
    292                }
    293
    294                if (obj instanceof List<?>) {
    295                        List<?> jl = (List<?>) obj;
    296                        int l = jl.size();
    297                        for (int i = 0; i < l; i++) {
    298                                int ldtype = getDTypeFromObject(jl.get(i));
    299                                if (ldtype > dtype) {
    300                                        dtype = ldtype;
    301                                }
    302                        }
    303                } else if (obj.getClass().isArray()) {
    304                        Class<?> ca = obj.getClass().getComponentType();
    305                        if (isClassSupportedAsElement(ca)) {
    306                                return getDTypeFromClass(ca);
    307                        }
    308                        int l = Array.getLength(obj);
    309                        for (int i = 0; i < l; i++) {
    310                                Object lo = Array.get(obj, i);
    311                                int ldtype = getDTypeFromObject(lo);
    312                                if (ldtype > dtype) {
    313                                        dtype = ldtype;
    314                                }
    315                        }
    316                } else if (obj instanceof Dataset) {
    317                        return ((Dataset) obj).getDType();
    318                } else if (obj instanceof ILazyDataset) {
    319                        dtype = getDTypeFromClass(((ILazyDataset) obj).getElementClass(), ((ILazyDataset) obj).getElementsPerItem());
    320                } else {
    321                        dtype = getDTypeFromClass(obj.getClass());
    322                }
    323                return dtype;
    324        }
    325
    326        /**
    327         * Get dataset type from given dataset
    328         * @param d
    329         * @return dataset type
    330         */
    331        public static int getDType(ILazyDataset d) {
    332                if (d instanceof LazyDatasetBase)
    333                        return ((LazyDatasetBase) d).getDType();
    334                return getDTypeFromClass(d.getElementClass(), d.getElementsPerItem());
    335        }
    336
    337        /**
    338         * The largest dataset type suitable for a summation of around a few thousand items without changing from the "kind"
    339         * of dataset
    340         *
    341         * @param otype
    342         * @return largest dataset type available for given dataset type
    343         */
    344        public static int getLargestDType(final int otype) {
    345                switch (otype) {
    346                case Dataset.BOOL:
    347                case Dataset.INT8:
    348                case Dataset.INT16:
    349                        return Dataset.INT32;
    350                case Dataset.INT32:
    351                case Dataset.INT64:
    352                        return Dataset.INT64;
    353                case Dataset.FLOAT32:
    354                case Dataset.FLOAT64:
    355                        return Dataset.FLOAT64;
    356                case Dataset.COMPLEX64:
    357                case Dataset.COMPLEX128:
    358                        return Dataset.COMPLEX128;
    359                case Dataset.ARRAYINT8:
    360                case Dataset.ARRAYINT16:
    361                        return Dataset.ARRAYINT32;
    362                case Dataset.ARRAYINT32:
    363                case Dataset.ARRAYINT64:
    364                        return Dataset.ARRAYINT64;
    365                case Dataset.ARRAYFLOAT32:
    366                case Dataset.ARRAYFLOAT64:
    367                        return Dataset.ARRAYFLOAT64;
    368                case Dataset.DATE:
    369                case Dataset.STRING:
    370                case Dataset.RGB:
    371                case Dataset.OBJECT:
    372                        return otype;
    373                }
    374                throw new IllegalArgumentException("Unsupported dataset type");
    375        }
    376
    377        /**
    378         * @param otype
    379         * @return elemental dataset type available for given dataset type
    380         */
    381        public static int getElementalDType(final int otype) {
    382                switch (otype) {
    383                case Dataset.COMPLEX64:
    384                        return Dataset.FLOAT32;
    385                case Dataset.COMPLEX128:
    386                        return Dataset.FLOAT64;
    387                case Dataset.ARRAYINT8:
    388                        return Dataset.INT8;
    389                case Dataset.ARRAYINT16:
    390                case Dataset.RGB:
    391                        return Dataset.INT16;
    392                case Dataset.ARRAYINT32:
    393                        return Dataset.INT32;
    394                case Dataset.ARRAYINT64:
    395                        return Dataset.INT64;
    396                case Dataset.ARRAYFLOAT32:
    397                        return Dataset.FLOAT32;
    398                case Dataset.ARRAYFLOAT64:
    399                        return Dataset.FLOAT64;
    400                default:
    401                        return otype;
    402                }
    403        }
    404
    405        /**
    406         * @param comp
    407         * @return true if supported
    408         */
    409        public static boolean isClassSupportedAsElement(Class<? extends Object> comp) {
    410                return comp.isPrimitive() || Number.class.isAssignableFrom(comp) || comp.equals(Boolean.class)
    411                                || comp.equals(Complex.class) || comp.equals(String.class) || comp.equals(Date.class);
    412        }
    413
    414        /**
    415         * @param dtype
    416         * @return number of elements per item
    417         */
    418        public static int getElementsPerItem(final int dtype) {
    419                switch (dtype) {
    420                case Dataset.ARRAYINT8:
    421                case Dataset.ARRAYINT16:
    422                case Dataset.ARRAYINT32:
    423                case Dataset.ARRAYINT64:
    424                case Dataset.ARRAYFLOAT32:
    425                case Dataset.ARRAYFLOAT64:
    426                        throw new UnsupportedOperationException("Multi-element type unsupported");
    427                case Dataset.COMPLEX64:
    428                case Dataset.COMPLEX128:
    429                        return 2;
    430                case Dataset.RGB:
    431                        return 3;
    432                }
    433                return 1;
    434        }
    435
    436        /**
    437         * @param dtype
    438         * @return length of single item in bytes
    439         */
    440        public static int getItemBytes(final int dtype) {
    441                return getItemBytes(dtype, getElementsPerItem(dtype));
    442        }
    443
    444        /**
    445         * @param dtype
    446         * @param isize
    447         *            number of elements in an item
    448         * @return length of single item in bytes
    449         */
    450        public static int getItemBytes(final int dtype, final int isize) {
    451                int size;
    452
    453                switch (dtype) {
    454                case Dataset.BOOL:
    455                        size = 1; // How is this defined?
    456                        break;
    457                case Dataset.INT8:
    458                case Dataset.ARRAYINT8:
    459                        size = Byte.SIZE / 8;
    460                        break;
    461                case Dataset.INT16:
    462                case Dataset.ARRAYINT16:
    463                case Dataset.RGB:
    464                        size = Short.SIZE / 8;
    465                        break;
    466                case Dataset.INT32:
    467                case Dataset.ARRAYINT32:
    468                        size = Integer.SIZE / 8;
    469                        break;
    470                case Dataset.INT64:
    471                case Dataset.ARRAYINT64:
    472                        size = Long.SIZE / 8;
    473                        break;
    474                case Dataset.FLOAT32:
    475                case Dataset.ARRAYFLOAT32:
    476                case Dataset.COMPLEX64:
    477                        size = Float.SIZE / 8;
    478                        break;
    479                case Dataset.FLOAT64:
    480                case Dataset.ARRAYFLOAT64:
    481                case Dataset.COMPLEX128:
    482                        size = Double.SIZE / 8;
    483                        break;
    484                default:
    485                        size = 0;
    486                        break;
    487                }
    488
    489                return size * isize;
    490        }
    491
    492        public static boolean toBoolean(final Object b) {
    493                if (b instanceof Number) {
    494                        return ((Number) b).longValue() != 0;
    495                } else if (b instanceof Boolean) {
    496                        return ((Boolean) b).booleanValue();
    497                } else if (b instanceof Complex) {
    498                        return ((Complex) b).getReal() != 0;
    499                } else if (b instanceof Dataset) {
    500                        Dataset db = (Dataset) b;
    501                        if (db.getSize() != 1) {
    502                                logger.error("Given dataset must have only one item");
    503                                throw new IllegalArgumentException("Given dataset must have only one item");
    504                        }
    505                        return db.getBoolean();
    506                } else if (b instanceof IDataset) {
    507                        IDataset db = (IDataset) b;
    508                        if (db.getSize() != 1) {
    509                                logger.error("Given dataset must have only one item");
    510                                throw new IllegalArgumentException("Given dataset must have only one item");
    511                        }
    512                        return db.getBoolean(new int[db.getRank()]);
    513                } else {
    514                        logger.error("Argument is of unsupported class");
    515                        throw new IllegalArgumentException("Argument is of unsupported class");
    516                }
    517        }
    518
    519        /**
    520         * @param d
    521         * @return returns a long or 0 if d is NaN or infinite
    522         * @since 2.1
    523         */
    524        public static final long toLong(double d) {
    525                if (Double.isInfinite(d) || Double.isNaN(d))
    526                        return 0l;
    527                return (long) d;
    528        }
    529
    530        /**
    531         * @param d
    532         * @return returns a long or 0 if d is NaN or infinite
    533         * @since 2.1
    534         */
    535        public static final long toLong(float d) {
    536                if (Float.isInfinite(d) || Float.isNaN(d))
    537                        return 0l;
    538                return (long) d;
    539        }
    540
    541        public static long toLong(final Object b) {
    542                if (b instanceof Number) {
    543                        final Number n = (Number) b;
    544                        return (n instanceof Double || n instanceof Float) ? toLong(n.doubleValue()) : n.longValue();
    545                } else if (b instanceof Boolean) {
    546                        return ((Boolean) b).booleanValue() ? 1 : 0;
    547                } else if (b instanceof Complex) {
    548                        return (long) ((Complex) b).getReal();
    549                } else if (b instanceof Dataset) {
    550                        Dataset db = (Dataset) b;
    551                        if (db.getSize() != 1) {
    552                                logger.error("Given dataset must have only one item");
    553                                throw new IllegalArgumentException("Given dataset must have only one item");
    554                        }
    555                        return db.getLong();
    556                } else if (b instanceof IDataset) {
    557                        IDataset db = (IDataset) b;
    558                        if (db.getSize() != 1) {
    559                                logger.error("Given dataset must have only one item");
    560                                throw new IllegalArgumentException("Given dataset must have only one item");
    561                        }
    562                        return db.getLong(new int[db.getRank()]);
    563                } else {
    564                        logger.error("Argument is of unsupported class");
    565                        throw new IllegalArgumentException("Argument is of unsupported class");
    566                }
    567        }
    568
    569        public static double toReal(final Object b) {
    570                if (b instanceof Number) {
    571                        return ((Number) b).doubleValue();
    572                } else if (b instanceof Boolean) {
    573                        return ((Boolean) b).booleanValue() ? 1 : 0;
    574                } else if (b instanceof Complex) {
    575                        return ((Complex) b).getReal();
    576                } else if (b.getClass().isArray()) {
    577                        if (Array.getLength(b) == 0)
    578                                return 0;
    579                        return toReal(Array.get(b, 0));
    580                } else if (b instanceof Dataset) {
    581                        Dataset db = (Dataset) b;
    582                        if (db.getSize() != 1) {
    583                                logger.error("Given dataset must have only one item");
    584                                throw new IllegalArgumentException("Given dataset must have only one item");
    585                        }
    586                        return db.getDouble();
    587                } else if (b instanceof IDataset) {
    588                        IDataset db = (Dataset) b;
    589                        if (db.getSize() != 1) {
    590                                logger.error("Given dataset must have only one item");
    591                                throw new IllegalArgumentException("Given dataset must have only one item");
    592                        }
    593                        return db.getDouble(new int[db.getRank()]);
    594                } else {
    595                        logger.error("Argument is of unsupported class");
    596                        throw new IllegalArgumentException("Argument is of unsupported class");
    597                }
    598        }
    599
    600        public static double toImag(final Object b) {
    601                if (b instanceof Number) {
    602                        return 0;
    603                } else if (b instanceof Boolean) {
    604                        return 0;
    605                } else if (b instanceof Complex) {
    606                        return ((Complex) b).getImaginary();
    607                } else if (b.getClass().isArray()) {
    608                        if (Array.getLength(b) < 2)
    609                                return 0;
    610                        return toReal(Array.get(b, 1));
    611                } else if (b instanceof Dataset) {
    612                        Dataset db = (Dataset) b;
    613                        if (db.getSize() != 1) {
    614                                logger.error("Given dataset must have only one item");
    615                                throw new IllegalArgumentException("Given dataset must have only one item");
    616                        }
    617                        return toImag(db.getObjectAbs(db.getOffset()));
    618                } else if (b instanceof IDataset) {
    619                        IDataset db = (Dataset) b;
    620                        if (db.getSize() != 1) {
    621                                logger.error("Given dataset must have only one item");
    622                                throw new IllegalArgumentException("Given dataset must have only one item");
    623                        }
    624                        return toImag(db.getObject(new int[db.getRank()]));
    625                } else {
    626                        logger.error("Argument is of unsupported class");
    627                        throw new IllegalArgumentException("Argument is of unsupported class");
    628                }
    629        }
    630
    631        public static double[] toDoubleArray(final Object b, final int itemSize) {
    632                double[] result = null;
    633
    634                // ensure array is of given length
    635                if (b instanceof Number) {
    636                        result = new double[itemSize];
    637                        final double val = ((Number) b).doubleValue();
    638                        for (int i = 0; i < itemSize; i++) {
    639                                result[i] = val;
    640                        }
    641                } else if (b instanceof double[]) {
    642                        final double[] old = (double[]) b;
    643                        result = old;
    644                        final int ilen = old.length;
    645                        if (ilen < itemSize) {
    646                                result = new double[itemSize];
    647                                for (int i = 0; i < ilen; i++) {
    648                                        result[i] = old[i];
    649                                }
    650                        }
    651                } else if (b instanceof List<?>) {
    652                        result = new double[itemSize];
    653                        List<?> jl = (List<?>) b;
    654                        int ilen = jl.size();
    655                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    656                                logger.error("Given array was not of a numerical primitive type");
    657                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    658                        }
    659                        ilen = Math.min(itemSize, ilen);
    660                        for (int i = 0; i < ilen; i++) {
    661                                result[i] = toReal(jl.get(i));
    662                        }
    663                } else if (b.getClass().isArray()) {
    664                        result = new double[itemSize];
    665                        int ilen = Array.getLength(b);
    666                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    667                                logger.error("Given array was not of a numerical primitive type");
    668                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    669                        }
    670                        ilen = Math.min(itemSize, ilen);
    671                        for (int i = 0; i < ilen; i++) {
    672                                result[i] = ((Number) Array.get(b, i)).doubleValue();
    673                        }
    674                } else if (b instanceof Complex) {
    675                        if (itemSize > 2) {
    676                                logger.error("Complex number will not fit in compound dataset");
    677                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    678                        }
    679                        Complex cb = (Complex) b;
    680                        switch (itemSize) {
    681                        default:
    682                        case 0:
    683                                break;
    684                        case 1:
    685                                result = new double[] {cb.getReal()};
    686                                break;
    687                        case 2:
    688                                result = new double[] {cb.getReal(), cb.getImaginary()};
    689                                break;
    690                        }
    691                } else if (b instanceof Dataset) {
    692                        Dataset db = (Dataset) b;
    693                        if (db.getSize() != 1) {
    694                                logger.error("Given dataset must have only one item");
    695                                throw new IllegalArgumentException("Given dataset must have only one item");
    696                        }
    697                        return toDoubleArray(db.getObjectAbs(db.getOffset()), itemSize);
    698                } else if (b instanceof IDataset) {
    699                        IDataset db = (Dataset) b;
    700                        if (db.getSize() != 1) {
    701                                logger.error("Given dataset must have only one item");
    702                                throw new IllegalArgumentException("Given dataset must have only one item");
    703                        }
    704                        return toDoubleArray(db.getObject(new int[db.getRank()]), itemSize);
    705                }
    706
    707                return result;
    708        }
    709
    710        public static float[] toFloatArray(final Object b, final int itemSize) {
    711                float[] result = null;
    712
    713                if (b instanceof Number) {
    714                        result = new float[itemSize];
    715                        final float val = ((Number) b).floatValue();
    716                        for (int i = 0; i < itemSize; i++)
    717                                result[i] = val;
    718                } else if (b instanceof float[]) {
    719                        final float[] old = (float[]) b;
    720                        result = old;
    721                        final int ilen = old.length;
    722                        if (ilen < itemSize) {
    723                                result = new float[itemSize];
    724                                for (int i = 0; i < ilen; i++) {
    725                                        result[i] = old[i];
    726                                }
    727                        }
    728                } else if (b instanceof double[]) {
    729                        final double[] old = (double[]) b;
    730                        final int ilen = Math.min(itemSize, old.length);
    731                        result = new float[itemSize];
    732                        for (int i = 0; i < ilen; i++) {
    733                                result[i] = (float) old[i];
    734                        }
    735                } else if (b instanceof List<?>) {
    736                        result = new float[itemSize];
    737                        List<?> jl = (List<?>) b;
    738                        int ilen = jl.size();
    739                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    740                                logger.error("Given array was not of a numerical primitive type");
    741                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    742                        }
    743                        ilen = Math.min(itemSize, ilen);
    744                        for (int i = 0; i < ilen; i++) {
    745                                result[i] = (float) toReal(jl.get(i));
    746                        }
    747                } else if (b.getClass().isArray()) {
    748                        result = new float[itemSize];
    749                        int ilen = Array.getLength(b);
    750                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    751                                logger.error("Given array was not of a numerical primitive type");
    752                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    753                        }
    754                        ilen = Math.min(itemSize, ilen);
    755                        for (int i = 0; i < ilen; i++) {
    756                                result[i] = ((Number) Array.get(b, i)).floatValue();
    757                        }
    758                } else if (b instanceof Complex) {
    759                        if (itemSize > 2) {
    760                                logger.error("Complex number will not fit in compound dataset");
    761                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    762                        }
    763                        Complex cb = (Complex) b;
    764                        switch (itemSize) {
    765                        default:
    766                        case 0:
    767                                break;
    768                        case 1:
    769                                result = new float[] {(float) cb.getReal()};
    770                                break;
    771                        case 2:
    772                                result = new float[] {(float) cb.getReal(), (float) cb.getImaginary()};
    773                                break;
    774                        }
    775                } else if (b instanceof Dataset) {
    776                        Dataset db = (Dataset) b;
    777                        if (db.getSize() != 1) {
    778                                logger.error("Given dataset must have only one item");
    779                                throw new IllegalArgumentException("Given dataset must have only one item");
    780                        }
    781                        return toFloatArray(db.getObjectAbs(db.getOffset()), itemSize);
    782                } else if (b instanceof IDataset) {
    783                        IDataset db = (Dataset) b;
    784                        if (db.getSize() != 1) {
    785                                logger.error("Given dataset must have only one item");
    786                                throw new IllegalArgumentException("Given dataset must have only one item");
    787                        }
    788                        return toFloatArray(db.getObject(new int[db.getRank()]), itemSize);
    789                }
    790
    791                return result;
    792        }
    793
    794        public static long[] toLongArray(final Object b, final int itemSize) {
    795                long[] result = null;
    796
    797                if (b instanceof Number) {
    798                        result = new long[itemSize];
    799                        final long val = toLong(b);
    800                        for (int i = 0; i < itemSize; i++) {
    801                                result[i] = val;
    802                        }
    803                } else if (b instanceof long[]) {
    804                        final long[] old = (long[]) b;
    805                        result = old;
    806                        final int ilen = result.length;
    807                        if (ilen < itemSize) {
    808                                result = new long[itemSize];
    809                                for (int i = 0; i < ilen; i++) {
    810                                        result[i] = old[i];
    811                                }
    812                        }
    813                } else if (b instanceof double[]) {
    814                        final double[] old = (double[]) b;
    815                        final int ilen = Math.min(itemSize, old.length);
    816                        result = new long[itemSize];
    817                        for (int i = 0; i < ilen; i++) {
    818                                result[i] = toLong(old[i]);
    819                        }
    820                } else if (b instanceof List<?>) {
    821                        result = new long[itemSize];
    822                        List<?> jl = (List<?>) b;
    823                        int ilen = jl.size();
    824                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    825                                logger.error("Given array was not of a numerical primitive type");
    826                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    827                        }
    828                        ilen = Math.min(itemSize, ilen);
    829                        for (int i = 0; i < ilen; i++) {
    830                                result[i] = toLong(jl.get(i));
    831                        }
    832                } else if (b.getClass().isArray()) {
    833                        result = new long[itemSize];
    834                        int ilen = Array.getLength(b);
    835                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    836                                logger.error("Given array was not of a numerical primitive type");
    837                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    838                        }
    839                        ilen = Math.min(itemSize, ilen);
    840                        for (int i = 0; i < ilen; i++) {
    841                                result[i] = toLong(Array.get(b, i));
    842                        }
    843                } else if (b instanceof Complex) {
    844                        if (itemSize > 2) {
    845                                logger.error("Complex number will not fit in compound dataset");
    846                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    847                        }
    848                        Complex cb = (Complex) b;
    849                        switch (itemSize) {
    850                        default:
    851                        case 0:
    852                                break;
    853                        case 1:
    854                                result = new long[] {(long) cb.getReal()};
    855                                break;
    856                        case 2:
    857                                result = new long[] {(long) cb.getReal(), (long) cb.getImaginary()};
    858                                break;
    859                        }
    860                } else if (b instanceof Dataset) {
    861                        Dataset db = (Dataset) b;
    862                        if (db.getSize() != 1) {
    863                                logger.error("Given dataset must have only one item");
    864                                throw new IllegalArgumentException("Given dataset must have only one item");
    865                        }
    866                        return toLongArray(db.getObjectAbs(db.getOffset()), itemSize);
    867                } else if (b instanceof IDataset) {
    868                        IDataset db = (Dataset) b;
    869                        if (db.getSize() != 1) {
    870                                logger.error("Given dataset must have only one item");
    871                                throw new IllegalArgumentException("Given dataset must have only one item");
    872                        }
    873                        return toLongArray(db.getObject(new int[db.getRank()]), itemSize);
    874                }
    875
    876                return result;
    877        }
    878
    879        public static int[] toIntegerArray(final Object b, final int itemSize) {
    880                int[] result = null;
    881
    882                if (b instanceof Number) {
    883                        result = new int[itemSize];
    884                        final int val = (int) toLong(b);
    885                        for (int i = 0; i < itemSize; i++) {
    886                                result[i] = val;
    887                        }
    888                } else if (b instanceof int[]) {
    889                        final int[] old = (int[]) b;
    890                        result = old;
    891                        final int ilen = result.length;
    892                        if (ilen < itemSize) {
    893                                result = new int[itemSize];
    894                                for (int i = 0; i < ilen; i++) {
    895                                        result[i] = old[i];
    896                                }
    897                        }
    898                } else if (b instanceof double[]) {
    899                        final double[] old = (double[]) b;
    900                        final int ilen = Math.min(itemSize, old.length);
    901                        result = new int[itemSize];
    902                        for (int i = 0; i < ilen; i++) {
    903                                result[i] = (int) toLong(old[i]);
    904                        }
    905                } else if (b instanceof List<?>) {
    906                        result = new int[itemSize];
    907                        List<?> jl = (List<?>) b;
    908                        int ilen = jl.size();
    909                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    910                                logger.error("Given array was not of a numerical primitive type");
    911                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    912                        }
    913                        ilen = Math.min(itemSize, ilen);
    914                        for (int i = 0; i < ilen; i++) {
    915                                result[i] = (int) toLong(jl.get(i));
    916                        }
    917                } else if (b.getClass().isArray()) {
    918                        result = new int[itemSize];
    919                        int ilen = Array.getLength(b);
    920                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    921                                logger.error("Given array was not of a numerical primitive type");
    922                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    923                        }
    924                        ilen = Math.min(itemSize, ilen);
    925                        for (int i = 0; i < ilen; i++) {
    926                                result[i] = (int) toLong(Array.get(b, i));
    927                        }
    928                } else if (b instanceof Complex) {
    929                        if (itemSize > 2) {
    930                                logger.error("Complex number will not fit in compound dataset");
    931                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    932                        }
    933                        Complex cb = (Complex) b;
    934                        switch (itemSize) {
    935                        default:
    936                        case 0:
    937                                break;
    938                        case 1:
    939                                result = new int[] {(int) cb.getReal()};
    940                                break;
    941                        case 2:
    942                                result = new int[] {(int) cb.getReal(), (int) cb.getImaginary()};
    943                                break;
    944                        }
    945                } else if (b instanceof Dataset) {
    946                        Dataset db = (Dataset) b;
    947                        if (db.getSize() != 1) {
    948                                logger.error("Given dataset must have only one item");
    949                                throw new IllegalArgumentException("Given dataset must have only one item");
    950                        }
    951                        return toIntegerArray(db.getObjectAbs(db.getOffset()), itemSize);
    952                } else if (b instanceof IDataset) {
    953                        IDataset db = (Dataset) b;
    954                        if (db.getSize() != 1) {
    955                                logger.error("Given dataset must have only one item");
    956                                throw new IllegalArgumentException("Given dataset must have only one item");
    957                        }
    958                        return toIntegerArray(db.getObject(new int[db.getRank()]), itemSize);
    959                }
    960
    961                return result;
    962        }
    963
    964        public static short[] toShortArray(final Object b, final int itemSize) {
    965                short[] result = null;
    966
    967                if (b instanceof Number) {
    968                        result = new short[itemSize];
    969                        final short val = (short) toLong(b);
    970                        for (int i = 0; i < itemSize; i++) {
    971                                result[i] = val;
    972                        }
    973                } else if (b instanceof short[]) {
    974                        final short[] old = (short[]) b;
    975                        result = old;
    976                        final int ilen = result.length;
    977                        if (ilen < itemSize) {
    978                                result = new short[itemSize];
    979                                for (int i = 0; i < ilen; i++) {
    980                                        result[i] = old[i];
    981                                }
    982                        }
    983                } else if (b instanceof double[]) {
    984                        final double[] old = (double[]) b;
    985                        final int ilen = Math.min(itemSize, old.length);
    986                        result = new short[itemSize];
    987                        for (int i = 0; i < ilen; i++) {
    988                                result[i] = (short) toLong(old[i]);
    989                        }
    990                } else if (b instanceof List<?>) {
    991                        result = new short[itemSize];
    992                        List<?> jl = (List<?>) b;
    993                        int ilen = jl.size();
    994                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    995                                logger.error("Given array was not of a numerical primitive type");
    996                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    997                        }
    998                        ilen = Math.min(itemSize, ilen);
    999                        for (int i = 0; i < ilen; i++) {
    1000                                result[i] = (short) toLong(jl.get(i));
    1001                        }
    1002                } else if (b.getClass().isArray()) {
    1003                        result = new short[itemSize];
    1004                        int ilen = Array.getLength(b);
    1005                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    1006                                logger.error("Given array was not of a numerical primitive type");
    1007                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    1008                        }
    1009                        ilen = Math.min(itemSize, ilen);
    1010                        for (int i = 0; i < ilen; i++) {
    1011                                result[i] = (short) toLong(Array.get(b, i));
    1012                        }
    1013                } else if (b instanceof Complex) {
    1014                        if (itemSize > 2) {
    1015                                logger.error("Complex number will not fit in compound dataset");
    1016                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    1017                        }
    1018                        Complex cb = (Complex) b;
    1019                        switch (itemSize) {
    1020                        default:
    1021                        case 0:
    1022                                break;
    1023                        case 1:
    1024                                result = new short[] {(short) cb.getReal()};
    1025                                break;
    1026                        case 2:
    1027                                result = new short[] {(short) cb.getReal(), (short) cb.getImaginary()};
    1028                                break;
    1029                        }
    1030                } else if (b instanceof Dataset) {
    1031                        Dataset db = (Dataset) b;
    1032                        if (db.getSize() != 1) {
    1033                                logger.error("Given dataset must have only one item");
    1034                                throw new IllegalArgumentException("Given dataset must have only one item");
    1035                        }
    1036                        return toShortArray(db.getObjectAbs(db.getOffset()), itemSize);
    1037                } else if (b instanceof IDataset) {
    1038                        IDataset db = (Dataset) b;
    1039                        if (db.getSize() != 1) {
    1040                                logger.error("Given dataset must have only one item");
    1041                                throw new IllegalArgumentException("Given dataset must have only one item");
    1042                        }
    1043                        return toShortArray(db.getObject(new int[db.getRank()]), itemSize);
    1044                }
    1045
    1046                return result;
    1047        }
    1048
    1049        public static byte[] toByteArray(final Object b, final int itemSize) {
    1050                byte[] result = null;
    1051
    1052                if (b instanceof Number) {
    1053                        result = new byte[itemSize];
    1054                        final byte val = (byte) toLong(b);
    1055                        for (int i = 0; i < itemSize; i++) {
    1056                                result[i] = val;
    1057                        }
    1058                } else if (b instanceof byte[]) {
    1059                        final byte[] old = (byte[]) b;
    1060                        result = old;
    1061                        final int ilen = result.length;
    1062                        if (ilen < itemSize) {
    1063                                result = new byte[itemSize];
    1064                                for (int i = 0; i < ilen; i++) {
    1065                                        result[i] = old[i];
    1066                                }
    1067                        }
    1068                } else if (b instanceof double[]) {
    1069                        final double[] old = (double[]) b;
    1070                        final int ilen = Math.min(itemSize, old.length);
    1071                        result = new byte[itemSize];
    1072                        for (int i = 0; i < ilen; i++) {
    1073                                result[i] = (byte) toLong(old[i]);
    1074                        }
    1075                } else if (b instanceof List<?>) {
    1076                        result = new byte[itemSize];
    1077                        List<?> jl = (List<?>) b;
    1078                        int ilen = jl.size();
    1079                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    1080                                logger.error("Given array was not of a numerical primitive type");
    1081                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    1082                        }
    1083                        ilen = Math.min(itemSize, ilen);
    1084                        for (int i = 0; i < ilen; i++) {
    1085                                result[i] = (byte) toLong(jl.get(i));
    1086                        }
    1087                } else if (b.getClass().isArray()) {
    1088                        result = new byte[itemSize];
    1089                        int ilen = Array.getLength(b);
    1090                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    1091                                logger.error("Given array was not of a numerical primitive type");
    1092                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    1093                        }
    1094                        ilen = Math.min(itemSize, ilen);
    1095                        for (int i = 0; i < ilen; i++) {
    1096                                result[i] = (byte) toLong(Array.get(b, i));
    1097                        }
    1098                } else if (b instanceof Complex) {
    1099                        if (itemSize > 2) {
    1100                                logger.error("Complex number will not fit in compound dataset");
    1101                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    1102                        }
    1103                        Complex cb = (Complex) b;
    1104                        switch (itemSize) {
    1105                        default:
    1106                        case 0:
    1107                                break;
    1108                        case 1:
    1109                                result = new byte[] {(byte) cb.getReal()};
    1110                                break;
    1111                        case 2:
    1112                                result = new byte[] {(byte) cb.getReal(), (byte) cb.getImaginary()};
    1113                                break;
    1114                        }
    1115                } else if (b instanceof Dataset) {
    1116                        Dataset db = (Dataset) b;
    1117                        if (db.getSize() != 1) {
    1118                                logger.error("Given dataset must have only one item");
    1119                                throw new IllegalArgumentException("Given dataset must have only one item");
    1120                        }
    1121                        return toByteArray(db.getObjectAbs(db.getOffset()), itemSize);
    1122                } else if (b instanceof IDataset) {
    1123                        IDataset db = (Dataset) b;
    1124                        if (db.getSize() != 1) {
    1125                                logger.error("Given dataset must have only one item");
    1126                                throw new IllegalArgumentException("Given dataset must have only one item");
    1127                        }
    1128                        return toByteArray(db.getObject(new int[db.getRank()]), itemSize);
    1129                }
    1130
    1131                return result;
    1132        }
    1133
    1134        public static Object fromDoublesToBiggestPrimitives(double[] x, int dtype) {
    1135                switch (dtype) {
    1136                case Dataset.BOOL:
    1137                case Dataset.INT8:
    1138                case Dataset.INT16:
    1139                case Dataset.INT32:
    1140                        int[] i32 = new int[x.length];
    1141                        for (int i = 0; i < x.length; i++)
    1142                                i32[i] = (int) (long) x[i];
    1143                        return i32;
    1144                case Dataset.INT64:
    1145                        long[] i64 = new long[x.length];
    1146                        for (int i = 0; i < x.length; i++)
    1147                                i64[i] = (long) x[i];
    1148                        return i64;
    1149                case Dataset.FLOAT32:
    1150                        float[] f32 = new float[x.length];
    1151                        for (int i = 0; i < x.length; i++)
    1152                                f32[i] = (float) x[i];
    1153                        return f32;
    1154                case Dataset.FLOAT64:
    1155                        return x;
    1156                }
    1157                return null;
    1158        }
    1159
    1160        /**
    1161         * @param x
    1162         * @param dtype
    1163         * @return biggest native primitive if integer (should test for 64bit?)
    1164         */
    1165        public static Number fromDoubleToBiggestNumber(double x, int dtype) {
    1166                switch (dtype) {
    1167                case Dataset.BOOL:
    1168                case Dataset.INT8:
    1169                case Dataset.INT16:
    1170                case Dataset.INT32:
    1171                        return Integer.valueOf((int) (long) x);
    1172                case Dataset.INT64:
    1173                        return Long.valueOf((long) x);
    1174                case Dataset.FLOAT32:
    1175                        return Float.valueOf((float) x);
    1176                case Dataset.FLOAT64:
    1177                        return Double.valueOf(x);
    1178                }
    1179                return null;
    1180        }
    1181
    1182        /**
    1183         * @param b
    1184         * @return length of object
    1185         */
    1186        public static final int getLength(final Object b) {
    1187                if (b instanceof Number) {
    1188                        return 1;
    1189                } else if (b instanceof Complex) {
    1190                        return 1;
    1191                } else if (b instanceof List<?>) {
    1192                        List<?> jl = (List<?>) b;
    1193                        return jl.size();
    1194                } else if (b.getClass().isArray()) {
    1195                        return Array.getLength(b);
    1196                } else if (b instanceof IDataset) {
    1197                        IDataset db = (Dataset) b;
    1198                        return db.getSize();
    1199                }
    1200
    1201                throw new IllegalArgumentException("Cannot find length as object not supported");
    1202        }
    1203
    1204        /**
    1205         * @param dtype
    1206         * @return (boxed) class of constituent element
    1207         */
    1208        public static Class<?> getElementClass(final int dtype) {
    1209                switch (dtype) {
    1210                case Dataset.BOOL:
    1211                        return Boolean.class;
    1212                case Dataset.INT8:
    1213                case Dataset.ARRAYINT8:
    1214                        return Byte.class;
    1215                case Dataset.INT16:
    1216                case Dataset.ARRAYINT16:
    1217                case Dataset.RGB:
    1218                        return Short.class;
    1219                case Dataset.INT32:
    1220                case Dataset.ARRAYINT32:
    1221                        return Integer.class;
    1222                case Dataset.INT64:
    1223                case Dataset.ARRAYINT64:
    1224                        return Long.class;
    1225                case Dataset.FLOAT32:
    1226                case Dataset.ARRAYFLOAT32:
    1227                        return Float.class;
    1228                case Dataset.FLOAT64:
    1229                case Dataset.ARRAYFLOAT64:
    1230                        return Double.class;
    1231                case Dataset.COMPLEX64:
    1232                        return Float.class;
    1233                case Dataset.COMPLEX128:
    1234                        return Double.class;
    1235                case Dataset.STRING:
    1236                        return String.class;
    1237                case Dataset.DATE:
    1238                        return Date.class;
    1239                }
    1240                return Object.class;
    1241        }
    1242
    1243}