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.math.BigInteger;
032
033/**
034 The Quantization class defines the mapping of numeric values with unlimited
035 precision to finite precision.
036 <p>
037 It comprises a
038 <ul>
039 <li>
040 <i>precision</i>: to define the accuracy of the finite precision numbers.
041 <li>
042 <b>Overflow</b>: to define the treatment of out-of-range numbers.
043 <li>
044 <b>Rounding</b>: to define the loss of precision for in-range numbers.
045 </ul>
046 The way in which <i>precision</i> is realised is a sub-class
047 responsibility. The standard fixed point binary functionality using a
048 Precision is provided by FixPointQuantization.
049 <p>
050 This abstract class is designed to support specification of required
051 numeric behavior through use of the yet-to-be-written FloatingQuantization
052 and FixedQuantization classes. Knowledge of the required numeric behavior,
053 rather than precise specification of an exact implementation, provides an
054 opportunity for code generation to select appropriate types supported by a
055 target architecture.
056 <p>
057 FixedQuantization provides for <i>modulo</i> equi-spaced values between
058 the inclusive <i>maximum</i> and <i>minimum</i> limits. <i>epsilon</i>,
059 the separation between values is given by
060 <i>(maximum - minimum) / (modulo - 1)</i>. Whether values beyond the
061 <i>maximum</i> and <i>minimum</i> wrap-around is determined by the overflow
062 strategy. FixedQuantization therefore describes the requirements of a
063 single fixed point range comprising just a mantissa.
064 <p>
065 FloatingQuantization adds an exponent to support multiple
066 floating point ranges; <i>maximum</i> defines the upper limit of the
067 coarsest scale and <i>tiny</i> defines the smallest representable non-zero
068 number on the finest scale. (<i>tiny</i> is the same as <i>epsilon</i> for
069 FixedQuantization.)
070 <p>
071 If <i>exactRounding</i> is specified, code generation must ensure that
072 arithmetic rounds to the specified <i>epsilon</i>. Otherwise, the code
073 generator may use arithmetic with higher precision.
074 <p>
075 If <i>exactOverflow</i> is specified, code generation must ensure that
076 arithmetic overflows saturate or wrap-around at the specified
077 <i>maximum</i> and <i>minimum</i>. Otherwise, the code generator may use
078 arithmetic with greater range.
079 <p>
080 The active class functionality is provided by the quantize method, which
081 is normally invoked from FixPoint.quantize or ScalarToken.quantize
082 to enforce quantization constraints upon the result of an unconstrained
083 computation.
084 <p>
085 An instance of the class is immutable, meaning
086 that its value is set in the constructor and cannot then be modified.
087
088 @author Ed Willink
089 @version $Id$
090 @since Ptolemy II 2.1
091 @Pt.ProposedRating Red (Ed.Willink)
092 @Pt.AcceptedRating Red
093 @see ptolemy.math.FixPoint
094 @see ptolemy.math.FixPointQuantization
095 @see ptolemy.math.Precision
096 @see ptolemy.math.Overflow
097 @see ptolemy.math.Rounding
098 */
099public abstract class Quantization implements Cloneable {
100    /** Construct a Quantization with the given precision, overflow
101     *  strategy, and rounding strategy.
102     *
103     * @param overflow The Overflow object to use by this Quantization
104     * strategy.
105     * @param rounding The Rounding object to use by this Quantization
106     * strategy.
107     */
108    public Quantization(Overflow overflow, Rounding rounding) {
109        _overflow = overflow;
110        _rounding = rounding;
111    }
112
113    ///////////////////////////////////////////////////////////////////
114    ////                         public methods                    ////
115
116    /** Return this, that is, return the reference to this object.
117     *  @return This Quantization.
118     */
119    @Override
120    public Object clone() {
121        return this;
122    }
123
124    /** Return true if the indicated object describes the same
125     *  mapping to quantized values.
126     *
127     *  @param object The Quantization object to use for equality
128     *  checking.
129     *  @return True if the quantizations are equal.
130     */
131    @Override
132    public boolean equals(Object object) {
133        if (object instanceof Quantization) {
134            Quantization other = (Quantization) object;
135
136            if (_overflow.equals(other._overflow)
137                    && _rounding.equals(other._rounding)) {
138                return true;
139            }
140        }
141
142        return false;
143    }
144
145    /** Return the separation between quantized values.
146     *  @return The quantization interval.
147     */
148    public double getEpsilonValue() {
149        double maxVal = getMaximumValue();
150        double minVal = getMinimumValue();
151        double modVal = getNumberOfLevels();
152        return (maxVal - minVal) / (modVal - 1.0);
153    }
154
155    /** Return the overflow bit-truth.
156     *  @return True if overflow must occur at the <i>maximum</i> and
157     *  <i>minimum</i> values, false if greater range is acceptable.
158     */
159    public boolean getExactOverflow() {
160        return false;
161    }
162
163    /** Return the rounding bit-truth.
164     *  @return True if rounding must occur exactly at <i>epsilon</i>,
165     *  false if finer resolution is acceptable.
166     */
167    public boolean getExactRounding() {
168        return false;
169    }
170
171    /** Return the number of bits to represent the exponent.
172     *  @return The length of the exponent.
173     */
174    public int getExponentBitLength() {
175        return 0;
176    }
177
178    /** Return the number of bits representing the fractional part
179     *  of the mantissa.
180     *  @return The length of the fractional part of the mantissa.
181     */
182    public int getFractionBitLength() {
183        return getMantissaPrecision().getFractionBitLength();
184    }
185
186    /** Return the number of bits representing the integer part
187     *  of the mantissa.
188     *  @return The length of the integer part of the mantissa.
189     */
190    public int getIntegerBitLength() {
191        return getMantissaPrecision().getIntegerBitLength();
192    }
193
194    /** Return the number of bits to represent the mantissa.
195     *  @return The length of the mantissa.
196     */
197    public int getMantissaBitLength() {
198        return getIntegerBitLength() + getFractionBitLength();
199    }
200
201    /** Return the precision fore the mantissa of a compliant
202     *  2's complement representation.
203     *
204     *  @return The precision.
205     */
206    public abstract Precision getMantissaPrecision();
207
208    /** Return the maximum quantizable value after scaling so that
209     *  quantization levels are represented by adjacent integers.
210     *  @return The maximum inclusive value.
211     */
212    public BigInteger getMaximumUnscaledValue() {
213        int numBits = getNumberOfBits();
214        return BigInteger.ZERO.setBit(numBits - 1).subtract(BigInteger.ONE);
215    }
216
217    /** Return the maximum quantizable value.
218     *  @return The maximum inclusive value.
219     */
220    public double getMaximumValue() {
221        double maxVal = getMaximumUnscaledValue().doubleValue();
222        return maxVal * Math.pow(0.5, getFractionBitLength());
223    }
224
225    /** Return the minimum quantizable value after scaling so that
226     *  quantization levels are represented by adjacent integers.
227     *  @return The minimum inclusive value.
228     */
229    public BigInteger getMinimumUnscaledValue() {
230        int numBits = getNumberOfBits();
231        return BigInteger.ZERO.setBit(numBits - 1).negate();
232    }
233
234    /** Return the minimum quantizable value.
235     *  @return The minimum inclusive value.
236     */
237    public double getMinimumValue() {
238        double minVal = getMinimumUnscaledValue().doubleValue();
239        return minVal * Math.pow(0.5, getFractionBitLength());
240    }
241
242    /** Return the modulo quantization range after scaling so that
243     *  quantization levels are represented by adjacent integers.
244     *  This is the same as the number of quantization levels in
245     *  the mantissa..
246     *  @return The modulo value.
247     *  @deprecated  ?
248     */
249    @Deprecated
250    public BigInteger getModuloUnscaledValue() {
251        int numBits = getNumberOfBits();
252        return BigInteger.ZERO.setBit(numBits);
253    }
254
255    /** Return the number of bits to represent the value.
256     *  @return The number of bits.
257     */
258    public int getNumberOfBits() {
259        return getMantissaBitLength() + getExponentBitLength();
260    }
261
262    /** Return the number of quantization levels in the mantissa.
263     *  @return The number of levels.
264     */
265    public double getNumberOfLevels() {
266        return Math.pow(2.0, getMantissaBitLength());
267    }
268
269    /** Return the overflow strategy.
270     *  @return The overflow strategy.
271     */
272    public Overflow getOverflow() {
273        return _overflow;
274    }
275
276    /** Return the Precision.
277     *
278     * @return The Precision object.
279     */
280    public abstract Precision getPrecision();
281
282    /** Return the rounding strategy.
283     *  @return The rounding strategy.
284     */
285    public Rounding getRounding() {
286        return _rounding;
287    }
288
289    /** Return the quantizable value nearest to and above zero.
290     *  @return The positive value nearest to zero.
291     */
292    public double getTinyValue() {
293        return getEpsilonValue();
294    }
295
296    /** Return a hash code value for this Quantization. This method returns the
297     *  bitwise and of the hashcode of the overflow and the hashcode of
298     *  the rounding.
299     *  @return A hash code value for this Quantization.
300     */
301    @Override
302    public int hashCode() {
303        return _overflow.hashCode() & _rounding.hashCode();
304    }
305
306    /** Return a string representing this quantization.
307     *  @return A string representing this quantization.
308     */
309    @Override
310    public abstract String toString();
311
312    ///////////////////////////////////////////////////////////////////
313    ////                         private variables                 ////
314
315    /** The overflow strategy. */
316    protected Overflow _overflow = Overflow.GENERAL;
317
318    /** The rounding strategy. */
319    protected Rounding _rounding = Rounding.GENERAL;
320}