src/share/classes/java/math/BigDecimal.java

Print this page




3699      *
3700      * <p>If the scales of val[0] and val[1] differ, rescale
3701      * (non-destructively) the lower-scaled {@code BigDecimal} so
3702      * they match.  That is, the lower-scaled reference will be
3703      * replaced by a reference to a new object with the same scale as
3704      * the other {@code BigDecimal}.
3705      *
3706      * @param  val array of two elements referring to the two
3707      *         {@code BigDecimal}s to be aligned.
3708      */
3709     private static void matchScale(BigDecimal[] val) {
3710         if (val[0].scale == val[1].scale) {
3711             return;
3712         } else if (val[0].scale < val[1].scale) {
3713             val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
3714         } else if (val[1].scale < val[0].scale) {
3715             val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
3716         }
3717     }
3718 
3719     private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();

3720     private static final long intCompactOffset;
3721     private static final long intValOffset;
3722     static {
3723         try {

3724             intCompactOffset = unsafe.objectFieldOffset
3725                 (BigDecimal.class.getDeclaredField("intCompact"));
3726             intValOffset = unsafe.objectFieldOffset
3727                 (BigDecimal.class.getDeclaredField("intVal"));
3728         } catch (Exception ex) {
3729             throw new Error(ex);
3730         }
3731     }
3732 
3733     private void setIntCompactVolatile(long val) {
3734         unsafe.putLongVolatile(this, intCompactOffset, val);
3735     }
3736 
3737     private void setIntValVolatile(BigInteger val) {
3738         unsafe.putObjectVolatile(this, intValOffset, val);

3739     }
3740 
3741     /**
3742      * Reconstitute the {@code BigDecimal} instance from a stream (that is,
3743      * deserialize it).
3744      *
3745      * @param s the stream being read.
3746      */
3747     private void readObject(java.io.ObjectInputStream s)
3748         throws java.io.IOException, ClassNotFoundException {
3749         // Read in all fields
3750         s.defaultReadObject();
3751         // validate possibly bad fields
3752         if (intVal == null) {
3753             String message = "BigDecimal: null intVal in stream";
3754             throw new java.io.StreamCorruptedException(message);
3755         // [all values of scale are now allowed]
3756         }
3757         setIntCompactVolatile(compactValFor(intVal));
3758     }
3759 
3760    /**
3761     * Serialize this {@code BigDecimal} to the stream in question
3762     *
3763     * @param s the stream to serialize to.
3764     */
3765    private void writeObject(java.io.ObjectOutputStream s)
3766        throws java.io.IOException {
3767        // Must inflate to maintain compatible serial form.
3768        if (this.intVal == null)
3769            this.setIntValVolatile(BigInteger.valueOf(this.intCompact));
3770        // Could reset intVal back to null if it has to be set.
3771        s.defaultWriteObject();
3772    }
3773 
3774     /**
3775      * Returns the length of the absolute value of a {@code long}, in decimal
3776      * digits.
3777      *
3778      * @param x the {@code long}
3779      * @return the length of the unscaled value, in deciaml digits.
3780      */
3781     static int longDigitLength(long x) {
3782         /*
3783          * As described in "Bit Twiddling Hacks" by Sean Anderson,
3784          * (http://graphics.stanford.edu/~seander/bithacks.html)
3785          * integer log 10 of x is within 1 of (1233/4096)* (1 +
3786          * integer log 2 of x). The fraction 1233/4096 approximates
3787          * log10(2). So we first do a version of log2 (a variant of
3788          * Long class with pre-checks and opposite directionality) and
3789          * then scale and check against powers table. This is a little




3699      *
3700      * <p>If the scales of val[0] and val[1] differ, rescale
3701      * (non-destructively) the lower-scaled {@code BigDecimal} so
3702      * they match.  That is, the lower-scaled reference will be
3703      * replaced by a reference to a new object with the same scale as
3704      * the other {@code BigDecimal}.
3705      *
3706      * @param  val array of two elements referring to the two
3707      *         {@code BigDecimal}s to be aligned.
3708      */
3709     private static void matchScale(BigDecimal[] val) {
3710         if (val[0].scale == val[1].scale) {
3711             return;
3712         } else if (val[0].scale < val[1].scale) {
3713             val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
3714         } else if (val[1].scale < val[0].scale) {
3715             val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
3716         }
3717     }
3718 
3719     private static class UnsafeHolder {
3720         private static final sun.misc.Unsafe unsafe;
3721         private static final long intCompactOffset;
3722         private static final long intValOffset;
3723         static {
3724             try {
3725                 unsafe = sun.misc.Unsafe.getUnsafe();
3726                 intCompactOffset = unsafe.objectFieldOffset
3727                     (BigDecimal.class.getDeclaredField("intCompact"));
3728                 intValOffset = unsafe.objectFieldOffset
3729                     (BigDecimal.class.getDeclaredField("intVal"));
3730             } catch (Exception ex) {
3731                 throw new ExceptionInInitializerError(ex);
3732             }
3733         }
3734         private static void setIntCompactVolatile(BigDecimal bd, long val) {
3735             unsafe.putLongVolatile(bd, intCompactOffset, val);

3736         }
3737         
3738         private static void setIntValVolatile(BigDecimal bd, BigInteger val) {
3739             unsafe.putObjectVolatile(bd, intValOffset, val);
3740         }
3741     }
3742 
3743     /**
3744      * Reconstitute the {@code BigDecimal} instance from a stream (that is,
3745      * deserialize it).
3746      *
3747      * @param s the stream being read.
3748      */
3749     private void readObject(java.io.ObjectInputStream s)
3750         throws java.io.IOException, ClassNotFoundException {
3751         // Read in all fields
3752         s.defaultReadObject();
3753         // validate possibly bad fields
3754         if (intVal == null) {
3755             String message = "BigDecimal: null intVal in stream";
3756             throw new java.io.StreamCorruptedException(message);
3757         // [all values of scale are now allowed]
3758         }
3759         UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal));
3760     }
3761 
3762    /**
3763     * Serialize this {@code BigDecimal} to the stream in question
3764     *
3765     * @param s the stream to serialize to.
3766     */
3767    private void writeObject(java.io.ObjectOutputStream s)
3768        throws java.io.IOException {
3769        // Must inflate to maintain compatible serial form.
3770        if (this.intVal == null)
3771            UnsafeHolder.setIntValVolatile(this, BigInteger.valueOf(this.intCompact));
3772        // Could reset intVal back to null if it has to be set.
3773        s.defaultWriteObject();
3774    }
3775 
3776     /**
3777      * Returns the length of the absolute value of a {@code long}, in decimal
3778      * digits.
3779      *
3780      * @param x the {@code long}
3781      * @return the length of the unscaled value, in deciaml digits.
3782      */
3783     static int longDigitLength(long x) {
3784         /*
3785          * As described in "Bit Twiddling Hacks" by Sean Anderson,
3786          * (http://graphics.stanford.edu/~seander/bithacks.html)
3787          * integer log 10 of x is within 1 of (1233/4096)* (1 +
3788          * integer log 2 of x). The fraction 1233/4096 approximates
3789          * log10(2). So we first do a version of log2 (a variant of
3790          * Long class with pre-checks and opposite directionality) and
3791          * then scale and check against powers table. This is a little