001/** A class defining quantization to a FixPoint number. 002 003 Copyright (c) 2002-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.util.StringTokenizer; 032 033/** 034 The FixPointQuantization class defines the mapping of numeric values 035 with unlimited precision to the finite precision supported by arithmetic 036 using the FixPoint class. 037 <p> 038 It comprises a 039 <ul> 040 <li> 041 <b>Precision</b>: to define the accuracy of the finite precision numbers. 042 <li> 043 <b>Overflow</b>: to define the treatment of out-of-range numbers. 044 <li> 045 <b>Rounding</b>: to define the loss of precision for in-range numbers. 046 </ul> 047 The active class functionality is provided by the quantize method, which 048 is normally invoked from FixPoint.quantize to enforce quantization 049 constraints upon the result of an unconstrained computation. 050 <p> 051 An instance of the class is immutable, meaning 052 that its value is set in the constructor and cannot then be modified. 053 054 @author Ed Willink 055 @version $Id$ 056 @since Ptolemy II 2.1 057 @Pt.ProposedRating Red (Ed.Willink) 058 @Pt.AcceptedRating Red 059 @see ptolemy.math.FixPoint 060 @see ptolemy.math.Precision 061 @see ptolemy.math.Overflow 062 @see ptolemy.math.Rounding 063 */ 064public class FixPointQuantization extends Quantization { 065 /** Construct a FixPointQuantization object based on the provided 066 * string. The string may consist of just <i>precision</i> or 067 * <i>precision, overflow</i> or 068 * <i>precision, overflow, rounding</i>, and may optionally be 069 * enclosed in parentheses. 070 * 071 * <p> <i>precision</i> must be one of the Precision formats; 072 * <i>integer-bits.fraction-bits</i> or 073 * <i>total-bits/integer-bits</i>. 074 * 075 * <p> <i>overflow</i> must be 076 * one of the Overflow strategies; e.g. <i>saturate</i> or 077 * <i>modulo</i> or <i>trap</i>. The default is <i>saturate</i>. 078 * 079 * <p> <i>rounding</i> must be one 080 * of the Rounding strategies; e.g. <i>up</i> or <i>half_even</i> 081 * or <i>unnecessary</i>. The default is <i>nearest</i>. 082 * 083 * 084 * @param string The string representing the 085 * quantization specification. 086 * @exception IllegalArgumentException If the precision string 087 * supplied, overflow strategy or rounding strategy does not 088 * match one of the known formats. 089 */ 090 public FixPointQuantization(String string) throws IllegalArgumentException { 091 super(Overflow.SATURATE, Rounding.NEAREST); 092 093 int strLen = string.length(); 094 095 if (strLen >= 2 && string.charAt(0) == '(' 096 && string.charAt(strLen - 1) == ')') { 097 string = string.substring(1, strLen - 1); 098 } 099 100 StringTokenizer st = new StringTokenizer(string, ","); 101 102 if (!st.hasMoreTokens()) { 103 throw new IllegalArgumentException("A precision string" 104 + " consisting of two integers separated " 105 + " by a '/', or '.' token is required"); 106 } 107 108 _precision = new Precision(st.nextToken()); 109 110 if (st.hasMoreTokens()) { 111 _overflow = Overflow.getName(st.nextToken()); 112 } 113 114 if (st.hasMoreTokens()) { 115 _rounding = Rounding.getName(st.nextToken()); 116 } 117 118 if (st.hasMoreTokens()) { 119 throw new IllegalArgumentException("FixPointQuantization " 120 + "requires at most a precision overflow and rounding,"); 121 } 122 } 123 124 /** Construct a FixPointQuantization with specified precision, overflow 125 * and rounding. 126 * 127 * @param precision The precision. 128 * @param overflow The overflow. 129 * @param rounding The rounding. 130 */ 131 public FixPointQuantization(Precision precision, Overflow overflow, 132 Rounding rounding) { 133 super(overflow, rounding); 134 _precision = precision; 135 } 136 137 /////////////////////////////////////////////////////////////////// 138 //// public methods //// 139 140 /** Return true if the given object describes the same 141 * mapping to quantized values as this object. 142 * 143 * @param object The FixPointQuantization object to use for equality 144 * checking. 145 * @return True if the quantizations are equal. 146 */ 147 @Override 148 public boolean equals(Object object) { 149 if (super.equals(object) && object instanceof FixPointQuantization) { 150 FixPointQuantization other = (FixPointQuantization) object; 151 152 if (_precision.equals(other._precision)) { 153 return true; 154 } 155 } 156 157 return false; 158 } 159 160 /** Return the precision of the mantissa of the value. 161 * @return The precision. 162 */ 163 @Override 164 public Precision getMantissaPrecision() { 165 return _precision; 166 } 167 168 /** 169 * Return the precision. 170 * 171 * @see #setPrecision(Precision) 172 * @return Precision object. 173 */ 174 @Override 175 public Precision getPrecision() { 176 return _precision; 177 } 178 179 /** Return a hash code value for this FixPointQuantization. This 180 * method returns the bitwise xor of the hashcode of the 181 * superclass (Quantization) and the hashcode of the precision. 182 * @return A hash code value for this Quantization. 183 */ 184 @Override 185 public int hashCode() { 186 return super.hashCode() >>> _precision.hashCode(); 187 } 188 189 /** Return a FixPointQuantization with a changed overflow strategy. 190 * @param overflow The new overflow strategy. 191 * @return A new quantization. 192 */ 193 public FixPointQuantization setOverflow(Overflow overflow) { 194 return new FixPointQuantization(_precision, overflow, getRounding()); 195 } 196 197 /** Return a FixPointQuantization with a changed precision. 198 * 199 * @see #getPrecision() 200 * @param precision The new precision. 201 * @return A new quantization. 202 */ 203 public FixPointQuantization setPrecision(Precision precision) { 204 return new FixPointQuantization(precision, getOverflow(), 205 getRounding()); 206 } 207 208 /** Return a FixPointQuantization with a changed rounding strategy. 209 * @param rounding The new rounding.strategy. 210 * @return A new quantization. 211 */ 212 public FixPointQuantization setRounding(Rounding rounding) { 213 return new FixPointQuantization(_precision, getOverflow(), rounding); 214 } 215 216 /** Return a string representing this quantization. The string is 217 * expressed as "(<i>m.n, o, p</i>)", where <i>m</i> 218 * indicates the number of integer bits, <i>n</i> represents 219 * the number of fractional bits and <i>o</i> represents 220 * the overflow strategy and <i>r</i> represents 221 * the rounding strategy. 222 * @return A string representing this quantization. 223 */ 224 @Override 225 public String toString() { 226 // TODO: check for null precision 227 return "(" + _precision.getIntegerBitLength() + "." 228 + _precision.getFractionBitLength() + "," 229 + getOverflow().toString() + "," + getRounding().toString() 230 + ")"; 231 } 232 233 /////////////////////////////////////////////////////////////////// 234 //// private variables //// 235 236 /** The precision. */ 237 protected Precision _precision = null; 238}