001/** 002 * NumericPrecision.java 003 * 004 * Copyright (c) 2004-2012, Nicole C. Tedesco. All rights reserved. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at: 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package net.sf.jaccumulator.scalars; 020 021import java.math.BigDecimal; 022import java.math.BigInteger; 023import java.util.IdentityHashMap; 024import java.util.Map; 025import java.util.concurrent.atomic.AtomicBoolean; 026import java.util.concurrent.atomic.AtomicInteger; 027import java.util.concurrent.atomic.AtomicLong; 028 029/** 030 * Non-UML semantic lemma that define numeric implementation precision, or 031 * implied total digits of any radix.<br/> 032 * <br/> 033 * All computer numbers are implemented using boolean vectors, the number of 034 * significant digits representable being roughly dependent upon the 035 * <i>known</i> {@link #size() size} of the implementing vector (bit 036 * count). Generally, "known" implies that it is more precise to <i>know</i> 037 * that zero digits are available than to not know at all which in turn implies 038 * that {@link #UNKNOWN} is <i>less</i> precise than {@link #NULL} which is a 039 * known precision (vector size of zero). {@link #isUnlimited() Unlimited} 040 * numbers however do not have known digit counts at design time but definitely 041 * have known digit counts at runtime so are said to be of higher precision than 042 * {@code UNKNOWN} and are, in fact, the highest since their <i>possible</i> 043 * digit counts are <i>known</i> to be for all practical purposes unlimited. 044 * 045 * @since JAccumulator 4.0 046 * @author Nicole Tedesco (<a 047 * href="mailto:Nicole@NicoleTedesco.com">Nicole@NicoleTedesco.com</a>) 048 */ 049public enum NumericPrecision 050{ 051 /** 052 * <b>Unknown</b> precision, which is even less precise than {@link #NULL} 053 * (empty set) 054 */ 055 UNKNOWN( String.class, String.class ) { /* 0 */ 056 @Override 057 public final int compare( final NumericPrecision prec ) { 058 return -1; 059 } 060 061 @Override 062 public final int size() { 063 return -1; 064 } 065 066 @Override 067 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 068 return false; 069 } 070 071 @Override 072 public final boolean isFinite() { 073 return false; 074 } 075 076 @Override 077 public final boolean isFloatingPoint() { 078 return false; 079 } 080 081 @Override 082 public final boolean isIeee754() { 083 return false; 084 } 085 086 @Override 087 public final boolean isIntegral() { 088 return false; 089 } 090 091 @Override 092 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 093 return prec != this; 094 } 095 096 @Override 097 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 098 return false; 099 } 100 101 @Override 102 public final boolean isNumeric() { 103 return false; 104 } 105 106 @Override 107 public final boolean isSigned() { 108 return false; 109 } 110 111 @Override 112 public final boolean isUnlimited() { 113 return false; 114 } 115 116 @Override 117 public final NumericPrecision promote() { 118 return UNKNOWN; 119 } 120 121 @Override 122 public final NumericPrecision promoteAgainst( 123 final NumericPrecision prec ) 124 { 125 return prec; 126 } 127 128 @Override 129 public final NumericPrecision toFloatingPoint() { 130 return UNKNOWN; 131 } 132 }, 133 134 /** 135 * No numeric domain, or the <b>empty set</b> (no digits, not even {@code 0} 136 * , though its field cardinality is 0) 137 */ 138 NULL( Void.class, Void.TYPE ) { /* 1 */ 139 @Override 140 public final int compare( final NumericPrecision prec ) { 141 if (prec == this) { 142 return 0; 143 } 144 if (prec == UNKNOWN) { 145 return +1; 146 } 147 return -1; 148 } 149 150 @Override 151 public final int size() { 152 return 0; 153 } 154 155 @Override 156 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 157 return prec == this; 158 } 159 160 @Override 161 public final boolean isFinite() { 162 return true; 163 } 164 165 @Override 166 public final boolean isFloatingPoint() { 167 return false; 168 } 169 170 @Override 171 public final boolean isIeee754() { 172 return false; 173 } 174 175 @Override 176 public final boolean isIntegral() { 177 return false; 178 } 179 180 @Override 181 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 182 return this.ordinal() < prec.ordinal(); 183 } 184 185 @Override 186 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 187 return prec == UNKNOWN; 188 } 189 190 @Override 191 public final boolean isNumeric() { 192 return false; 193 } 194 195 @Override 196 public final boolean isSigned() { 197 return false; 198 } 199 200 @Override 201 public final boolean isUnlimited() { 202 return false; 203 } 204 205 @Override 206 public final NumericPrecision promote() { 207 return BIT; 208 } 209 210 @Override 211 public final NumericPrecision promoteAgainst( 212 final NumericPrecision prec ) 213 { 214 return this.isLessPreciseThan(prec) ? prec : this; 215 } 216 217 @Override 218 public final NumericPrecision toFloatingPoint() { 219 return FLOAT; 220 } 221 }, 222 223 /** 224 * <b>Boolean</b> domain which includes {@code 0} and {@link 1} (field 225 * cardinality is 2) 226 */ 227 BIT( Boolean.class, boolean.class ) { /* 2 */ 228 @Override 229 public final int compare( final NumericPrecision prec ) { 230 if (prec == this) { 231 return 0; 232 } 233 if (this.isLessPreciseThan(prec)) { 234 return -1; 235 } 236 return +1; 237 } 238 239 @Override 240 public final int size() { 241 return 1; 242 } 243 244 @Override 245 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 246 return prec == this; 247 } 248 249 @Override 250 public final boolean isFinite() { 251 return true; 252 } 253 254 @Override 255 public final boolean isFloatingPoint() { 256 return false; 257 } 258 259 @Override 260 public final boolean isIeee754() { 261 return false; 262 } 263 264 @Override 265 public final boolean isIntegral() { 266 return true; 267 } 268 269 @Override 270 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 271 return this.ordinal() < prec.ordinal(); 272 } 273 274 @Override 275 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 276 return prec.ordinal() < this.ordinal(); 277 } 278 279 @Override 280 public final boolean isNumeric() { 281 return true; 282 } 283 284 @Override 285 public final boolean isSigned() { 286 return false; 287 } 288 289 @Override 290 public final boolean isUnlimited() { 291 return false; 292 } 293 294 @Override 295 public final NumericPrecision promote() { 296 return BYTE; 297 } 298 299 @Override 300 public final NumericPrecision promoteAgainst( 301 final NumericPrecision prec ) 302 { 303 return this.isLessPreciseThan(prec) ? prec : this; 304 } 305 306 @Override 307 public final NumericPrecision toFloatingPoint() { 308 return FLOAT; 309 } 310 }, 311 312 /** 313 * <b>Byte</b> field, or 8 bits, for a total value count (field cardinality) 314 * of 2<sup>8</sup> and a <i>signed</i> value range of <span 315 * style="white-space=nowrap">-2<sup>7</sup></span> to <span 316 * style="white-space=nowrap">2<sup>7</sup>-1</span> 317 */ 318 BYTE( Byte.class, byte.class ) { /* 3 */ 319 @Override 320 public final int compare( final NumericPrecision prec ) { 321 if (prec == this) { 322 return 0; 323 } 324 if (this.isLessPreciseThan(prec)) { 325 return -1; 326 } 327 return +1; 328 } 329 330 @Override 331 public final int size() { 332 return Byte.SIZE; 333 } 334 335 @Override 336 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 337 return prec == this; 338 } 339 340 @Override 341 public final boolean isFinite() { 342 return true; 343 } 344 345 @Override 346 public final boolean isFloatingPoint() { 347 return false; 348 } 349 350 @Override 351 public final boolean isIeee754() { 352 return false; 353 } 354 355 @Override 356 public final boolean isIntegral() { 357 return true; 358 } 359 360 @Override 361 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 362 return this.ordinal() < prec.ordinal(); 363 } 364 365 @Override 366 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 367 return prec.ordinal() < this.ordinal(); 368 } 369 370 @Override 371 public final boolean isNumeric() { 372 return true; 373 } 374 375 @Override 376 public final boolean isSigned() { 377 return true; 378 } 379 380 @Override 381 public final boolean isUnlimited() { 382 return false; 383 } 384 385 @Override 386 public final NumericPrecision promote() { 387 return SHORT; 388 } 389 390 @Override 391 public final NumericPrecision promoteAgainst( 392 final NumericPrecision prec ) 393 { 394 return this.isLessPreciseThan(prec) ? prec : this; 395 } 396 397 @Override 398 public final NumericPrecision toFloatingPoint() { 399 return FLOAT; 400 } 401 }, 402 403 /** 404 * <b>Short</b> field, or two {@link #BYTE bytes}, for a total value count 405 * (field cardinality) of 2<sup>16</sup> and a <i>signed</i> value range of 406 * <span style="white-space=nowrap">-2<sup>15</sup></span> to <span 407 * style="white-space=nowrap">2<sup>15</sup>-1</span> 408 */ 409 SHORT( Short.class, short.class ) { /* 4 */ 410 @Override 411 public final int compare( final NumericPrecision prec ) { 412 if (this.isEquallyPreciseAs(prec)) { 413 return 0; 414 } 415 if (this.isLessPreciseThan(prec)) { 416 return -1; 417 } 418 return +1; 419 } 420 421 @Override 422 public final int size() { 423 return Short.SIZE; 424 } 425 426 @Override 427 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 428 return (prec == this) || (prec == CHARACTER); 429 } 430 431 @Override 432 public final boolean isFinite() { 433 return true; 434 } 435 436 @Override 437 public final boolean isFloatingPoint() { 438 return false; 439 } 440 441 @Override 442 public final boolean isIeee754() { 443 return false; 444 } 445 446 @Override 447 public final boolean isIntegral() { 448 return true; 449 } 450 451 @Override 452 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 453 return CHARACTER.ordinal() < prec.ordinal(); 454 } 455 456 @Override 457 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 458 return prec.ordinal() < this.ordinal(); 459 } 460 461 @Override 462 public final boolean isNumeric() { 463 return true; 464 } 465 466 @Override 467 public final boolean isSigned() { 468 return true; 469 } 470 471 @Override 472 public final boolean isUnlimited() { 473 return false; 474 } 475 476 @Override 477 public final NumericPrecision promote() { 478 return INTEGER; 479 } 480 481 @Override 482 public final NumericPrecision promoteAgainst( 483 final NumericPrecision prec ) 484 { 485 return this.isLessPreciseThan(prec) ? prec : this; 486 } 487 488 @Override 489 public final NumericPrecision toFloatingPoint() { 490 return FLOAT; 491 } 492 }, 493 494 /** 495 * Unsigned <b>character</b> field with the same bit count as {@link #SHORT} 496 * , so it shares both its cardinality (2<sup>16</sup>) and precision, 497 * though its <i>unsigned</i> value range is <span 498 * style="white-space=nowrap">0</span> to <span 499 * style="white-space=nowrap">2<sup>16</sup>-1</span> 500 */ 501 CHARACTER( Character.class, char.class ) { /* 5 */ 502 @Override 503 public final int compare( final NumericPrecision prec ) { 504 if (this.isEquallyPreciseAs(prec)) { 505 return 0; 506 } 507 if (this.isLessPreciseThan(prec)) { 508 return -1; 509 } 510 return +1; 511 } 512 513 @Override 514 public final int size() { 515 return Character.SIZE; 516 } 517 518 @Override 519 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 520 return (prec == this) || (prec == SHORT); 521 } 522 523 @Override 524 public final boolean isFinite() { 525 return true; 526 } 527 528 @Override 529 public final boolean isFloatingPoint() { 530 return false; 531 } 532 533 @Override 534 public final boolean isIeee754() { 535 return false; 536 } 537 538 @Override 539 public final boolean isIntegral() { 540 return true; 541 } 542 543 @Override 544 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 545 return this.ordinal() < prec.ordinal(); 546 } 547 548 @Override 549 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 550 return prec.ordinal() < SHORT.ordinal(); 551 } 552 553 @Override 554 public final boolean isNumeric() { 555 return true; 556 } 557 558 @Override 559 public final boolean isSigned() { 560 return false; 561 } 562 563 @Override 564 public final boolean isUnlimited() { 565 return false; 566 } 567 568 @Override 569 public final NumericPrecision promote() { 570 return INTEGER; 571 } 572 573 @Override 574 public final NumericPrecision promoteAgainst( 575 final NumericPrecision prec ) 576 { 577 return this.isLessPreciseThan(prec) ? prec : this; 578 } 579 580 @Override 581 public final NumericPrecision toFloatingPoint() { 582 return FLOAT; 583 } 584 }, 585 586 /** 587 * <b>Integer</b> field, or 4 bytes (32 bits), for a total value count 588 * (field cardinality) of 2<sup>32</sup> and a value range of <span 589 * style="white-space=nowrap">-2<sup>31</sup></span> to <span 590 * style="white-space=nowrap">2<sup>31</sup>-1</span> 591 */ 592 INTEGER( Integer.class, int.class ) { /* 6 */ 593 @Override 594 public final int compare( final NumericPrecision prec ) { 595 if (prec == this) { 596 return 0; 597 } 598 if (this.isLessPreciseThan(prec)) { 599 return -1; 600 } 601 return +1; 602 } 603 604 @Override 605 public final int size() { 606 return Integer.SIZE; 607 } 608 609 @Override 610 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 611 return prec == this; 612 } 613 614 @Override 615 public final boolean isFinite() { 616 return true; 617 } 618 619 @Override 620 public final boolean isFloatingPoint() { 621 return false; 622 } 623 624 @Override 625 public final boolean isIeee754() { 626 return false; 627 } 628 629 @Override 630 public final boolean isIntegral() { 631 return true; 632 } 633 634 @Override 635 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 636 return this.ordinal() < prec.ordinal(); 637 } 638 639 @Override 640 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 641 return prec.ordinal() < this.ordinal(); 642 } 643 644 @Override 645 public final boolean isNumeric() { 646 return true; 647 } 648 649 @Override 650 public final boolean isSigned() { 651 return true; 652 } 653 654 @Override 655 public final boolean isUnlimited() { 656 return false; 657 } 658 659 @Override 660 public final NumericPrecision promote() { 661 return LONG; 662 } 663 664 @Override 665 public final NumericPrecision promoteAgainst( 666 final NumericPrecision prec ) 667 { 668 return this.isLessPreciseThan(prec) ? prec : this; 669 } 670 671 @Override 672 public final NumericPrecision toFloatingPoint() { 673 return FLOAT; 674 } 675 }, 676 677 /** 678 * <b>Integer</b> field, or 8 bytes (64 bits), for a total value count 679 * (field cardinality) of 2<sup>64</sup> and a value range of <span 680 * style="white-space=nowrap">-2<sup>63</sup></span> to <span 681 * style="white-space=nowrap">2<sup>63</sup>-1</span> 682 */ 683 LONG( Long.class, long.class ) { /* 7 */ 684 @Override 685 public final int compare( final NumericPrecision prec ) { 686 if (prec == this) { 687 return 0; 688 } 689 if (this.isLessPreciseThan(prec)) { 690 return -1; 691 } 692 return +1; 693 } 694 695 @Override 696 public final int size() { 697 return Long.SIZE; 698 } 699 700 @Override 701 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 702 return prec == this; 703 } 704 705 @Override 706 public final boolean isFinite() { 707 return true; 708 } 709 710 @Override 711 public final boolean isFloatingPoint() { 712 return false; 713 } 714 715 @Override 716 public final boolean isIeee754() { 717 return false; 718 } 719 720 @Override 721 public final boolean isIntegral() { 722 return true; 723 } 724 725 @Override 726 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 727 return this.ordinal() < prec.ordinal(); 728 } 729 730 @Override 731 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 732 return prec.ordinal() < this.ordinal(); 733 } 734 735 @Override 736 public final boolean isNumeric() { 737 return true; 738 } 739 740 @Override 741 public final boolean isSigned() { 742 return true; 743 } 744 745 @Override 746 public final boolean isUnlimited() { 747 return false; 748 } 749 750 @Override 751 public final NumericPrecision promote() { 752 return UNLIMITED_INTEGER; 753 } 754 755 @Override 756 public final NumericPrecision promoteAgainst( 757 final NumericPrecision prec ) 758 { 759 if (prec == FLOAT) return DOUBLE; 760 return this.isLessPreciseThan(prec) ? prec : this; 761 } 762 763 @Override 764 public final NumericPrecision toFloatingPoint() { 765 return DOUBLE; 766 } 767 }, 768 769 /** 770 * IEEE <a href="http://en.wikipedia.org/wiki/Ieee_float">754-2008</a> 771 * single precision {@code float} value (32 bits). Though, strictly 772 * speaking, the value field size is actually smaller than that of a 32 bit 773 * {@link #INTEGER integer} due to the {@code float}'s 23 bit <a 774 * href="http://en.wikipedia.org/wiki/Significand">significand</a> size, 775 * {@code float} is treated as a <i>more</i> precise value because of its 776 * significantly increased minimum-to-maximum value range. 777 */ 778 FLOAT( Float.class, float.class ) { /* 8 */ 779 @Override 780 public final int compare( final NumericPrecision prec ) { 781 if (prec == this) { 782 return 0; 783 } 784 if (this.isLessPreciseThan(prec)) { 785 return -1; 786 } 787 return +1; 788 } 789 790 @Override 791 public final int size() { 792 return Float.SIZE; 793 } 794 795 @Override 796 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 797 return prec == this; 798 } 799 800 @Override 801 public final boolean isFinite() { 802 return true; 803 } 804 805 @Override 806 public final boolean isFloatingPoint() { 807 return true; 808 } 809 810 @Override 811 public final boolean isIeee754() { 812 return true; 813 } 814 815 @Override 816 public final boolean isIntegral() { 817 return false; 818 } 819 820 @Override 821 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 822 return this.ordinal() < prec.ordinal(); 823 } 824 825 @Override 826 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 827 return prec.ordinal() < this.ordinal(); 828 } 829 830 @Override 831 public final boolean isNumeric() { 832 return true; 833 } 834 835 @Override 836 public final boolean isSigned() { 837 return true; 838 } 839 840 @Override 841 public final boolean isUnlimited() { 842 return false; 843 } 844 845 @Override 846 public final NumericPrecision promote() { 847 return DOUBLE; 848 } 849 850 @Override 851 public final NumericPrecision promoteAgainst( 852 final NumericPrecision prec ) 853 { 854 if (prec == LONG) return DOUBLE; 855 if (prec == UNLIMITED_INTEGER) return UNLIMITED_DECIMAL; 856 if ((prec == DOUBLE) || (prec == UNLIMITED_DECIMAL)) { 857 return prec; 858 } 859 return this; 860 } 861 862 @Override 863 public final NumericPrecision toFloatingPoint() { 864 return this; 865 } 866 }, 867 868 /** 869 * IEEE <a href="http://en.wikipedia.org/wiki/Ieee_float">754-2008</a> 870 * single precision {@code float} value (32 bits). Though, strictly 871 * speaking, the value field size is actually smaller than that of a 64 bit 872 * {@link #LONG long} due to the {@code double}'s 53 bit <a 873 * href="http://en.wikipedia.org/wiki/Significand">significand</a> size, 874 * {@code double} is treated as a <i>more</i> precise value because of its 875 * significantly increased minimum-to-maximum value range. 876 */ 877 DOUBLE( Double.class, double.class ) { /* 9 */ 878 @Override 879 public final int compare( final NumericPrecision prec ) { 880 if (prec == this) { 881 return 0; 882 } 883 if (this.isLessPreciseThan(prec)) { 884 return -1; 885 } 886 return +1; 887 } 888 889 @Override 890 public final int size() { 891 return Double.SIZE; 892 } 893 894 @Override 895 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 896 return prec == this; 897 } 898 899 @Override 900 public final boolean isFinite() { 901 return true; 902 } 903 904 @Override 905 public final boolean isFloatingPoint() { 906 return true; 907 } 908 909 @Override 910 public final boolean isIeee754() { 911 return true; 912 } 913 914 @Override 915 public final boolean isIntegral() { 916 return false; 917 } 918 919 @Override 920 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 921 return this.ordinal() < prec.ordinal(); 922 } 923 924 @Override 925 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 926 return prec.ordinal() < this.ordinal(); 927 } 928 929 @Override 930 public final boolean isNumeric() { 931 return true; 932 } 933 934 @Override 935 public final boolean isSigned() { 936 return true; 937 } 938 939 @Override 940 public final boolean isUnlimited() { 941 return false; 942 } 943 944 @Override 945 public final NumericPrecision promote() { 946 return UNLIMITED_DECIMAL; 947 } 948 949 @Override 950 public final NumericPrecision promoteAgainst( 951 final NumericPrecision prec ) 952 { 953 if (prec == UNLIMITED_INTEGER) return UNLIMITED_DECIMAL; 954 return prec == UNLIMITED_DECIMAL ? UNLIMITED_DECIMAL : this; 955 } 956 957 @Override 958 public final NumericPrecision toFloatingPoint() { 959 return this; 960 } 961 }, 962 963 /** 964 * <b>Unlimited integer</b> value of arbitrary precision, which is only less 965 * precise than the unlimited {@link #UNLIMITED_DECIMAL decimal} precision 966 */ 967 UNLIMITED_INTEGER( BigInteger.class, BigInteger.class ) { /* 10 */ 968 @Override 969 public final int compare( final NumericPrecision prec ) { 970 if (prec == this) { 971 return 0; 972 } 973 if (this.isLessPreciseThan(prec)) { 974 return -1; 975 } 976 return +1; 977 } 978 979 @Override 980 public final int size() { 981 return -1; 982 } 983 984 @Override 985 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 986 return prec == this; 987 } 988 989 @Override 990 public final boolean isFinite() { 991 return false; 992 } 993 994 @Override 995 public final boolean isFloatingPoint() { 996 return false; 997 } 998 999 @Override 1000 public final boolean isIeee754() { 1001 return false; 1002 } 1003 1004 @Override 1005 public final boolean isIntegral() { 1006 return true; 1007 } 1008 1009 @Override 1010 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 1011 return prec == UNLIMITED_DECIMAL; 1012 } 1013 1014 @Override 1015 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 1016 if (prec == this) { 1017 return false; 1018 } 1019 if (prec == UNLIMITED_DECIMAL) { 1020 return false; 1021 } 1022 return true; 1023 } 1024 1025 @Override 1026 public final boolean isNumeric() { 1027 return true; 1028 } 1029 1030 @Override 1031 public final boolean isSigned() { 1032 return true; 1033 } 1034 1035 @Override 1036 public final boolean isUnlimited() { 1037 return true; 1038 } 1039 1040 @Override 1041 public final NumericPrecision promote() { 1042 return UNLIMITED_DECIMAL; 1043 } 1044 1045 @Override 1046 public final NumericPrecision promoteAgainst( 1047 final NumericPrecision prec ) 1048 { 1049 return prec.isFloatingPoint() ? UNLIMITED_DECIMAL : this; 1050 } 1051 1052 @Override 1053 public final NumericPrecision toFloatingPoint() { 1054 return UNLIMITED_DECIMAL; 1055 } 1056 }, 1057 1058 /** 1059 * <b>Unlimited decimal</b> value of arbitrary precision and the highest 1060 * precision of any specifiable value 1061 */ 1062 UNLIMITED_DECIMAL( BigDecimal.class, BigDecimal.class ) { /* 11 */ 1063 @Override 1064 public final int compare( final NumericPrecision prec ) { 1065 if (prec == this) { 1066 return 0; 1067 } 1068 return +1; 1069 } 1070 1071 @Override 1072 public final int size() { 1073 return -1; 1074 } 1075 1076 @Override 1077 public final boolean isEquallyPreciseAs( final NumericPrecision prec ) { 1078 return prec == this; 1079 } 1080 1081 @Override 1082 public final boolean isFinite() { 1083 return false; 1084 } 1085 1086 @Override 1087 public final boolean isFloatingPoint() { 1088 return true; 1089 } 1090 1091 @Override 1092 public final boolean isIeee754() { 1093 return false; 1094 } 1095 1096 @Override 1097 public final boolean isIntegral() { 1098 return false; 1099 } 1100 1101 @Override 1102 public final boolean isLessPreciseThan( final NumericPrecision prec ) { 1103 return false; 1104 } 1105 1106 @Override 1107 public final boolean isMorePreciseThan( final NumericPrecision prec ) { 1108 return prec != this; 1109 } 1110 1111 @Override 1112 public final boolean isNumeric() { 1113 return true; 1114 } 1115 1116 @Override 1117 public final boolean isSigned() { 1118 return true; 1119 } 1120 1121 @Override 1122 public final boolean isUnlimited() { 1123 return true; 1124 } 1125 1126 @Override 1127 public final NumericPrecision promote() { 1128 return this; 1129 } 1130 1131 @Override 1132 public final NumericPrecision promoteAgainst( 1133 final NumericPrecision prec ) 1134 { 1135 return this; 1136 } 1137 1138 @Override 1139 public final NumericPrecision toFloatingPoint() { 1140 return this; 1141 } 1142 }, 1143 1144 ; 1145 1146 private final static Map<Class<?>,NumericPrecision> _theClassPrecisionMap = new IdentityHashMap<Class<?>,NumericPrecision>(); 1147 1148 public static NumericPrecision MAXIMUM = UNLIMITED_DECIMAL; 1149 public static NumericPrecision MINIMUM = UNKNOWN; 1150 1151 static { 1152 for (final NumericPrecision prec : NumericPrecision.values()) { 1153 _theClassPrecisionMap.put(prec.getNumberClass(), prec); 1154 _theClassPrecisionMap.put(prec.getPrimitiveClass(), prec); 1155 } 1156 _theClassPrecisionMap.put(null, NULL); 1157 _theClassPrecisionMap.put(AtomicBoolean.class, BIT); 1158 _theClassPrecisionMap.put(AtomicInteger.class, INTEGER); 1159 _theClassPrecisionMap.put(AtomicLong.class, LONG); 1160 _theClassPrecisionMap.put(Appendable.class, UNKNOWN); 1161 _theClassPrecisionMap.put(StringBuilder.class, UNKNOWN); 1162 _theClassPrecisionMap.put(StringBuffer.class, UNKNOWN); 1163 _theClassPrecisionMap.put(CharSequence.class, UNKNOWN); 1164 } 1165 1166 private final Class<?> _theNumberClass; 1167 private final Class<?> _thePrimitiveClass; 1168 1169 private NumericPrecision( 1170 final Class<?> aNumberClass, 1171 final Class<?> aPrimitiveClass ) 1172 { 1173 this._theNumberClass = aNumberClass; 1174 this._thePrimitiveClass = aPrimitiveClass; 1175 } 1176 1177 /** 1178 * {@link Comparable#compareTo(Object) Primitive1} this precision against 1179 * another. This method is included, and named what it is because 1180 * {@link Enum} implements {@code compareTo} to simply compare the 1181 * {@link Enum#ordinal() ordinal} values of any two compatible enumerations. 1182 * 1183 * @param prec 1184 * another precision 1185 * @return 0 if this precision and the specified one are the same precision, 1186 * -1 if this precision is less precise, or +1 if this precision is 1187 * more precise 1188 * @see Comparable#compareTo(Object) 1189 */ 1190 public abstract int compare( final NumericPrecision prec ); 1191 1192 public final Class<?> getNumberClass() { 1193 return this._theNumberClass; 1194 } 1195 1196 public final Class<?> getPrimitiveClass() { 1197 return this._thePrimitiveClass; 1198 } 1199 1200 /** 1201 * @param prec 1202 * another precision enumeration 1203 * @return {@code true} if this precision is as precise as the specified 1204 * precision 1205 */ 1206 public abstract boolean isEquallyPreciseAs( NumericPrecision prec ); 1207 1208 /** 1209 * @return {@code true} if this precision is known and finite 1210 */ 1211 public abstract boolean isFinite(); 1212 1213 /** 1214 * @return {@code true} if this precision represents a floating point value 1215 */ 1216 public abstract boolean isFloatingPoint(); 1217 1218 /** 1219 * @return {@code true} if this precision represents an IEEE 754 floating 1220 * point value 1221 * @see <a href="http://en.wikipedia.org/wiki/IEEE_754">IEEE 754</a> 1222 * (Wikipedia) 1223 */ 1224 public abstract boolean isIeee754(); 1225 1226 /** 1227 * @return {@code true} if this precision represents an integral (no decimal 1228 * point) value 1229 */ 1230 public abstract boolean isIntegral(); 1231 1232 /** 1233 * @param prec 1234 * another precision enumeration 1235 * @return {@code true} if this precision is less precise or as equally 1236 * precise as the specified precision 1237 */ 1238 public final boolean isLessOrEquallyPreciseAs( final NumericPrecision prec ) 1239 { 1240 if (this.isEquallyPreciseAs(prec)) { 1241 return true; 1242 } 1243 if (this.isLessPreciseThan(prec)) { 1244 return true; 1245 } 1246 return false; 1247 } 1248 1249 /** 1250 * @param prec 1251 * another precision enumeration 1252 * @return {@code true} if this precision is less precise than the specified 1253 * precision 1254 */ 1255 public abstract boolean isLessPreciseThan( NumericPrecision prec ); 1256 1257 /** 1258 * @param prec 1259 * another precision enumeration 1260 * @return {@code true} if this precision is more precise or as equally 1261 * precise as the specified precision 1262 */ 1263 public final boolean isMoreOrEquallyPreciseAs( final NumericPrecision prec ) 1264 { 1265 if (this.isEquallyPreciseAs(prec)) { 1266 return true; 1267 } 1268 if (this.isMorePreciseThan(prec)) { 1269 return true; 1270 } 1271 return false; 1272 } 1273 1274 /** 1275 * @param prec 1276 * another precision enumeration 1277 * @return {@code true} if this precision is more precise than the specified 1278 * precision 1279 */ 1280 public abstract boolean isMorePreciseThan( final NumericPrecision prec ); 1281 1282 /** 1283 * @return {@code true} if this is a valid numeric precision 1284 */ 1285 public abstract boolean isNumeric(); 1286 1287 /** 1288 * @return {@code true} if this precision is known and signed 1289 */ 1290 public abstract boolean isSigned(); 1291 1292 /** 1293 * @return {@code true} if objects with this precision are implemented using 1294 * unlimited precision (e.g., {@link BigInteger} or 1295 * {@link BigDecimal}) 1296 */ 1297 public abstract boolean isUnlimited(); 1298 1299 public final NumericPrecision maximumOf( final NumericPrecision prec ) { 1300 if (this.isMoreOrEquallyPreciseAs(prec)) { 1301 return this; 1302 } 1303 return prec; 1304 } 1305 1306 public final NumericPrecision maximumOfAll( 1307 final NumericPrecision... precisions ) 1308 { 1309 NumericPrecision max = this; 1310 for (final NumericPrecision prec : precisions) { 1311 max = max.maximumOf(prec); 1312 } 1313 return max; 1314 } 1315 1316 /** 1317 * @return a minimally more, or the "next" more, numerically precise 1318 * enumeration value 1319 */ 1320 public abstract NumericPrecision promote(); 1321 1322 /** 1323 * Answer a precision value such that any mathematical operation between 1324 * values of this precision and those of the specified one will not result 1325 * in a loss of information. The dynamics of this promotion are such that 1326 * all primitive promotions will rapidly converge upon {@link #DOUBLE} 1327 * unless precisions smaller than {@link #LONG} are explicitly promoted 1328 * against {@link #FLOAT}. {@link #isIntegral() Integral} numbers are always 1329 * promoted to floating points (rational real numbers when compared against 1330 * them. The {@link #isUnlimited() unlimited} precision types (e.g., 1331 * {@link BigInteger} and {@link BigDecimal}) will always force a promotion 1332 * to themselves.<br> 1333 * <br> 1334 * Note that this algorithm may not be recommended under all circumstances, 1335 * for instance under division where it may be desirable to promote to a 1336 * floating point precision under all circumstances. Therefore treat this 1337 * promotion behavior as a default behavior which remains agnostic to 1338 * specific operations. 1339 * 1340 * @param prec 1341 * a precision to test against 1342 * @return a precision such that any mathematical operation between values 1343 * of this precision and those of the specified one will not result 1344 * in a loss of information 1345 */ 1346 public abstract NumericPrecision promoteAgainst( final NumericPrecision prec ); 1347 1348 /** 1349 * @return the number of bits used to represent values of this type in this 1350 * system or -1 for {@link #UNKNOWN} or {@link #isUnlimited() 1351 * unlimited} 1352 */ 1353 public abstract int size(); 1354 1355 /** 1356 * @return a minimally more, or the "next" more, precise <i>floating 1357 * point</i> enumeration value if this was integral or otherwise 1358 * answer itself 1359 */ 1360 public abstract NumericPrecision toFloatingPoint(); 1361 1362 public final static NumericPrecision getPrecisionFor( final Class<?> aClass ) 1363 { 1364 final NumericPrecision prec = _theClassPrecisionMap.get(aClass); 1365 if ( prec == null ) { 1366 return UNKNOWN; 1367 } 1368 return prec; 1369 } 1370 1371 public final static NumericPrecision getPrecisionFor( final Object aValue ) 1372 { 1373 final Class<?> aClass = aValue.getClass(); 1374 final NumericPrecision prec = _theClassPrecisionMap.get(aClass); 1375 if (prec != null) { 1376 return prec; 1377 } 1378 if (aValue instanceof SealedScalarDomain) { 1379 final SealedScalarDomain aDomain = (SealedScalarDomain)aValue; 1380 return aDomain.getPrecision(); 1381 } 1382 return UNKNOWN; 1383 } 1384}