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