diff --git a/icu4c/source/i18n/measunit_extra.cpp b/icu4c/source/i18n/measunit_extra.cpp index 090cb803ac0..e39d6dab697 100644 --- a/icu4c/source/i18n/measunit_extra.cpp +++ b/icu4c/source/i18n/measunit_extra.cpp @@ -87,7 +87,7 @@ const struct SIPrefixStrings { { "yocto", UMEASURE_SI_PREFIX_YOCTO }, }; -// FIXME: Get this list from data +// TODO(ICU-20920): Get this list from data const char16_t* const gSimpleUnits[] = { u"one", // note: expected to be index 0 u"100kilometer", @@ -308,7 +308,7 @@ private: int32_t fMatch; }; -struct PowerUnit { +struct SingleUnit { int8_t power = 1; UMeasureSIPrefix siPrefix = UMEASURE_SI_PREFIX_ONE; int32_t simpleUnitIndex = 0; @@ -357,13 +357,13 @@ struct PowerUnit { class CompoundUnit { public: - typedef MaybeStackVector PowerUnitList; + typedef MaybeStackVector SingleUnitList; - void append(PowerUnit&& powerUnit, UErrorCode& status) { - if (powerUnit.power >= 0) { - appendImpl(numerator, std::move(powerUnit), status); + void append(SingleUnit&& singleUnit, UErrorCode& status) { + if (singleUnit.power >= 0) { + appendImpl(numerator, std::move(singleUnit), status); } else { - appendImpl(denominator, std::move(powerUnit), status); + appendImpl(denominator, std::move(singleUnit), status); } } @@ -373,7 +373,7 @@ public: denominator = std::move(temp); } - void appendTo(CharString& builder, UErrorCode& status) { + void appendTo(CharString& builder, UErrorCode& status) const { if (numerator.length() == 0) { builder.append("one", status); } else { @@ -385,19 +385,23 @@ public: } } - const PowerUnitList& getNumeratorUnits() { + const SingleUnitList& getNumeratorUnits() const { return numerator; } - const PowerUnitList& getDenominatorUnits() { + const SingleUnitList& getDenominatorUnits() const { return denominator; } -private: - PowerUnitList numerator; - PowerUnitList denominator; + bool isSingle() const { + return numerator.length() + denominator.length() == 1; + } - void appendToImpl(const PowerUnitList& unitList, int32_t len, CharString& builder, UErrorCode& status) { +private: + SingleUnitList numerator; + SingleUnitList denominator; + + void appendToImpl(const SingleUnitList& unitList, int32_t len, CharString& builder, UErrorCode& status) const { bool first = true; for (int32_t i = 0; i < len; i++) { if (first) { @@ -409,23 +413,23 @@ private: } } - void appendImpl(PowerUnitList& unitList, PowerUnit&& powerUnit, UErrorCode& status) { + void appendImpl(SingleUnitList& unitList, SingleUnit&& singleUnit, UErrorCode& status) { // Check that the same simple unit doesn't already exist for (int32_t i = 0; i < unitList.length(); i++) { - PowerUnit* candidate = unitList[i]; - if (candidate->simpleUnitIndex == powerUnit.simpleUnitIndex - && candidate->siPrefix == powerUnit.siPrefix) { - candidate->power += powerUnit.power; + SingleUnit* candidate = unitList[i]; + if (candidate->simpleUnitIndex == singleUnit.simpleUnitIndex + && candidate->siPrefix == singleUnit.siPrefix) { + candidate->power += singleUnit.power; return; } } // Add a new unit - PowerUnit* destination = unitList.emplaceBack(); + SingleUnit* destination = unitList.emplaceBack(); if (!destination) { status = U_MEMORY_ALLOCATION_ERROR; return; } - *destination = std::move(powerUnit); + *destination = std::move(singleUnit); } }; @@ -446,10 +450,10 @@ public: return fIndex < fSource.length(); } - PowerUnit getOnlyPowerUnit(UErrorCode& status) { + SingleUnit getOnlySingleUnit(UErrorCode& status) { bool sawPlus; - PowerUnit retval; - nextPowerUnit(retval, sawPlus, status); + SingleUnit retval; + nextSingleUnit(retval, sawPlus, status); if (U_FAILURE(status)) { return retval; } @@ -468,13 +472,13 @@ public: } while (hasNext()) { int32_t previ = fIndex; - PowerUnit powerUnit; - nextPowerUnit(powerUnit, sawPlus, status); + SingleUnit singleUnit; + nextSingleUnit(singleUnit, sawPlus, status); if (sawPlus) { fIndex = previ; break; } - result.append(std::move(powerUnit), status); + result.append(std::move(singleUnit), status); } return; } @@ -537,7 +541,7 @@ private: return Token(match); } - void nextPowerUnit(PowerUnit& result, bool& sawPlus, UErrorCode& status) { + void nextSingleUnit(SingleUnit& result, bool& sawPlus, UErrorCode& status) { sawPlus = false; if (U_FAILURE(status)) { return; @@ -607,7 +611,7 @@ private: case Token::TYPE_ONE: // Skip "one" and go to the next unit - return nextPowerUnit(result, sawPlus, status); + return nextSingleUnit(result, sawPlus, status); case Token::TYPE_SIMPLE_UNIT: result.simpleUnitIndex = token.getSimpleUnitIndex(); @@ -654,42 +658,61 @@ MeasureUnit MeasureUnit::forIdentifier(const char* identifier, UErrorCode& statu return MeasureUnit(builder.cloneData(status)); } +UMeasureUnitComplexity MeasureUnit::getComplexity(UErrorCode& status) const { + const char* id = getIdentifier(); + UnitIdentifierParser parser = UnitIdentifierParser::from(id, status); + if (U_FAILURE(status)) { + // Unrecoverable error + return UMEASURE_UNIT_SINGLE; + } + + CompoundUnit compoundUnit; + parser.nextCompoundUnit(compoundUnit, status); + if (compoundUnit.isSingle()) { + return UMEASURE_UNIT_SINGLE; + } else if (parser.hasNext()) { + return UMEASURE_UNIT_SEQUENCE; + } else { + return UMEASURE_UNIT_COMPOUND; + } +} + UMeasureSIPrefix MeasureUnit::getSIPrefix(UErrorCode& status) const { const char* id = getIdentifier(); - return UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status).siPrefix; + return UnitIdentifierParser::from(id, status).getOnlySingleUnit(status).siPrefix; } MeasureUnit MeasureUnit::withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const { const char* id = getIdentifier(); - PowerUnit powerUnit = UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status); + SingleUnit singleUnit = UnitIdentifierParser::from(id, status).getOnlySingleUnit(status); if (U_FAILURE(status)) { return *this; } - powerUnit.siPrefix = prefix; + singleUnit.siPrefix = prefix; CharString builder; - powerUnit.appendTo(builder, status); + singleUnit.appendTo(builder, status); return MeasureUnit(builder.cloneData(status)); } int8_t MeasureUnit::getPower(UErrorCode& status) const { const char* id = getIdentifier(); - return UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status).power; + return UnitIdentifierParser::from(id, status).getOnlySingleUnit(status).power; } MeasureUnit MeasureUnit::withPower(int8_t power, UErrorCode& status) const { const char* id = getIdentifier(); - PowerUnit powerUnit = UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status); + SingleUnit singleUnit = UnitIdentifierParser::from(id, status).getOnlySingleUnit(status); if (U_FAILURE(status)) { return *this; } CharString builder; - powerUnit.power = power; + singleUnit.power = power; if (power < 0) { builder.append("one-per-", status); } - powerUnit.appendTo(builder, status); + singleUnit.appendTo(builder, status); return MeasureUnit(builder.cloneData(status)); } @@ -729,15 +752,15 @@ MeasureUnit MeasureUnit::product(const MeasureUnit& other, UErrorCode& status) c return MeasureUnit(builder.cloneData(status)); } -LocalArray MeasureUnit::getSimpleUnits(UErrorCode& status) const { +LocalArray MeasureUnit::getSingleUnits(UErrorCode& status) const { const char* id = getIdentifier(); CompoundUnit compoundUnit = UnitIdentifierParser::from(id, status).getOnlyCompoundUnit(status); if (U_FAILURE(status)) { return LocalArray::withLength(nullptr, 0); } - const CompoundUnit::PowerUnitList& numerator = compoundUnit.getNumeratorUnits(); - const CompoundUnit::PowerUnitList& denominator = compoundUnit.getDenominatorUnits(); + const CompoundUnit::SingleUnitList& numerator = compoundUnit.getNumeratorUnits(); + const CompoundUnit::SingleUnitList& denominator = compoundUnit.getDenominatorUnits(); int32_t count = numerator.length() + denominator.length(); MeasureUnit* arr = new MeasureUnit[count]; diff --git a/icu4c/source/i18n/unicode/measunit.h b/icu4c/source/i18n/unicode/measunit.h index c9947d3edff..cdf760fdbdb 100644 --- a/icu4c/source/i18n/unicode/measunit.h +++ b/icu4c/source/i18n/unicode/measunit.h @@ -31,6 +31,44 @@ U_NAMESPACE_BEGIN class StringEnumeration; +/** + * Enumeration for unit complexity. There are three levels: + * + * - SINGLE: A single unit, optionally with a power and/or SI prefix. Examples: hectare, + * square-kilometer, kilojoule, one-per-second. + * - COMPOUND: A unit composed of the product of multiple single units. Examples: + * meter-per-second, kilowatt-hour, kilogram-meter-per-square-second. + * - SEQUENCE: A unit composed of the sum of multiple compound units. Examples: foot+inch, + * hour+minute+second, hectare+square-meter. + * + * The complexity determines which operations are available. For example, you cannot set the power + * or SI prefix of a compound unit. + * + * @draft ICU 67 + */ +enum UMeasureUnitComplexity { + /** + * A single unit, like kilojoule. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_SINGLE, + + /** + * A compound unit, like meter-per-second. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_COMPOUND, + + /** + * A sequence unit, like hour+minute. + * + * @draft ICU 67 + */ + UMEASURE_UNIT_SEQUENCE +}; + /** * Enumeration for SI prefixes, such as "kilo". * @@ -297,60 +335,74 @@ class U_I18N_API MeasureUnit: public UObject { const char* getIdentifier() const; /** - * Creates a MeasureUnit which is this MeasureUnit augmented with the specified SI prefix. + * Compute the complexity of the unit. See UMeasureUnitComplexity for more information. + * + * @param status Set if an error occurs. + * @return The unit complexity. + * @draft ICU 67 + */ + UMeasureUnitComplexity getComplexity(UErrorCode& status) const; + + /** + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified SI prefix. * For example, UMEASURE_SI_PREFIX_KILO for "kilo". * * There is sufficient locale data to format all standard SI prefixes. * - * This method only works if the MeasureUnit is composed of only one simple unit. An error - * will be set if called on a MeasureUnit containing multiple units. + * NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. * * @param prefix The SI prefix, from UMeasureSIPrefix. - * @param status ICU error code - * @return A new MeasureUnit. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. */ MeasureUnit withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const; /** - * Gets the current SI prefix of this MeasureUnit. For example, if the unit has the SI prefix + * Gets the current SI prefix of this SINGLE unit. For example, if the unit has the SI prefix * "kilo", then UMEASURE_SI_PREFIX_KILO is returned. * - * If the MeasureUnit is composed of multiple simple units, the SI prefix of the first simple - * unit is returned. For example, from "centimeter-kilogram-per-second", the SI prefix - * UMEASURE_SI_PREFIX_CENTI will be returned. + * NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. * - * @return The SI prefix of the first simple unit, from UMeasureSIPrefix. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The SI prefix of this SINGLE unit, from UMeasureSIPrefix. */ UMeasureSIPrefix getSIPrefix(UErrorCode& status) const; /** - * Creates a MeasureUnit which is this MeasureUnit augmented with the specified power. For + * Creates a MeasureUnit which is this SINGLE unit augmented with the specified power. For * example, if power is 2, the unit will be squared. * - * This method only works if the MeasureUnit is composed of only one simple unit. An error - * will be set if called on a MeasureUnit containing multiple units. + * NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. * * @param power The power. - * @param status ICU error code - * @return A new MeasureUnit. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return A new SINGLE unit. */ MeasureUnit withPower(int8_t power, UErrorCode& status) const; /** * Gets the power of this MeasureUnit. For example, if the unit is square, then 2 is returned. * - * If the MeasureUnit is composed of multiple simple units, the power of the first simple unit - * is returned. For example, from "cubic-meter-per-square-second", 3 is returned. + * NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. * - * @return The power of the first simple unit. + * @param status Set if this is not a SINGLE unit or if another error occurs. + * @return The power of this simple unit. */ int8_t getPower(UErrorCode& status) const; /** - * Gets the reciprocal of the unit, with the numerator and denominator flipped. + * Gets the reciprocal of this MeasureUnit, with the numerator and denominator flipped. * * For example, if the receiver is "meter-per-second", the unit "second-per-meter" is returned. * + * NOTE: Only works on SINGLE and COMPOUND units. If this is a SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is a SEQUENCE unit or if another error occurs. * @return The reciprocal of the target unit. */ MeasureUnit reciprocal(UErrorCode& status) const; @@ -364,88 +416,42 @@ class U_I18N_API MeasureUnit: public UObject { * For example, if the receiver is "kilowatt" and the argument is "hour-per-day", then the * unit "kilowatt-hour-per-day" is returned. * + * NOTE: Only works on SINGLE and COMPOUND units. If either unit (receivee and argument) is a + * SEQUENCE unit, an error will occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this or other is a SEQUENCE unit or if another error occurs. * @return The product of the target unit with the provided unit. */ MeasureUnit product(const MeasureUnit& other, UErrorCode& status) const; /** - * Gets the number of constituent simple units. + * Gets the list of single units contained within a compound unit. * - * For example, if the receiver is "meter-per-square-second", then 2 is returned, since there - * are two simple units: "meter" and "second". + * For example, given "meter-kilogram-per-second", three units will be returned: "meter", + * "kilogram", and "one-per-second". * - * @return The number of constituent units. + * If this is a SINGLE unit, an array of length 1 will be returned. + * + * NOTE: Only works on SINGLE and COMPOUND units. If this is a SEQUENCE unit, an error will + * occur. For more information, see UMeasureUnitComplexity. + * + * @param status Set if this is a SEQUENCE unit or if another error occurs. + * @return An array of single units, owned by the caller. */ - size_t getSimpleUnitCount(UErrorCode& status) const; - - LocalArray getSimpleUnits(UErrorCode& status) const; - - LocalArray getSequenceUnits(UErrorCode& status) const; + LocalArray getSingleUnits(UErrorCode& status) const; /** - * Gets the constituent unit at the given index. - * - * For example, to loop over all simple units: - * - *
-     * MeasureUnit unit(u"meter-per-square-second");
-     * for (size_t i = 0; i < unit.getSimpleUnitCount(); i++) {
-     *     std::cout << unit.simpleUnitAt(i).toString() << std::endl;
-     * }
-     * 
- * - * Expected output: meter, one-per-square-second - * - * @param index Zero-based index. If out of range, the dimensionless unit is returned. - * @return The constituent simple unit at the specified position. + * Gets the list of compound units contained within a sequence unit. + * + * For example, given "hour+minute+second", three units will be returned: "hour", "minute", + * and "second". + * + * If this is a SINGLE or COMPOUND unit, an array of length 1 will be returned. + * + * @param status Set of an error occurs. + * @return An array of compound units, owned by the caller. */ - MeasureUnit simpleUnitAt(size_t index, UErrorCode& status) const; - - /** - * Composes this unit with a super unit. - * - * A super unit, used for formatting only, should be a larger unit sharing the same dimension. - * For example, if the current unit is "inch", a super unit could be "foot", in order to - * render 71 inches as "5 feet, 11 inches". If the super unit is invalid, an error will occur - * during formatting. - * - * A unit can have multiple super units; for example, "second" could have both "minute" and - * "hour" as super units. - * - * Super units are ignored and left untouched in most other methods, such as withSIPrefix, - * withPower, and reciprocal. - * - * @param other The super unit to compose with the target unit. - * @return The composition of the given super unit with this unit. - */ - MeasureUnit withSuperUnit(const MeasureUnit& other, UErrorCode& status) const; - - /** - * Gets the number of super units in the receiver. - * - * For example, "foot+inch" has one super unit. - * - * @return The number of super units. - */ - size_t getSuperUnitCount(UErrorCode& status) const; - - /** - * Gets the super unit at the given index. - * - * For example, to loop over all super units: - * - *
-     * MeasureUnit unit(u"hour+minute+second");
-     * for (size_t i = 0; i < unit.getSuperUnitCount(); i++) {
-     *     std::cout << unit.superUnitAt(i).toCoreUnitIdentifier() << std::endl;
-     * }
-     * 
- * - * Expected output: hour, minute - * - * @return The super unit at the specified position. - */ - MeasureUnit superUnitAt(size_t index, UErrorCode& status) const; + LocalArray getCompoundUnits(UErrorCode& status) const; /** * getAvailable gets all of the available units. diff --git a/icu4c/source/test/intltest/measfmttest.cpp b/icu4c/source/test/intltest/measfmttest.cpp index 5af03b77e64..b15ca5b0128 100644 --- a/icu4c/source/test/intltest/measfmttest.cpp +++ b/icu4c/source/test/intltest/measfmttest.cpp @@ -139,7 +139,7 @@ private: NumberFormat::EAlignmentFields field, int32_t start, int32_t end); - void verifyPowerUnit( + void verifySingleUnit( const MeasureUnit& unit, UMeasureSIPrefix siPrefix, int8_t power, @@ -3239,11 +3239,11 @@ void MeasureFormatTest::TestCompoundUnitOperations() { MeasureUnit centimeter2 = meter.withSIPrefix(UMEASURE_SI_PREFIX_CENTI, status); MeasureUnit cubicDecimeter = cubicMeter.withSIPrefix(UMEASURE_SI_PREFIX_DECI, status); - verifyPowerUnit(kilometer, UMEASURE_SI_PREFIX_KILO, 1, "kilometer"); - verifyPowerUnit(meter, UMEASURE_SI_PREFIX_ONE, 1, "meter"); - verifyPowerUnit(centimeter1, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter"); - verifyPowerUnit(centimeter2, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter"); - verifyPowerUnit(cubicDecimeter, UMEASURE_SI_PREFIX_DECI, 3, "cubic-decimeter"); + verifySingleUnit(kilometer, UMEASURE_SI_PREFIX_KILO, 1, "kilometer"); + verifySingleUnit(meter, UMEASURE_SI_PREFIX_ONE, 1, "meter"); + verifySingleUnit(centimeter1, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter"); + verifySingleUnit(centimeter2, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter"); + verifySingleUnit(cubicDecimeter, UMEASURE_SI_PREFIX_DECI, 3, "cubic-decimeter"); assertTrue("centimeter equality", centimeter1 == centimeter2); assertTrue("kilometer inequality", centimeter1 != kilometer); @@ -3253,10 +3253,10 @@ void MeasureFormatTest::TestCompoundUnitOperations() { MeasureUnit quarticKilometer = kilometer.withPower(4, status); MeasureUnit overQuarticKilometer1 = kilometer.withPower(-4, status); - verifyPowerUnit(squareMeter, UMEASURE_SI_PREFIX_ONE, 2, "square-meter"); - verifyPowerUnit(overCubicCentimeter, UMEASURE_SI_PREFIX_CENTI, -3, "one-per-cubic-centimeter"); - verifyPowerUnit(quarticKilometer, UMEASURE_SI_PREFIX_KILO, 4, "p4-kilometer"); - verifyPowerUnit(overQuarticKilometer1, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); + verifySingleUnit(squareMeter, UMEASURE_SI_PREFIX_ONE, 2, "square-meter"); + verifySingleUnit(overCubicCentimeter, UMEASURE_SI_PREFIX_CENTI, -3, "one-per-cubic-centimeter"); + verifySingleUnit(quarticKilometer, UMEASURE_SI_PREFIX_KILO, 4, "p4-kilometer"); + verifySingleUnit(overQuarticKilometer1, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); assertTrue("power inequality", quarticKilometer != overQuarticKilometer1); @@ -3266,8 +3266,8 @@ void MeasureFormatTest::TestCompoundUnitOperations() { .product(kilometer, status) .reciprocal(status); - verifyPowerUnit(overQuarticKilometer2, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); - verifyPowerUnit(overQuarticKilometer3, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); + verifySingleUnit(overQuarticKilometer2, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); + verifySingleUnit(overQuarticKilometer3, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer"); assertTrue("reciprocal equality", overQuarticKilometer1 == overQuarticKilometer2); assertTrue("reciprocal equality", overQuarticKilometer1 == overQuarticKilometer3); @@ -3281,7 +3281,7 @@ void MeasureFormatTest::TestCompoundUnitOperations() { MeasureUnit secondCentimeter = kiloSquareSecond.product(meter.withSIPrefix(UMEASURE_SI_PREFIX_CENTI, status), status); MeasureUnit secondCentimeterPerKilometer = secondCentimeter.product(kilometer.reciprocal(status), status); - verifyPowerUnit(kiloSquareSecond, UMEASURE_SI_PREFIX_KILO, 2, "square-kilosecond"); + verifySingleUnit(kiloSquareSecond, UMEASURE_SI_PREFIX_KILO, 2, "square-kilosecond"); const char* meterSecondSub[] = {"meter", "square-kilosecond"}; verifyCompoundUnit(meterSecond, "meter-square-kilosecond", meterSecondSub, UPRV_LENGTHOF(meterSecondSub)); @@ -3387,12 +3387,12 @@ void MeasureFormatTest::verifyFormat( } } -void MeasureFormatTest::verifyPowerUnit( +void MeasureFormatTest::verifySingleUnit( const MeasureUnit& unit, UMeasureSIPrefix siPrefix, int8_t power, const char* identifier) { - IcuTestErrorCode status(*this, "verifyPowerUnit"); + IcuTestErrorCode status(*this, "verifySingleUnit"); UnicodeString uid(identifier, -1, US_INV); assertEquals(uid + ": SI prefix", siPrefix, @@ -3409,6 +3409,10 @@ void MeasureFormatTest::verifyPowerUnit( assertTrue(uid + ": Constructor", unit == MeasureUnit::forIdentifier(identifier, status)); status.errIfFailureAndReset("%s: Constructor", identifier); + assertEquals(uid + ": Complexity", + UMEASURE_UNIT_SINGLE, + unit.getComplexity(status)); + status.errIfFailureAndReset("%s: Complexity", identifier); } void MeasureFormatTest::verifyCompoundUnit( @@ -3425,14 +3429,21 @@ void MeasureFormatTest::verifyCompoundUnit( assertTrue(uid + ": Constructor", unit == MeasureUnit::forIdentifier(identifier, status)); status.errIfFailureAndReset("%s: Constructor", identifier); + assertEquals(uid + ": Complexity", + UMEASURE_UNIT_COMPOUND, + unit.getComplexity(status)); + status.errIfFailureAndReset("%s: Complexity", identifier); - LocalArray subUnits = unit.getSimpleUnits(status); + LocalArray subUnits = unit.getSingleUnits(status); assertEquals(uid + ": Length", subIdentifierCount, subUnits.length()); for (int32_t i = 0;; i++) { if (i >= subIdentifierCount || i >= subUnits.length()) break; assertEquals(uid + ": Sub-unit #" + Int64ToUnicodeString(i), subIdentifiers[i], subUnits[i].getIdentifier()); + assertEquals(uid + ": Sub-unit Complexity", + UMEASURE_UNIT_SINGLE, + subUnits[i].getComplexity(status)); } }