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