return;
}
}
+
this->init(*biggestUnit, ratesInfo, status);
}
+ComplexUnitsConverter::ComplexUnitsConverter(StringPiece inputUnitIdentifier,
+ StringPiece outputUnitsIdentifier, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ MeasureUnitImpl inputUnit = MeasureUnitImpl::forIdentifier(inputUnitIdentifier, status);
+ MeasureUnitImpl outputUnits = MeasureUnitImpl::forIdentifier(outputUnitsIdentifier, status);
+
+ this->units_ = outputUnits.extractIndividualUnitsWithIndices(status);
+ U_ASSERT(units_.length() != 0);
+
+ this->init(inputUnit, ConversionRates(status), status);
+}
+
ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnitImpl &inputUnit,
const MeasureUnitImpl &outputUnits,
const ConversionRates &ratesInfo, UErrorCode &status)
* Constructs `ComplexUnitsConverter` for an `targetUnit` that could be Single, Compound or Mixed.
* In case of:
* 1- Single and Compound units,
- * the conversion will not perform anything, the input will be equal to the output.
+ * the conversion will not perform anything, the input will be equal to the output.
* 2- Mixed Unit
- * the conversion will consider the input is the biggest unit. And will convert it to be spread
- * through the target units. For example: if target unit is "inch-and-foot", and the input is 2.5. The
- * converter will consider the input value in "foot", because foot is the biggest unit. Then, it
- * will convert 2.5 feet to "inch-and-foot".
+ * the conversion will consider the input is the biggest unit. And will convert it to be spread
+ * through the target units. For example: if target unit is "inch-and-foot", and the input is 2.5.
+ * The converter will consider the input value in "foot", because foot is the biggest unit.
+ * Then, it will convert 2.5 feet to "inch-and-foot".
*
- * @param targetUnit could be any type. (single, compound or mixed).
+ * @param targetUnit could be any units type (single, compound or mixed).
+ * @param ratesInfo
* @param status
*/
ComplexUnitsConverter(const MeasureUnitImpl &targetUnit, const ConversionRates &ratesInfo,
* @param outputUnits represents the output unit. could be any type. (single, compound or mixed).
* @param status
*/
+ ComplexUnitsConverter(StringPiece inputUnitIdentifier, StringPiece outputUnitsIdentifier,
+ UErrorCode &status);
+
+ /**
+ * Constructor of `ComplexUnitsConverter`.
+ * NOTE:
+ * - inputUnit and outputUnits must be under the same category
+ * - e.g. meter to feet and inches --> all of them are length units.
+ *
+ * @param inputUnit represents the source unit. (should be single or compound unit).
+ * @param outputUnits represents the output unit. could be any type. (single, compound or mixed).
+ * @param ratesInfo
+ * @param status
+ */
ComplexUnitsConverter(const MeasureUnitImpl &inputUnit, const MeasureUnitImpl &outputUnits,
const ConversionRates &ratesInfo, UErrorCode &status);
void UnitsTest::testComplexUnitsConverter() {
IcuTestErrorCode status(*this, "UnitsTest::testComplexUnitsConverter");
- // DBL_EPSILON is aproximately 2.22E-16, and is the precision of double for
+ // DBL_EPSILON is approximately 2.22E-16, and is the precision of double for
// values in the range [1.0, 2.0), but half the precision of double for
// [2.0, 4.0).
U_ASSERT(1.0 + DBL_EPSILON > 1.0);
MeasureUnit input, output;
MeasureUnitImpl tempInput, tempOutput;
MaybeStackVector<Measure> measures;
- for (const TestCase &testCase : testCases) {
- input = MeasureUnit::forIdentifier(testCase.input, status);
- output = MeasureUnit::forIdentifier(testCase.output, status);
- const MeasureUnitImpl& inputImpl = MeasureUnitImpl::forMeasureUnit(input, tempInput, status);
- const MeasureUnitImpl& outputImpl = MeasureUnitImpl::forMeasureUnit(output, tempOutput, status);
- auto converter = ComplexUnitsConverter(inputImpl, outputImpl, rates, status);
+ auto testATestCase = [&](const ComplexUnitsConverter& converter ,StringPiece initMsg , const TestCase &testCase) {
measures = converter.convert(testCase.value, nullptr, status);
- CharString msg;
+ CharString msg(initMsg, status);
msg.append(testCase.msg, status);
msg.append(" ", status);
msg.append(testCase.input, status);
assertEquals(msg.data(), testCase.expected[i].getUnit().getIdentifier(),
measures[i]->getUnit().getIdentifier());
}
+ };
+
+ for (const auto &testCase : testCases)
+ {
+ input = MeasureUnit::forIdentifier(testCase.input, status);
+ output = MeasureUnit::forIdentifier(testCase.output, status);
+ const MeasureUnitImpl& inputImpl = MeasureUnitImpl::forMeasureUnit(input, tempInput, status);
+ const MeasureUnitImpl& outputImpl = MeasureUnitImpl::forMeasureUnit(output, tempOutput, status);
+
+ ComplexUnitsConverter converter1(inputImpl, outputImpl, rates, status);
+ testATestCase(converter1, "ComplexUnitsConverter #1 " , testCase);
+
+ // Test ComplexUnitsConverter created with CLDR units identifiers.
+ ComplexUnitsConverter converter2( testCase.input, testCase.output, status);
+ testATestCase(converter2, "ComplexUnitsConverter #1 " , testCase);
}
+
+
status.assertSuccess();
// TODO(icu-units#63): test negative numbers!
}
}
}
-
- MeasureUnitImpl source = MeasureUnitImpl::forIdentifier("meter", status);
- MeasureUnitImpl target = MeasureUnitImpl::forIdentifier("inch-and-foot", status);
-
- ComplexUnitsConverter complexConverter(source, target, conversionRates, status);
- auto measures = complexConverter.convert(10.0, nullptr, status);
-
- if (2 == measures.length()) {
- assertEquals("inch-and-foot unit 0", "inch", measures[0]->getUnit().getIdentifier());
- assertEquals("inch-and-foot unit 1", "foot", measures[1]->getUnit().getIdentifier());
-
- assertEqualsNear("inch-and-foot value 0", 9.7008, measures[0]->getNumber().getDouble(), 0.0001);
- assertEqualsNear("inch-and-foot value 1", 32, measures[1]->getNumber().getInt64(), 0.00001);
- }
}
/**
* Constructs <code>ComplexUnitsConverter</code> NOTE: - inputUnit and outputUnits must be under the same category -
* e.g. meter to feet and inches --> all of them are length units.
*
- * @param targetUnit
+ * @param inputUnitIdentifier
+ * represents the source unit identifier. (should be single or compound unit).
+ * @param outputUnitsIdentifier
+ * represents the output unit identifier. could be any type. (single, compound or mixed).
+ */
+ public ComplexUnitsConverter(String inputUnitIdentifier, String outputUnitsIdentifier) {
+ this(
+ MeasureUnitImpl.forIdentifier(inputUnitIdentifier),
+ MeasureUnitImpl.forIdentifier(outputUnitsIdentifier),
+ new ConversionRates()
+ );
+ }
+
+ /**
+ * Constructs <code>ComplexUnitsConverter</code> NOTE: - inputUnit and outputUnits must be under the same category -
+ * e.g. meter to feet and inches --> all of them are length units.
+ *
+ * @param inputUnit
* represents the source unit. (should be single or compound unit).
* @param outputUnits
* represents the output unit. could be any type. (single, compound or mixed).
+ * @param conversionRates
*/
- public ComplexUnitsConverter(MeasureUnitImpl targetUnit, MeasureUnitImpl outputUnits,
+ public ComplexUnitsConverter(MeasureUnitImpl inputUnit, MeasureUnitImpl outputUnits,
ConversionRates conversionRates) {
- this.inputUnit_ = targetUnit;
+ this.inputUnit_ = inputUnit;
this.units_ = outputUnits.extractIndividualUnitsWithIndices();
assert (!this.units_.isEmpty());
this.expected = expected;
this.accuracy = accuracy;
}
+
+ void testATestCase(ComplexUnitsConverter converter) {
+ List<Measure> measures = converter.convert(value, null).measures;
+
+ assertEquals("measures length", expected.length, measures.size());
+ int i = 0;
+ for (Measure measure : measures) {
+ double accuracy = 0.0;
+ if (i == expected.length - 1) {
+ accuracy = accuracy;
+ }
+ assertTrue("input " + value + ", output measure " + i + ": expected " +
+ expected[i] + ", expected unit " +
+ expected[i].getUnit() + " got unit " + measure.getUnit(),
+ expected[i].getUnit().equals(measure.getUnit()));
+ assertEquals("input " + value + ", output measure " + i + ": expected " +
+ expected[i] + ", expected number " +
+ expected[i].getNumber() + " got number " + measure.getNumber(),
+ expected[i].getNumber().doubleValue(),
+ measure.getNumber().doubleValue(), accuracy);
+ i++;
+ }
+ }
}
+
TestCase[] testCases = new TestCase[] {
// Significantly less than 2.0.
new TestCase(
0),
};
+
ConversionRates rates = new ConversionRates();
MeasureUnit input, output;
- List<Measure> measures;
for (TestCase testCase : testCases) {
input = MeasureUnit.forIdentifier(testCase.input);
output = MeasureUnit.forIdentifier(testCase.output);
final MeasureUnitImpl inputImpl = MeasureUnitImpl.forIdentifier(input.getIdentifier());
final MeasureUnitImpl outputImpl = MeasureUnitImpl.forIdentifier(output.getIdentifier());
- ComplexUnitsConverter converter = new ComplexUnitsConverter(inputImpl, outputImpl, rates);
- measures = converter.convert(testCase.value, null).measures;
-
- assertEquals("measures length", testCase.expected.length, measures.size());
- int i = 0;
- for (Measure measure : measures) {
- double accuracy = 0.0;
- if (i == testCase.expected.length - 1) {
- accuracy = testCase.accuracy;
- }
- assertTrue("input " + testCase.value + ", output measure " + i + ": expected " +
- testCase.expected[i] + ", expected unit " +
- testCase.expected[i].getUnit() + " got unit " + measure.getUnit(),
- testCase.expected[i].getUnit().equals(measure.getUnit()));
- assertEquals("input " + testCase.value + ", output measure " + i + ": expected " +
- testCase.expected[i] + ", expected number " +
- testCase.expected[i].getNumber() + " got number " + measure.getNumber(),
- testCase.expected[i].getNumber().doubleValue(),
- measure.getNumber().doubleValue(), accuracy);
- i++;
- }
+ ComplexUnitsConverter converter1 = new ComplexUnitsConverter(inputImpl, outputImpl, rates);
+
+ testCase.testATestCase(converter1);
+
+ // Test ComplexUnitsConverter created with CLDR units identifiers.
+ ComplexUnitsConverter converter2 = new ComplexUnitsConverter(testCase.input, testCase.output);
+ testCase.testATestCase(converter2);
}
// TODO(icu-units#63): test negative numbers!
@Test
- public void testComplexUnitConverterSorting() {
+ public void testComplexUnitsConverterSorting() {
class TestCase {
String message;
String inputUnit;