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