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