use of com.amazon.ion.Decimal in project ion-java by amzn.
the class IonReaderBinaryRawX method readDecimal.
protected final Decimal readDecimal(int len) throws IOException {
MathContext mathContext = MathContext.UNLIMITED;
Decimal bd;
// we only write out the '0' value as the nibble 0
if (len == 0) {
bd = Decimal.valueOf(0, mathContext);
} else {
// otherwise we to it the hard way ....
long save_limit = NO_LIMIT;
if (_local_remaining != NO_LIMIT) {
save_limit = _local_remaining - len;
}
_local_remaining = len;
int exponent = readVarInt();
BigInteger value;
int signum;
if (_local_remaining > 0) {
byte[] bits = new byte[(int) _local_remaining];
readAll(bits, 0, (int) _local_remaining);
signum = 1;
if (bits[0] < 0) {
// value is negative, clear the sign
bits[0] &= 0x7F;
signum = -1;
}
value = new BigInteger(signum, bits);
} else {
signum = 0;
value = BigInteger.ZERO;
}
// Ion stores exponent, BigDecimal uses the negation "scale"
int scale = -exponent;
if (value.signum() == 0 && signum == -1) {
assert value.equals(BigInteger.ZERO);
bd = Decimal.negativeZero(scale, mathContext);
} else {
bd = Decimal.valueOf(value, scale, mathContext);
}
_local_remaining = save_limit;
}
return bd;
}
use of com.amazon.ion.Decimal in project ion-java by amzn.
the class IonReaderBinarySystemX method load_scalar_value.
private final void load_scalar_value() throws IOException {
// make sure we're trying to load a scalar value here
switch(_value_type) {
case NULL:
case BOOL:
case INT:
case FLOAT:
case DECIMAL:
case TIMESTAMP:
case SYMBOL:
case STRING:
break;
default:
return;
}
// well as when we encounter a null of any other type
if (_value_is_null) {
_v.setValueToNull(_value_type);
_v.setAuthoritativeType(AS_TYPE.null_value);
return;
}
switch(_value_type) {
default:
return;
case BOOL:
_v.setValue(_value_is_true);
_v.setAuthoritativeType(AS_TYPE.boolean_value);
break;
case INT:
boolean is_negative = _value_tid == _Private_IonConstants.tidNegInt;
if (_value_len == 0) {
if (is_negative) {
throwIllegalNegativeZeroException();
}
int v = 0;
_v.setValue(v);
_v.setAuthoritativeType(AS_TYPE.int_value);
} else if (_value_len <= MAX_BINARY_LENGTH_LONG) {
long v = readULong((int) _value_len);
if (v < 0) {
// we probably can't fit this magnitude properly into a Java long
int signum = !is_negative ? 1 : -1;
BigInteger big = IonBinary.unsignedLongToBigInteger(signum, v);
_v.setValue(big);
// boundary condition
if (big.compareTo(MIN_LONG_VALUE) < 0 || big.compareTo(MAX_LONG_VALUE) > 0) {
_v.setAuthoritativeType(AS_TYPE.bigInteger_value);
} else {
// fits in long
// keep the BigInteger value set in case the user wants to resurrect it as such
_v.addValue(big.longValue());
_v.setAuthoritativeType(AS_TYPE.long_value);
}
} else {
if (is_negative) {
if (v == 0) {
throwIllegalNegativeZeroException();
}
v = -v;
}
if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
_v.setValue(v);
_v.setAuthoritativeType(AS_TYPE.long_value);
} else {
_v.setValue((int) v);
_v.setAuthoritativeType(AS_TYPE.int_value);
}
}
} else {
BigInteger v = readBigInteger((int) _value_len, is_negative);
_v.setValue(v);
_v.setAuthoritativeType(AS_TYPE.bigInteger_value);
}
break;
case FLOAT:
double d;
if (_value_len == 0) {
d = 0.0;
} else {
d = readFloat((int) _value_len);
}
_v.setValue(d);
_v.setAuthoritativeType(AS_TYPE.double_value);
break;
case DECIMAL:
Decimal dec = readDecimal((int) _value_len);
_v.setValue(dec);
_v.setAuthoritativeType(AS_TYPE.decimal_value);
break;
case TIMESTAMP:
// TODO: it looks like a 0 length return a null timestamp - is that right?
Timestamp t = readTimestamp((int) _value_len);
_v.setValue(t);
_v.setAuthoritativeType(AS_TYPE.timestamp_value);
break;
case SYMBOL:
long sid = readULong((int) _value_len);
if (sid < 0 || sid > Integer.MAX_VALUE) {
String message = "symbol id [" + sid + "] out of range " + "(1-" + Integer.MAX_VALUE + ")";
throwErrorAt(message);
}
// TODO: is treating this as an int too misleading?
_v.setValue((int) sid);
_v.setAuthoritativeType(AS_TYPE.int_value);
break;
case STRING:
String s = readString((int) _value_len);
_v.setValue(s);
_v.setAuthoritativeType(AS_TYPE.string_value);
break;
}
_state = State.S_AFTER_VALUE;
}
use of com.amazon.ion.Decimal in project ion-java by amzn.
the class IonDecimalLite method hashCode.
@Override
int hashCode(SymbolTableProvider symbolTableProvider) {
int result = HASH_SIGNATURE;
// strict equality checks between two IonDecimals.
if (!isNullValue()) {
Decimal dec = decimalValue();
result ^= dec.hashCode();
if (dec.isNegativeZero()) {
result ^= NEGATIVE_ZERO_HASH_SIGNATURE;
}
}
return hashTypeAnnotations(result, symbolTableProvider);
}
use of com.amazon.ion.Decimal in project ion-java by amzn.
the class ReaderTest method testReadingFloatAsBigDecimal.
/**
* This isn't allowed by the documentation, but it's allowed by the text
* and binary readers. Not allowed by the tree reader.
*
* We need to specify the conversion too, its non-trivial: does 0e0
* convert to 0d0 or 0.0? The latter is happening at this writing, but
* it's not what one would expect.
*/
@Test
@Ignore
public // TODO amzn/ion-java/issues/56
void testReadingFloatAsBigDecimal() {
BigDecimal actualBd = readBigDecimal("null.float");
assertEquals(in.isNullValue(), actualBd == null);
Decimal actualDec = readDecimal("null.decimal");
assertEquals(in.isNullValue(), actualDec == null);
assertEquals(actualBd, actualDec);
// Note that one can't represent Long.MAX_VALUE as a double, there's
// not enough bits in the mantissa!
assertEquals(readBigDecimal("-0e0"), readDecimal("-0."));
assertEquals(readBigDecimal("0e0"), readDecimal("0."));
assertEquals(readBigDecimal("9223372036854776000e0"), readDecimal("9223372036854776000."));
assertEquals(readBigDecimal("9223372036854776000e12"), readDecimal("9223372036854776000d12"));
assertEquals(readBigDecimal("2e24"), readDecimal("2000000000000000000000000."));
}
use of com.amazon.ion.Decimal in project ion-java by amzn.
the class _Private_IonTextAppender method printDecimal.
public void printDecimal(_Private_IonTextWriterBuilder _options, BigDecimal value) throws IOException {
if (value == null) {
appendAscii("null.decimal");
return;
}
BigInteger unscaled = value.unscaledValue();
int signum = value.signum();
if (signum < 0) {
appendAscii('-');
unscaled = unscaled.negate();
} else if (value instanceof Decimal && ((Decimal) value).isNegativeZero()) {
// for the various forms of negative zero we have to
// write the sign ourselves, since neither BigInteger
// nor BigDecimal recognize negative zero, but Ion does.
appendAscii('-');
}
final String unscaledText = unscaled.toString();
final int significantDigits = unscaledText.length();
final int scale = value.scale();
final int exponent = -scale;
if (_options._decimal_as_float) {
appendAscii(unscaledText);
appendAscii('e');
appendAscii(Integer.toString(exponent));
} else if (exponent == 0) {
appendAscii(unscaledText);
appendAscii('.');
} else if (exponent < 0) {
// Avoid printing small negative exponents using a heuristic
// adapted from http://speleotrove.com/decimal/daconvs.html
final int adjustedExponent = significantDigits - 1 - scale;
if (adjustedExponent >= 0) {
int wholeDigits = significantDigits - scale;
appendAscii(unscaledText, 0, wholeDigits);
appendAscii('.');
appendAscii(unscaledText, wholeDigits, significantDigits);
} else if (adjustedExponent >= -6) {
appendAscii("0.");
appendAscii("00000", 0, scale - significantDigits);
appendAscii(unscaledText);
} else {
appendAscii(unscaledText);
appendAscii("d-");
appendAscii(Integer.toString(scale));
}
} else // (exponent > 0)
{
// We cannot move the decimal point to the right, adding
// rightmost zeros, because that would alter the precision.
appendAscii(unscaledText);
appendAscii('d');
appendAscii(Integer.toString(exponent));
}
}
Aggregations