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 = sun.misc.Unsafe.getUnsafe();
3721         private static final long intCompactOffset;
3722         private static final long intValOffset;
3723         static {
3724             try {
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 Error(ex);
3731             }
3732         }
3733         private static void setIntCompactVolatile(BigDecimal bd, long val) {
3734             unsafe.putLongVolatile(bd, intCompactOffset, val);

3735         }
3736         
3737         private 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