1 33 package smallsql.database; 34 35 import java.math.*; 36 37 class MutableNumeric extends Number implements Mutable{ 38 39 private static final long serialVersionUID = -750525164208565056L; 40 private int[] value; 41 private int scale; 42 private int signum; 43 44 45 48 MutableNumeric(byte[] complement){ 49 setValue(complement); 50 } 51 52 private void setValue(byte[] complement){ 53 int length = complement.length; 54 if(length == 0){ 55 value = EMPTY_INTS; 56 signum = 0; 57 return; 58 } 59 value = new int[ (length + 3) / 4 ]; 60 if(complement[0] < 0){ 61 negate( complement ); 62 signum = -1; 63 }else{ 64 signum = 0; 65 for(int i=0; i<complement.length; i++) 66 if(complement[i] != 0){ 67 signum = 1; 68 break; 69 } 70 } 71 for(int v=value.length-1; v>=0; v--){ 72 int temp = 0; 73 for(int i=0; i<4 && 0<length; i++){ 74 temp |= (complement[ --length ] & 0xFF) << (i*8); 75 } 76 value[v] = temp; 77 } 78 } 79 80 MutableNumeric(int complement){ 81 if(complement == 0){ 82 signum = 0; 83 value = EMPTY_INTS; 84 }else{ 85 value = new int[1]; 86 if(complement < 0){ 87 value[0] = -complement; 88 signum = -1; 89 }else{ 90 value[0] = complement; 91 signum = 1; 92 } 93 } 94 } 95 96 MutableNumeric(int complement, int scale){ 97 this( complement ); 98 this.scale = scale; 99 } 100 101 MutableNumeric(long complement){ 102 if(complement == 0){ 103 signum = 0; 104 value = EMPTY_INTS; 105 }else{ 106 value = new int[2]; 107 if(complement < 0){ 108 value[0] = (int)(~(complement >> 32)); 109 value[1] = (int)(-complement); 110 signum = -1; 111 }else{ 112 value[0] = (int)(complement >> 32); 113 value[1] = (int)complement; 114 signum = 1; 115 } 116 } 117 } 118 119 MutableNumeric(long complement, int scale){ 120 this( complement ); 121 this.scale = scale; 122 } 123 124 MutableNumeric(double val){ 125 this( new BigDecimal( String.valueOf(val) ) ); 127 } 128 129 MutableNumeric(float val){ 130 this( new BigDecimal( String.valueOf(val) ) ); 132 } 133 134 MutableNumeric(String val){ 135 this( new BigDecimal( val ) ); 136 } 137 138 MutableNumeric( BigDecimal big ){ 139 this(big.unscaledValue().toByteArray() ); 140 scale = big.scale(); 141 } 142 143 MutableNumeric(int signum, int[] value, int scale){ 144 this.signum = signum; 145 this.value = value; 146 this.scale = scale; 147 } 148 149 MutableNumeric(MutableNumeric numeric){ 150 this.signum = numeric.signum; 151 this.value = new int[numeric.value.length]; 152 System.arraycopy(numeric.value, 0, value, 0, value.length); 153 this.scale = numeric.scale; 154 } 155 156 157 int[] getInternalValue(){ 158 return value; 159 } 160 161 162 void add(MutableNumeric num){ 164 if(num.scale < scale){ 165 num.setScale(scale); 166 }else 167 if(num.scale > scale){ 168 setScale(num.scale); 169 } 170 add( num.signum, num.value ); 171 } 172 173 174 private void add( int sig2, int[] val2){ 175 if(val2.length > value.length){ 176 int[] temp = val2; 177 val2 = value; 178 value = temp; 179 int tempi = signum; 180 signum = sig2; 181 sig2 = tempi; 182 } 183 if(signum != sig2) 184 sub(val2); 185 else 186 add(val2); 187 } 188 189 private void add( int[] val2){ 192 long temp = 0; 193 int v1 = value.length; 194 for(int v2 = val2.length; v2>0; ){ 195 temp = (value[--v1] & 0xFFFFFFFFL) + (val2 [--v2] & 0xFFFFFFFFL) + (temp >>> 32); 196 value[v1] = (int)temp; 197 } 198 boolean uebertrag = (temp >>> 32) != 0; 199 while(v1 > 0 && uebertrag) 200 uebertrag = (value[--v1] = value[v1] + 1) == 0; 201 202 if(uebertrag){ 204 resizeValue(1); 205 } 206 } 207 208 209 210 214 private void resizeValue(int highBits){ 215 int val[] = new int[value.length+1]; 216 val[0] = highBits; 217 System.arraycopy(value, 0, val, 1, value.length); 218 value = val; 219 } 220 221 222 void sub(MutableNumeric num){ 224 if(num.scale < scale){ 225 num.setScale(scale); 226 }else 227 if(num.scale > scale){ 228 setScale(num.scale); 229 } 230 add( -num.signum, num.value ); 231 } 232 233 private void sub(int[] val2){ 236 long temp = 0; 237 int v1 = value.length; 238 for(int v2 = val2.length; v2>0; ){ 239 temp = (value[--v1] & 0xFFFFFFFFL) - (val2 [--v2] & 0xFFFFFFFFL) + (temp >>>= 32); 240 value[v1] = (int)temp; 241 } 242 243 boolean uebertrag = (temp >>> 32) != 0; 244 while(v1 > 0 && uebertrag) 245 uebertrag = (value[--v1] = value[v1] - 1) == -1; 246 247 if(uebertrag){ 248 signum = -signum; 249 int last = value.length-1; 250 for(int i=0; i<=last; i++){ 251 value[i] = (i == last) ? -value[i] : ~value[i]; 252 } 253 } 254 } 255 256 void mul(MutableNumeric num){ 257 BigDecimal big = toBigDecimal().multiply(num.toBigDecimal() ); 259 setValue( big.unscaledValue().toByteArray() ); 260 scale = big.scale(); 261 signum = big.signum(); 262 } 263 264 final void mul(int factor){ 265 if(factor < 0){ 266 factor = - factor; 267 signum = -signum; 268 } 269 long carryover = 0; 270 for(int i = value.length-1; i>=0; i--){ 271 long v = (value[i] & 0xFFFFFFFFL) * factor + carryover; 272 value[i] = (int)v; 273 carryover = v >> 32; 274 } 275 if(carryover > 0){ 276 resizeValue( (int)carryover ); 277 } 278 } 279 280 281 void div(MutableNumeric num){ 282 int newScale = Math.max(scale+5, num.scale +4); 284 BigDecimal big = toBigDecimal().divide(num.toBigDecimal(), newScale, BigDecimal.ROUND_HALF_EVEN); 285 setValue( big.unscaledValue().toByteArray() ); 286 scale = big.scale(); 287 signum = big.signum(); 288 } 289 290 291 final void div(int quotient){ 292 mul(100000); 294 scale += 5; 295 296 divImpl(quotient); 297 } 298 299 300 final private void divImpl(int quotient){ 301 if(quotient == 1) return; 302 if(quotient < 0){ 303 quotient = - quotient; 304 signum = -signum; 305 } 306 int valueLength = value.length; 307 long carryover = 0; 308 for(int i = 0; i<valueLength; i++){ 309 long v = (value[i] & 0xFFFFFFFFL) + carryover; 310 value[i] = (int)(v / quotient); 311 carryover = ((v % quotient) << 32); 312 } 313 carryover /= quotient; 314 if(carryover > 2147483648L || (carryover == 2147483648L && (value[valueLength-1] % 2 == 1))){ 316 int i = valueLength-1; 317 boolean isCarryOver = true; 318 while(i >= 0 && isCarryOver) 319 isCarryOver = (value[i--] += 1) == 0; 320 } 321 if(valueLength>1 && value[0] == 0){ 322 int[] temp = new int[valueLength-1]; 323 System.arraycopy(value, 1, temp, 0, valueLength-1); 324 value = temp; 325 } 326 327 } 328 329 330 void mod(MutableNumeric num){ 331 num = new MutableNumeric( doubleValue() % num.doubleValue() ); 333 value = num.value; 334 scale = num.scale; 335 signum = num.signum; 336 } 337 338 339 int getScale(){ 340 return scale; 341 } 342 343 344 void setScale(int newScale){ 345 if(newScale == scale) return; 346 int factor = 1; 347 if(newScale > scale){ 348 for(;newScale>scale; scale++){ 349 factor *=10; 350 if(factor == 1000000000){ 351 mul(factor); 352 factor = 1; 353 } 354 } 355 mul(factor); 356 }else{ 357 for(;newScale<scale; scale--){ 358 factor *=10; 359 if(factor == 1000000000){ 360 divImpl(factor); 361 factor = 1; 362 } 363 } 364 divImpl(factor); 365 } 366 } 367 368 369 370 371 374 int getSignum() { 375 return signum; 376 } 377 378 379 void setSignum(int signum){ 380 this.signum = signum; 381 } 382 383 384 void floor(){ 385 int oldScale = scale; 387 setScale(0); 388 setScale(oldScale); 389 } 390 391 392 private void negate(byte[] complement){ 393 int last = complement.length-1; 394 for(int i=0; i<=last; i++){ 395 complement[i] = (byte)( (i == last) ? -complement[i] : ~complement[i]); 396 } 397 } 398 399 400 405 byte[] toByteArray(){ 406 if(signum == 0) return EMPTY_BYTES; 407 byte[] complement; 408 int offset; 409 410 int v = 0; 411 while(v < value.length && value[v] == 0) v++; 412 if (v == value.length) return EMPTY_BYTES; 413 414 if(value[v] < 0){ 415 complement = new byte[(value.length-v)*4 + 4]; 418 if(signum < 0) 419 complement[0] = complement[1] = complement[2] = complement[3] = -1; 420 offset = 4; 421 }else{ 422 complement = new byte[(value.length-v)*4]; 423 offset = 0; 424 } 425 int last = value.length-1; 426 for(; v <= last; v++){ 427 int val = (signum>0) ? value[v] : (v == last) ? -value[v] : ~value[v]; 428 complement[offset++] = (byte)(val >> 24); 429 complement[offset++] = (byte)(val >> 16); 430 complement[offset++] = (byte)(val >> 8); 431 complement[offset++] = (byte)(val); 432 } 433 return complement; 434 } 435 436 public int intValue(){ 437 return Utils.long2int(longValue()); 438 } 439 440 441 public long longValue(){ 442 if(value.length == 0 || signum == 0){ 443 return 0; 444 }else{ 445 if (value.length == 1 && (value[0] > 0)){ 446 return Utils.double2long(value[0] / scaleDoubleFactor[scale] * signum); 448 }else 449 if (value.length == 1){ 450 long temp = value[0] & 0xFFFFFFFFL; 452 return Utils.double2long(temp / scaleDoubleFactor[scale] * signum); 453 }else 454 if (value.length == 2 && (value[0] > 0)){ 455 long temp = (((long)value[0]) << 32) | (value[1] & 0xFFFFFFFFL); 457 return Utils.double2long(temp / scaleDoubleFactor[scale] * signum); 458 }else{ 459 if(scale != 0){ 460 MutableNumeric numeric = new MutableNumeric(this); 461 numeric.setScale(0); 462 return numeric.longValue(); 463 } 464 return (signum > 0) ? Long.MAX_VALUE : Long.MIN_VALUE; 465 } 466 } 467 } 468 469 470 public float floatValue(){ 471 if(value.length == 0 || signum == 0){ 472 return 0; 473 }else{ 474 if (value.length == 1 && (value[0] > 0)){ 475 return value[0] / scaleFloatFactor[scale] * signum; 477 }else 478 if (value.length == 1){ 479 long temp = value[0] & 0xFFFFFFFFL; 481 return temp / scaleFloatFactor[scale] * signum; 482 }else 483 if (value.length == 2 && (value[0] > 0)){ 484 long temp = (((long)value[0]) << 32) | (value[1] & 0xFFFFFFFFL); 486 return temp / scaleFloatFactor[scale] * signum; 487 }else{ 488 return new BigDecimal( new BigInteger( toByteArray() ), scale ).floatValue(); 489 } 490 } 491 } 492 493 public double doubleValue(){ 494 if(value.length == 0 || signum == 0){ 495 return 0; 496 }else{ 497 if (value.length == 1 && (value[0] > 0)){ 498 return value[0] / scaleDoubleFactor[scale] * signum; 500 }else 501 if (value.length == 1){ 502 long temp = value[0] & 0xFFFFFFFFL; 504 return temp / scaleDoubleFactor[scale] * signum; 505 }else 506 if (value.length == 2 && (value[0] > 0)){ 507 long temp = (((long)value[0]) << 32) | (value[1] & 0xFFFFFFFFL); 509 return temp / scaleDoubleFactor[scale] * signum; 510 }else{ 511 return new BigDecimal( new BigInteger( toByteArray() ), scale ).doubleValue(); 512 } 513 } 514 } 515 516 public String toString(){ 517 StringBuffer buf = new StringBuffer (); 518 if(value.length == 0 || signum == 0){ 519 buf.append( '0' ); 520 }else{ 521 if (value.length == 1 && (value[0] > 0)){ 522 buf.append( Integer.toString(value[0]) ); 524 }else 525 if (value.length == 1){ 526 long temp = value[0] & 0xFFFFFFFFL; 528 buf.append( Long.toString( temp ) ); 529 }else 530 if (value.length == 2 && (value[0] > 0)){ 531 long temp = (((long)value[0]) << 32) | (value[1] & 0xFFFFFFFFL); 533 buf.append( Long.toString( temp ) ); 534 }else{ 535 return new BigDecimal( new BigInteger( toByteArray() ), scale ).toString(); 536 } 537 } 538 if(scale > 0){ 539 while(buf.length() <= scale) buf.insert( 0, '0' ); 540 buf.insert( buf.length() - scale, '.' ); 541 } 542 if (signum < 0) buf.insert( 0, '-'); 543 return buf.toString(); 544 } 545 546 public int compareTo(MutableNumeric numeric){ 547 return toBigDecimal().compareTo(numeric.toBigDecimal()); 549 } 550 551 public boolean equals(Object obj){ 552 if(!(obj instanceof MutableNumeric)) return false; 553 return compareTo((MutableNumeric)obj) == 0; 554 } 555 556 public BigDecimal toBigDecimal(){ 557 if(signum == 0) return new BigDecimal( BigInteger.ZERO, scale); 558 return new BigDecimal( new BigInteger( toByteArray() ), scale ); 559 } 560 561 public BigDecimal toBigDecimal(int scale){ 562 if(scale == this.scale) return toBigDecimal(); 563 return toBigDecimal().setScale( scale, BigDecimal.ROUND_HALF_EVEN); 564 } 565 566 public Object getImmutableObject(){ 567 return toBigDecimal(); 568 } 569 570 571 private static final byte[] EMPTY_BYTES = new byte[0]; 572 private static final int [] EMPTY_INTS = new int [0]; 573 private static final double[] scaleDoubleFactor = { 1, 10, 100, 1000, 10000, 100000, 1000000 }; 574 private static final float[] scaleFloatFactor = { 1, 10, 100, 1000, 10000, 100000, 1000000 }; 575 } | Popular Tags |