use compact BigDecimal

This commit is contained in:
jianghang.loujh
2022-11-16 16:14:11 +08:00
parent 4c7cdbc7f3
commit afef45500e

View File

@@ -16,6 +16,8 @@ import java.util.BitSet;
*/
public class LogBuffer {
static final BigDecimal DECIMAL_ZERO_1_SCALE = BigDecimal.valueOf(0, 1);
static final BigDecimal DECIMAL_ONE_1_SCALE = BigDecimal.valueOf(10, 1);
protected byte[] buffer;
protected int origin, limit;
@@ -1263,6 +1265,15 @@ public class LogBuffer {
throw new IllegalArgumentException("limit excceed: " + (position + binSize - origin));
}
if (precision <= 20 && intg <= 18 && frac <= 9) {
// use compact BigDecimal
BigDecimal compactDecimal = getBigDecimalCompact(precision, scale, intg, frac, intg0x);
if (compactDecimal != null) {
position += binSize;
return compactDecimal;
}
}
BigDecimal decimal = getDecimal0(position, intg, frac, // NL
intg0,
frac0,
@@ -1272,6 +1283,162 @@ public class LogBuffer {
return decimal;
}
/**
* use compact BigDecimal
*/
private BigDecimal getBigDecimalCompact(int precision, int scale, int intg, int frac, int intg0x) {
if (precision > 20 || intg > 18 && frac > 9) {
return null;
}
BigDecimal compactDecimal = null;
long longValue = 0;
int small = 0;
int pos = position;
byte b0 = buffer[position];
final int mask = ((b0 & 0x80) == 0x80) ? 0 : -1;
b0 ^= 0x80;
switch (intg0x) {
case 0:
if (intg == 0) {
longValue = 0;
} else {
longValue = (b0 << 24)
| ((0xff & buffer[pos + 1]) << 16)
| ((0xff & buffer[pos + 2]) << 8)
| (0xff & buffer[pos + 3]);
longValue ^= mask;
pos += 4;
}
break;
case 1:
case 2:
longValue = b0;
longValue ^= mask;
pos += 1;
break;
case 3:
case 4:
longValue = (b0 << 8) | (0xff & buffer[pos + 1]);
longValue ^= mask;
pos += 2;
break;
case 5:
case 6:
longValue = (b0 << 16) | ((0xff & buffer[pos + 1]) << 8) | (0xff & buffer[pos + 2]);
longValue ^= mask;
pos += 3;
break;
case 7:
case 8:
longValue = (b0 << 24)
| ((0xff & buffer[pos + 1]) << 16)
| ((0xff & buffer[pos + 2]) << 8)
| (0xff & buffer[pos + 3]);
longValue ^= mask;
pos += 4;
break;
default:
break;
}
if (intg > 9) {
int value = getInt32BE(buffer, pos);
value ^= mask;
longValue *= 1_000_000_000;
longValue += value;
pos += 4;
}
int power = 1;
if (pos != position) {
b0 = buffer[pos];
}
switch (frac) {
case 0:
small = 0;
break;
case 1:
case 2:
power = frac == 1 ? 10 : 100;
small = b0;
small ^= mask;
break;
case 3:
case 4:
power = frac == 3 ? 1_000 : 10_000;
small = (b0 << 8) | (0xff & buffer[pos + 1]);
small ^= mask;
break;
case 5:
case 6:
power = frac == 5 ? 100_000 : 1_000_000;
small = (b0 << 16) | ((0xff & buffer[pos + 1]) << 8) | (0xff & buffer[pos + 2]);
small ^= mask;
break;
case 7:
case 8:
case 9:
power = frac == 7 ? 10_000_000 : frac == 8 ? 100_000_000 : 1_000_000_000;
small = (b0 << 24)
| ((0xff & buffer[pos + 1]) << 16)
| ((0xff & buffer[pos + 2]) << 8)
| (0xff & buffer[pos + 3]);
small ^= mask;
break;
default:
break;
}
if (small == 0) {
if (frac == 0) {
if (mask != 0) {
longValue = -longValue;
}
compactDecimal = BigDecimal.valueOf(longValue, 0);
} else if (longValue == 0) {
if (scale < 9) {
compactDecimal = DECIMAL_ZERO_1_SCALE;
} else {
compactDecimal = BigDecimal.valueOf(longValue, scale);
}
} else {
if (scale < 9) {
long unscaleValue = longValue * 10;
if (unscaleValue >= longValue) {
if (mask != 0) {
unscaleValue = -unscaleValue;
}
if (unscaleValue == 10) {
compactDecimal = DECIMAL_ONE_1_SCALE;
} else {
compactDecimal = BigDecimal.valueOf(unscaleValue, 1);
}
}
} else {
long unscaleValue = longValue * power;
if (unscaleValue >= longValue) {
if (mask != 0) {
unscaleValue = -unscaleValue;
}
compactDecimal = BigDecimal.valueOf(unscaleValue, scale);
}
}
}
} else {
long unscaleValue = longValue * power + small;
if (unscaleValue >= longValue) {
if (mask != 0) {
unscaleValue = -unscaleValue;
}
compactDecimal = BigDecimal.valueOf(unscaleValue, scale);
}
}
return compactDecimal;
}
/**
* Return big decimal from buffer.
*
@@ -1445,8 +1612,9 @@ public class LogBuffer {
}
d_copy[begin] ^= 0x80; /* restore sign */
String decimal = String.valueOf(buf, 0, pos);
return new BigDecimal(decimal);
// String decimal = String.valueOf(buf, 0, pos);
// return new BigDecimal(decimal);
return new BigDecimal(buf, 0, pos);
}
/**