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