001/** A class representing the precision of a FixPoint number. 002 003 Copyright (c) 1998-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 028 */ 029package ptolemy.math; 030 031import java.math.BigDecimal; 032import java.math.BigInteger; 033import java.util.regex.Matcher; 034import java.util.regex.Pattern; 035 036/** 037 This class defines the precision of a signed or unsigned fixed point 038 value. The precision of a fixed point value is represented as 039 internally as three fields: the number of bits (<i>n</i>), the 040 binary exponent (<i>e</i>), and a sign bit (<i>s</i>). 041 042 The number of bits (<i>n</i>) defines the dynamic range of 043 the format (2<sup>n</sup>). 044 045 The exponent (<i>e</i>) determines the placement of the binary point 046 for all values of this format. This binary point placement is "fixed" 047 and is specified within the precision format rather than within individual 048 Fixed point values. The mantissa bits of all fixed point values 049 using this this precision format are multiplied by 2<sup>m</sup>. Note that 050 <i>m</i> can take on a positive, negative, or zero value. This allows 051 the binary point to be placed anywhere necessary and even beyond the bounds 052 of the mantissa (i.e. to the right of the lsb or to the left of the msb). 053 054 The sign value <i>s</i> is used to indicate whether the fixed point 055 precision value is treated as signed (s = 1) or unsigned (s = 0). <p> 056 057 <b>Signed</b> fixed point formats are represented in a 2's complement 058 format. As a consequence, a single bit is used to represent the 059 sign of the number. The value of a multi-bit signed number is: <p> 060 061 Signed(B) = 2^m x (- b_{n-1} x 2^{n-1} + \sum_{i=0}^{n-2} b_i x 2^i), 062 063 where b_i is the value of bit i of the bit vector. <p> 064 065 <b>Unsigned</b> fixed formats are represented as unsigned binary 066 values. No bits are used to represent the sign and all values are 067 positive. The actual value of a multi-bit unsigned fixed 068 point number is:<p> 069 070 Unsigned(B) = 2^m x (\sum_{i=0}^{n-1} b_i x 2^i) <p> 071 072 <p> 073 This class supports several different String formats for specifying and 074 displaying the Precision. These String formats are supported by several 075 classes that extend the {@link PrecisionFormat} class. Several such classes 076 have been created. Any given precision string format can be represented in 077 any of the valid precision string formats. The four supported Precision 078 String formats are shown in the table below. A static singleton object of 079 each of these formats is provided in this class. Each String Representation 080 column of the table represent equivalent Precision formats: 081 082 <table border = 1> 083 <caption>Precision Formats.</caption> 084 <tr><td><b>Format Name</b></td> <td><b>Format Spec</b></td> 085 <td colspan = "6"><center><b>String Representation</b></center></td> 086 </tr> 087 <tr><td>{@link IntegerFractionPrecisionFormat}</td> 088 <td> [integer bits].[fraction bits] </td> 089 <td>3.2</td> 090 <td>0.7</td> 091 <td>-2.12</td> 092 <td>12.-4</td> 093 <td>32.0</td> 094 <td>U1.7</td> 095 </tr> 096 <tr><td>{@link LengthIntegerPrecisionFormat}</td> 097 <td>[total bits]/[integer bits]</td> 098 <td>5/3</td> 099 <td>7/0</td> 100 <td>10/-2</td> 101 <td>8/12</td> 102 <td>32/32</td> 103 <td>U8/1</td> 104 </tr> 105 <tr><td>{@link VHDLPrecisionFormat}</td> 106 <td>[MSb position]:[LSb position]</td> 107 <td>2:-2</td> 108 <td>-1:-7</td> 109 <td>-3:-12</td> 110 <td>11:4</td> 111 <td>31:0</td> 112 <td>U0:-7</td> 113 </tr> 114 <tr><td>{@link LengthExponentPrecisionFormat}</td> 115 <td>[total bits]e[binary point position]</td> 116 <td>5e-2</td> 117 <td>7e-7</td> 118 <td>10e-12</td> 119 <td>8e4</td> 120 <td>32e0</td> 121 <td>U8e-7</td> 122 </tr> 123 </table> 124 125 <p> 126 An instance of the class is immutable, meaning 127 that its value is set in the constructor and cannot then be modified. 128 129 @author Bart Kienhuis, Contributor: Mike Wirthlin 130 @version $Id$ 131 @since Ptolemy II 0.4 132 @Pt.ProposedRating Yellow (kienhuis) 133 @Pt.AcceptedRating Red (kienhuis) 134 @see FixPoint 135 */ 136public class Precision implements Cloneable { 137 138 /** Construct a Precision object based on the provided string. The 139 * string can describe the precision in any of the 140 * syntaxes explained in the description of this class. 141 * 142 * @param str The string representing the precision. 143 * @exception IllegalArgumentException If the precision string 144 * supplied does not match one of the known formats. 145 */ 146 public Precision(String str) throws IllegalArgumentException { 147 Precision p = null; 148 149 if ((p = INTEGER_FRACTION.parseString(str)) != null) { 150 _format = INTEGER_FRACTION; 151 } else if ((p = LENGTH_INTEGER.parseString(str)) != null) { 152 _format = LENGTH_INTEGER; 153 } else if ((p = LENGTH_EXPONENT.parseString(str)) != null) { 154 _format = LENGTH_EXPONENT; 155 } else if ((p = VHDL.parseString(str)) != null) { 156 _format = VHDL; 157 } 158 159 if (p != null) { 160 _length = p._length; 161 _exponent = p._exponent; 162 _sign = p._sign; 163 return; 164 } 165 166 throw new IllegalArgumentException( 167 "Unrecognized Precision String:" + str); 168 } 169 170 /** Construct a Precision object based on the length/integer 171 * bits format. This constructor will create 172 * a new <i>signed</i> Precision object with <i>length</i> 173 * bits and an exponent of <i>-fracBits</i>. 174 * 175 * @param length The total number of bits. 176 * @param integerBits The number of integer bits. 177 * @exception IllegalArgumentException If the given values are 178 * negative or when the integer number of bits is larger than the 179 * total number of bits. 180 */ 181 public Precision(int length, int integerBits) 182 throws IllegalArgumentException { 183 this(1, length, integerBits - length); 184 } 185 186 /** Construct a Precision object based on the sign, length, and 187 * exponent format. 188 * 189 * @param sign The presence of a sign bit (1 = signed, 0 = unsigned). 190 * @param length The total number of bits. 191 * @param exponent The bit location of the exponent. 192 * @exception IllegalArgumentException If the Precision arguments 193 * are inconsistent. 194 */ 195 public Precision(int sign, int length, int exponent) 196 throws IllegalArgumentException { 197 if (sign != 0 && sign != 1) { 198 throw new IllegalArgumentException("Incorrect definition of " 199 + "Precision. Sign must be 0 or 1"); 200 } 201 202 if (length < 0) { 203 throw new IllegalArgumentException("Incorrect definition of " 204 + "Precision. Do not use negative total length "); 205 } 206 207 _sign = sign; 208 _length = length; 209 _exponent = exponent; 210 } 211 212 /////////////////////////////////////////////////////////////////// 213 //// public methods //// 214 215 /** Return this, that is, return the reference to this object. 216 * @return This Precision. 217 */ 218 @Override 219 public Object clone() { 220 // FIXME: Note that we do not call super.clone() here. Is that right? 221 return this; 222 } 223 224 /** Return true if the indicated object is an instance of Precision 225 * and the precision format matches exactly. 226 * @param object Object to test for equality 227 * @return True if the precisions are equal. 228 */ 229 @Override 230 public boolean equals(Object object) { 231 if (object instanceof Precision) { 232 Precision other = (Precision) object; 233 234 if (other._length == _length && other._exponent == _exponent 235 && other._sign == _sign) { 236 return true; 237 } 238 } 239 240 return false; 241 } 242 243 /** Return the maximum obtainable value in this precision. 244 * This value is obtained by multiplying the result of 245 * {@link #getMaximumUnscaledValue()} by 2<sup>exponent</sup>. 246 * 247 * @return The maximum value obtainable for this precision. 248 */ 249 public BigDecimal findMaximum() { 250 BigDecimal bd = new BigDecimal(getMaximumUnscaledValue()); 251 return shiftBigDecimal(bd, _exponent); 252 } 253 254 /** Return the minimum obtainable value for this precision. 255 * This value is obtained by multiplying the result of 256 * {@link #getMinimumUnscaledValue()} by 2<sup>exponent</sup>. 257 * 258 * @return The minimum value obtainable for the given precision. 259 */ 260 public BigDecimal findMinimum() { 261 if (!isSigned()) { 262 return new BigDecimal(0); 263 } 264 BigDecimal bd = new BigDecimal(getMinimumUnscaledValue()); 265 return shiftBigDecimal(bd, _exponent); 266 } 267 268 /** Return the incremental value between discrete values under 269 * the given Precision format. This is calculated as 2^exponent. 270 * 271 * @return Incremental (epsilon) value. 272 */ 273 public BigDecimal getEpsilon() { 274 return new BigDecimal(Math.pow(2, _exponent)); 275 } 276 277 /** Return the location of the binary exponent. 278 * @return the location of the fixed binary exponent. 279 */ 280 public int getExponent() { 281 return _exponent; 282 } 283 284 /** Return the number of bits representing the fractional part. 285 * The is computed as -exponent. 286 * @return The length of the fractional part. 287 */ 288 public int getFractionBitLength() { 289 return -_exponent; 290 } 291 292 /** Return the number of bits representing the integer part. 293 * This is computed as length + exponent. 294 * @return the length of the integer part. 295 */ 296 public int getIntegerBitLength() { 297 return _length + _exponent; 298 } 299 300 /** 301 * Return the bit position of the least significant bit of the 302 * given fixed point precision. This value is the same as 303 * the exponent value of this format. Bit 0 refers to 304 * the bit just to the left of the binary point. 305 * 306 * @return Least significant bit position. 307 */ 308 public int getLeastSignificantBitPosition() { 309 return _exponent; 310 } 311 312 /** Return the maximum integer value <i>before</i> scaling so that 313 * quantization levels are represented by adjacent integers. 314 * 315 * For signed values, this number is 2^(n-1) - 1 316 * For unsigned values, this number is 2^(n) - 1 317 * @return The maximum inclusive value. 318 */ 319 public BigInteger getMaximumUnscaledValue() { 320 // Create a positive "bit vector" that is the length 321 // of the this precision and has all ones. 322 BigInteger val = BigInteger.ZERO.setBit(_length - _sign); 323 val = val.subtract(BigInteger.ONE); 324 return val; 325 } 326 327 /** Return the minimum integer value <i>before</i> scaling so 328 * that quantization levels are represented by adjacent 329 * integers. 330 * 331 * For signed values, this number is -(2^(n-1)) 332 * For unsigned values, this number is 0. 333 * 334 * @return The minimum unscaled value value obtainable 335 * for the given precision. 336 */ 337 public BigInteger getMinimumUnscaledValue() { 338 if (isSigned()) { 339 return BigInteger.ZERO.setBit(_length - 1).negate(); 340 } 341 342 return BigInteger.ZERO; 343 } 344 345 /** 346 * Return the bit position of the most significant bit of the 347 * given fixed point precision. Bit 0 refers to 348 * the bit just to the left of the binary point. 349 * 350 * @return Least significant bit position. 351 */ 352 public int getMostSignificantBitPosition() { 353 return _exponent + _length - 1; 354 } 355 356 /** 357 * Return the bit position of the most significant 358 * data bit of the given fixed point precision. If this 359 * Precision is signed, this will return 360 * getMostSignificantBitPosition - 1. If this Precision 361 * is unsigned, this will return getMostSignificantBitPosition. 362 * 363 * @return Least significant bit position. 364 */ 365 public int getMostSignificantDataBitPosition() { 366 return _exponent + _length - 1 - _sign; 367 } 368 369 /** Return the total number of bits. 370 * @return the total number of bits. 371 */ 372 public int getNumberOfBits() { 373 return _length; 374 } 375 376 /** Return the total number of discrete values possible. 377 * @return the total number of levels. 378 */ 379 public BigInteger getNumberOfLevels() { 380 int numBits = getNumberOfBits(); 381 return BigInteger.ZERO.setBit(numBits); 382 //return Math.pow(2.0, _length); 383 } 384 385 /** Return the sign (0 = unsigned, 1 = signed). 386 * @return the sign status. 387 */ 388 public int getSign() { 389 return _sign; 390 } 391 392 /** Return a hash code value for this Precision. This method returns the 393 * bitwise and of the length, exponent and sign. 394 * @return A hash code value for this Precision. 395 */ 396 @Override 397 public int hashCode() { 398 return Integer.valueOf(_length).hashCode() >>> Integer 399 .valueOf(_exponent) 400 .hashCode() >>> Integer.valueOf(_sign).hashCode(); 401 } 402 403 /** 404 * Determine if the fixed point format is signed or not. 405 * 406 * @return true if format is signed 407 */ 408 public boolean isSigned() { 409 return _sign == 1; 410 } 411 412 /** Return the precision that is the maximum of the two supplied 413 * precisions in both the length and exponent. This 414 * method is used to align instances of FixPoint onto a single 415 * precision representation. If either Precision object is 416 * signed, the new Precision object will be signed. 417 * 418 * @param precisionA A precision 419 * @param precisionB Another precision 420 * @return A precision at least as precise as the two arguments. 421 */ 422 public static Precision union(Precision precisionA, Precision precisionB) { 423 424 int minExponent = precisionA._exponent < precisionB._exponent 425 ? precisionA._exponent 426 : precisionB._exponent; 427 428 int aDataMSB = precisionA.getMostSignificantDataBitPosition(); 429 int bDataMSB = precisionB.getMostSignificantDataBitPosition(); 430 431 int maxDataMSB = aDataMSB > bDataMSB ? aDataMSB : bDataMSB; 432 int newLength = maxDataMSB - minExponent + 1; 433 434 int newSign = precisionA._sign == 1 || precisionB._sign == 1 ? 1 : 0; 435 newLength += newSign; 436 437 return new Precision(newSign, newLength, minExponent); 438 } 439 440 /** Shift the BigDecimal value either right or left by 441 * a power of 2 value. This method will perform a 442 * multiplication by 2^<sup>shiftval</sup> on the BigDecimal 443 * value when shiftval is positive and will perform a 444 * divide by 2^<sup>-shiftval</sup> on the BigDecimal value 445 * when shiftval is negative. 446 * 447 * 448 * @param val BigDecimal value to shift. 449 * @param shiftval Amount of "power of 2" shifting to perform 450 * on the BigDecimal value 451 * @return shifted BigDecimal value. 452 */ 453 public static BigDecimal shiftBigDecimal(BigDecimal val, int shiftval) { 454 455 // No shifting takes place. Return the BigDecimal value 456 if (shiftval == 0) { 457 return val; 458 } 459 460 // Left shifting is going to occur. Multiply value by 461 // 2^shiftval 462 if (shiftval > 0) { 463 return val.multiply(_getTwoRaisedTo(shiftval)); 464 } 465 466 // Right shifting is going to occur. Divide value by 467 // 2^(-shiftval) since shiftval is negative. 468 469 // When dividing BigDecimal values, we need to know the maximum 470 // number of decimal places will be added to the right 471 // as a result of the divide 472 // to preserve the precision of the result. Since we are 473 // dividing by a number of the form, 2^n, the division 474 // is essentially a divide by 2 for n times. Every 475 // divide by two will add at most one new 476 // least significant decimal digit to the right of the decimal 477 // point. To preserve all of the precision of the divide, 478 // set the BigDecimal "scale" to n + val.scale() where 479 // n is the power of 2. 480 int scaleShift = -shiftval + val.scale(); 481 482 BigDecimal result = val.divide(_getTwoRaisedTo(-shiftval), scaleShift, 483 BigDecimal.ROUND_HALF_EVEN); 484 return result; 485 } 486 487 /** Return a string representing this precision. The string is 488 * expressed as "(<i>m.n</i>)", where <i>m</i> 489 * indicates the number of integer bits and <i>n</i> represents 490 * the number of fractional bits. 491 * @return A string representing this precision. 492 */ 493 @Override 494 public String toString() { 495 return _format.printPrecisionFormat(this); 496 } 497 498 /** 499 * Return a string representation of this format in one of several 500 * styles. 501 * @param format The String format represented desired for printing. 502 * @return String representation of the object using the given 503 * PrecisionFormat 504 */ 505 public String toString(PrecisionFormat format) { 506 return format.printPrecisionFormat(this); 507 } 508 509 /** Defines a String format for specifying a Precision object. 510 * This abstract class defines a method for parsing the string 511 * format and a method for creating a valid String representation 512 * of a Precision object. The printing and parsing methods should 513 * be consistent (i.e. the parsing method should successfully parse 514 * the result of the printing method). 515 */ 516 public static abstract class PrecisionFormat { 517 518 /** 519 * Parse the given String argument using the rules of the specific 520 * PrecisionFormat that is defined. This method will return a 521 * valid Precision object from the String. If the String parsing 522 * does not produce a valid match, this method will return a null. 523 * If the String match is successful but there is a problem in 524 * the interpretation of the match, this method will throw 525 * a IllegalArgumentException. 526 * 527 * @param str String to parse 528 * @return A Precision object. Returns a null if the String does 529 * not match the particular string format. 530 * @exception IllegalArgumentException If there is a problem 531 * parsing the String (i.e. an illegal string). 532 */ 533 public abstract Precision parseString(String str) 534 throws IllegalArgumentException; 535 536 /** Creates a valid String representation of the Precision object 537 * based on the rules of the given string format. The format of this 538 * String should be consistent with the format used in the 539 * parseString method. 540 * 541 * @param p Precision object to represent as a String. 542 * @return String representing the Precision object 543 */ 544 public abstract String printPrecisionFormat(Precision p); 545 546 /** Parse a String as an integer. This method calls the 547 * Integer.parseInt method but throws the IllegalArgumentException 548 * instead of the NumberFormatException when there is a problem. 549 * 550 * @param str The integer string to parse 551 * @return The integer value of the string. 552 * @exception IllegalArgumentException If the parsing of the 553 * Integer value fails (i.e. NumberFormatException). 554 */ 555 public static int parseInteger(String str) 556 throws IllegalArgumentException { 557 int value = 0; 558 559 try { 560 value = Integer.parseInt(str); 561 } catch (NumberFormatException e) { 562 throw new IllegalArgumentException( 563 "Invalid integer number:" + str + " " + e); 564 } 565 566 return value; 567 } 568 569 /** Parse the 'U' or 'S' sign specifier. 570 * 571 * @param str String to parse for a sign indicator. 572 * @return Return a 0 for unsigned and a 1 for signed. 573 * @exception IllegalArgumentException If the 574 * string does not match the 'U' or 'S' characters. 575 */ 576 public static int parseSignString(String str) 577 throws IllegalArgumentException { 578 if (str.equalsIgnoreCase("U")) { 579 return 0; 580 } else if (str.equalsIgnoreCase("S")) { 581 return 1; 582 } 583 584 throw new IllegalArgumentException("Invalid signed format string:'" 585 + str + "'. Expecting 'U' or 'S'"); 586 } 587 588 /** The following static String objects are used for convenience 589 * when performing regular expression matches on Precision 590 * Strings. The following explanation will help explain the 591 * meaning of some of these cryptic strings: 592 * 593 * "\\" 594 * This corresponds to a single "\" in the regular expression 595 * matcher. A single "\" must be represetned within Java as an 596 * escape sequence (i.e. "\\"). A single "\" will not compile as 597 * the \" corresponds to the string """ (i.e. a single quotation 598 * mark). 599 * 600 * GROUP 601 * Any variable with the GROUP in its name corresponds to a 602 * regular expression with the "capturing group" parenthesis 603 * around the regular expression. This "capturing" is used 604 * to obtain the matching string associated with the 605 * regular expression. 606 * 607 */ 608 609 /** Regular expression definition for a comma "," or a 610 * forward slash "/". */ 611 public final static String COMMA_OR_FORWARDSLASH = "[,/]"; 612 613 /** Regular expression definition for an optional left parenthesis. **/ 614 public final static String OPTIONAL_L_PARAN = "\\(?"; 615 616 /** Regular expression definition for an optional left parenthesis 617 * or left bracket. **/ 618 public final static String OPTIONAL_L_PARANBRACKET = "[\\(\\[]?"; 619 620 /** Regular expression definition for an optional right parenthesis. **/ 621 public final static String OPTIONAL_R_PARAN = "\\)?"; 622 623 /** Regular expression definition for an optional right parenthesis 624 * or left bracket. **/ 625 public final static String OPTIONAL_R_PARANBRACKET = "[\\)\\]]?"; 626 627 /** Regular expression definition for a Period ".". */ 628 public final static String PERIOD = "\\."; 629 630 /** Regular expression for a grouped signed integer 631 * (positive or negative). **/ 632 public final static String SIGNED_INTEGER_GROUP = "(-?\\d+)"; 633 634 /** Regular expression for an optional 'S' or 'U' "group". */ 635 public final static String OPTIONAL_U_OR_S_GROUP = "([USus])?"; 636 637 /** Regular expression for a grouped unsigned integer. **/ 638 public final static String UNSIGNED_INTEGER_GROUP = "(\\d+)"; 639 640 /** Regular expression for optional white space. **/ 641 public final static String OPTIONAL_WHITE_SPACE = "\\s*"; 642 } 643 644 /** Defines a Precision string format using the INTEGER.FRACTION 645 * precision format. The INTEGER value specifies the number of 646 * integer bits and the FRACTION value specifies the number of 647 * fractional bits. Negative values are allowed for either INTEGER 648 * or FRACTION (but not both). <p> 649 * 650 * This format supports the specification of either signed or 651 * unsigned values. The character 'U' must precede the 652 * integer.fraction format to specify an unsigned value. An 'S' character 653 * may be applied to specify a signed number. If no 'U' or 'S' 654 * signed specification is provided, the precision will default 655 * to a signed value. <p> 656 * 657 * The exponent in this format is set to -fraction. 658 * <p> 659 * Parenthesis or brackets are optional around this specification. 660 * 661 * Examples: 662 * <ul> 663 * <li> (3.5) 664 * <li> (U2.1) 665 * <li> [S2.1] 666 * <li> [S6.-2] 667 * <li> S-2.4 668 * </ul> 669 * 670 * When printed, this format will always use parenthesis and 671 * only use the signed format specification for unsigned numbers 672 * (i.e. 'U' used for unsigned numbers and NO 'S' for signed 673 * numbers). 674 * 675 */ 676 public static class IntegerFractionPrecisionFormat extends PrecisionFormat { 677 678 /** Regular expression for IntegerFractionPrecisionFormat. 679 * Example: (S3.2) */ 680 protected final static String _regex = OPTIONAL_WHITE_SPACE 681 + OPTIONAL_L_PARANBRACKET + OPTIONAL_WHITE_SPACE 682 + OPTIONAL_U_OR_S_GROUP + OPTIONAL_WHITE_SPACE 683 + SIGNED_INTEGER_GROUP + PERIOD + SIGNED_INTEGER_GROUP 684 + OPTIONAL_WHITE_SPACE + OPTIONAL_R_PARANBRACKET 685 + OPTIONAL_WHITE_SPACE; 686 687 @Override 688 public Precision parseString(String str) 689 throws IllegalArgumentException { 690 int sign = 1; 691 int intLength = 0; 692 int fracLength = 0; 693 Matcher matcher; 694 695 matcher = Pattern.compile(_regex).matcher(str); 696 697 if (matcher.matches()) { 698 String signString = matcher.group(1); 699 700 if (signString != null) { 701 sign = parseSignString(signString); 702 } 703 704 intLength = parseInteger(matcher.group(2)); 705 fracLength = parseInteger(matcher.group(3)); 706 707 int length = fracLength + intLength; 708 int exponent = -fracLength; 709 710 if (length < 1) { 711 throw new IllegalArgumentException("Precision format " 712 + " must be at least 1 bit:" + str); 713 } 714 715 return new Precision(sign, length, exponent); 716 } 717 718 return null; 719 } 720 721 @Override 722 public String printPrecisionFormat(Precision p) { 723 String sign = p.isSigned() ? "" : "U"; 724 return "(" + sign + p.getIntegerBitLength() + "." 725 + p.getFractionBitLength() + ")"; 726 } 727 } 728 729 /** Defines a Precision string format using the LENGTH/INTEGER 730 * precision format. The LENGTH value specifies the length 731 * of the format in bits. The INTEGER field specifies the 732 * number of integer bits (i.e. bits to the left of the 733 * binary point). Negative values are allowed for the INTEGER 734 * field. <p> 735 * 736 * The exponent in this format is set to -(length - integer); 737 * <p> 738 * 739 * This format supports the specification of either signed or 740 * unsigned values. The character 'U' must precede the 741 * LENGTH/INTEGER format to specify an unsigned value. An 'S' character 742 * may be applied to specify a signed number. If no 'U' or 'S' 743 * signed specification is provided, the precision will default 744 * to a signed value. <p> 745 * 746 * Parenthesis or brackets are optional around this specification. 747 * A comma (,) may be used in place of the slash ('/'). 748 * 749 * Examples: 750 * <ul> 751 * <li> (3/2) 752 * <li> (U5/0) 753 * <li> [8,-2] 754 * <li> [S6,6] 755 * <li> S8/4 756 * </ul> 757 * 758 * When printed, this format will always use parenthesis, always 759 * use the slash '/', and 760 * only use the signed format specification for unsigned numbers 761 * (i.e. 'U' used for unsigned numbers and NO 'S' for signed 762 * numbers). 763 * 764 */ 765 public static class LengthIntegerPrecisionFormat extends PrecisionFormat { 766 /** Regular expression for IntegerFractionPrecisionFormat. 767 * Example (S3,2) or (S3/2) */ 768 protected final static String _regex = OPTIONAL_WHITE_SPACE 769 + OPTIONAL_L_PARANBRACKET + OPTIONAL_WHITE_SPACE 770 + OPTIONAL_U_OR_S_GROUP + OPTIONAL_WHITE_SPACE 771 + UNSIGNED_INTEGER_GROUP + COMMA_OR_FORWARDSLASH 772 + OPTIONAL_WHITE_SPACE + SIGNED_INTEGER_GROUP 773 + OPTIONAL_WHITE_SPACE + OPTIONAL_R_PARANBRACKET 774 + OPTIONAL_WHITE_SPACE; 775 776 @Override 777 public Precision parseString(String str) 778 throws IllegalArgumentException { 779 int sign = 1; 780 int intLength = 0; 781 int length = 0; 782 Matcher matcher; 783 784 matcher = Pattern.compile(_regex).matcher(str); 785 786 if (matcher.matches()) { 787 String signString = matcher.group(1); 788 789 if (signString != null) { 790 sign = parseSignString(signString); 791 } 792 793 length = parseInteger(matcher.group(2)); 794 intLength = parseInteger(matcher.group(3)); 795 796 int exponent = -(length - intLength); 797 798 if (length < 1) { 799 throw new IllegalArgumentException("Precision format " 800 + "must be at least 1 bit:" + str); 801 } 802 803 return new Precision(sign, length, exponent); 804 } 805 806 return null; 807 } 808 809 @Override 810 public String printPrecisionFormat(Precision p) { 811 String sign = p.isSigned() ? "" : "U"; 812 return "(" + sign + p.getNumberOfBits() + "/" 813 + p.getIntegerBitLength() + ")"; 814 } 815 } 816 817 /** Precision format for use with the Expression Language. */ 818 public static class ExpressionLanguagePrecisionFormat 819 extends LengthIntegerPrecisionFormat { 820 /** Regular expression for ExpressionLanguagePrecisionFormat. 821 * For example: (3,2). 822 */ 823 @Override 824 public String printPrecisionFormat(Precision p) { 825 return "(" + p.getNumberOfBits() + "," + p.getIntegerBitLength() 826 + ")"; 827 } 828 } 829 830 /** Defines a Precision string format using the LENGTHeEXPONENT 831 * precision format. The LENGTH value specifies the length 832 * of the format in bits and the EXPONENT specifies the 833 * location of the exponent. Negative values are allowed for the 834 * EXPONENT field. <p> 835 * 836 * This format supports the specification of either signed or 837 * unsigned values. The character 'U' must precede the 838 * LENGTH/INTEGER format to specify an unsigned value. An 'S' character 839 * may be applied to specify a signed number. If no 'U' or 'S' 840 * signed specification is provided, the precision will default 841 * to a signed value. <p> 842 * 843 * Parenthesis or brackets are optional around this specification. 844 * 845 * Examples: 846 * <ul> 847 * <li> (3e2) 848 * <li> (U5e0) 849 * <li> [8e-2] 850 * <li> [S6e6] 851 * <li> S8e-4 852 * </ul> 853 * 854 * When printed, this format will always use parenthesis and 855 * only use the signed format specification for unsigned numbers 856 * (i.e. 'U' used for unsigned numbers and NO 'S' for signed 857 * numbers). 858 * 859 */ 860 public static class LengthExponentPrecisionFormat extends PrecisionFormat { 861 /** Regular expression for IntegerFractionPrecisionFormat. 862 * Example (S3e2) */ 863 protected final String _regex = OPTIONAL_WHITE_SPACE 864 + OPTIONAL_L_PARANBRACKET + OPTIONAL_WHITE_SPACE 865 + OPTIONAL_U_OR_S_GROUP + OPTIONAL_WHITE_SPACE 866 + UNSIGNED_INTEGER_GROUP + "e" + SIGNED_INTEGER_GROUP 867 + OPTIONAL_WHITE_SPACE + OPTIONAL_R_PARANBRACKET 868 + OPTIONAL_WHITE_SPACE; 869 870 @Override 871 public Precision parseString(String str) 872 throws IllegalArgumentException { 873 int sign = 1; 874 int exponent = 0; 875 int length = 0; 876 Matcher matcher; 877 878 matcher = Pattern.compile(_regex).matcher(str); 879 880 if (matcher.matches()) { 881 String signString = matcher.group(1); 882 883 if (signString != null) { 884 sign = parseSignString(signString); 885 } 886 887 length = parseInteger(matcher.group(2)); 888 exponent = parseInteger(matcher.group(3)); 889 890 if (length < 1) { 891 throw new IllegalArgumentException("Precision format " 892 + "must be at least 1 bit:" + str); 893 } 894 895 return new Precision(sign, length, exponent); 896 } 897 898 return null; 899 } 900 901 @Override 902 public String printPrecisionFormat(Precision p) { 903 String sign = p.isSigned() ? "" : "U"; 904 return "(" + sign + p.getNumberOfBits() + "e" + p.getExponent() 905 + ")"; 906 } 907 } 908 909 /** Defines a Precision string format using the VHDL MSB:LSB 910 * precision format. The MSB value specifies the location 911 * of the most significant bit and LSB specifies the location 912 * of the least significant bit. 913 * Negative values are allowed for both MSB and LSB so long as 914 * the MSB is greater than the LSB. <p> 915 * 916 * This format supports the specification of either signed or 917 * unsigned values. The character 'U' must precede the 918 * MSB:LSB format to specify an unsigned value. An 'S' character 919 * may be applied to specify a signed number. If no 'U' or 'S' 920 * signed specification is provided, the precision will default 921 * to a signed value. <p> 922 * 923 * Parenthesis or brackets are optional around this specification. 924 * 925 * Examples: 926 * <ul> 927 * <li> (2:3) 928 * <li> (4:-3) 929 * <li> [7:0] 930 * <li> [-3:-8] 931 * <li> 4:3 932 * </ul> 933 * 934 * When printed, this format will always use parenthesis and 935 * only use the signed format specification for unsigned numbers 936 * (i.e. 'U' used for unsigned numbers and NO 'S' for signed 937 * numbers). 938 * 939 */ 940 public static class VHDLPrecisionFormat extends PrecisionFormat { 941 /** Regular expression for IntegerFractionPrecisionFormat. 942 * Example ([US]{digit}:{digit}) */ 943 protected final String _regex = OPTIONAL_WHITE_SPACE + OPTIONAL_L_PARAN 944 + OPTIONAL_WHITE_SPACE + OPTIONAL_U_OR_S_GROUP 945 + OPTIONAL_WHITE_SPACE + SIGNED_INTEGER_GROUP 946 + OPTIONAL_WHITE_SPACE + ":" + OPTIONAL_WHITE_SPACE 947 + SIGNED_INTEGER_GROUP + OPTIONAL_WHITE_SPACE + OPTIONAL_R_PARAN 948 + OPTIONAL_WHITE_SPACE; 949 950 @Override 951 public Precision parseString(String str) { 952 int sign = 1; 953 int msb = 0; 954 int lsb = 0; 955 Matcher matcher; 956 957 matcher = Pattern.compile(_regex).matcher(str); 958 959 if (matcher.matches()) { 960 String signString = matcher.group(1); 961 962 if (signString != null) { 963 sign = parseSignString(signString); 964 } 965 966 msb = parseInteger(matcher.group(2)); 967 lsb = parseInteger(matcher.group(3)); 968 969 if (msb <= lsb) { 970 throw new IllegalArgumentException("MSb of VHDL " 971 + "format must be greater than LSb:" + str); 972 } 973 974 int length = msb - lsb + 1; 975 int exponent = lsb; 976 return new Precision(sign, length, exponent); 977 } 978 979 return null; 980 } 981 982 @Override 983 public String printPrecisionFormat(Precision p) { 984 String sign = p.isSigned() ? "" : "U"; 985 return "(" + sign + p.getMostSignificantBitPosition() + ":" 986 + p.getLeastSignificantBitPosition() + ")"; 987 } 988 } 989 990 /////////////////////////////////////////////////////////////////// 991 //// public variables //// 992 993 /** 994 * static IntegerFractionPrecisionFormat object. 995 */ 996 public final static PrecisionFormat INTEGER_FRACTION = new IntegerFractionPrecisionFormat(); 997 998 /** 999 * static LengthExponentPrecisionFormat object. 1000 */ 1001 public final static PrecisionFormat LENGTH_EXPONENT = new LengthExponentPrecisionFormat(); 1002 1003 /** 1004 * static LengthIntegerPrecisionFormat object. 1005 */ 1006 public final static PrecisionFormat LENGTH_INTEGER = new LengthIntegerPrecisionFormat(); 1007 1008 /** 1009 * static ExpressionLanguagePrecisionFormat object. 1010 */ 1011 public final static PrecisionFormat EXPRESSION_LANGUAGE = new ExpressionLanguagePrecisionFormat(); 1012 1013 /** 1014 * static VHDLPrecisionFormat object. 1015 */ 1016 public final static PrecisionFormat VHDL = new VHDLPrecisionFormat(); 1017 1018 /////////////////////////////////////////////////////////////////// 1019 //// private methods //// 1020 1021 /** Get the BigDecimal which is the 2^exponent. If the value is 1022 * already calculated, return this cached value, else calculate 1023 * the value. 1024 * 1025 * @param number the exponent. 1026 * @return the BigDecimal representing 2^exponent. 1027 */ 1028 private static BigDecimal _getTwoRaisedTo(int number) { 1029 // Since this is a private method we know that number is positive. 1030 if (number < _twoRaisedTo.length) { 1031 return _twoRaisedTo[number]; 1032 } else { 1033 return new BigDecimal(BigInteger.ZERO.setBit(number)); 1034 } 1035 } 1036 1037 /////////////////////////////////////////////////////////////////// 1038 //// private variables //// 1039 1040 /** The total number of bits. */ 1041 private int _length = 0; 1042 1043 /** The exponent for all values of this type. */ 1044 private int _exponent = 0; 1045 1046 /** The presence of a sign bit (0 = unsigned, 1 = signed) */ 1047 private int _sign = 0; 1048 1049 /** The precision format used for parsing/printing precision information. 1050 */ 1051 private PrecisionFormat _format = INTEGER_FRACTION; 1052 1053 /////////////////////////////////////////////////////////////////// 1054 //// static variables //// 1055 1056 /** The size of the pre-computed _twoRaisedTo powers of two array. 1057 * 65 entries are used to cache all powers of 2 from 0 to 64. 1058 **/ 1059 private static final int TWORAISEDTOSIZE = 64 + 1; 1060 1061 /** Calculate the table containing 2^x, with 0 <= x < TWORAISEDTOSIZE. 1062 * Purpose is to speed up calculations involving calculating 1063 * 2^x. The table is calculated using BigDecimal, since this 1064 * make the transformation from string of bits to a double 1065 * easier. 1066 **/ 1067 private static BigDecimal[] _twoRaisedTo = new BigDecimal[TWORAISEDTOSIZE]; 1068 1069 /////////////////////////////////////////////////////////////////// 1070 //// static initializers //// 1071 static { 1072 BigDecimal powerOf2 = BigDecimal.valueOf(1); 1073 1074 for (int i = 0; i < _twoRaisedTo.length; i++) { 1075 _twoRaisedTo[i] = powerOf2; 1076 powerOf2 = powerOf2.add(powerOf2); 1077 } 1078 } 1079 1080}