]> granicus.if.org Git - icu/commitdiff
add most of the functions, still need to be tested
authorYounies <younies.mahmoud@gmail.com>
Fri, 14 Feb 2020 13:27:10 +0000 (14:27 +0100)
committerYounies <younies.mahmoud@gmail.com>
Fri, 14 Feb 2020 13:27:10 +0000 (14:27 +0100)
icu4c/source/i18n/number_decnum.h
icu4c/source/i18n/number_utils.cpp
icu4c/source/i18n/unitconverter.cpp
icu4c/source/i18n/unitconverter.h
icu4c/source/test/intltest/intltest.cpp
icu4c/source/test/intltest/intltest.h
icu4c/source/test/intltest/unitstest.cpp

index 548f00eafddbcc726a81aac148ad1e33d4152091..9ea3017eaba41b62721a57ac751f0b505d867de4 100644 (file)
@@ -48,8 +48,8 @@ class U_I18N_API DecNum : public UMemory {
     /** Sets the decNumber to the BCD representation. */
     void setTo(const uint8_t* bcd, int32_t length, int32_t scale, bool isNegative, UErrorCode& status);
 
-    /** Returns the double representation of the `DecNum` */
-    double toDouble(UErrorCode& status) const;
+    /** Returns integral value of the `DecNum` */
+    int32_t toInt32() const;
 
     void normalize();
 
index ad780a72905e46426b4be030e990d2712bf26707..61ede6940075edf0bb3cd9003520a962eee16568 100644 (file)
@@ -238,11 +238,10 @@ void DecNum::setTo(const uint8_t *bcd, int32_t length, int32_t scale, bool isNeg
     }
 }
 
-double DecNum::toDouble(UErrorCode &status) const {
-    double result = 0.0;
-    // TODO(younies): implement
-    return result;
-}
+int32_t DecNum::toInt32() const {
+    decContext fContext;
+    return uprv_decNumberToInt32(fData, &fContext);
+ }
 
 void DecNum::normalize() { uprv_decNumberReduce(fData, fData, &fContext); }
 
@@ -281,7 +280,7 @@ void DecNum::add(double rhs, UErrorCode &status) {
 }
 
 void DecNum::add(const DecNum &rhs, UErrorCode &status) {
-    uprv_decNumberAdd_66(fData, fData, rhs.fData, &fContext);
+    uprv_decNumberAdd(fData, fData, rhs.fData, &fContext);
     if (fContext.status != 0) {
         status = U_INTERNAL_PROGRAM_ERROR;
     }
@@ -294,7 +293,7 @@ void DecNum::subtract(double rhs, UErrorCode &status) {
 }
 
 void DecNum::subtract(const DecNum &rhs, UErrorCode &status) {
-    uprv_decNumberSubtract_66(fData, fData, rhs.fData, &fContext);
+    uprv_decNumberSubtract(fData, fData, rhs.fData, &fContext);
     if (fContext.status != 0) {
         status = U_INTERNAL_PROGRAM_ERROR;
     }
@@ -305,29 +304,42 @@ bool DecNum::isNegative() const { return decNumberIsNegative(fData.getAlias());
 bool DecNum::isZero() const { return decNumberIsZero(fData.getAlias()); }
 
 bool DecNum::lessThan(const DecNum &rhs, UErrorCode &status) const {
-    // return uprv_decNumberCompare_66(fData, fData, rhs.fData, fContext);
-
-    return false; // TODO(younies): implement this function
+    // lhs < rhs --> lhs - rhs < 0 ==> lhs - rhs (is negative).
+    DecNum temp;
+    temp.setTo(*this, status);
+    temp.subtract(rhs, status);
+    return temp.isNegative();
 }
 
 bool DecNum::greaterThan(const DecNum &rhs, UErrorCode &status) const {
-    // return uprv_decNumberCompare_66(fData, fData, rhs.fData, fContext);
+    // lhs > rhs --> 0 > rhs - lhs ==> rhs - lhs (is negative).
+    DecNum temp;
+    temp.setTo(rhs, status);
+    temp.subtract(*this, status);
 
-    return false; // TODO(younies): implement this function
+    return temp.isNegative();
 }
 
 bool DecNum::equalTo(const DecNum &rhs, UErrorCode &status) const {
-    // return uprv_decNumberCompare_66(fData, fData, rhs.fData, fContext);
+    // lhs == rhs --> lhs - rhs == 0 ==> lhs - rhs (is zero).
+    DecNum temp;
+    temp.setTo(*this, status);
+    temp.subtract(rhs, status);
 
-    return false; // TODO(younies): implement this function
+    return temp.isZero();
 }
 
 StringPiece DecNum::toString(UErrorCode &status) const {
-    std::string result;
-    StringByteSink<std::string> output(&result);
-    toString(output, status);
+    if (U_FAILURE(status)) {
+        return StringPiece();
+    }
+
+    // "string must be at least dn->digits+14 characters long"
+    int32_t minCapacity = fData.getAlias()->digits + 14;
+    MaybeStackArray<char, 30> buffer(minCapacity);
+    uprv_decNumberToString(fData, buffer.getAlias());
 
-    return StringPiece(result);
+    return StringPiece(buffer.getAlias());
 }
 
 void DecNum::toString(ByteSink &output, UErrorCode &status) const {
index 90720b400514ab709ec6bd037e5afba5c2452955..ca8ca5bfca8c240a1b0f31150e93cfb01588d341 100644 (file)
@@ -30,7 +30,7 @@ struct Factor {
     number::impl::DecNum offset;
     bool reciprocal = false;
 
-    int8_t constants[CONSTANTS_COUNT] = {};
+    int32_t constants[CONSTANTS_COUNT] = {};
 
     Factor(UErrorCode &status) {
         factorNum.setTo(1.0, status);
@@ -47,7 +47,7 @@ struct Factor {
     }
 
     void divideBy(const Factor &rhs, UErrorCode &status) {
-        factorNum.divideBy(rhs.factorNum, status);
+        factorNum.divideBy(rhs.factorNum, status); // Error if Numerator equal zero !
         factorDen.divideBy(rhs.factorDen, status);
         for (int i = 0; i < CONSTANTS_COUNT; i++)
             constants[i] -= rhs.constants[i]; // TODO(younies): fix this
@@ -162,17 +162,17 @@ class UnitConversionRatesSink : public ResourceSink {
 void addSingleFactorConstant(Factor &factor, StringPiece baseStr, number::impl::DecNum &power,
                              int32_t signal, UErrorCode &status) {
     if (baseStr == "ft2m") {
-        factor.constants[CONSTANT_FT2M] += power.toDouble(status);
+        factor.constants[CONSTANT_FT2M] += power.toInt32();
     } else if (baseStr == "G") {
-        factor.constants[CONSTANT_G] += power.toDouble(status);
+        factor.constants[CONSTANT_G] += power.toInt32();
     } else if (baseStr == "gravity") {
-        factor.constants[CONSTANT_GRAVITY] += power.toDouble(status);
+        factor.constants[CONSTANT_GRAVITY] += power.toInt32();
     } else if (baseStr == "lb2kg") {
-        factor.constants[CONSTANT_LB2KG] += power.toDouble(status);
+        factor.constants[CONSTANT_LB2KG] += power.toInt32();
     } else if (baseStr == "cup2m3") {
-        factor.constants[CONSTANT_CUP2M3] += power.toDouble(status);
+        factor.constants[CONSTANT_CUP2M3] += power.toInt32();
     } else if (baseStr == "pi") {
-        factor.constants[CONSTANT_PI] += power.toDouble(status);
+        factor.constants[CONSTANT_PI] += power.toInt32();
     } else {
         if (U_FAILURE(status)) return;
 
@@ -220,7 +220,7 @@ void addFactorElement(Factor &factor, StringPiece elementStr, int32_t signal, UE
         baseStr = elementStr;
     }
 
-    power.multiplyBy(signalDecNum, status);
+    power.multiplyBy(signalDecNum, status); // The power needs to take the same sign as `signal`.
     addSingleFactorConstant(factor, baseStr, power, signal, status);
 }
 
@@ -298,14 +298,16 @@ void substituteSingleConstant(Factor &factor, int32_t constValue,
                               const DecNum &constSub /* constant actual value, e.g. G= 9.88888 */,
                               UErrorCode &status) {
     bool positive = constValue >= 0;
-    bool absConstValue = std::abs(constValue);
+    int32_t absConstValue = std::abs(constValue);
 
-    for (int i = 0; i < absConstValue; i++) {
-        if (positive) {
-            factor.factorNum.multiplyBy(constSub, status);
-        } else {
-            factor.factorDen.multiplyBy(constSub, status);
-        }
+    DecNum finalConstSub;
+    finalConstSub.setTo(constSub, status);
+    finalConstSub.multiplyBy(absConstValue, status);
+
+    if (positive) {
+        factor.factorNum.multiplyBy(finalConstSub, status);
+    } else {
+        factor.factorDen.multiplyBy(finalConstSub, status);
     }
 }
 
@@ -321,7 +323,9 @@ void substituteConstants(Factor &factor, UErrorCode &status) {
     constSubs[CONSTANT_LB2KG].setTo("0.453592", status);
 
     for (int i = 0; i < CONSTANTS_COUNT; i++) {
+        if (factor.constants[i] == 0) continue;
         substituteSingleConstant(factor, factor.constants[i], constSubs[i], status);
+        factor.constants[i] = 0;
     }
 }
 
@@ -344,7 +348,7 @@ void loadConversionRate(ConversionRate &conversionRate, StringPiece source, Stri
     loadCompoundFactor(TargettoMiddle, target, status);
 
     finalFactor.multiplyBy(SourcetoMiddle, status);
-    finalFactor.divideBy(SourcetoMiddle, status);
+    finalFactor.divideBy(TargettoMiddle, status);
 
     substituteConstants(finalFactor, status);
 
@@ -376,6 +380,9 @@ UnitConverter::UnitConverter(MeasureUnit source, MeasureUnit target, UErrorCode
 }
 
 void UnitConverter::convert(const DecNum &input_value, DecNum &output_value, UErrorCode status) {
+    std::printf(conversion_rate_.factorNum.toString(status).data());
+    std::printf(conversion_rate_.factorDen.toString(status).data());
+    std::printf(conversion_rate_.offset.toString(status).data());
 
     DecNum result(input_value, status);
     result.multiplyBy(conversion_rate_.factorNum, status);
index 0272abb0477ba14289e1c060345a60e245f5a958..b28aeedc0dc046f83d65fe5f1c0790ed5a45ed5d 100644 (file)
@@ -20,7 +20,7 @@ enum Constants {
     CONSTANT_FT2M, // ft2m stands for foot to meter.
     CONSTANT_PI,
     CONSTANT_GRAVITY,
-    CONSTANT_G,      
+    CONSTANT_G,
     CONSTANT_CUP2M3, // CUP2M3 stands for cup to cubic meter.
     CONSTANT_LB2KG,
 
@@ -48,7 +48,7 @@ struct ConversionRate {
 };
 
 // The data in this namespace are temporary, it is just for testing
-namespace temporarily {    
+namespace temporarily {
 
 struct entry {
     StringPiece source;
@@ -58,120 +58,118 @@ struct entry {
     bool reciprocal;
 } dataEntries[] = {
     // Base Units
-    {"kilogram", "kilogram", "", "", false},
-    {"candela", "candela", "", "", false},
-    {"meter", "meter", "", "", false},
-    {"second", "second", "", "", false},
-    {"year", "year", "", "", false},
-    {"ampere", "ampere", "", "", false},
-    {"kelvin", "kelvin", "", "", false},
-    {"revolution", "revolution", "", "", false},
-    {"item", "item", "", "", false},
-    {"portion", "portion", "", "", false},
-    {"bit", "bit", "", "", false},
-    {"pixel", "pixel", "", "", false},
-    {"em", "em", "", "", false},
+    {"kilogram", "kilogram", "1", "0", false},
+    {"candela", "candela", "1", "0", false},
+    {"meter", "meter", "1", "0", false},
+    {"second", "second", "1", "0", false},
+    {"year", "year", "1", "0", false},
+    {"ampere", "ampere", "1", "0", false},
+    {"kelvin", "kelvin", "1", "0", false},
+    {"revolution", "revolution", "1", "0", false},
+    {"item", "item", "1", "0", false},
+    {"portion", "portion", "1", "0", false},
+    {"bit", "bit", "1", "0", false},
+    {"pixel", "pixel", "1", "0", false},
+    {"em", "em", "1", "0", false},
 
     // Unit conversions Rates
-    {"atmosphere", "kilogram-per-meter-square-second", "101325", "", false},
-    {"byte", "bit", "8", "", false},
-    {"day", "second", "86400", "", false},
-    {"day-person", "second", "86400", "", false},
-    {"hour", "second", "3600", "", false},
-    {"minute", "second", "60", "", false},
-    {"week", "second", "604800", "", false},
-    {"week-person", "second", "604800", "", false},
-    {"ohm", "kilogram-square-meter-per-cubic-second-square-ampere", "1", "", false},
-    {"volt", "kilogram-square-meter-per-cubic-second-ampere", "1", "", false},
-    {"light-year", "meter", "9460730000000000", "", false},
-    {"parsec", "meter", "30856780000000000", "", false},
-    {"g-force", "meter-per-square-second", "gravity", "", false},
-    {"degree", "revolution", "1/360", "", false},
-    {"arc-minute", "revolution", "1/360*60", "", false},
-    {"arc-second", "revolution", "1/360*60*60", "", false},
-    {"radian", "revolution", "1/2*PI", "", false},
-    {"mole", "item", "602214076000000000000000", "", false},
-    {"percent", "portion", "1/100", "", false},
-    {"permille", "portion", "1/1000", "", false},
-    {"permyriad", "portion", "1/10000", "", false},
-    {"calorie", "kilogram-square-meter-per-square-second", "4.184", "", false},
-    {"electronvolt", "kilogram-square-meter-per-square-second", "0.0000000000000000001602177", "",
+    {"atmosphere", "kilogram-per-meter-square-second", "101325", "0", false},
+    {"byte", "bit", "8", "0", false},
+    {"day", "second", "86400", "0", false},
+    {"day-person", "second", "86400", "0", false},
+    {"hour", "second", "3600", "0", false},
+    {"minute", "second", "60", "0", false},
+    {"week", "second", "604800", "0", false},
+    {"week-person", "second", "604800", "0", false},
+    {"ohm", "kilogram-square-meter-per-cubic-second-square-ampere", "1", "0", false},
+    {"volt", "kilogram-square-meter-per-cubic-second-ampere", "1", "0", false},
+    {"light-year", "meter", "9460730000000000", "0", false},
+    {"parsec", "meter", "30856780000000000", "0", false},
+    {"g-force", "meter-per-square-second", "gravity", "0", false},
+    {"degree", "revolution", "1/360", "0", false},
+    {"arc-minute", "revolution", "1/360*60", "0", false},
+    {"arc-second", "revolution", "1/360*60*60", "0", false},
+    {"radian", "revolution", "1/2*PI", "0", false},
+    {"mole", "item", "602214076000000000000000", "0", false},
+    {"percent", "portion", "1/100", "0", false},
+    {"permille", "portion", "1/1000", "0", false},
+    {"permyriad", "portion", "1/10000", "0", false},
+    {"calorie", "kilogram-square-meter-per-square-second", "4.184", "0", false},
+    {"electronvolt", "kilogram-square-meter-per-square-second", "0.0000000000000000001602177", "0",
      false},
-    {"foodcalorie", "kilogram-square-meter-per-square-second", "4184", "", false},
-    {"hertz", "revolution-per-second", "1", "", false},
-    {"astronomical-unit", "meter", "149597900000", "", false},
-    {"acre", "square-meter", "ft2m^2*43560", "", false},
-    {"therm-us", "kilogram-square-meter-per-square-second", "105506000", "", false},
-    {"pound-force", "kilogram-meter-per-square-second", "lb2kg*gravity", "", false},
-    {"fathom", "meter", "ft2m*6", "", false},
-    {"foot", "meter", "ft2m", "", false},
-    {"furlong", "meter", "ft2m*660", "", false},
-    {"inch", "meter", "ft2m/12", "", false},
-    {"mile", "meter", "ft2m*5280", "", false},
-    {"nautical-mile", "meter", "1852", "", false},
-    {"yard", "meter", "ft2m*3", "", false},
-    {"100-kilometer", "meter", "100000", "", false},
-    {"ounce", "kilogram", "lb2kg/16", "", false},
-    {"ounce-troy", "kilogram", "0.03110348", "", false},
-    {"pound", "kilogram", "lb2kg", "", false},
-    {"stone", "kilogram", "lb2kg*14", "", false},
-    {"ton", "kilogram", "lb2kg*2000", "", false},
-    {"horsepower", "kilogram-square-meter-per-cubic-second", "ft2m*lb2kg*gravity*550", "", false},
-    {"inch-hg", "kilogram-per-meter-square-second", "3386.389", "", false},
-    {"knot", "meter-per-second", "1852/3600", "", false},
+    {"foodcalorie", "kilogram-square-meter-per-square-second", "4184", "0", false},
+    {"hertz", "revolution-per-second", "1", "0", false},
+    {"astronomical-unit", "meter", "149597900000", "0", false},
+    {"acre", "square-meter", "ft2m^2*43560", "0", false},
+    {"therm-us", "kilogram-square-meter-per-square-second", "105506000", "0", false},
+    {"pound-force", "kilogram-meter-per-square-second", "lb2kg*gravity", "0", false},
+    {"fathom", "meter", "ft2m*6", "0", false},
+    {"foot", "meter", "ft2m", "0", false},
+    {"furlong", "meter", "ft2m*660", "0", false},
+    {"inch", "meter", "ft2m/12", "0", false},
+    {"mile", "meter", "ft2m*5280", "0", false},
+    {"nautical-mile", "meter", "1852", "0", false},
+    {"yard", "meter", "ft2m*3", "0", false},
+    {"100-kilometer", "meter", "100000", "0", false},
+    {"ounce", "kilogram", "lb2kg/16", "0", false},
+    {"ounce-troy", "kilogram", "0.03110348", "0", false},
+    {"pound", "kilogram", "lb2kg", "0", false},
+    {"stone", "kilogram", "lb2kg*14", "0", false},
+    {"ton", "kilogram", "lb2kg*2000", "0", false},
+    {"horsepower", "kilogram-square-meter-per-cubic-second", "ft2m*lb2kg*gravity*550", "0", false},
+    {"inch-hg", "kilogram-per-meter-square-second", "3386.389", "0", false},
+    {"knot", "meter-per-second", "1852/3600", "0", false},
     {"fahrenheit", "kelvin", "5/9", "2298.35/9", false},
-    {"barrel", "cubic-meter", "cup2m3*672", "", false},
-    {"bushel", "cubic-meter", "0.03523907", "", false},
-    {"cup", "cubic-meter", "cup2m3", "", false},
-    {"fluid-ounce", "cubic-meter", "cup2m3/8", "", false},
-    {"gallon", "cubic-meter", "cup2m3*16", "", false},
-    {"tablespoon", "cubic-meter", "cup2m3/16", "", false},
-    {"teaspoon", "cubic-meter", "cup2m3/48", "", false},
-    {"karat", "portion", "1/24", "", false},
-    {"pint", "cubic-meter", "cup2m3*2", "", false},
-    {"quart", "cubic-meter", "cup2m3*4", "", false},
-    {"fluid-ounce-imperial", "cubic-meter", "0.00002841306", "", false},
-    {"gallon-imperial", "cubic-meter", "0.00454609", "", false},
-    {"dunam", "square-meter", "1000", "", false},
-    {"mile-scandinavian", "meter", "10000", "", false},
-    {"hectare", "square-meter", "10000", "", false},
-    {"joule", "kilogram-square-meter-per-square-second", "1", "", false},
-    {"newton", "kilogram-meter-per-square-second", "1", "", false},
-    {"carat", "kilogram", "0.0002", "", false},
-    {"gram", "kilogram", "0.001", "", false},
-    {"metric-ton", "kilogram", "1000", "", false},
-    {"watt", "kilogram-square-meter-per-cubic-second", "1", "", false},
-    {"bar", "kilogram-per-meter-square-second", "100000", "", false},
-    {"pascal", "kilogram-per-meter-square-second", "1", "", false},
+    {"barrel", "cubic-meter", "cup2m3*672", "0", false},
+    {"bushel", "cubic-meter", "0.03523907", "0", false},
+    {"cup", "cubic-meter", "cup2m3", "0", false},
+    {"fluid-ounce", "cubic-meter", "cup2m3/8", "0", false},
+    {"gallon", "cubic-meter", "cup2m3*16", "0", false},
+    {"tablespoon", "cubic-meter", "cup2m3/16", "0", false},
+    {"teaspoon", "cubic-meter", "cup2m3/48", "0", false},
+    {"karat", "portion", "1/24", "0", false},
+    {"pint", "cubic-meter", "cup2m3*2", "0", false},
+    {"quart", "cubic-meter", "cup2m3*4", "0", false},
+    {"fluid-ounce-imperial", "cubic-meter", "0.00002841306", "0", false},
+    {"gallon-imperial", "cubic-meter", "0.00454609", "0", false},
+    {"dunam", "square-meter", "1000", "0", false},
+    {"mile-scandinavian", "meter", "10000", "0", false},
+    {"hectare", "square-meter", "10000", "0", false},
+    {"joule", "kilogram-square-meter-per-square-second", "1", "0", false},
+    {"newton", "kilogram-meter-per-square-second", "1", "0", false},
+    {"carat", "kilogram", "0.0002", "0", false},
+    {"gram", "kilogram", "0.001", "0", false},
+    {"metric-ton", "kilogram", "1000", "0", false},
+    {"watt", "kilogram-square-meter-per-cubic-second", "1", "0", false},
+    {"bar", "kilogram-per-meter-square-second", "100000", "0", false},
+    {"pascal", "kilogram-per-meter-square-second", "1", "0", false},
     {"celsius", "kelvin", "1", "-273.15", false},
-    {"cup-metric", "cubic-meter", "0.00025", "", false},
-    {"liter", "cubic-meter", "0.001", "", false},
-    {"pint-metric", "cubic-meter", "0.0005", "", false},
-    {"centimeter", "meter", "1/100", "", false},
-    {"century", "year", "100", "", false},
-    {"decade", "year", "10", "", false},
-    {"dot", "pixel", "100", "", false},
-    {"month", "year", "12", "", false},
-    {"month-person", "year", "12", "", false},
-    {"solar-luminosity", "kilogram-square-meter-per-cubic-second", "382800000000000000000000000", "",
+    {"cup-metric", "cubic-meter", "0.00025", "0", false},
+    {"liter", "cubic-meter", "0.001", "0", false},
+    {"pint-metric", "cubic-meter", "0.0005", "0", false},
+    {"centimeter", "meter", "1/100", "0", false},
+    {"century", "year", "100", "0", false},
+    {"decade", "year", "10", "0", false},
+    {"dot", "pixel", "100", "0", false},
+    {"month", "year", "12", "0", false},
+    {"month-person", "year", "12", "0", false},
+    {"solar-luminosity", "kilogram-square-meter-per-cubic-second", "382800000000000000000000000", "0",
      false},
-    {"solar-radius", "meter", "132712440000000000000/G", "", false},
-    {"earth-radius", "meter", "6378100", "", false},
-    {"solar-mass", "kilogram", "19884700000000000000000000000000", "", false},
-    {"earth-mass", "kilogram", "5972200000000000000000000", "", false},
-    {"year-person", "year", "1", "", false},
-    {"part-per-million", "portion", "1/1000000", "", false},
-    {"millimeter-of-mercury", "kilogram-per-meter-square-second", "10132500/760000", "", false},
-    {"british-thermal-unit", "kilogram-square-meter-per-square-second", "1055.06", "", false},
-    {"point", "meter", "ft2m/864", "", false},
-    {"dalton", "kilogram-square-meter-per-square-second", "0.000000000149241808560", "", false},
-    {"lux", "candela-square-meter-per-square-meter", "1", "", false},
+    {"solar-radius", "meter", "132712440000000000000/G", "0", false},
+    {"earth-radius", "meter", "6378100", "0", false},
+    {"solar-mass", "kilogram", "19884700000000000000000000000000", "0", false},
+    {"earth-mass", "kilogram", "5972200000000000000000000", "0", false},
+    {"year-person", "year", "1", "0", false},
+    {"part-per-million", "portion", "1/1000000", "0", false},
+    {"millimeter-of-mercury", "kilogram-per-meter-square-second", "10132500/760000", "0", false},
+    {"british-thermal-unit", "kilogram-square-meter-per-square-second", "1055.06", "0", false},
+    {"point", "meter", "ft2m/864", "0", false},
+    {"dalton", "kilogram-square-meter-per-square-second", "0.000000000149241808560", "0", false},
+    {"lux", "candela-square-meter-per-square-meter", "1", "0", false},
 };
 
 } // namespace temporarily
 
-
-
 /**
  * Converts from a source `MeasureUnit` to a target `MeasureUnit`.
  */
index 5231d7e86db867e20d266360fa8162b129e556d2..097086ec95ebb7f982e85fdace8b52962410ac46 100644 (file)
@@ -44,6 +44,7 @@
 #include "udbgutil.h"
 #include "umutex.h"
 #include "uoptions.h"
+#include "number_decnum.h"
 
 #ifdef XP_MAC_CONSOLE
 #include <console.h>
@@ -2155,18 +2156,12 @@ UBool IntlTest::assertEquals(const char* message,
     return TRUE;
 }
 
-std::string decNumToString(const number::impl::DecNum& decNum) {   
-    std::string result;
-    // TODO(younies): implement.
-    return result;
-}
-
 UBool IntlTest::assertEquals(const char* message,
         const number::impl::DecNum& expected, const number::impl::DecNum& actual) {
             UErrorCode status;
     if (!expected.equalTo(actual, status)) {
-        std::string expectedAsString = decNumToString(expected);
-        std::string actualAsString = decNumToString(actual);
+        std::string expectedAsString = expected.toString(status).data();
+        std::string actualAsString = actual.toString(status).data();
         errln((UnicodeString)"FAIL: " + message +
             "; got " + actualAsString.c_str() +
             "; expected " + expectedAsString.c_str());
@@ -2174,33 +2169,40 @@ UBool IntlTest::assertEquals(const char* message,
     }
 #ifdef VERBOSE_ASSERTIONS
     else {
-        logln((UnicodeString)"Ok: " + message + "; got " + decNumToString(actual).c_str());
+        logln((UnicodeString)"Ok: " + message + "; got " + static_cast<std::string>(actual.toString(status).data()).c_str());
     }
 #endif
     return TRUE;
 }
 
-UBool IntlTest::assertNearlyEquals(const char* message,
-        const number::impl::DecNum& expected, const number::impl::DecNum& actual, double precision){
-            UErrorCode status;
-            double diff = std::abs( expected.toDouble(status) - actual.toDouble(status) );
+UBool IntlTest::assertEqualsNear(const char *message, const number::impl::DecNum &expected,
+                                 const number::impl::DecNum &actual, double precision) {
+    UErrorCode status = UErrorCode::U_ZERO_ERROR;
+    number::impl::DecNum difference;
 
-    if (!U_FAILURE(status) && diff <= precision) {
-        std::string expectedAsString = decNumToString(expected);
-        std::string actualAsString = decNumToString(actual);
-        errln((UnicodeString)"FAIL: " + message +
-            "; got " + actualAsString.c_str() +
-            "; expected " + expectedAsString.c_str());
+    number::impl::DecNum decNumPrecision;
+    decNumPrecision.setTo(precision, status);
+
+    difference.setTo(expected, status);
+    difference.subtract(actual, status);
+    if (difference.isNegative()) difference.multiplyBy(-1, status);
+
+    if (difference.greaterThan(decNumPrecision, status) || U_FAILURE(status) || true) {
+        std::string expectedAsString = expected.toString(status).data();
+        std::string actualAsString = actual.toString(status).data();
+        errln((UnicodeString) "FAIL: " + message + "; got " + actualAsString.c_str() + "; expected " +
+              expectedAsString.c_str());
         return FALSE;
     }
 #ifdef VERBOSE_ASSERTIONS
     else {
-        logln((UnicodeString)"Ok: " + message + "; got " + decNumToString(actual).c_str());
+        logln((UnicodeString) "Ok: " + message + "; got " +
+              static_cast<std::string>(actual.toString(status).data()).c_str());
     }
 #endif
     return TRUE;
 }
-     
+
 static char ASSERT_BUF[256];
 
 static const char* extractToAssertBuf(const UnicodeString& message) {
index dc771fdc26076a8143960c340c1f0e716b4bb049..964df7aa4f30b1afd1138bd6859732ed651f1520 100644 (file)
@@ -306,7 +306,7 @@ public:
         const std::vector<std::string>& expected, const std::vector<std::string>& actual);
     UBool assertEquals(const char* message,
         const number::impl::DecNum& expected, const number::impl::DecNum& actual);
-    UBool assertNearlyEquals(const char* message,
+    UBool assertEqualsNear(const char* message,
         const number::impl::DecNum& expected, const number::impl::DecNum& actual, double precision);     
 #if !UCONFIG_NO_FORMATTING
     UBool assertEquals(const char* message, const Formattable& expected,
index da980637ebf182fa121122d255890ebb4f24be0c..a604c8c3157b364b39b57f7025adf38ca657ebe5 100644 (file)
@@ -7,6 +7,14 @@
 
 #include "../../i18n/unitconverter.h"
 #include "intltest.h"
+#include "number_decnum.h"
+
+struct UnitConversionTestCase {
+    const StringPiece source;
+    const StringPiece target;
+    const double inputValue;
+    const double expectedValue;
+};
 
 class UnitsTest : public IntlTest {
   public:
@@ -21,8 +29,7 @@ class UnitsTest : public IntlTest {
     void testArea();
 
     // TODO(younies): fix this.
-    void assertConversion(StringPiece message, StringPiece source, StringPiece target, double inputValue,
-                          double expectedValue);
+    void verifyTestCase(const UnitConversionTestCase &testCase);
 };
 
 extern IntlTest *createUnitsTest() { return new UnitsTest(); }
@@ -40,22 +47,36 @@ void UnitsTest::runIndexedTest(int32_t index, UBool exec, const char *&name, cha
     TESTCASE_AUTO_END;
 }
 
+void UnitsTest::verifyTestCase(const UnitConversionTestCase &testCase) {
+    UErrorCode status;
+
+    MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
+    MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
+
+    UnitConverter converter(sourceUnit, targetUnit, status);
+
+    number::impl::DecNum inputValue;
+    inputValue.setTo(testCase.inputValue, status);
+
+    number::impl::DecNum expectedValue;
+    expectedValue.setTo(testCase.expectedValue, status);
+
+    number::impl::DecNum actualConversionResult;
+    converter.convert(inputValue, actualConversionResult, status);
+
+    assertEqualsNear("test Conversion", expectedValue, actualConversionResult, 0.01);
+}
+
 void UnitsTest::testBasic() {
     IcuTestErrorCode status(*this, "Units testBasic");
 
-    // Test Cases
-    struct TestCase {
-        const StringPiece source;
-        const StringPiece target;
-        const double inputValue;
-        const double expectedValue;
-    } testCases[]{
+    UnitConversionTestCase testCases[]{
         {"meter", "foot", 1.0, 3.28084},    //
         {"kilometer", "foot", 1.0, 328.084} //
     };
 
     for (const auto &testCase : testCases) {
-        UErrorCode status;
+        UErrorCode status = U_ZERO_ERROR;
 
         MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
         MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
@@ -71,19 +92,14 @@ void UnitsTest::testBasic() {
         number::impl::DecNum actualConversionResult;
         converter.convert(inputValue, actualConversionResult, status);
 
-        assertNearlyEquals("test Conversion", actualConversionResult, expectedValue, 0.01);
+        assertEqualsNear("test Conversion", expectedValue, actualConversionResult, 0.01);
     }
 }
 
 void UnitsTest::testSiPrefixes() {
     IcuTestErrorCode status(*this, "Units testSiPrefixes");
-    // Test Cases
-    struct TestCase {
-        const StringPiece source;
-        const StringPiece target;
-        const double inputValue;
-        const double expectedValue;
-    } testCases[]{
+
+    UnitConversionTestCase testCases[]{
         {"gram", "kilogram", 1.0, 0.001},            //
         {"milligram", "kilogram", 1.0, 0.000001},    //
         {"microgram", "kilogram", 1.0, 0.000000001}, //
@@ -93,36 +109,14 @@ void UnitsTest::testSiPrefixes() {
     };
 
     for (const auto &testCase : testCases) {
-        UErrorCode status;
-
-        MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
-        MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
-
-        UnitConverter converter(sourceUnit, targetUnit, status);
-
-        number::impl::DecNum inputValue;
-        inputValue.setTo(testCase.inputValue, status);
-
-        number::impl::DecNum expectedValue;
-        expectedValue.setTo(testCase.expectedValue, status);
-
-        number::impl::DecNum actualConversionResult;
-        converter.convert(inputValue, actualConversionResult, status);
-
-        assertNearlyEquals("test Conversion", actualConversionResult, expectedValue, 0.01);
+        verifyTestCase(testCase);
     }
 }
 
 void UnitsTest::testMass() {
     IcuTestErrorCode status(*this, "Units testMass");
 
-    // Test Cases
-    struct TestCase {
-        const StringPiece source;
-        const StringPiece target;
-        const double inputValue;
-        const double expectedValue;
-    } testCases[]{
+    UnitConversionTestCase testCases[]{
         {"gram", "kilogram", 1.0, 0.001},      //
         {"pound", "kilogram", 1.0, 0.453592},  //
         {"pound", "kilogram", 2.0, 0.907185},  //
@@ -134,35 +128,14 @@ void UnitsTest::testMass() {
     };
 
     for (const auto &testCase : testCases) {
-        UErrorCode status;
-
-        MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
-        MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
-
-        UnitConverter converter(sourceUnit, targetUnit, status);
-
-        number::impl::DecNum inputValue;
-        inputValue.setTo(testCase.inputValue, status);
-
-        number::impl::DecNum expectedValue;
-        expectedValue.setTo(testCase.expectedValue, status);
-
-        number::impl::DecNum actualConversionResult;
-        converter.convert(inputValue, actualConversionResult, status);
-
-        assertNearlyEquals("test Conversion", actualConversionResult, expectedValue, 0.01);
+        verifyTestCase(testCase);
     }
 }
 
 void UnitsTest::testTemperature() {
     IcuTestErrorCode status(*this, "Units testTemperature");
-    // Test Cases
-    struct TestCase {
-        const StringPiece source;
-        const StringPiece target;
-        const double inputValue;
-        const double expectedValue;
-    } testCases[]{
+
+    UnitConversionTestCase testCases[]{
         {"celsius", "fahrenheit", 0.0, 32.0},   //
         {"celsius", "fahrenheit", 10.0, 50.0},  //
         {"fahrenheit", "celsius", 32.0, 0.0},   //
@@ -174,36 +147,14 @@ void UnitsTest::testTemperature() {
     };
 
     for (const auto &testCase : testCases) {
-        UErrorCode status;
-
-        MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
-        MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
-
-        UnitConverter converter(sourceUnit, targetUnit, status);
-
-        number::impl::DecNum inputValue;
-        inputValue.setTo(testCase.inputValue, status);
-
-        number::impl::DecNum expectedValue;
-        expectedValue.setTo(testCase.expectedValue, status);
-
-        number::impl::DecNum actualConversionResult;
-        converter.convert(inputValue, actualConversionResult, status);
-
-        assertNearlyEquals("test Conversion", actualConversionResult, expectedValue, 0.01);
+        verifyTestCase(testCase);
     }
 }
 
 void UnitsTest::testArea() {
     IcuTestErrorCode status(*this, "Units Area");
 
-    // Test Cases
-    struct TestCase {
-        const StringPiece source;
-        const StringPiece target;
-        const double inputValue;
-        const double expectedValue;
-    } testCases[]{
+    UnitConversionTestCase testCases[]{
         {"square-meter", "square-yard", 10.0, 11.9599} //
         ,
         {"hectare", "square-yard", 1.0, 11959.9} //
@@ -224,23 +175,7 @@ void UnitsTest::testArea() {
     };
 
     for (const auto &testCase : testCases) {
-        UErrorCode status;
-
-        MeasureUnit sourceUnit = MeasureUnit::forIdentifier(testCase.source, status);
-        MeasureUnit targetUnit = MeasureUnit::forIdentifier(testCase.target, status);
-
-        UnitConverter converter(sourceUnit, targetUnit, status);
-
-        number::impl::DecNum inputValue;
-        inputValue.setTo(testCase.inputValue, status);
-
-        number::impl::DecNum expectedValue;
-        expectedValue.setTo(testCase.expectedValue, status);
-
-        number::impl::DecNum actualConversionResult;
-        converter.convert(inputValue, actualConversionResult, status);
-
-        assertNearlyEquals("test Conversion", actualConversionResult, expectedValue, 0.01);
+        verifyTestCase(testCase);
     }
 }