    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         * @param comp
    406         * @return true if supported
    407         */
    408        public static boolean isClassSupportedAsElement(Class<? extends Object> comp) {
    409                return comp.isPrimitive() || Number.class.isAssignableFrom(comp) || comp.equals(Boolean.class)
    410                                || comp.equals(Complex.class) || comp.equals(String.class) || comp.equals(Date.class);
    411        }
    412
    413        /**
    414         * @param dtype
    415         * @return number of elements per item
    416         */
    417        public static int getElementsPerItem(final int dtype) {
    418                switch (dtype) {
    419                case Dataset.ARRAYINT8:
    420                case Dataset.ARRAYINT16:
    421                case Dataset.ARRAYINT32:
    422                case Dataset.ARRAYINT64:
    423                case Dataset.ARRAYFLOAT32:
    424                case Dataset.ARRAYFLOAT64:
    425                        throw new UnsupportedOperationException("Multi-element type unsupported");
    426                case Dataset.COMPLEX64:
    427                case Dataset.COMPLEX128:
    428                        return 2;
    429                case Dataset.RGB:
    430                        return 3;
    431                }
    432                return 1;
    433        }
    434
    435        /**
    436         * @param dtype
    437         * @return length of single item in bytes
    438         */
    439        public static int getItemBytes(final int dtype) {
    440                return getItemBytes(dtype, getElementsPerItem(dtype));
    441        }
    442
    443        /**
    444         * @param dtype
    445         * @param isize
    446         *            number of elements in an item
    447         * @return length of single item in bytes
    448         */
    449        public static int getItemBytes(final int dtype, final int isize) {
    450                int size;
    451
    452                switch (dtype) {
    453                case Dataset.BOOL:
    454                        size = 1; // How is this defined?
    455                        break;
    456                case Dataset.INT8:
    457                case Dataset.ARRAYINT8:
    458                        size = Byte.SIZE / 8;
    459                        break;
    460                case Dataset.INT16:
    461                case Dataset.ARRAYINT16:
    462                case Dataset.RGB:
    463                        size = Short.SIZE / 8;
    464                        break;
    465                case Dataset.INT32:
    466                case Dataset.ARRAYINT32:
    467                        size = Integer.SIZE / 8;
    468                        break;
    469                case Dataset.INT64:
    470                case Dataset.ARRAYINT64:
    471                        size = Long.SIZE / 8;
    472                        break;
    473                case Dataset.FLOAT32:
    474                case Dataset.ARRAYFLOAT32:
    475                case Dataset.COMPLEX64:
    476                        size = Float.SIZE / 8;
    477                        break;
    478                case Dataset.FLOAT64:
    479                case Dataset.ARRAYFLOAT64:
    480                case Dataset.COMPLEX128:
    481                        size = Double.SIZE / 8;
    482                        break;
    483                default:
    484                        size = 0;
    485                        break;
    486                }
    487
    488                return size * isize;
    489        }
    490
    491        public static boolean toBoolean(final Object b) {
    492                if (b instanceof Number) {
    493                        return ((Number) b).longValue() != 0;
    494                } else if (b instanceof Boolean) {
    495                        return ((Boolean) b).booleanValue();
    496                } else if (b instanceof Complex) {
    497                        return ((Complex) b).getReal() != 0;
    498                } else if (b instanceof Dataset) {
    499                        Dataset db = (Dataset) b;
    500                        if (db.getSize() != 1) {
    501                                logger.error("Given dataset must have only one item");
    502                                throw new IllegalArgumentException("Given dataset must have only one item");
    503                        }
    504                        return toBoolean(db.getObjectAbs(0));
    505                } else if (b instanceof IDataset) {
    506                        IDataset db = (IDataset) b;
    507                        if (db.getSize() != 1) {
    508                                logger.error("Given dataset must have only one item");
    509                                throw new IllegalArgumentException("Given dataset must have only one item");
    510                        }
    511                        return toBoolean(db.getObject(new int[db.getRank()]));
    512                } else {
    513                        logger.error("Argument is of unsupported class");
    514                        throw new IllegalArgumentException("Argument is of unsupported class");
    515                }
    516        }
    517
    518        public static long toLong(final Object b) {
    519                if (b instanceof Number) {
    520                        return ((Number) b).longValue();
    521                } else if (b instanceof Boolean) {
    522                        return ((Boolean) b).booleanValue() ? 1 : 0;
    523                } else if (b instanceof Complex) {
    524                        return (long) ((Complex) b).getReal();
    525                } else if (b instanceof Dataset) {
    526                        Dataset db = (Dataset) b;
    527                        if (db.getSize() != 1) {
    528                                logger.error("Given dataset must have only one item");
    529                                throw new IllegalArgumentException("Given dataset must have only one item");
    530                        }
    531                        return toLong(db.getObjectAbs(0));
    532                } else if (b instanceof IDataset) {
    533                        IDataset db = (IDataset) b;
    534                        if (db.getSize() != 1) {
    535                                logger.error("Given dataset must have only one item");
    536                                throw new IllegalArgumentException("Given dataset must have only one item");
    537                        }
    538                        return toLong(db.getObject(new int[db.getRank()]));
    539                } else {
    540                        logger.error("Argument is of unsupported class");
    541                        throw new IllegalArgumentException("Argument is of unsupported class");
    542                }
    543        }
    544
    545        public static double toReal(final Object b) {
    546                if (b instanceof Number) {
    547                        return ((Number) b).doubleValue();
    548                } else if (b instanceof Boolean) {
    549                        return ((Boolean) b).booleanValue() ? 1 : 0;
    550                } else if (b instanceof Complex) {
    551                        return ((Complex) b).getReal();
    552                } else if (b.getClass().isArray()) {
    553                        if (Array.getLength(b) == 0)
    554                                return 0;
    555                        return toReal(Array.get(b, 0));
    556                } else if (b instanceof Dataset) {
    557                        Dataset db = (Dataset) 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 toReal(db.getObjectAbs(0));
    563                } else if (b instanceof IDataset) {
    564                        IDataset db = (Dataset) b;
    565                        if (db.getSize() != 1) {
    566                                logger.error("Given dataset must have only one item");
    567                                throw new IllegalArgumentException("Given dataset must have only one item");
    568                        }
    569                        return toReal(db.getObject(new int[db.getRank()]));
    570                } else {
    571                        logger.error("Argument is of unsupported class");
    572                        throw new IllegalArgumentException("Argument is of unsupported class");
    573                }
    574        }
    575
    576        public static double toImag(final Object b) {
    577                if (b instanceof Number) {
    578                        return 0;
    579                } else if (b instanceof Boolean) {
    580                        return 0;
    581                } else if (b instanceof Complex) {
    582                        return ((Complex) b).getImaginary();
    583                } else if (b.getClass().isArray()) {
    584                        if (Array.getLength(b) < 2)
    585                                return 0;
    586                        return toReal(Array.get(b, 1));
    587                } else if (b instanceof Dataset) {
    588                        Dataset 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 toImag(db.getObjectAbs(0));
    594                } else if (b instanceof IDataset) {
    595                        IDataset db = (Dataset) b;
    596                        if (db.getSize() != 1) {
    597                                logger.error("Given dataset must have only one item");
    598                                throw new IllegalArgumentException("Given dataset must have only one item");
    599                        }
    600                        return toImag(db.getObject(new int[db.getRank()]));
    601                } else {
    602                        logger.error("Argument is of unsupported class");
    603                        throw new IllegalArgumentException("Argument is of unsupported class");
    604                }
    605        }
    606
    607        public static double[] toDoubleArray(final Object b, final int itemSize) {
    608                double[] result = null;
    609
    610                // ensure array is of given length
    611                if (b instanceof Number) {
    612                        result = new double[itemSize];
    613                        double val = ((Number) b).doubleValue();
    614                        for (int i = 0; i < itemSize; i++)
    615                                result[i] = val;
    616                } else if (b instanceof double[]) {
    617                        result = (double[]) b;
    618                        if (result.length < itemSize) {
    619                                result = new double[itemSize];
    620                                int ilen = result.length;
    621                                for (int i = 0; i < ilen; i++)
    622                                        result[i] = ((double[]) b)[i];
    623                        }
    624                } else if (b instanceof List<?>) {
    625                        result = new double[itemSize];
    626                        List<?> jl = (List<?>) b;
    627                        int ilen = jl.size();
    628                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    629                                logger.error("Given array was not of a numerical primitive type");
    630                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    631                        }
    632                        ilen = Math.min(itemSize, ilen);
    633                        for (int i = 0; i < ilen; i++) {
    634                                result[i] = toReal(jl.get(i));
    635                        }
    636                } else if (b.getClass().isArray()) {
    637                        result = new double[itemSize];
    638                        int ilen = Array.getLength(b);
    639                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    640                                logger.error("Given array was not of a numerical primitive type");
    641                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    642                        }
    643                        ilen = Math.min(itemSize, ilen);
    644                        for (int i = 0; i < ilen; i++)
    645                                result[i] = ((Number) Array.get(b, i)).doubleValue();
    646                } else if (b instanceof Complex) {
    647                        if (itemSize > 2) {
    648                                logger.error("Complex number will not fit in compound dataset");
    649                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    650                        }
    651                        Complex cb = (Complex) b;
    652                        switch (itemSize) {
    653                        default:
    654                        case 0:
    655                                break;
    656                        case 1:
    657                                result = new double[] {cb.getReal()};
    658                                break;
    659                        case 2:
    660                                result = new double[] {cb.getReal(), cb.getImaginary()};
    661                                break;
    662                        }
    663                } else if (b instanceof Dataset) {
    664                        Dataset db = (Dataset) b;
    665                        if (db.getSize() != 1) {
    666                                logger.error("Given dataset must have only one item");
    667                                throw new IllegalArgumentException("Given dataset must have only one item");
    668                        }
    669                        return toDoubleArray(db.getObjectAbs(0), itemSize);
    670                } else if (b instanceof IDataset) {
    671                        IDataset db = (Dataset) b;
    672                        if (db.getSize() != 1) {
    673                                logger.error("Given dataset must have only one item");
    674                                throw new IllegalArgumentException("Given dataset must have only one item");
    675                        }
    676                        return toDoubleArray(db.getObject(new int[db.getRank()]), itemSize);
    677                }
    678
    679                return result;
    680        }
    681
    682        public static float[] toFloatArray(final Object b, final int itemSize) {
    683                float[] result = null;
    684
    685                if (b instanceof Number) {
    686                        result = new float[itemSize];
    687                        float val = ((Number) b).floatValue();
    688                        for (int i = 0; i < itemSize; i++)
    689                                result[i] = val;
    690                } else if (b instanceof float[]) {
    691                        result = (float[]) b;
    692                        if (result.length < itemSize) {
    693                                result = new float[itemSize];
    694                                int ilen = result.length;
    695                                for (int i = 0; i < ilen; i++)
    696                                        result[i] = ((float[]) b)[i];
    697                        }
    698                } else if (b instanceof List<?>) {
    699                        result = new float[itemSize];
    700                        List<?> jl = (List<?>) b;
    701                        int ilen = jl.size();
    702                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    703                                logger.error("Given array was not of a numerical primitive type");
    704                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    705                        }
    706                        ilen = Math.min(itemSize, ilen);
    707                        for (int i = 0; i < ilen; i++) {
    708                                result[i] = (float) toReal(jl.get(i));
    709                        }
    710                } else if (b.getClass().isArray()) {
    711                        result = new float[itemSize];
    712                        int ilen = Array.getLength(b);
    713                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    714                                logger.error("Given array was not of a numerical primitive type");
    715                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    716                        }
    717                        ilen = Math.min(itemSize, ilen);
    718                        for (int i = 0; i < ilen; i++)
    719                                result[i] = ((Number) Array.get(b, i)).floatValue();
    720                } else if (b instanceof Complex) {
    721                        if (itemSize > 2) {
    722                                logger.error("Complex number will not fit in compound dataset");
    723                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    724                        }
    725                        Complex cb = (Complex) b;
    726                        switch (itemSize) {
    727                        default:
    728                        case 0:
    729                                break;
    730                        case 1:
    731                                result = new float[] {(float) cb.getReal()};
    732                                break;
    733                        case 2:
    734                                result = new float[] {(float) cb.getReal(), (float) cb.getImaginary()};
    735                                break;
    736                        }
    737                } else if (b instanceof Dataset) {
    738                        Dataset db = (Dataset) b;
    739                        if (db.getSize() != 1) {
    740                                logger.error("Given dataset must have only one item");
    741                                throw new IllegalArgumentException("Given dataset must have only one item");
    742                        }
    743                        return toFloatArray(db.getObjectAbs(0), itemSize);
    744                } else if (b instanceof IDataset) {
    745                        IDataset db = (Dataset) b;
    746                        if (db.getSize() != 1) {
    747                                logger.error("Given dataset must have only one item");
    748                                throw new IllegalArgumentException("Given dataset must have only one item");
    749                        }
    750                        return toFloatArray(db.getObject(new int[db.getRank()]), itemSize);
    751                }
    752
    753                return result;
    754        }
    755
    756        public static long[] toLongArray(final Object b, final int itemSize) {
    757                long[] result = null;
    758
    759                if (b instanceof Number) {
    760                        result = new long[itemSize];
    761                        long val = ((Number) b).longValue();
    762                        for (int i = 0; i < itemSize; i++)
    763                                result[i] = val;
    764                } else if (b instanceof long[]) {
    765                        result = (long[]) b;
    766                        if (result.length < itemSize) {
    767                                result = new long[itemSize];
    768                                int ilen = result.length;
    769                                for (int i = 0; i < ilen; i++)
    770                                        result[i] = ((long[]) b)[i];
    771                        }
    772                } else if (b instanceof List<?>) {
    773                        result = new long[itemSize];
    774                        List<?> jl = (List<?>) b;
    775                        int ilen = jl.size();
    776                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    777                                logger.error("Given array was not of a numerical primitive type");
    778                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    779                        }
    780                        ilen = Math.min(itemSize, ilen);
    781                        for (int i = 0; i < ilen; i++) {
    782                                result[i] = toLong(jl.get(i));
    783                        }
    784                } else if (b.getClass().isArray()) {
    785                        result = new long[itemSize];
    786                        int ilen = Array.getLength(b);
    787                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    788                                logger.error("Given array was not of a numerical primitive type");
    789                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    790                        }
    791                        ilen = Math.min(itemSize, ilen);
    792                        for (int i = 0; i < ilen; i++)
    793                                result[i] = ((Number) Array.get(b, i)).longValue();
    794                } else if (b instanceof Complex) {
    795                        if (itemSize > 2) {
    796                                logger.error("Complex number will not fit in compound dataset");
    797                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    798                        }
    799                        Complex cb = (Complex) b;
    800                        switch (itemSize) {
    801                        default:
    802                        case 0:
    803                                break;
    804                        case 1:
    805                                result = new long[] {(long) cb.getReal()};
    806                                break;
    807                        case 2:
    808                                result = new long[] {(long) cb.getReal(), (long) cb.getImaginary()};
    809                                break;
    810                        }
    811                } else if (b instanceof Dataset) {
    812                        Dataset db = (Dataset) b;
    813                        if (db.getSize() != 1) {
    814                                logger.error("Given dataset must have only one item");
    815                                throw new IllegalArgumentException("Given dataset must have only one item");
    816                        }
    817                        return toLongArray(db.getObjectAbs(0), itemSize);
    818                } else if (b instanceof IDataset) {
    819                        IDataset db = (Dataset) b;
    820                        if (db.getSize() != 1) {
    821                                logger.error("Given dataset must have only one item");
    822                                throw new IllegalArgumentException("Given dataset must have only one item");
    823                        }
    824                        return toLongArray(db.getObject(new int[db.getRank()]), itemSize);
    825                }
    826
    827                return result;
    828        }
    829
    830        public static int[] toIntegerArray(final Object b, final int itemSize) {
    831                int[] result = null;
    832
    833                if (b instanceof Number) {
    834                        result = new int[itemSize];
    835                        int val = ((Number) b).intValue();
    836                        for (int i = 0; i < itemSize; i++)
    837                                result[i] = val;
    838                } else if (b instanceof int[]) {
    839                        result = (int[]) b;
    840                        if (result.length < itemSize) {
    841                                result = new int[itemSize];
    842                                int ilen = result.length;
    843                                for (int i = 0; i < ilen; i++)
    844                                        result[i] = ((int[]) b)[i];
    845                        }
    846                } else if (b instanceof List<?>) {
    847                        result = new int[itemSize];
    848                        List<?> jl = (List<?>) b;
    849                        int ilen = jl.size();
    850                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    851                                logger.error("Given array was not of a numerical primitive type");
    852                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    853                        }
    854                        ilen = Math.min(itemSize, ilen);
    855                        for (int i = 0; i < ilen; i++) {
    856                                result[i] = (int) toLong(jl.get(i));
    857                        }
    858                } else if (b.getClass().isArray()) {
    859                        result = new int[itemSize];
    860                        int ilen = Array.getLength(b);
    861                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    862                                logger.error("Given array was not of a numerical primitive type");
    863                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    864                        }
    865                        ilen = Math.min(itemSize, ilen);
    866                        for (int i = 0; i < ilen; i++)
    867                                result[i] = (int) ((Number) Array.get(b, i)).longValue();
    868                } else if (b instanceof Complex) {
    869                        if (itemSize > 2) {
    870                                logger.error("Complex number will not fit in compound dataset");
    871                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    872                        }
    873                        Complex cb = (Complex) b;
    874                        switch (itemSize) {
    875                        default:
    876                        case 0:
    877                                break;
    878                        case 1:
    879                                result = new int[] {(int) cb.getReal()};
    880                                break;
    881                        case 2:
    882                                result = new int[] {(int) cb.getReal(), (int) cb.getImaginary()};
    883                                break;
    884                        }
    885                } else if (b instanceof Dataset) {
    886                        Dataset db = (Dataset) b;
    887                        if (db.getSize() != 1) {
    888                                logger.error("Given dataset must have only one item");
    889                                throw new IllegalArgumentException("Given dataset must have only one item");
    890                        }
    891                        return toIntegerArray(db.getObjectAbs(0), itemSize);
    892                } else if (b instanceof IDataset) {
    893                        IDataset db = (Dataset) b;
    894                        if (db.getSize() != 1) {
    895                                logger.error("Given dataset must have only one item");
    896                                throw new IllegalArgumentException("Given dataset must have only one item");
    897                        }
    898                        return toIntegerArray(db.getObject(new int[db.getRank()]), itemSize);
    899                }
    900
    901                return result;
    902        }
    903
    904        public static short[] toShortArray(final Object b, final int itemSize) {
    905                short[] result = null;
    906
    907                if (b instanceof Number) {
    908                        result = new short[itemSize];
    909                        short val = ((Number) b).shortValue();
    910                        for (int i = 0; i < itemSize; i++)
    911                                result[i] = val;
    912                } else if (b instanceof short[]) {
    913                        result = (short[]) b;
    914                        if (result.length < itemSize) {
    915                                result = new short[itemSize];
    916                                int ilen = result.length;
    917                                for (int i = 0; i < ilen; i++)
    918                                        result[i] = ((short[]) b)[i];
    919                        }
    920                } else if (b instanceof List<?>) {
    921                        result = new short[itemSize];
    922                        List<?> jl = (List<?>) b;
    923                        int ilen = jl.size();
    924                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    925                                logger.error("Given array was not of a numerical primitive type");
    926                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    927                        }
    928                        ilen = Math.min(itemSize, ilen);
    929                        for (int i = 0; i < ilen; i++) {
    930                                result[i] = (short) toLong(jl.get(i));
    931                        }
    932                } else if (b.getClass().isArray()) {
    933                        result = new short[itemSize];
    934                        int ilen = Array.getLength(b);
    935                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    936                                logger.error("Given array was not of a numerical primitive type");
    937                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    938                        }
    939                        ilen = Math.min(itemSize, ilen);
    940                        for (int i = 0; i < ilen; i++)
    941                                result[i] = (short) ((Number) Array.get(b, i)).longValue();
    942                } else if (b instanceof Complex) {
    943                        if (itemSize > 2) {
    944                                logger.error("Complex number will not fit in compound dataset");
    945                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    946                        }
    947                        Complex cb = (Complex) b;
    948                        switch (itemSize) {
    949                        default:
    950                        case 0:
    951                                break;
    952                        case 1:
    953                                result = new short[] {(short) cb.getReal()};
    954                                break;
    955                        case 2:
    956                                result = new short[] {(short) cb.getReal(), (short) cb.getImaginary()};
    957                                break;
    958                        }
    959                } else if (b instanceof Dataset) {
    960                        Dataset db = (Dataset) b;
    961                        if (db.getSize() != 1) {
    962                                logger.error("Given dataset must have only one item");
    963                                throw new IllegalArgumentException("Given dataset must have only one item");
    964                        }
    965                        return toShortArray(db.getObjectAbs(0), itemSize);
    966                } else if (b instanceof IDataset) {
    967                        IDataset db = (Dataset) b;
    968                        if (db.getSize() != 1) {
    969                                logger.error("Given dataset must have only one item");
    970                                throw new IllegalArgumentException("Given dataset must have only one item");
    971                        }
    972                        return toShortArray(db.getObject(new int[db.getRank()]), itemSize);
    973                }
    974
    975                return result;
    976        }
    977
    978        public static byte[] toByteArray(final Object b, final int itemSize) {
    979                byte[] result = null;
    980
    981                if (b instanceof Number) {
    982                        result = new byte[itemSize];
    983                        final byte val = ((Number) b).byteValue();
    984                        for (int i = 0; i < itemSize; i++) {
    985                                result[i] = val;
    986                        }
    987                } else if (b instanceof byte[]) {
    988                        result = (byte[]) b;
    989                        if (result.length < itemSize) {
    990                                result = new byte[itemSize];
    991                                int ilen = result.length;
    992                                for (int i = 0; i < ilen; i++) {
    993                                        result[i] = ((byte[]) b)[i];
    994                                }
    995                        }
    996                } else if (b instanceof List<?>) {
    997                        result = new byte[itemSize];
    998                        List<?> jl = (List<?>) b;
    999                        int ilen = jl.size();
    1000                        if (ilen > 0 && !(jl.get(0) instanceof Number)) {
    1001                                logger.error("Given array was not of a numerical primitive type");
    1002                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    1003                        }
    1004                        ilen = Math.min(itemSize, ilen);
    1005                        for (int i = 0; i < ilen; i++) {
    1006                                result[i] = (byte) toLong(jl.get(i));
    1007                        }
    1008                } else if (b.getClass().isArray()) {
    1009                        result = new byte[itemSize];
    1010                        int ilen = Array.getLength(b);
    1011                        if (ilen > 0 && !(Array.get(b, 0) instanceof Number)) {
    1012                                logger.error("Given array was not of a numerical primitive type");
    1013                                throw new IllegalArgumentException("Given array was not of a numerical primitive type");
    1014                        }
    1015                        ilen = Math.min(itemSize, ilen);
    1016                        for (int i = 0; i < ilen; i++) {
    1017                                result[i] = (byte) ((Number) Array.get(b, i)).longValue();
    1018                        }
    1019                } else if (b instanceof Complex) {
    1020                        if (itemSize > 2) {
    1021                                logger.error("Complex number will not fit in compound dataset");
    1022                                throw new IllegalArgumentException("Complex number will not fit in compound dataset");
    1023                        }
    1024                        Complex cb = (Complex) b;
    1025                        switch (itemSize) {
    1026                        default:
    1027                        case 0:
    1028                                break;
    1029                        case 1:
    1030                                result = new byte[] {(byte) cb.getReal()};
    1031                                break;
    1032                        case 2:
    1033                                result = new byte[] {(byte) cb.getReal(), (byte) cb.getImaginary()};
    1034                                break;
    1035                        }
    1036                } else if (b instanceof Dataset) {
    1037                        Dataset db = (Dataset) b;
    1038                        if (db.getSize() != 1) {
    1039                                logger.error("Given dataset must have only one item");
    1040                                throw new IllegalArgumentException("Given dataset must have only one item");
    1041                        }
    1042                        return toByteArray(db.getObjectAbs(0), itemSize);
    1043                } else if (b instanceof IDataset) {
    1044                        IDataset db = (Dataset) b;
    1045                        if (db.getSize() != 1) {
    1046                                logger.error("Given dataset must have only one item");
    1047                                throw new IllegalArgumentException("Given dataset must have only one item");
    1048                        }
    1049                        return toByteArray(db.getObject(new int[db.getRank()]), itemSize);
    1050                }
    1051
    1052                return result;
    1053        }
    1054
    1055        public static Object fromDoublesToBiggestPrimitives(double[] x, int dtype) {
    1056                switch (dtype) {
    1057                case Dataset.BOOL:
    1058                case Dataset.INT8:
    1059                case Dataset.INT16:
    1060                case Dataset.INT32:
    1061                        int[] i32 = new int[x.length];
    1062                        for (int i = 0; i < x.length; i++)
    1063                                i32[i] = (int) (long) x[i];
    1064                        return i32;
    1065                case Dataset.INT64:
    1066                        long[] i64 = new long[x.length];
    1067                        for (int i = 0; i < x.length; i++)
    1068                                i64[i] = (long) x[i];
    1069                        return i64;
    1070                case Dataset.FLOAT32:
    1071                        float[] f32 = new float[x.length];
    1072                        for (int i = 0; i < x.length; i++)
    1073                                f32[i] = (float) x[i];
    1074                        return f32;
    1075                case Dataset.FLOAT64:
    1076                        return x;
    1077                }
    1078                return null;
    1079        }
    1080
    1081        /**
    1082         * @param x
    1083         * @param dtype
    1084         * @return biggest native primitive if integer (should test for 64bit?)
    1085         */
    1086        public static Number fromDoubleToBiggestNumber(double x, int dtype) {
    1087                switch (dtype) {
    1088                case Dataset.BOOL:
    1089                case Dataset.INT8:
    1090                case Dataset.INT16:
    1091                case Dataset.INT32:
    1092                        return Integer.valueOf((int) (long) x);
    1093                case Dataset.INT64:
    1094                        return Long.valueOf((long) x);
    1095                case Dataset.FLOAT32:
    1096                        return Float.valueOf((float) x);
    1097                case Dataset.FLOAT64:
    1098                        return Double.valueOf(x);
    1099                }
    1100                return null;
    1101        }
    1102
    1103        /**
    1104         * @param b
    1105         * @return length of object
    1106         */
    1107        public static final int getLength(final Object b) {
    1108                if (b instanceof Number) {
    1109                        return 1;
    1110                } else if (b instanceof Complex) {
    1111                        return 1;
    1112                } else if (b instanceof List<?>) {
    1113                        List<?> jl = (List<?>) b;
    1114                        return jl.size();
    1115                } else if (b.getClass().isArray()) {
    1116                        return Array.getLength(b);
    1117                } else if (b instanceof IDataset) {
    1118                        IDataset db = (Dataset) b;
    1119                        return db.getSize();
    1120                }
    1121
    1122                throw new IllegalArgumentException("Cannot find length as object not supported");
    1123        }
    1124
    1125        /**
    1126         * @param dtype
    1127         * @return (boxed) class of constituent element
    1128         */
    1129        public static Class<?> getElementClass(final int dtype) {
    1130                switch (dtype) {
    1131                case Dataset.BOOL:
    1132                        return Boolean.class;
    1133                case Dataset.INT8:
    1134                case Dataset.ARRAYINT8:
    1135                        return Byte.class;
    1136                case Dataset.INT16:
    1137                case Dataset.ARRAYINT16:
    1138                case Dataset.RGB:
    1139                        return Short.class;
    1140                case Dataset.INT32:
    1141                case Dataset.ARRAYINT32:
    1142                        return Integer.class;
    1143                case Dataset.INT64:
    1144                case Dataset.ARRAYINT64:
    1145                        return Long.class;
    1146                case Dataset.FLOAT32:
    1147                case Dataset.ARRAYFLOAT32:
    1148                        return Float.class;
    1149                case Dataset.FLOAT64:
    1150                case Dataset.ARRAYFLOAT64:
    1151                        return Double.class;
    1152                case Dataset.COMPLEX64:
    1153                        return Float.class;
    1154                case Dataset.COMPLEX128:
    1155                        return Double.class;
    1156                case Dataset.STRING:
    1157                        return String.class;
    1158                case Dataset.DATE:
    1159                        return Date.class;
    1160                }
    1161                return Object.class;
    1162        }
    1163
    1164}