home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / nmfmtrt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  8.6 KB  |  308 lines

  1. /*
  2. ********************************************************************
  3. * COPYRIGHT: 
  4. * (C) Copyright International Business Machines Corporation, 1998
  5. * Licensed Material - Program-Property of IBM - All Rights Reserved. 
  6. * US Government Users Restricted Rights - Use, duplication, or disclosure 
  7. * restricted by GSA ADP Schedule Contract with IBM Corp. 
  8. *
  9. ********************************************************************
  10. */
  11.  
  12. #include "nmfmtrt.h"
  13.  
  14. #include "dcfmtsym.h"
  15. #include "decimfmt.h"
  16. #include "locid.h"
  17.  
  18. #include <float.h>
  19. #include <stdio.h>    // for sprintf
  20.  
  21. // *****************************************************************************
  22. // class NumberFormatRoundTripTest
  23. // *****************************************************************************
  24.  
  25. bool_t NumberFormatRoundTripTest::verbose                    = FALSE;
  26. bool_t NumberFormatRoundTripTest::STRING_COMPARE            = TRUE;
  27. bool_t NumberFormatRoundTripTest::EXACT_NUMERIC_COMPARE        = FALSE;
  28. bool_t NumberFormatRoundTripTest::DEBUG                        = FALSE;
  29. double NumberFormatRoundTripTest::MAX_ERROR                    = 1e-14;
  30. double NumberFormatRoundTripTest::max_numeric_error            = 0.0;
  31. double NumberFormatRoundTripTest::min_numeric_error            = 1.0;
  32.  
  33. #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;
  34.  
  35. void NumberFormatRoundTripTest::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
  36. {
  37.     // if (exec) logln((UnicodeString)"TestSuite NumberFormatRoundTripTest");
  38.     switch (index) {
  39.         CASE(0, start)
  40.         default: name = ""; break;
  41.     }
  42. }
  43.  
  44. bool_t 
  45. NumberFormatRoundTripTest::failure(UErrorCode status, const char* msg)
  46. {
  47.     if(U_FAILURE(status)) {
  48.         errln(UnicodeString("FAIL: ") + msg + " failed, error " + errorName(status));
  49.         return TRUE;
  50.     }
  51.  
  52.     return FALSE;
  53. }
  54.  
  55. void 
  56. NumberFormatRoundTripTest::start()
  57. {
  58. // test(NumberFormat.getInstance(new Locale("sr", "", "")));
  59.     
  60.     UErrorCode status = U_ZERO_ERROR;
  61.  
  62.     NumberFormat *fmt = NULL;
  63.  
  64.     logln("Default Locale");
  65.  
  66.     fmt = NumberFormat::createInstance(status);
  67.     failure(status, "NumberFormat::createInstance");
  68.     test(fmt);
  69.     delete fmt;
  70.     
  71.     fmt = NumberFormat::createCurrencyInstance(status);
  72.     failure(status, "NumberFormat::createCurrencyInstance");
  73.     test(fmt);
  74.     delete fmt;
  75.     
  76.     fmt = NumberFormat::createPercentInstance(status);
  77.     failure(status, "NumberFormat::createPercentInstance");
  78.     test(fmt);
  79.     delete fmt;
  80.  
  81.  
  82.     int32_t locCount = 0;
  83.     const Locale *loc = NumberFormat::getAvailableLocales(locCount);
  84.     if(quick) {
  85.         if(locCount > 5)
  86.             locCount = 5;
  87.         logln("Quick mode: only testing first 5 Locales");
  88.     }
  89.     for(int i = 0; i < locCount; ++i) {
  90.         UnicodeString name;
  91.         logln(loc[i].getDisplayName(name));
  92.  
  93.         fmt = NumberFormat::createInstance(loc[i], status);
  94.         failure(status, "NumberFormat::createInstance");
  95.         test(fmt);
  96.         delete fmt;
  97.     
  98.         fmt = NumberFormat::createCurrencyInstance(loc[i], status);
  99.         failure(status, "NumberFormat::createCurrencyInstance");
  100.         test(fmt);
  101.         delete fmt;
  102.     
  103.         fmt = NumberFormat::createPercentInstance(loc[i], status);
  104.         failure(status, "NumberFormat::createPercentInstance");
  105.         test(fmt);
  106.         delete fmt;
  107.     }
  108.  
  109.     logln(UnicodeString("Numeric error ") + min_numeric_error + " to " + max_numeric_error);
  110. }
  111.  
  112.  
  113. void 
  114. NumberFormatRoundTripTest::test(NumberFormat *fmt)
  115. {
  116.     if (TRUE)
  117.     {
  118.         test(fmt, icu_getNaN());
  119.         test(fmt, icu_getInfinity());
  120.         test(fmt, -icu_getInfinity());
  121.  
  122.         test(fmt, (int32_t)500);
  123.         test(fmt, (int32_t)0);
  124.         test(fmt, (int32_t)-0);
  125.         test(fmt, 0.0);
  126.         double negZero = 0.0; negZero /= -1.0;
  127.         test(fmt, negZero);
  128.         test(fmt, 9223372036854775808.0);
  129.         test(fmt, -9223372036854775809.0);
  130.  
  131.         for(int i = 0; i < 10; ++i) {
  132.             test(fmt, randomDouble(1));
  133.             test(fmt, randomDouble(10000));
  134.             test(fmt, icu_floor((randomDouble(10000))));
  135.             test(fmt, randomDouble(1e50));
  136.             test(fmt, randomDouble(1e-50));
  137.             test(fmt, randomDouble(1e100));
  138.             // {sfb} When formatting with a percent instance, numbers very close to
  139.             // DBL_MAX will fail the round trip.  This is because:
  140.             // 1) Format the double into a string --> INF% (since 100 * double > DBL_MAX)
  141.             // 2) Parse the string into a double --> INF
  142.             // 3) Re-format the double --> INF%
  143.             // 4) The strings are equal, so that works.
  144.             // 5) Calculate the proportional error --> INF, so the test will fail
  145.             // I'll get around this by dividing by the multiplier to make sure
  146.             // the double will stay in range.
  147.             //if(fmt->getMultipler() == 1)
  148.             if(fmt->getDynamicClassID() == DecimalFormat::getStaticClassID())
  149.                 test(fmt, randomDouble(1e308) / ((DecimalFormat*)fmt)->getMultiplier());
  150.  
  151. #ifndef XP_MAC
  152.             test(fmt, randomDouble(1e-323));
  153. #else
  154. // PowerPC doesn't support denormalized doubles, so the low-end range
  155. // doesn't match NT
  156.             test(fmt, randomDouble(1e-290));
  157. #endif
  158.             test(fmt, randomDouble(1e-100));
  159.         }
  160.     }
  161. }
  162.  
  163. /**
  164.  * Return a random value from -range..+range.
  165.  */
  166. double 
  167. NumberFormatRoundTripTest::randomDouble(double range)
  168. {
  169.     double a = randFraction();
  170.     return (2.0 * range * a) - range;
  171. }
  172.  
  173. void 
  174. NumberFormatRoundTripTest::test(NumberFormat *fmt, double value)
  175. {
  176.     test(fmt, Formattable(value));
  177. }
  178.  
  179. void 
  180. NumberFormatRoundTripTest::test(NumberFormat *fmt, int32_t value)
  181. {
  182.     test(fmt, Formattable(value));
  183. }
  184.  
  185. void 
  186. NumberFormatRoundTripTest::test(NumberFormat *fmt, const Formattable& value)
  187. {
  188.     fmt->setMaximumFractionDigits(999);
  189.     
  190.     UErrorCode status = U_ZERO_ERROR;
  191.     UnicodeString s, s2, temp;
  192.     if(isDouble(value))
  193.         s = fmt->format(value.getDouble(), s);
  194.     else
  195.         s = fmt->format(value.getLong(), s);
  196.  
  197.     Formattable n;
  198.     bool_t show = verbose;
  199.     if(DEBUG)
  200.         logln(UnicodeString("  ") + /*value.getString(temp) +*/ " F> " + escape(s));
  201.  
  202.     fmt->parse(s, n, status);
  203.     failure(status, "fmt->parse");
  204.     if(DEBUG) 
  205.         logln("  " + escape(s) + " P> " /*+ n.getString(temp)*/);
  206.  
  207.     if(isDouble(n))
  208.         s2 = fmt->format(n.getDouble(), s2);
  209.     else
  210.         s2 = fmt->format(n.getLong(), s2);
  211.     
  212.     if(DEBUG) 
  213.         logln(UnicodeString("  ") + /*n.getString(temp) +*/ " F> " + escape(s2));
  214.  
  215.     if(STRING_COMPARE) {
  216.         if (s != s2) {
  217.             errln(" *** STRING ERROR");
  218.             show = TRUE;
  219.         }
  220.     }
  221.  
  222.     if(EXACT_NUMERIC_COMPARE) {
  223.         if(value != n) {
  224.             errln(" *** NUMERIC ERROR");
  225.             show = TRUE;
  226.         }
  227.     }
  228.     else {
  229.         // Compute proportional error
  230.         double error = proportionalError(value, n);
  231.  
  232.         if(error > MAX_ERROR) {
  233.             errln(UnicodeString(" *** NUMERIC ERROR ") + error);
  234.             show = TRUE;
  235.         }
  236.  
  237.         if (error > max_numeric_error) 
  238.             max_numeric_error = error;
  239.         if (error < min_numeric_error) 
  240.             min_numeric_error = error;
  241.     }
  242.  
  243.     if(show)
  244.         logln(/*value.getString(temp) +*/ typeOf(value, temp) + " F> " +
  245.             escape(s) + " P> " +
  246.             /*n.getString(temp) +*/ typeOf(n, temp) + " F> " +
  247.             escape(s2));
  248. }
  249.  
  250. double 
  251. NumberFormatRoundTripTest::proportionalError(const Formattable& a, const Formattable& b)
  252. {
  253.     double aa,bb;
  254.     
  255.     if(isDouble(a))
  256.         aa = a.getDouble();
  257.     else
  258.         aa = a.getLong();
  259.  
  260.     if(isDouble(b))
  261.         bb = b.getDouble();
  262.     else
  263.         bb = b.getLong();
  264.  
  265.     double error = aa - bb;
  266.     if(aa != 0 && bb != 0) 
  267.         error /= aa;
  268.     
  269.     return icu_fabs(error);
  270. }
  271.  
  272. UnicodeString& 
  273. NumberFormatRoundTripTest::typeOf(const Formattable& n, UnicodeString& result)
  274. {
  275.     if(n.getType() == Formattable::kLong) {
  276.         result = UnicodeString(" Long");
  277.     }
  278.     else if(n.getType() == Formattable::kDouble) {
  279.         result = UnicodeString(" Double");
  280.     }
  281.     else if(n.getType() == Formattable::kString) {
  282.         result = UnicodeString(" UnicodeString");
  283.         UnicodeString temp;
  284.     }
  285.  
  286.     return result;
  287. }
  288.  
  289.  
  290. UnicodeString& 
  291. NumberFormatRoundTripTest::escape(UnicodeString& s)
  292. {
  293.     UnicodeString copy(s);
  294.     s.remove();
  295.     for(int i = 0; i < copy.size(); ++i) {
  296.         UChar c = copy[i];
  297.         if(c < 0x00FF) 
  298.             s += c;
  299.         else {
  300.             s += "+U";
  301.             char temp[16];
  302.             sprintf(temp, "%4X", c);        // might not work
  303.             s += temp;
  304.         }
  305.     }
  306.     return s;
  307. }
  308.