1 package net.sf.saxon.value; 2 import net.sf.saxon.Err; 3 import net.sf.saxon.ConversionContext; 4 import net.sf.saxon.expr.Token; 5 import net.sf.saxon.expr.XPathContext; 6 import net.sf.saxon.trans.DynamicError; 7 import net.sf.saxon.trans.XPathException; 8 import net.sf.saxon.type.BuiltInAtomicType; 9 import net.sf.saxon.type.ItemType; 10 import net.sf.saxon.type.Type; 11 import net.sf.saxon.type.ValidationException; 12 13 import java.math.BigDecimal ; 14 15 18 19 public final class FloatValue extends NumericValue { 20 private float value; 21 22 25 26 public FloatValue(CharSequence val) throws DynamicError { 27 try { 28 this.value = (float)Value.stringToNumber(val); 29 } catch (NumberFormatException e) { 30 throw new DynamicError("Cannot convert string " + Err.wrap(val, Err.VALUE) + " to a float"); 31 } 32 } 33 34 38 39 public FloatValue(float value) { 40 this.value = value; 41 } 42 43 46 47 public float getValue() { 48 return value; 49 } 50 51 public double getDoubleValue() { 52 return (double)value; 53 } 54 55 59 60 public int hashCode() { 61 if (value > Integer.MIN_VALUE && value < Integer.MAX_VALUE) { 62 return (int)value; 63 } else { 64 return new Double (this.getDoubleValue()).hashCode(); 65 } 66 } 67 68 71 72 public boolean isNaN() { 73 return Float.isNaN(value); 74 } 75 76 81 public boolean effectiveBooleanValue(XPathContext context) { 82 return (value!=0.0 && !Float.isNaN(value)); 83 } 84 85 91 92 public AtomicValue convertPrimitive(BuiltInAtomicType requiredType, boolean validate, ConversionContext conversion) { 93 switch(requiredType.getPrimitiveType()) { 94 case Type.BOOLEAN: 95 return BooleanValue.get(value!=0.0 && !Float.isNaN(value)); 96 case Type.FLOAT: 97 case Type.NUMBER: 98 case Type.ATOMIC: 99 case Type.ITEM: 100 return this; 101 case Type.INTEGER: 102 if (Float.isNaN(value)) { 103 ValidationException err = new ValidationException("Cannot convert float NaN to an integer"); 104 err.setErrorCode("FORG0001"); 105 return new ValidationErrorValue(err); 107 } 108 if (Float.isInfinite(value)) { 109 ValidationException err = new ValidationException("Cannot convert float infinity to an integer"); 110 err.setErrorCode("FORG0001"); 111 return new ValidationErrorValue(err); 113 } 114 if (value > Long.MAX_VALUE || value < Long.MIN_VALUE) { 115 return new BigIntegerValue(new BigDecimal (value).toBigInteger()); 116 } 117 return new IntegerValue((long)value); 118 case Type.DECIMAL: 119 try { 120 return new DecimalValue(value); 121 } catch (ValidationException e) { 122 return new ValidationErrorValue(e); 123 } 124 case Type.DOUBLE: 125 return new DoubleValue((double)value); 126 case Type.STRING: 127 return new StringValue(getStringValueCS()); 128 case Type.UNTYPED_ATOMIC: 129 return new UntypedAtomicValue(getStringValueCS()); 130 default: 131 ValidationException err = new ValidationException("Cannot convert float to " + 132 requiredType.getDisplayName()); 133 err.setErrorCode("FORG0001"); 135 return new ValidationErrorValue(err); 136 } 137 } 138 139 140 144 145 public String getStringValue() { 146 return DoubleValue.doubleToString((double)value, Float.toString(value)); 147 } 148 149 153 154 public ItemType getItemType() { 155 return Type.FLOAT_TYPE; 156 } 157 158 161 162 public NumericValue negate() { 163 return new FloatValue(-value); 164 } 165 166 169 170 public NumericValue floor() { 171 return new FloatValue((float)Math.floor(value)); 172 } 173 174 177 178 public NumericValue ceiling() { 179 return new FloatValue((float)Math.ceil(value)); 180 } 181 182 185 186 public NumericValue round() { 187 if (Float.isNaN(value)) return this; 188 if (Float.isInfinite(value)) return this; 189 if (value==0.0) return this; if (value > -0.5 && value < 0.0) return new DoubleValue(-0.0); 191 if (value > Integer.MIN_VALUE && value < Integer.MAX_VALUE) { 192 return new FloatValue((float)Math.round(value)); 193 } 194 195 199 return this; 200 } 201 202 205 206 public NumericValue roundToHalfEven(int scale) { 207 try { 208 return (FloatValue)new DoubleValue((double)value).roundToHalfEven(scale).convert(Type.FLOAT, null); 209 } catch (XPathException err) { 210 throw new AssertionError (err); 211 } 212 } 213 214 218 219 public double signum() { 220 if (Float.isNaN(value)) { 221 return value; 222 } 223 if (value > 0) return 1; 224 if (value == 0) return 0; 225 return -1; 226 } 227 228 232 233 public boolean isWholeNumber() { 234 return value == Math.floor(value) && !Float.isInfinite(value); 235 } 236 237 240 241 public NumericValue arithmetic(int operator, NumericValue other, XPathContext context) throws XPathException { 242 if (other instanceof FloatValue) { 243 switch(operator) { 244 case Token.PLUS: 245 return new FloatValue(value + ((FloatValue)other).value); 246 case Token.MINUS: 247 return new FloatValue(value - ((FloatValue)other).value); 248 case Token.MULT: 249 return new FloatValue(value * ((FloatValue)other).value); 250 case Token.DIV: 251 return new FloatValue(value / ((FloatValue)other).value); 252 case Token.IDIV: 253 if (((FloatValue)other).value == 0.0) { 254 DynamicError e = new DynamicError("Integer division by zero"); 255 e.setErrorCode("FOAR0001"); 256 e.setXPathContext(context); 257 throw e; 258 } 259 return (NumericValue)(new FloatValue(value / ((FloatValue)other).value).convert(Type.INTEGER, context)); 260 case Token.MOD: 261 return new FloatValue(value % ((FloatValue)other).value); 262 default: 263 throw new UnsupportedOperationException ("Unknown operator"); 264 } 265 } else if (other instanceof DoubleValue) { 266 return ((DoubleValue)convert(Type.DOUBLE, context)).arithmetic(operator, other, context); 267 } else { 268 return arithmetic(operator, (FloatValue)other.convert(Type.FLOAT, context), context); 269 } 270 } 271 272 279 280 public boolean schemaEquals(Value obj) { 281 if (obj instanceof AtomicValue) { 282 obj = ((AtomicValue)obj).getPrimitiveValue(); 283 } 284 if (obj instanceof FloatValue) { 285 return value == ((FloatValue)obj).value; 286 } else { 287 return false; 288 } 289 } 290 291 294 295 public Object convertToJava(Class target, XPathContext context) throws XPathException { 296 if (target==Object .class) { 297 return new Double (value); 298 } else if (target.isAssignableFrom(DoubleValue.class)) { 299 return this; 300 } else if (target==boolean.class || target==Boolean .class) { 301 return Boolean.valueOf(value != 0.0 && !Float.isNaN(value)); 302 } else if (target==String .class || target==CharSequence .class) { 303 return getStringValue(); 304 } else if (target==double.class || target==Double .class) { 305 return new Double ((double)value); 306 } else if (target==float.class ||target==Float .class ) { 307 return new Float (value); 308 } else if (target==long.class || target==Long .class) { 309 return new Long ((long)value); 310 } else if (target==int.class || target==Integer .class) { 311 return new Integer ((int)value); 312 } else if (target==short.class || target==Short .class) { 313 return new Short ((short)value); 314 } else if (target==byte.class || target==Byte .class) { 315 return new Byte ((byte)value); 316 } else if (target==char.class || target==Character .class) { 317 return new Character ((char)value); 318 } else { 319 Object o = super.convertToJava(target, context); 320 if (o == null) { 321 DynamicError err = new DynamicError("Conversion of float to " + target.getName() + 322 " is not supported"); 323 err.setXPathContext(context); 324 err.setErrorCode("SAXON:0000"); 325 } 326 return o; 327 } 328 } 329 330 } 331 332 348 | Popular Tags |