blob: e58e59eab1a176ce5e06ba0f52c327a06ab634b0 [file] [log] [blame]
/* GENERATED SOURCE. DO NOT MODIFY. */
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package android.icu.dev.test.number;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import android.icu.dev.impl.number.DecimalQuantity_64BitBCD;
import android.icu.dev.impl.number.DecimalQuantity_ByteArrayBCD;
import android.icu.dev.impl.number.DecimalQuantity_SimpleStorage;
import android.icu.dev.test.TestFmwk;
import android.icu.impl.number.DecimalFormatProperties;
import android.icu.impl.number.DecimalQuantity;
import android.icu.impl.number.DecimalQuantity_DualStorageBCD;
import android.icu.number.LocalizedNumberFormatter;
import android.icu.number.NumberFormatter;
import android.icu.text.CompactDecimalFormat.CompactStyle;
import android.icu.text.DecimalFormatSymbols;
import android.icu.util.ULocale;
import android.icu.testsharding.MainTestShard;
@MainTestShard
@RunWith(JUnit4.class)
public class DecimalQuantityTest extends TestFmwk {
@Ignore
@Test
public void testBehavior() throws ParseException {
// Make a list of several formatters to test the behavior of DecimalQuantity.
List<LocalizedNumberFormatter> formats = new ArrayList<LocalizedNumberFormatter>();
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
DecimalFormatProperties properties = new DecimalFormatProperties();
formats.add(
NumberFormatter.fromDecimalFormat(properties, symbols, null).locale(ULocale.ENGLISH));
properties = new DecimalFormatProperties().setMinimumSignificantDigits(3)
.setMaximumSignificantDigits(3).setCompactStyle(CompactStyle.LONG);
formats.add(
NumberFormatter.fromDecimalFormat(properties, symbols, null).locale(ULocale.ENGLISH));
properties = new DecimalFormatProperties().setMinimumExponentDigits(1).setMaximumIntegerDigits(3)
.setMaximumFractionDigits(1);
formats.add(
NumberFormatter.fromDecimalFormat(properties, symbols, null).locale(ULocale.ENGLISH));
properties = new DecimalFormatProperties().setRoundingIncrement(new BigDecimal("0.5"));
formats.add(
NumberFormatter.fromDecimalFormat(properties, symbols, null).locale(ULocale.ENGLISH));
String[] cases = {
"1.0",
"2.01",
"1234.56",
"3000.0",
"0.00026418",
"0.01789261",
"468160.0",
"999000.0",
"999900.0",
"999990.0",
"0.0",
"12345678901.0",
"-5193.48", };
String[] hardCases = {
"9999999999999900.0",
"789000000000000000000000.0",
"789123123567853156372158.0",
"987654321987654321987654321987654321987654311987654321.0", };
String[] doubleCases = {
"512.0000000000017",
"4095.9999999999977",
"4095.999999999998",
"4095.9999999999986",
"4095.999999999999",
"4095.9999999999995",
"4096.000000000001",
"4096.000000000002",
"4096.000000000003",
"4096.000000000004",
"4096.000000000005",
"4096.0000000000055",
"4096.000000000006",
"4096.000000000007", };
int i = 0;
for (String str : cases) {
testDecimalQuantity(i++, str, formats, 0);
}
i = 0;
for (String str : hardCases) {
testDecimalQuantity(i++, str, formats, 1);
}
i = 0;
for (String str : doubleCases) {
testDecimalQuantity(i++, str, formats, 2);
}
}
static void testDecimalQuantity(
int t,
String str,
List<LocalizedNumberFormatter> formats,
int mode) {
if (mode == 2) {
assertEquals("Double is not valid", Double.toString(Double.parseDouble(str)), str);
}
List<DecimalQuantity> qs = new ArrayList<DecimalQuantity>();
BigDecimal d = new BigDecimal(str);
qs.add(new DecimalQuantity_SimpleStorage(d));
if (mode == 0)
qs.add(new DecimalQuantity_64BitBCD(d));
qs.add(new DecimalQuantity_ByteArrayBCD(d));
qs.add(new DecimalQuantity_DualStorageBCD(d));
if (new BigDecimal(Double.toString(d.doubleValue())).compareTo(d) == 0) {
double dv = d.doubleValue();
qs.add(new DecimalQuantity_SimpleStorage(dv));
if (mode == 0)
qs.add(new DecimalQuantity_64BitBCD(dv));
qs.add(new DecimalQuantity_ByteArrayBCD(dv));
qs.add(new DecimalQuantity_DualStorageBCD(dv));
}
if (new BigDecimal(Long.toString(d.longValue())).compareTo(d) == 0) {
double lv = d.longValue();
qs.add(new DecimalQuantity_SimpleStorage(lv));
if (mode == 0)
qs.add(new DecimalQuantity_64BitBCD(lv));
qs.add(new DecimalQuantity_ByteArrayBCD(lv));
qs.add(new DecimalQuantity_DualStorageBCD(lv));
}
testDecimalQuantityExpectedOutput(qs.get(0), str);
if (qs.size() == 1) {
return;
}
for (int i = 1; i < qs.size(); i++) {
DecimalQuantity q0 = qs.get(0);
DecimalQuantity q1 = qs.get(i);
testDecimalQuantityExpectedOutput(q1, str);
testDecimalQuantityRounding(q0, q1);
testDecimalQuantityRoundingInterval(q0, q1);
testDecimalQuantityMath(q0, q1);
testDecimalQuantityWithFormats(q0, q1, formats);
}
}
private static void testDecimalQuantityExpectedOutput(DecimalQuantity rq, String expected) {
DecimalQuantity q0 = rq.createCopy();
// Force an accurate double
q0.roundToInfinity();
q0.setIntegerLength(1, Integer.MAX_VALUE);
q0.setFractionLength(1, Integer.MAX_VALUE);
String actual = q0.toPlainString();
assertEquals("Unexpected output from simple string conversion (" + q0 + ")", expected, actual);
}
private static final MathContext MATH_CONTEXT_HALF_EVEN = new MathContext(0, RoundingMode.HALF_EVEN);
private static final MathContext MATH_CONTEXT_CEILING = new MathContext(0, RoundingMode.CEILING);
@SuppressWarnings("unused")
private static final MathContext MATH_CONTEXT_FLOOR = new MathContext(0, RoundingMode.FLOOR);
private static final MathContext MATH_CONTEXT_PRECISION = new MathContext(3, RoundingMode.HALF_UP);
private static void testDecimalQuantityRounding(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN);
q1.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_CEILING);
q1.roundToMagnitude(-1, MATH_CONTEXT_CEILING);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToMagnitude(-1, MATH_CONTEXT_PRECISION);
q1.roundToMagnitude(-1, MATH_CONTEXT_PRECISION);
testDecimalQuantityBehavior(q0, q1);
}
private static void testDecimalQuantityRoundingInterval(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN);
q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING);
q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING);
testDecimalQuantityBehavior(q0, q1);
}
private static void testDecimalQuantityMath(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
q0.adjustMagnitude(-3);
q1.adjustMagnitude(-3);
testDecimalQuantityBehavior(q0, q1);
q0 = rq0.createCopy();
q1 = rq1.createCopy();
q0.multiplyBy(new BigDecimal("3.14159"));
q1.multiplyBy(new BigDecimal("3.14159"));
testDecimalQuantityBehavior(q0, q1);
}
private static void testDecimalQuantityWithFormats(
DecimalQuantity rq0,
DecimalQuantity rq1,
List<LocalizedNumberFormatter> formats) {
for (LocalizedNumberFormatter format : formats) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
String s1 = format.format(q0).toString();
String s2 = format.format(q1).toString();
assertEquals("Different output from formatter (" + q0 + ", " + q1 + ")", s1, s2);
}
}
private static void testDecimalQuantityBehavior(DecimalQuantity rq0, DecimalQuantity rq1) {
DecimalQuantity q0 = rq0.createCopy();
DecimalQuantity q1 = rq1.createCopy();
assertEquals("Different sign (" + q0 + ", " + q1 + ")", q0.isNegative(), q1.isNegative());
assertEquals("Different fingerprint (" + q0 + ", " + q1 + ")",
q0.getPositionFingerprint(),
q1.getPositionFingerprint());
assertDoubleEquals("Different double values (" + q0 + ", " + q1 + ")",
q0.toDouble(),
q1.toDouble());
assertBigDecimalEquals("Different BigDecimal values (" + q0 + ", " + q1 + ")",
q0.toBigDecimal(),
q1.toBigDecimal());
q0.roundToInfinity();
q1.roundToInfinity();
assertEquals("Different lower display magnitude",
q0.getLowerDisplayMagnitude(),
q1.getLowerDisplayMagnitude());
assertEquals("Different upper display magnitude",
q0.getUpperDisplayMagnitude(),
q1.getUpperDisplayMagnitude());
for (int m = q0.getUpperDisplayMagnitude(); m >= q0.getLowerDisplayMagnitude(); m--) {
assertEquals("Different digit at magnitude " + m + " (" + q0 + ", " + q1 + ")",
q0.getDigit(m),
q1.getDigit(m));
}
if (rq0 instanceof DecimalQuantity_DualStorageBCD) {
String message = ((DecimalQuantity_DualStorageBCD) rq0).checkHealth();
if (message != null)
errln(message);
}
if (rq1 instanceof DecimalQuantity_DualStorageBCD) {
String message = ((DecimalQuantity_DualStorageBCD) rq1).checkHealth();
if (message != null)
errln(message);
}
}
@Test
public void testSwitchStorage() {
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
fq.setToLong(1234123412341234L);
assertFalse("Should not be using byte array", fq.isUsingBytes());
assertEquals("Failed on initialize", "1234123412341234E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
// Long -> Bytes
fq.appendDigit((byte) 5, 0, true);
assertTrue("Should be using byte array", fq.isUsingBytes());
assertEquals("Failed on multiply", "12341234123412345E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
// Bytes -> Long
fq.roundToMagnitude(5, MATH_CONTEXT_HALF_EVEN);
assertFalse("Should not be using byte array", fq.isUsingBytes());
assertEquals("Failed on round", "123412341234E5", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
}
@Test
public void testAppend() {
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
fq.appendDigit((byte) 1, 0, true);
assertEquals("Failed on append", "1E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 2, 0, true);
assertEquals("Failed on append", "12E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 3, 1, true);
assertEquals("Failed on append", "1203E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 0, 1, true);
assertEquals("Failed on append", "1203E2", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 4, 0, true);
assertEquals("Failed on append", "1203004E0", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 0, 0, true);
assertEquals("Failed on append", "1203004E1", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 5, 0, false);
assertEquals("Failed on append", "120300405E-1", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 6, 0, false);
assertEquals("Failed on append", "1203004056E-2", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
fq.appendDigit((byte) 7, 3, false);
assertEquals("Failed on append", "12030040560007E-6", fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
StringBuilder baseExpected = new StringBuilder("12030040560007");
for (int i = 0; i < 10; i++) {
fq.appendDigit((byte) 8, 0, false);
baseExpected.append('8');
StringBuilder expected = new StringBuilder(baseExpected);
expected.append("E");
expected.append(-7 - i);
assertEquals("Failed on append", expected.toString(), fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
}
fq.appendDigit((byte) 9, 2, false);
baseExpected.append("009");
StringBuilder expected = new StringBuilder(baseExpected);
expected.append('E');
expected.append("-19");
assertEquals("Failed on append", expected.toString(), fq.toNumberString());
assertNull("Failed health check", fq.checkHealth());
}
@Ignore
@Test
public void testConvertToAccurateDouble() {
// based on https://github.com/google/double-conversion/issues/28
double[] hardDoubles = {
1651087494906221570.0,
-5074790912492772E-327,
83602530019752571E-327,
2.207817077636718750000000000000,
1.818351745605468750000000000000,
3.941719055175781250000000000000,
3.738609313964843750000000000000,
3.967735290527343750000000000000,
1.328025817871093750000000000000,
3.920967102050781250000000000000,
1.015235900878906250000000000000,
1.335227966308593750000000000000,
1.344520568847656250000000000000,
2.879127502441406250000000000000,
3.695838928222656250000000000000,
1.845344543457031250000000000000,
3.793952941894531250000000000000,
3.211402893066406250000000000000,
2.565971374511718750000000000000,
0.965156555175781250000000000000,
2.700004577636718750000000000000,
0.767097473144531250000000000000,
1.780448913574218750000000000000,
2.624839782714843750000000000000,
1.305290222167968750000000000000,
3.834922790527343750000000000000, };
double[] integerDoubles = {
51423,
51423e10,
4.503599627370496E15,
6.789512076111555E15,
9.007199254740991E15,
9.007199254740992E15 };
for (double d : hardDoubles) {
checkDoubleBehavior(d, true, "");
}
for (double d : integerDoubles) {
checkDoubleBehavior(d, false, "");
}
assertEquals("NaN check failed",
Double.NaN,
new DecimalQuantity_DualStorageBCD(Double.NaN).toDouble());
assertEquals("Inf check failed",
Double.POSITIVE_INFINITY,
new DecimalQuantity_DualStorageBCD(Double.POSITIVE_INFINITY).toDouble());
assertEquals("-Inf check failed",
Double.NEGATIVE_INFINITY,
new DecimalQuantity_DualStorageBCD(Double.NEGATIVE_INFINITY).toDouble());
// Generate random doubles
String alert = "UNEXPECTED FAILURE: PLEASE REPORT THIS MESSAGE TO THE ICU TEAM: ";
Random rnd = new Random();
for (int i = 0; i < 10000; i++) {
double d = Double.longBitsToDouble(rnd.nextLong());
if (Double.isNaN(d) || Double.isInfinite(d))
continue;
checkDoubleBehavior(d, false, alert);
}
}
private static void checkDoubleBehavior(double d, boolean explicitRequired, String alert) {
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d);
if (explicitRequired) {
assertTrue(alert + "Should be using approximate double", !fq.explicitExactDouble);
}
assertEquals(alert + "Initial construction from hard double", d, fq.toDouble());
fq.roundToInfinity();
if (explicitRequired) {
assertTrue(alert + "Should not be using approximate double", fq.explicitExactDouble);
}
assertDoubleEquals(alert + "After conversion to exact BCD (double)", d, fq.toDouble());
assertBigDecimalEquals(alert + "After conversion to exact BCD (BigDecimal)",
new BigDecimal(Double.toString(d)),
fq.toBigDecimal());
}
@Test
public void testUseApproximateDoubleWhenAble() {
Object[][] cases = {
{ 1.2345678, 1, MATH_CONTEXT_HALF_EVEN, false },
{ 1.2345678, 7, MATH_CONTEXT_HALF_EVEN, false },
{ 1.2345678, 12, MATH_CONTEXT_HALF_EVEN, false },
{ 1.2345678, 13, MATH_CONTEXT_HALF_EVEN, true },
{ 1.235, 1, MATH_CONTEXT_HALF_EVEN, false },
{ 1.235, 2, MATH_CONTEXT_HALF_EVEN, true },
{ 1.235, 3, MATH_CONTEXT_HALF_EVEN, false },
{ 1.000000000000001, 0, MATH_CONTEXT_HALF_EVEN, false },
{ 1.000000000000001, 0, MATH_CONTEXT_CEILING, true },
{ 1.235, 1, MATH_CONTEXT_CEILING, false },
{ 1.235, 2, MATH_CONTEXT_CEILING, false },
{ 1.235, 3, MATH_CONTEXT_CEILING, true } };
for (Object[] cas : cases) {
double d = (Double) cas[0];
int maxFrac = (Integer) cas[1];
MathContext mc = (MathContext) cas[2];
boolean usesExact = (Boolean) cas[3];
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d);
assertTrue("Should be using approximate double", !fq.explicitExactDouble);
fq.roundToMagnitude(-maxFrac, mc);
assertEquals(
"Using approximate double after rounding: " + d + " maxFrac=" + maxFrac + " " + mc,
usesExact,
fq.explicitExactDouble);
}
}
@Test
public void testDecimalQuantityBehaviorStandalone() {
DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD();
assertToStringAndHealth(fq, "<DecimalQuantity 999:0:0:-999 long 0E0>");
fq.setToInt(51423);
assertToStringAndHealth(fq, "<DecimalQuantity 999:0:0:-999 long 51423E0>");
fq.adjustMagnitude(-3);
assertToStringAndHealth(fq, "<DecimalQuantity 999:0:0:-999 long 51423E-3>");
fq.setToLong(999999999999000L);
assertToStringAndHealth(fq, "<DecimalQuantity 999:0:0:-999 long 999999999999E3>");
fq.setIntegerLength(2, 5);
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:0:-999 long 999999999999E3>");
fq.setFractionLength(3, 6);
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:-3:-6 long 999999999999E3>");
fq.setToDouble(987.654321);
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:-3:-6 long 987654321E-6>");
fq.roundToInfinity();
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:-3:-6 long 987654321E-6>");
fq.roundToIncrement(new BigDecimal("0.005"), MATH_CONTEXT_HALF_EVEN);
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:-3:-6 long 987655E-3>");
fq.roundToMagnitude(-2, MATH_CONTEXT_HALF_EVEN);
assertToStringAndHealth(fq, "<DecimalQuantity 5:2:-3:-6 long 98766E-2>");
}
@Test
public void testFitsInLong() {
DecimalQuantity_DualStorageBCD quantity = new DecimalQuantity_DualStorageBCD();
quantity.setToInt(0);
assertTrue("Zero should fit", quantity.fitsInLong());
quantity.setToInt(42);
assertTrue("Small int should fit", quantity.fitsInLong());
quantity.setToDouble(0.1);
assertFalse("Fraction should not fit", quantity.fitsInLong());
quantity.setToDouble(42.1);
assertFalse("Fraction should not fit", quantity.fitsInLong());
quantity.setToLong(1000000);
assertTrue("Large low-precision int should fit", quantity.fitsInLong());
quantity.setToLong(1000000000000000000L);
assertTrue("10^19 should fit", quantity.fitsInLong());
quantity.setToLong(1234567890123456789L);
assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong());
quantity.setToLong(1234567890000000000L);
assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong());
quantity.setToLong(9223372026854775808L);
assertTrue("A number less than max long but with similar digits should fit",
quantity.fitsInLong());
quantity.setToLong(9223372036854775806L);
assertTrue("One less than max long should fit", quantity.fitsInLong());
quantity.setToLong(9223372036854775807L);
assertTrue("Max long should fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372036854775808"));
assertFalse("One greater than max long long should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372046854775806"));
assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372046800000000"));
assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("10000000000000000000"));
assertFalse("10^20 should not fit", quantity.fitsInLong());
}
@Test
public void testHardDoubleConversion() {
// This test is somewhat duplicated from previous tests, but it is needed
// for ICU4C compatibility.
Object[][] cases = {
{ 512.0000000000017, "512.0000000000017" },
{ 4095.9999999999977, "4095.9999999999977" },
{ 4095.999999999998, "4095.999999999998" },
{ 4095.9999999999986, "4095.9999999999986" },
{ 4095.999999999999, "4095.999999999999" },
{ 4095.9999999999995, "4095.9999999999995" },
{ 4096.000000000001, "4096.000000000001" },
{ 4096.000000000002, "4096.000000000002" },
{ 4096.000000000003, "4096.000000000003" },
{ 4096.000000000004, "4096.000000000004" },
{ 4096.000000000005, "4096.000000000005" },
{ 4096.0000000000055, "4096.0000000000055" },
{ 4096.000000000006, "4096.000000000006" },
{ 4096.000000000007, "4096.000000000007" } };
for (Object[] cas : cases) {
double input = (Double) cas[0];
String expectedOutput = (String) cas[1];
DecimalQuantity q = new DecimalQuantity_DualStorageBCD(input);
q.roundToInfinity();
String actualOutput = q.toPlainString();
assertEquals("", expectedOutput, actualOutput);
}
}
static void assertDoubleEquals(String message, double d1, double d2) {
boolean equal = (Math.abs(d1 - d2) < 1e-6) || (Math.abs((d1 - d2) / d1) < 1e-6);
handleAssert(equal, message, d1, d2, null, false);
}
static void assertBigDecimalEquals(String message, String d1, BigDecimal d2) {
assertBigDecimalEquals(message, new BigDecimal(d1), d2);
}
static void assertBigDecimalEquals(String message, BigDecimal d1, BigDecimal d2) {
boolean equal = d1.compareTo(d2) == 0;
handleAssert(equal, message, d1, d2, null, false);
}
static void assertToStringAndHealth(DecimalQuantity_DualStorageBCD fq, String expected) {
String actual = fq.toString();
assertEquals("DecimalQuantity toString", expected, actual);
String health = fq.checkHealth();
assertNull("DecimalQuantity health", health);
}
}