KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > value > NumericValue


1 package net.sf.saxon.value;
2 import net.sf.saxon.expr.XPathContext;
3 import net.sf.saxon.trans.XPathException;
4 import net.sf.saxon.type.ItemType;
5 import net.sf.saxon.type.Type;
6
7 /**
8  * NumericValue is an abstract superclass for IntegerValue, DecimalValue,
9  * FloatValue, and DoubleValue
10  */

11
12 public abstract class NumericValue extends AtomicValue implements Comparable JavaDoc {
13
14     /**
15      * Get a numeric value by parsing a string; the type of numeric value depends
16      * on the lexical form of the string, following the rules for XPath numeric
17      * literals.
18      * @param in the input string
19      * @return a NumericValue representing the value of the string. Returns Double.NaN if the
20      * value cannot be parsed as a string.
21      */

22
23     public static NumericValue parseNumber(String JavaDoc in) {
24         if (in.indexOf('e') >= 0 || in.indexOf('E') >= 0) {
25             return new DoubleValue(Double.parseDouble(in));
26         } else if (in.indexOf('.') >= 0) {
27             AtomicValue v = DecimalValue.makeDecimalValue(in, true);
28             if (v instanceof ValidationErrorValue) {
29                 return DoubleValue.NaN;
30             } else {
31                 return (NumericValue)v;
32             }
33         } else {
34             AtomicValue v = IntegerValue.stringToInteger(in);
35             if (v instanceof ValidationErrorValue) {
36                 return DoubleValue.NaN;
37             } else {
38                 return (NumericValue)v;
39             }
40         }
41     }
42     /**
43      * Get the numeric value as a double
44      *
45      * @return A double representing this numeric value; NaN if it cannot be
46      * converted
47      */

48     public double getDoubleValue() {
49         try {
50             return ((DoubleValue)convert(Type.DOUBLE, null)).getDoubleValue();
51         } catch (XPathException err) {
52             return Double.NaN;
53         }
54     }
55
56     /**
57      * Test whether the value is the double/float value NaN
58      */

59
60     public boolean isNaN() {
61         return false;
62     }
63
64     /**
65      * Test whether the value is an integer (an instance of a subtype of xs:integer)
66      */

67
68     public static boolean isInteger(AtomicValue value) {
69         if (value instanceof IntegerValue) {
70             return true;
71         } else if (value instanceof BigIntegerValue) {
72             return true;
73         } else if (!value.hasBuiltInType() && NumericValue.isInteger(value.getPrimitiveValue())) {
74             return true;
75         }
76         return false;
77     }
78
79     /**
80      * Return the numeric value as a Java long.
81      *
82      * @exception net.sf.saxon.trans.XPathException if the value cannot be converted
83      * @return the numeric value as a Java long. This performs truncation
84      * towards zero.
85      */

86     public long longValue() throws XPathException {
87         return ((IntegerValue)convert(Type.INTEGER, null)).longValue();
88     }
89
90     /**
91      * Change the sign of the number
92      *
93      * @return a value, of the same type as the original, with its sign
94      * inverted
95      */

96
97     public abstract NumericValue negate();
98
99     /**
100      * Implement the XPath floor() function
101      *
102      * @return a value, of the same type as that supplied, rounded towards
103      * minus infinity
104      */

105
106     public abstract NumericValue floor();
107
108     /**
109      * Implement the XPath ceiling() function
110      *
111      * @return a value, of the same type as that supplied, rounded towards
112      * plus infinity
113      */

114
115     public abstract NumericValue ceiling();
116
117     /**
118      * Implement the XPath round() function
119      *
120      * @return a value, of the same type as that supplied, rounded towards the
121      * nearest whole number (0.5 rounded up)
122      */

123
124     public abstract NumericValue round();
125
126     /**
127      * Implement the XPath 2.0 round-to-half-even() function
128      *
129      * @param scale the decimal position for rounding: e.g. 2 rounds to a
130      * multiple of 0.01, while -2 rounds to a multiple of 100
131      * @return a value, of the same type as the original, rounded towards the
132      * nearest multiple of 10**(-scale), with rounding towards the nearest
133      * even number if two values are equally near
134      */

135
136     public abstract NumericValue roundToHalfEven(int scale);
137
138     /**
139      * Determine whether the value is negative, zero, or positive
140      * @return -1 if negative, 0 if zero (including negative zero), +1 if positive, NaN if NaN
141      */

142
143     public abstract double signum();
144
145     /**
146      * Perform a binary arithmetic operation
147      *
148      * @param operator the binary arithmetic operation to be performed. Uses
149      * the constants defined in the Tokenizer class
150      * @param other the other operand
151      * @exception XPathException if an arithmetic error occurs
152      * @return the result of the arithmetic operation
153      * @see net.sf.saxon.expr.Tokenizer
154      */

155
156     public abstract NumericValue arithmetic(int operator, NumericValue other, XPathContext context)
157     throws XPathException;
158
159     /**
160      * Determine whether the value is a whole number, that is, whether it compares
161      * equal to some integer
162      *
163      * @return true if the value is a whole number
164      */

165
166     public abstract boolean isWholeNumber();
167
168     /**
169      * Compare the value to another numeric value
170      *
171      * @exception ClassCastException if the other value is not a NumericValue
172      * (the parameter is declared as Object to satisfy the Comparable
173      * interface)
174      * @param other The other numeric value
175      * @return -1 if this one is the lower, 0 if they are numerically equal,
176      * +1 if this one is the higher.
177      */

178
179     // This is the default implementation. Subclasses of number avoid the conversion to double
180
// when comparing with another number of the same type.
181

182     public int compareTo(Object JavaDoc other) {
183         if (other instanceof AtomicValue && !((AtomicValue)other).hasBuiltInType()) {
184             return compareTo(((AtomicValue)other).getPrimitiveValue());
185         }
186         if (!(other instanceof NumericValue)) {
187             throw new ClassCastException JavaDoc("Numeric values are not comparable to " + other.getClass());
188         }
189         double a = this.getDoubleValue();
190         double b = ((NumericValue)other).getDoubleValue();
191         if (a == b) return 0;
192         if (a < b) return -1;
193         return +1;
194     }
195
196     /**
197      * The equals() function compares numeric equality among integers, decimals, floats, doubles, and
198      * their subtypes
199      *
200      * @param other the value to be compared with this one
201      * @return true if the two values are numerically equal
202      */

203
204     public final boolean equals(Object JavaDoc other) {
205         return compareTo(other) == 0;
206         // Note: this is implementing the XPath definition of equality, not the XML Schema definition.
207
// However, the equals() function is probably used largely for XML Schema comparisons...
208
}
209
210     /**
211      * Identify lowest common supertype of two numeric values for promotion purposes
212      *
213      * @param v1 the item type of the first operand
214      * @param v2 the item type of the second operand
215      * @return the item type that should be used for arithmetic between
216      * operands of the two specified item types
217      */

218
219     public static ItemType promote(ItemType v1, ItemType v2) {
220         ItemType t1 = (Type.isSubType(v1, Type.NUMBER_TYPE) ? v1 : Type.DOUBLE_TYPE);
221         ItemType t2 = (Type.isSubType(v2, Type.NUMBER_TYPE) ? v2 : Type.DOUBLE_TYPE);
222
223         if (t1 == t2) return t1;
224
225         if (t1 == Type.DOUBLE_TYPE || t2 == Type.DOUBLE_TYPE) {
226             return Type.DOUBLE_TYPE;
227         }
228
229         if (t1 == Type.FLOAT_TYPE || t2 == Type.FLOAT_TYPE) {
230             return Type.FLOAT_TYPE;
231         }
232
233         if (t1 == Type.DECIMAL_TYPE || t2 == Type.DECIMAL_TYPE) {
234             return Type.DECIMAL_TYPE;
235         }
236
237         return Type.INTEGER_TYPE;
238     }
239
240     /**
241      * hashCode() must be the same for two values that are equal. One
242      * way to ensure this is to convert the value to a double, and take the
243      * hashCode of the double. But this is expensive in the common case where
244      * we are comparing integers. So we adopt the rule: for values that are in
245      * the range of a Java Integer, we use the int value as the hashcode. For
246      * values outside that range, we convert to a double and take the hashCode of
247      * the double. This method needs to have a compatible implementation in
248      * each subclass.
249      *
250      * @return the hash code of the numeric value
251      */

252
253     public abstract int hashCode();
254
255     /**
256      * Produce a string representation of the value
257      * @return The result of casting the number to a string
258      */

259     public String JavaDoc toString() {
260         return getStringValue();
261     }
262
263 }
264
265 //
266
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
267
// you may not use this file except in compliance with the License. You may obtain a copy of the
268
// License at http://www.mozilla.org/MPL/
269
//
270
// Software distributed under the License is distributed on an "AS IS" basis,
271
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
272
// See the License for the specific language governing rights and limitations under the License.
273
//
274
// The Original Code is: all this file.
275
//
276
// The Initial Developer of the Original Code is Saxonica Limited
277
//
278
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
279
//
280
// Contributor(s): none
281
//
Popular Tags