35
35
import java .io .ObjectInputStream ;
36
36
import java .io .ObjectStreamException ;
37
37
import java .io .StreamCorruptedException ;
38
+ import java .nio .charset .CharacterCodingException ;
39
+ import java .nio .charset .StandardCharsets ;
38
40
import java .util .Arrays ;
39
41
import java .util .Objects ;
40
42
43
+ import jdk .internal .access .JavaLangAccess ;
44
+ import jdk .internal .access .SharedSecrets ;
45
+ import jdk .internal .util .DecimalDigits ;
46
+
41
47
/**
42
48
* Immutable, arbitrary-precision signed decimal numbers. A {@code
43
49
* BigDecimal} consists of an arbitrary precision integer
328
334
* @since 1.1
329
335
*/
330
336
public class BigDecimal extends Number implements Comparable <BigDecimal > {
337
+ private static final JavaLangAccess JLA = SharedSecrets .getJavaLangAccess ();
338
+
331
339
/*
332
340
* Let l = log_2(10).
333
341
* Then, L < l < L + ulp(L) / 2, that is, L = roundTiesToEven(l).
@@ -4164,103 +4172,6 @@ public BigDecimal ulp() {
4164
4172
return BigDecimal .valueOf (1 , this .scale (), 1 );
4165
4173
}
4166
4174
4167
- // Private class to build a string representation for BigDecimal object. The
4168
- // StringBuilder field acts as a buffer to hold the temporary representation
4169
- // of BigDecimal. The cmpCharArray holds all the characters for the compact
4170
- // representation of BigDecimal (except for '-' sign' if it is negative) if
4171
- // its intCompact field is not INFLATED.
4172
- static class StringBuilderHelper {
4173
- final StringBuilder sb ; // Placeholder for BigDecimal string
4174
- final char [] cmpCharArray ; // character array to place the intCompact
4175
-
4176
- StringBuilderHelper () {
4177
- sb = new StringBuilder (32 );
4178
- // All non negative longs can be made to fit into 19 character array.
4179
- cmpCharArray = new char [19 ];
4180
- }
4181
-
4182
- // Accessors.
4183
- StringBuilder getStringBuilder () {
4184
- sb .setLength (0 );
4185
- return sb ;
4186
- }
4187
-
4188
- char [] getCompactCharArray () {
4189
- return cmpCharArray ;
4190
- }
4191
-
4192
- /**
4193
- * Places characters representing the intCompact in {@code long} into
4194
- * cmpCharArray and returns the offset to the array where the
4195
- * representation starts.
4196
- *
4197
- * @param intCompact the number to put into the cmpCharArray.
4198
- * @return offset to the array where the representation starts.
4199
- * Note: intCompact must be greater or equal to zero.
4200
- */
4201
- int putIntCompact (long intCompact ) {
4202
- assert intCompact >= 0 ;
4203
-
4204
- long q ;
4205
- int r ;
4206
- // since we start from the least significant digit, charPos points to
4207
- // the last character in cmpCharArray.
4208
- int charPos = cmpCharArray .length ;
4209
-
4210
- // Get 2 digits/iteration using longs until quotient fits into an int
4211
- while (intCompact > Integer .MAX_VALUE ) {
4212
- q = intCompact / 100 ;
4213
- r = (int )(intCompact - q * 100 );
4214
- intCompact = q ;
4215
- cmpCharArray [--charPos ] = DIGIT_ONES [r ];
4216
- cmpCharArray [--charPos ] = DIGIT_TENS [r ];
4217
- }
4218
-
4219
- // Get 2 digits/iteration using ints when i2 >= 100
4220
- int q2 ;
4221
- int i2 = (int )intCompact ;
4222
- while (i2 >= 100 ) {
4223
- q2 = i2 / 100 ;
4224
- r = i2 - q2 * 100 ;
4225
- i2 = q2 ;
4226
- cmpCharArray [--charPos ] = DIGIT_ONES [r ];
4227
- cmpCharArray [--charPos ] = DIGIT_TENS [r ];
4228
- }
4229
-
4230
- cmpCharArray [--charPos ] = DIGIT_ONES [i2 ];
4231
- if (i2 >= 10 )
4232
- cmpCharArray [--charPos ] = DIGIT_TENS [i2 ];
4233
-
4234
- return charPos ;
4235
- }
4236
-
4237
- static final char [] DIGIT_TENS = {
4238
- '0' , '0' , '0' , '0' , '0' , '0' , '0' , '0' , '0' , '0' ,
4239
- '1' , '1' , '1' , '1' , '1' , '1' , '1' , '1' , '1' , '1' ,
4240
- '2' , '2' , '2' , '2' , '2' , '2' , '2' , '2' , '2' , '2' ,
4241
- '3' , '3' , '3' , '3' , '3' , '3' , '3' , '3' , '3' , '3' ,
4242
- '4' , '4' , '4' , '4' , '4' , '4' , '4' , '4' , '4' , '4' ,
4243
- '5' , '5' , '5' , '5' , '5' , '5' , '5' , '5' , '5' , '5' ,
4244
- '6' , '6' , '6' , '6' , '6' , '6' , '6' , '6' , '6' , '6' ,
4245
- '7' , '7' , '7' , '7' , '7' , '7' , '7' , '7' , '7' , '7' ,
4246
- '8' , '8' , '8' , '8' , '8' , '8' , '8' , '8' , '8' , '8' ,
4247
- '9' , '9' , '9' , '9' , '9' , '9' , '9' , '9' , '9' , '9' ,
4248
- };
4249
-
4250
- static final char [] DIGIT_ONES = {
4251
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4252
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4253
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4254
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4255
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4256
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4257
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4258
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4259
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4260
- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
4261
- };
4262
- }
4263
-
4264
4175
/**
4265
4176
* Lay out this {@code BigDecimal} into a {@code char[]} array.
4266
4177
* The Java 1.2 equivalent to this was called {@code getValueString}.
@@ -4271,6 +4182,8 @@ int putIntCompact(long intCompact) {
4271
4182
* {@code BigDecimal}
4272
4183
*/
4273
4184
private String layoutChars (boolean sci ) {
4185
+ long intCompact = this .intCompact ;
4186
+ int scale = this .scale ;
4274
4187
if (scale == 0 ) // zero scale is trivial
4275
4188
return (intCompact != INFLATED ) ?
4276
4189
Long .toString (intCompact ):
@@ -4280,18 +4193,25 @@ private String layoutChars(boolean sci) {
4280
4193
// currency fast path
4281
4194
int lowInt = (int )intCompact % 100 ;
4282
4195
int highInt = (int )intCompact / 100 ;
4283
- return (Integer .toString (highInt ) + '.' +
4284
- StringBuilderHelper .DIGIT_TENS [lowInt ] +
4285
- StringBuilderHelper .DIGIT_ONES [lowInt ]) ;
4196
+ int highIntSize = DecimalDigits .stringSize (highInt );
4197
+ byte [] buf = new byte [highIntSize + 3 ];
4198
+ DecimalDigits .getCharsLatin1 (highInt , highIntSize , buf );
4199
+ buf [highIntSize ] = '.' ;
4200
+ DecimalDigits .putPairLatin1 (buf , highIntSize + 1 , lowInt );
4201
+ try {
4202
+ return JLA .newStringNoRepl (buf , StandardCharsets .ISO_8859_1 );
4203
+ } catch (CharacterCodingException cce ) {
4204
+ throw new AssertionError (cce );
4205
+ }
4286
4206
}
4287
4207
4288
- StringBuilderHelper sbHelper = new StringBuilderHelper ();
4289
4208
char [] coeff ;
4290
4209
int offset ; // offset is the starting index for coeff array
4291
4210
// Get the significand as an absolute value
4292
4211
if (intCompact != INFLATED ) {
4293
- offset = sbHelper .putIntCompact (Math .abs (intCompact ));
4294
- coeff = sbHelper .getCompactCharArray ();
4212
+ // All non negative longs can be made to fit into 19 character array.
4213
+ coeff = new char [19 ];
4214
+ offset = DecimalDigits .getChars (Math .abs (intCompact ), coeff .length , coeff );
4295
4215
} else {
4296
4216
offset = 0 ;
4297
4217
coeff = intVal .abs ().toString ().toCharArray ();
@@ -4301,7 +4221,7 @@ private String layoutChars(boolean sci) {
4301
4221
// If E-notation is needed, length will be: +1 if negative, +1
4302
4222
// if '.' needed, +2 for "E+", + up to 10 for adjusted exponent.
4303
4223
// Otherwise it could have +1 if negative, plus leading "0.00000"
4304
- StringBuilder buf = sbHelper . getStringBuilder () ;
4224
+ StringBuilder buf = new StringBuilder ( 32 ); ;
4305
4225
if (signum () < 0 ) // prefix '-' if negative
4306
4226
buf .append ('-' );
4307
4227
int coeffLen = coeff .length - offset ;
0 commit comments