1 4 package gnu.xquery.util; 5 import gnu.math.*; 6 import gnu.mapping.*; 7 import java.math.BigDecimal ; 8 import gnu.kawa.functions.Arithmetic; 9 import gnu.kawa.xml.*; 10 import gnu.xml.TextUtils; 11 12 public class NumberValue extends Procedure1 13 { 14 public static final NumberValue numberValue = new NumberValue(); 15 16 public static final Double NaN = new Double (Double.NaN); 17 18 public static boolean isNaN (Object arg) 19 { 20 return ((arg instanceof Double || arg instanceof Float 21 || arg instanceof DFloNum) 22 && Double.isNaN(((Number ) arg).doubleValue())); 23 } 24 25 public Object apply1(Object arg) 26 { 27 if (arg != Values.empty && arg != null) 28 { 29 try 30 { 31 return numberValue(arg); 32 } 33 catch (Throwable ex) 34 { 35 } 37 } 38 return NaN; 39 } 40 41 public static Number numberCast (Object value) 42 { 43 if (value == Values.empty || value == null) 44 return null; 45 if (value instanceof Values) 46 { 47 Values vals = (Values) value; 48 int ipos = vals.startPos(); 49 int count = 0; 50 while ((ipos = vals.nextPos(ipos)) != 0) 51 { 52 if (count > 0) 53 throw new ClassCastException ("non-singleton sequence cast to number"); 54 value = vals.getPosPrevious(ipos); 55 count++; 56 } 57 } 58 if (value instanceof KNode || value instanceof UntypedAtomic) 59 return (Double ) XDataType.doubleType.valueOf(TextUtils.stringValue(value)); 60 return (Number ) value; 61 } 62 63 public static Object numberValue (Object value) 64 { 65 value = KNode.atomicValue(value); 66 double d; 67 if (value instanceof UntypedAtomic || value instanceof String ) 68 { 69 try 70 { 71 return XDataType.doubleType 72 .valueOf(TextUtils.stringValue(value)); 73 } 74 catch (Throwable ex) 75 { 76 d = Double.NaN; 77 } 78 } 79 else if (value instanceof Number 80 && (value instanceof RealNum || ! (value instanceof Numeric))) 81 d = (((Number ) value).doubleValue()); 82 else 83 d = Double.NaN; 84 return XDataType.makeDouble(d); 85 } 86 87 public static Object abs (Object value) 88 { 89 if (value == null || value == Values.empty) 90 return value; 91 value = numberCast(value); 92 if (value instanceof Double ) 93 { 94 Double d = (Double ) value; 95 double x = d.doubleValue(); 96 long bits = Double.doubleToRawLongBits(x); 97 if (bits >= 0) 98 return d; 99 bits &= 0x7fffffffffffffffL; 100 x = Double.longBitsToDouble(bits); 101 102 104 return new Double (x); 105 106 } 107 if (value instanceof Float ) 108 { 109 Float d = (Float ) value; 110 float x = d.floatValue(); 111 int bits = Float.floatToRawIntBits(x); 112 if (bits >= 0) 113 return d; 114 bits &= 0x7fffffff; 115 x = Float.intBitsToFloat(bits); 116 117 119 return new Float (x); 120 121 } 122 if (value instanceof BigDecimal ) 123 { 124 BigDecimal dec = (BigDecimal ) value; 125 if (dec.signum() < 0) 126 dec = dec.negate(); 127 return dec; 128 } 129 return ((Numeric) value).abs(); 130 } 131 132 public static Object floor (Object val) 133 { 134 Number value = numberCast(val); 135 if (value == null) 136 return val; 137 if (value instanceof Double ) 138 return XDataType.makeDouble(Math.floor(((Double ) value).doubleValue())); 139 if (value instanceof Float ) 140 return XDataType.makeFloat((float) Math.floor(((Float ) value).floatValue())); 141 if (value instanceof BigDecimal ) 142 { 143 BigDecimal dec = (BigDecimal ) value; 144 return Arithmetic.asIntNum(dec.divide(XDataType.DECIMAL_ONE, 0, BigDecimal.ROUND_FLOOR).toBigInteger()); 145 } 146 return ((RealNum) value).toInt(Numeric.FLOOR); 147 } 148 149 public static Object ceiling (Object val) 150 { 151 Number value = numberCast(val); 152 if (value == null) 153 return val; 154 if (value instanceof Double ) 155 return XDataType.makeDouble(Math.ceil(((Double ) value).doubleValue())); 156 if (value instanceof Float ) 157 return XDataType.makeFloat((float) Math.ceil(((Float ) value).floatValue())); 158 if (value instanceof BigDecimal ) 159 { 160 BigDecimal dec = (BigDecimal ) value; 161 return Arithmetic.asIntNum(dec.divide(XDataType.DECIMAL_ONE, 0, BigDecimal.ROUND_CEILING).toBigInteger()); 162 } 163 return ((RealNum) value).toInt(Numeric.CEILING); 164 } 165 166 public static Object round (Object arg) 167 { 168 Number value = numberCast(arg); 169 if (value == null) 170 return arg; 171 if (value instanceof Double ) 172 { 173 double val = ((Double ) value).doubleValue(); 174 if (val >= -0.5 && val <= 0.0 175 && (val < 0.0 || Double.doubleToLongBits(val) < 0)) 176 val = -0.0; 177 else 178 val = Math.floor(val+0.5); 179 return XDataType.makeDouble(val); 180 } 181 if (value instanceof Float ) 182 { 183 float val = ((Float ) value).floatValue(); 184 if (val >= -0.5 && val <= 0.0 185 && (val < 0.0 || Float.floatToIntBits(val) < 0)) 186 val = (float) (-0.0); 187 else 188 val = (float) Math.floor(val+0.5); 189 return XDataType.makeFloat(val); 190 } 191 if (value instanceof BigDecimal ) 192 { 193 BigDecimal dec = (BigDecimal ) value; 194 int mode = dec.signum() >= 0 ? BigDecimal.ROUND_HALF_UP 195 : BigDecimal.ROUND_HALF_DOWN; 196 dec = dec.divide(XDataType.DECIMAL_ONE, 0, mode); 197 return Arithmetic.asIntNum(dec.toBigInteger()); 198 } 199 return ((RealNum) value).toInt(Numeric.ROUND); 200 } 201 202 public static Object roundHalfToEven (Object value, IntNum precision) 203 { 204 Number number = numberCast(value); 205 if (number == null) 206 return value; 207 BigDecimal dec = (BigDecimal ) XDataType.decimalType.cast(number); 208 int prec = precision.intValue(); 209 210 if (prec < 0) 211 { 212 BigDecimal power = null; 213 int shift = -prec; 214 if (shift >= 6) 215 { 216 BigDecimal million = BigDecimal.valueOf(1000000); 217 power = million; 218 while ((shift -= 6) >= 6) 219 power = power.multiply(million); 220 } 221 if (shift > 0) 222 { 223 int i = 10; 224 while (--shift > 0) 225 i = 10 * i; 226 BigDecimal tens = BigDecimal.valueOf(i); 227 power = power == null ? tens : power.multiply(tens); 228 } 229 dec = dec.divide(power, 0, BigDecimal.ROUND_HALF_EVEN); 230 dec = dec.multiply(power); 231 } 232 else 233 234 dec = dec.setScale(prec, BigDecimal.ROUND_HALF_EVEN); 235 if (number instanceof Double ) 236 return XDataType.makeDouble(dec.doubleValue()); 237 if (number instanceof Float ) 238 return XDataType.makeFloat(dec.floatValue()); 239 if (number instanceof IntNum) 240 return XIntegerType.integerType.cast(dec); 241 return dec; 242 } 243 244 public static Object roundHalfToEven (Object value) 245 { 246 return roundHalfToEven(value, IntNum.zero()); 247 } 248 } 249 | Popular Tags |