From cbdbb7cef42af7c919cb93d6eeccc4d04391eb24 Mon Sep 17 00:00:00 2001 From: Younies Date: Tue, 18 Feb 2020 20:21:04 +0100 Subject: [PATCH] Siprefex, mass, area test passes --- icu4c/source/i18n/number_decnum.h | 8 +- icu4c/source/i18n/number_utils.cpp | 36 ++++++++- icu4c/source/i18n/unitconverter.cpp | 93 ++++++++++-------------- icu4c/source/test/intltest/intltest.cpp | 4 +- icu4c/source/test/intltest/unitstest.cpp | 4 +- 5 files changed, 82 insertions(+), 63 deletions(-) diff --git a/icu4c/source/i18n/number_decnum.h b/icu4c/source/i18n/number_decnum.h index 9ea3017eaba..18b599c6562 100644 --- a/icu4c/source/i18n/number_decnum.h +++ b/icu4c/source/i18n/number_decnum.h @@ -51,6 +51,9 @@ class U_I18N_API DecNum : public UMemory { /** Returns integral value of the `DecNum` */ int32_t toInt32() const; + /** Returns double value of the `DecNum` */ + double toDouble() const; + void normalize(); void multiplyBy(double rhs, UErrorCode& status); @@ -65,8 +68,9 @@ class U_I18N_API DecNum : public UMemory { void subtract(double rhs, UErrorCode& status); void subtract(const DecNum& rhs, UErrorCode& status); - void power(int32_t power); - + void power(int32_t p, UErrorCode& status); + void power(const DecNum& rhs, UErrorCode& status); + bool isNegative() const; bool isZero() const; diff --git a/icu4c/source/i18n/number_utils.cpp b/icu4c/source/i18n/number_utils.cpp index 61ede694007..c9948c73520 100644 --- a/icu4c/source/i18n/number_utils.cpp +++ b/icu4c/source/i18n/number_utils.cpp @@ -241,7 +241,17 @@ void DecNum::setTo(const uint8_t *bcd, int32_t length, int32_t scale, bool isNeg int32_t DecNum::toInt32() const { decContext fContext; return uprv_decNumberToInt32(fData, &fContext); - } +} + +double DecNum::toDouble() const { + UErrorCode status = U_ZERO_ERROR; + StringPiece strNumber = toString(status); + if (U_FAILURE(status)) { + return std::numeric_limits::quiet_NaN(); + } + + return std::atof(strNumber.data()); +} void DecNum::normalize() { uprv_decNumberReduce(fData, fData, &fContext); } @@ -265,6 +275,16 @@ void DecNum::divideBy(double rhs, UErrorCode &status) { } void DecNum::divideBy(const DecNum &rhs, UErrorCode &status) { + if (rhs.isZero()) { + status = U_INTERNAL_PROGRAM_ERROR; // TODO(younies) + return; + } + + // For testing (remove) + StringPiece lhsStr = toString(status); + StringPiece rhsStr = rhs.toString(status); + // End for testing + uprv_decNumberDivide(fData, fData, rhs.fData, &fContext); if ((fContext.status & DEC_Inexact) != 0) { // Ignore. @@ -299,6 +319,20 @@ void DecNum::subtract(const DecNum &rhs, UErrorCode &status) { } } +void DecNum::power(int32_t p, UErrorCode &status) { + DecNum rhs; + rhs.setTo(p, status); + power(rhs, status); +} + +void DecNum::power(const DecNum& rhs, UErrorCode& status) { + uprv_decNumberPower(fData, fData, rhs.fData, &fContext); + + if(fContext.status != 0){ + status = U_INTERNAL_PROGRAM_ERROR; + } +} + bool DecNum::isNegative() const { return decNumberIsNegative(fData.getAlias()); } bool DecNum::isZero() const { return decNumberIsZero(fData.getAlias()); } diff --git a/icu4c/source/i18n/unitconverter.cpp b/icu4c/source/i18n/unitconverter.cpp index d4363351a58..2b971da0e72 100644 --- a/icu4c/source/i18n/unitconverter.cpp +++ b/icu4c/source/i18n/unitconverter.cpp @@ -29,11 +29,6 @@ struct Factor { number::impl::DecNum factorDen; number::impl::DecNum offset; - /*For Debugging*/ - StringPiece factorNumStr; - StringPiece factorDenStr; - StringPiece factorOffsetStr; - bool reciprocal = false; int32_t constants[CONSTANTS_COUNT] = {}; @@ -44,29 +39,19 @@ struct Factor { offset.setTo(0.0, status); } - void setStrings(UErrorCode &status) { - factorNumStr = factorNum.toString(status); - factorDenStr = factorDen.toString(status); - factorOffsetStr = offset.toString(status); - } - void multiplyBy(const Factor &rhs, UErrorCode &status) { factorNum.multiplyBy(rhs.factorNum, status); factorDen.multiplyBy(rhs.factorDen, status); for (int i = 0; i < CONSTANTS_COUNT; i++) constants[i] += rhs.constants[i]; offset.add(rhs.offset, status); // TODO(younies): fix this. - - setStrings(status); } void divideBy(const Factor &rhs, UErrorCode &status) { - factorNum.divideBy(rhs.factorNum, status); // Error if Numerator equal zero ! - factorDen.divideBy(rhs.factorDen, status); + factorNum.multiplyBy(rhs.factorDen, status); + factorDen.multiplyBy(rhs.factorNum, status); for (int i = 0; i < CONSTANTS_COUNT; i++) constants[i] -= rhs.constants[i]; // TODO(younies): fix this - - setStrings(status); } // apply the power to the factor. @@ -75,28 +60,19 @@ struct Factor { for (int i = 0; i < CONSTANTS_COUNT; i++) constants[i] *= power; - DecNum originNum(factorNum, status); - DecNum originDen(factorDen, status); - - factorNum.setTo(1, status); - factorDen.setTo(1, status); - - bool positive = power >= 0; + bool shouldFlip = power < 0; // This means that after applying the absolute power, we should flip + // the Numerator and Denomerator. int32_t absPower = std::abs(power); - for (int i = 0; i < absPower; i++) { - factorNum.multiplyBy(originNum, status); - factorDen.multiplyBy(originNum, status); - } + factorNum.power(absPower, status); + factorDen.power(absPower, status); - if (!positive) { + if (shouldFlip) { + // Flip Numerator and Denomirator. DecNum temp(factorNum, status); factorNum.setTo(factorDen, status); factorDen.setTo(temp, status); } - - - setStrings(status); } // Flip the `Factor`, for example, factor= 2/3, flippedFactor = 3/2 @@ -109,33 +85,15 @@ struct Factor { for (int i = 0; i < CONSTANTS_COUNT; i++) { constants[i] *= -1; } - - - setStrings(status); } // Apply SI prefix to the `Factor` void applySiPrefix(UMeasureSIPrefix siPrefix, UErrorCode &status) { - DecNum e; - e.setTo(1, status); - DecNum ten; - ten.setTo(10, status); - - bool positive = siPrefix > 0; - int32_t absSi = std::abs(siPrefix); - - for (int i = 0; i < absSi; i++) { - e.multiplyBy(ten, status); - } - - if (positive) { - factorNum.multiplyBy(e, status); - } else { - factorDen.multiplyBy(e, status); - } + DecNum siPrefixDecNum; + siPrefixDecNum.setTo(10, status); + siPrefixDecNum.power(siPrefix, status); - - setStrings(status); + factorNum.multiplyBy(siPrefixDecNum, status); } }; @@ -327,7 +285,7 @@ void substituteSingleConstant(Factor &factor, int32_t constValue, DecNum finalConstSub; finalConstSub.setTo(constSub, status); - finalConstSub.multiplyBy(absConstValue, status); + finalConstSub.power(absConstValue, status); if (positive) { factor.factorNum.multiplyBy(finalConstSub, status); @@ -372,11 +330,25 @@ void loadConversionRate(ConversionRate &conversionRate, StringPiece source, Stri loadCompoundFactor(SourcetoMiddle, source, status); loadCompoundFactor(TargettoMiddle, target, status); + double testing00 = finalFactor.factorNum.toDouble(); + double testing0 = finalFactor.factorDen.toDouble(); + + double testing1 = SourcetoMiddle.factorNum.toDouble(); + double testing2 = SourcetoMiddle.factorDen.toDouble(); + double testing3 = TargettoMiddle.factorNum.toDouble(); + double testing4 = TargettoMiddle.factorDen.toDouble(); + finalFactor.multiplyBy(SourcetoMiddle, status); finalFactor.divideBy(TargettoMiddle, status); + double testing5 = finalFactor.factorNum.toDouble(); + double testing6 = finalFactor.factorDen.toDouble(); + substituteConstants(finalFactor, status); + double testing8 = finalFactor.factorNum.toDouble(); + double testing9 = finalFactor.factorDen.toDouble(); + conversionRate.source = source; conversionRate.target = target; @@ -407,6 +379,8 @@ UnitConverter::UnitConverter(MeasureUnit source, MeasureUnit target, UErrorCode } void UnitConverter::convert(const DecNum &input_value, DecNum &output_value, UErrorCode status) { + + /* DecNum result(input_value, status); result.multiplyBy(conversion_rate_.factorNum, status); result.divideBy(conversion_rate_.factorDen, status); @@ -422,7 +396,14 @@ void UnitConverter::convert(const DecNum &input_value, DecNum &output_value, UEr output_value.setTo(result, status); } else { output_value.setTo(result, status); - } + }*/ + + double result = input_value.toDouble(); + double num = conversion_rate_.factorNum.toDouble(); + double den = conversion_rate_.factorDen.toDouble(); + result *= num / den; + + output_value.setTo(result, status); } U_NAMESPACE_END diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp index 7208dd68c51..0533e9eb49b 100644 --- a/icu4c/source/test/intltest/intltest.cpp +++ b/icu4c/source/test/intltest/intltest.cpp @@ -2184,10 +2184,10 @@ UBool IntlTest::assertEqualsNear(const char *message, const number::impl::DecNum decNumPrecision.setTo(precision, status); difference.setTo(expected, status); - // difference.subtract(actual, status); + difference.subtract(actual, status); if (difference.isNegative()) difference.multiplyBy(-1, status); - if (difference.greaterThan(decNumPrecision, status) || U_FAILURE(status) || true) { + if (difference.greaterThan(decNumPrecision, status) || U_FAILURE(status)) { std::string expectedAsString = expected.toString(status).data(); std::string actualAsString = actual.toString(status).data(); errln((UnicodeString) "FAIL: " + message + "; got " + actualAsString.c_str() + "; expected " + diff --git a/icu4c/source/test/intltest/unitstest.cpp b/icu4c/source/test/intltest/unitstest.cpp index a604c8c3157..997a1211e9b 100644 --- a/icu4c/source/test/intltest/unitstest.cpp +++ b/icu4c/source/test/intltest/unitstest.cpp @@ -48,7 +48,7 @@ void UnitsTest::runIndexedTest(int32_t index, UBool exec, const char *&name, cha } void UnitsTest::verifyTestCase(const UnitConversionTestCase &testCase) { - UErrorCode status; + UErrorCode status = U_ZERO_ERROR; MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status); MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status); @@ -72,7 +72,7 @@ void UnitsTest::testBasic() { UnitConversionTestCase testCases[]{ {"meter", "foot", 1.0, 3.28084}, // - {"kilometer", "foot", 1.0, 328.084} // + {"kilometer", "foot", 1.0, 3280.84} // }; for (const auto &testCase : testCases) { -- 2.40.0