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

Print this page




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