3698 * 3699 * <p>If the scales of val[0] and val[1] differ, rescale 3700 * (non-destructively) the lower-scaled {@code BigDecimal} so 3701 * they match. That is, the lower-scaled reference will be 3702 * replaced by a reference to a new object with the same scale as 3703 * the other {@code BigDecimal}. 3704 * 3705 * @param val array of two elements referring to the two 3706 * {@code BigDecimal}s to be aligned. 3707 */ 3708 private static void matchScale(BigDecimal[] val) { 3709 if (val[0].scale == val[1].scale) { 3710 return; 3711 } else if (val[0].scale < val[1].scale) { 3712 val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY); 3713 } else if (val[1].scale < val[0].scale) { 3714 val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY); 3715 } 3716 } 3717 3718 private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); 3719 private static final long intCompactOffset; 3720 private static final long intValOffset; 3721 static { 3722 try { 3723 intCompactOffset = unsafe.objectFieldOffset 3724 (BigDecimal.class.getDeclaredField("intCompact")); 3725 intValOffset = unsafe.objectFieldOffset 3726 (BigDecimal.class.getDeclaredField("intVal")); 3727 } catch (Exception ex) { 3728 throw new Error(ex); 3729 } 3730 } 3731 3732 private void setIntCompactVolatile(long val) { 3733 unsafe.putLongVolatile(this, intCompactOffset, val); 3734 } 3735 3736 private void setIntValVolatile(BigInteger val) { 3737 unsafe.putObjectVolatile(this, intValOffset, val); 3738 } 3739 3740 /** 3741 * Reconstitute the {@code BigDecimal} instance from a stream (that is, 3742 * deserialize it). 3743 * 3744 * @param s the stream being read. 3745 */ 3746 private void readObject(java.io.ObjectInputStream s) 3747 throws java.io.IOException, ClassNotFoundException { 3748 // Read in all fields 3749 s.defaultReadObject(); 3750 // validate possibly bad fields 3751 if (intVal == null) { 3752 String message = "BigDecimal: null intVal in stream"; 3753 throw new java.io.StreamCorruptedException(message); 3754 // [all values of scale are now allowed] 3755 } 3756 setIntCompactVolatile(compactValFor(intVal)); 3757 } 3758 3759 /** 3760 * Serialize this {@code BigDecimal} to the stream in question 3761 * 3762 * @param s the stream to serialize to. 3763 */ 3764 private void writeObject(java.io.ObjectOutputStream s) 3765 throws java.io.IOException { 3766 // Must inflate to maintain compatible serial form. 3767 if (this.intVal == null) 3768 this.setIntValVolatile(BigInteger.valueOf(this.intCompact)); 3769 // Could reset intVal back to null if it has to be set. 3770 s.defaultWriteObject(); 3771 } 3772 3773 /** 3774 * Returns the length of the absolute value of a {@code long}, in decimal 3775 * digits. 3776 * 3777 * @param x the {@code long} 3778 * @return the length of the unscaled value, in deciaml digits. 3779 */ 3780 static int longDigitLength(long x) { 3781 /* 3782 * As described in "Bit Twiddling Hacks" by Sean Anderson, 3783 * (http://graphics.stanford.edu/~seander/bithacks.html) 3784 * integer log 10 of x is within 1 of (1233/4096)* (1 + 3785 * integer log 2 of x). The fraction 1233/4096 approximates 3786 * log10(2). So we first do a version of log2 (a variant of 3787 * Long class with pre-checks and opposite directionality) and 3788 * then scale and check against powers table. This is a little | 3698 * 3699 * <p>If the scales of val[0] and val[1] differ, rescale 3700 * (non-destructively) the lower-scaled {@code BigDecimal} so 3701 * they match. That is, the lower-scaled reference will be 3702 * replaced by a reference to a new object with the same scale as 3703 * the other {@code BigDecimal}. 3704 * 3705 * @param val array of two elements referring to the two 3706 * {@code BigDecimal}s to be aligned. 3707 */ 3708 private static void matchScale(BigDecimal[] val) { 3709 if (val[0].scale == val[1].scale) { 3710 return; 3711 } else if (val[0].scale < val[1].scale) { 3712 val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY); 3713 } else if (val[1].scale < val[0].scale) { 3714 val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY); 3715 } 3716 } 3717 3718 private static class UnsafeHolder { 3719 private static final sun.misc.Unsafe unsafe; 3720 private static final long intCompactOffset; 3721 private static final long intValOffset; 3722 static { 3723 try { 3724 unsafe = sun.misc.Unsafe.getUnsafe(); 3725 intCompactOffset = unsafe.objectFieldOffset 3726 (BigDecimal.class.getDeclaredField("intCompact")); 3727 intValOffset = unsafe.objectFieldOffset 3728 (BigDecimal.class.getDeclaredField("intVal")); 3729 } catch (Exception ex) { 3730 throw new ExceptionInInitializerError(ex); 3731 } 3732 } 3733 static void setIntCompactVolatile(BigDecimal bd, long val) { 3734 unsafe.putLongVolatile(bd, intCompactOffset, val); 3735 } 3736 3737 static void setIntValVolatile(BigDecimal bd, BigInteger val) { 3738 unsafe.putObjectVolatile(bd, intValOffset, val); 3739 } 3740 } 3741 3742 /** 3743 * Reconstitute the {@code BigDecimal} instance from a stream (that is, 3744 * deserialize it). 3745 * 3746 * @param s the stream being read. 3747 */ 3748 private void readObject(java.io.ObjectInputStream s) 3749 throws java.io.IOException, ClassNotFoundException { 3750 // Read in all fields 3751 s.defaultReadObject(); 3752 // validate possibly bad fields 3753 if (intVal == null) { 3754 String message = "BigDecimal: null intVal in stream"; 3755 throw new java.io.StreamCorruptedException(message); 3756 // [all values of scale are now allowed] 3757 } 3758 UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal)); 3759 } 3760 3761 /** 3762 * Serialize this {@code BigDecimal} to the stream in question 3763 * 3764 * @param s the stream to serialize to. 3765 */ 3766 private void writeObject(java.io.ObjectOutputStream s) 3767 throws java.io.IOException { 3768 // Must inflate to maintain compatible serial form. 3769 if (this.intVal == null) 3770 UnsafeHolder.setIntValVolatile(this, BigInteger.valueOf(this.intCompact)); 3771 // Could reset intVal back to null if it has to be set. 3772 s.defaultWriteObject(); 3773 } 3774 3775 /** 3776 * Returns the length of the absolute value of a {@code long}, in decimal 3777 * digits. 3778 * 3779 * @param x the {@code long} 3780 * @return the length of the unscaled value, in deciaml digits. 3781 */ 3782 static int longDigitLength(long x) { 3783 /* 3784 * As described in "Bit Twiddling Hacks" by Sean Anderson, 3785 * (http://graphics.stanford.edu/~seander/bithacks.html) 3786 * integer log 10 of x is within 1 of (1233/4096)* (1 + 3787 * integer log 2 of x). The fraction 1233/4096 approximates 3788 * log10(2). So we first do a version of log2 (a variant of 3789 * Long class with pre-checks and opposite directionality) and 3790 * then scale and check against powers table. This is a little |