]> granicus.if.org Git - icu/commitdiff
Siprefex, mass, area test passes
authorYounies <younies.mahmoud@gmail.com>
Tue, 18 Feb 2020 19:21:04 +0000 (20:21 +0100)
committerYounies <younies.mahmoud@gmail.com>
Tue, 18 Feb 2020 19:21:04 +0000 (20:21 +0100)
icu4c/source/i18n/number_decnum.h
icu4c/source/i18n/number_utils.cpp
icu4c/source/i18n/unitconverter.cpp
icu4c/source/test/intltest/intltest.cpp
icu4c/source/test/intltest/unitstest.cpp

index 9ea3017eaba41b62721a57ac751f0b505d867de4..18b599c656234c9f8a0bc28faa75dd745011a2ef 100644 (file)
@@ -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;
index 61ede6940075edf0bb3cd9003520a962eee16568..c9948c7352012eda4996b93d7c5e2f440b3c1cf5 100644 (file)
@@ -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<double>::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()); }
index d4363351a58fe1d56ac9cd0be8b4f4c7e6e3626c..2b971da0e7275354b5b8f19d3c4469bbb024fcb9 100644 (file)
@@ -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
index 7208dd68c51f9ab91a4e4e5c4f73199dfc54b20c..0533e9eb49b951c713e039a9494b05c6619c065a 100644 (file)
@@ -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 " +
index a604c8c3157b364b39b57f7025adf38ca657ebe5..997a1211e9b318c26c194536486c3c22a77d8611 100644 (file)
@@ -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) {