summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp
diff options
context:
space:
mode:
authorJonathan Kew <jfkthame@googlemail.com>2006-07-25 12:37:43 +0000
committerJonathan Kew <jfkthame@googlemail.com>2006-07-25 12:37:43 +0000
commit10c60368cd42904bd991453f02b684ebe02ef915 (patch)
treec6fb06ccf22a81c80af08f79df1b436120703de4 /Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp
parent4d8b2aac6036acbb6878236c27e2fb110dad8643 (diff)
adding ICU library sources used by xetex
git-svn-id: svn://tug.org/texlive/trunk@1915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp')
-rw-r--r--Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp b/Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp
new file mode 100644
index 00000000000..77da5c6823f
--- /dev/null
+++ b/Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp
@@ -0,0 +1,349 @@
+/***********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2005, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ ***********************************************************************/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "nmfmtrt.h"
+
+#include "unicode/dcfmtsym.h"
+#include "unicode/decimfmt.h"
+#include "unicode/locid.h"
+#include "putilimp.h"
+
+#include <float.h>
+#include <stdio.h> // for sprintf
+#include <stdlib.h>
+
+// *****************************************************************************
+// class NumberFormatRoundTripTest
+// *****************************************************************************
+
+UBool NumberFormatRoundTripTest::verbose = FALSE;
+UBool NumberFormatRoundTripTest::STRING_COMPARE = TRUE;
+UBool NumberFormatRoundTripTest::EXACT_NUMERIC_COMPARE = FALSE;
+UBool NumberFormatRoundTripTest::DEBUG = FALSE;
+double NumberFormatRoundTripTest::MAX_ERROR = 1e-14;
+double NumberFormatRoundTripTest::max_numeric_error = 0.0;
+double NumberFormatRoundTripTest::min_numeric_error = 1.0;
+
+#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;
+
+void NumberFormatRoundTripTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
+{
+ // if (exec) logln((UnicodeString)"TestSuite NumberFormatRoundTripTest");
+ switch (index) {
+ CASE(0, start)
+ default: name = ""; break;
+ }
+}
+
+UBool
+NumberFormatRoundTripTest::failure(UErrorCode status, const char* msg)
+{
+ if(U_FAILURE(status)) {
+ errln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+uint32_t
+NumberFormatRoundTripTest::randLong()
+{
+ // Assume 8-bit (or larger) rand values. Also assume
+ // that the system rand() function is very poor, which it always is.
+ uint32_t d;
+ uint32_t i;
+ char* poke = (char*)&d;
+ for (i=0; i < sizeof(uint32_t); ++i)
+ {
+ poke[i] = (char)(rand() & 0xFF);
+ }
+ return d;
+}
+
+/**
+ * Return a random value from -range..+range.
+ */
+double
+NumberFormatRoundTripTest::randomDouble(double range)
+{
+ double a = randFraction();
+ return (2.0 * range * a) - range;
+}
+
+void
+NumberFormatRoundTripTest::start()
+{
+// test(NumberFormat.getInstance(new Locale("sr", "", "")));
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ NumberFormat *fmt = NULL;
+
+ logln("Default Locale");
+
+ fmt = NumberFormat::createInstance(status);
+ if (!failure(status, "NumberFormat::createInstance")){
+ test(fmt);
+ }
+ delete fmt;
+
+ fmt = NumberFormat::createCurrencyInstance(status);
+ if (!failure(status, "NumberFormat::createCurrencyInstance")){
+ test(fmt);
+ }
+ delete fmt;
+
+ fmt = NumberFormat::createPercentInstance(status);
+ if (!failure(status, "NumberFormat::createPercentInstance")){
+ test(fmt);
+ }
+ delete fmt;
+
+
+ int32_t locCount = 0;
+ const Locale *loc = NumberFormat::getAvailableLocales(locCount);
+ if(quick) {
+ if(locCount > 5)
+ locCount = 5;
+ logln("Quick mode: only testing first 5 Locales");
+ }
+ for(int i = 0; i < locCount; ++i) {
+ UnicodeString name;
+ logln(loc[i].getDisplayName(name));
+
+ fmt = NumberFormat::createInstance(loc[i], status);
+ failure(status, "NumberFormat::createInstance");
+ test(fmt);
+ delete fmt;
+
+ fmt = NumberFormat::createCurrencyInstance(loc[i], status);
+ failure(status, "NumberFormat::createCurrencyInstance");
+ test(fmt);
+ delete fmt;
+
+ fmt = NumberFormat::createPercentInstance(loc[i], status);
+ failure(status, "NumberFormat::createPercentInstance");
+ test(fmt);
+ delete fmt;
+ }
+
+ logln(UnicodeString("Numeric error ") + min_numeric_error + " to " + max_numeric_error);
+}
+
+
+void
+NumberFormatRoundTripTest::test(NumberFormat *fmt)
+{
+#if IEEE_754 && !defined(OS400)
+ test(fmt, uprv_getNaN());
+ test(fmt, uprv_getInfinity());
+ test(fmt, -uprv_getInfinity());
+#endif
+
+ test(fmt, (int32_t)500);
+ test(fmt, (int32_t)0);
+ test(fmt, (int32_t)-0);
+ test(fmt, 0.0);
+ double negZero = 0.0; negZero /= -1.0;
+ test(fmt, negZero);
+ test(fmt, 9223372036854775808.0);
+ test(fmt, -9223372036854775809.0);
+
+ for(int i = 0; i < 10; ++i) {
+ test(fmt, randomDouble(1));
+ test(fmt, randomDouble(10000));
+ test(fmt, uprv_floor((randomDouble(10000))));
+ test(fmt, randomDouble(1e50));
+ test(fmt, randomDouble(1e-50));
+#if !defined(OS390) && !defined(OS400)
+ test(fmt, randomDouble(1e100));
+#elif IEEE_754
+ test(fmt, randomDouble(1e75)); /*OS390 and OS400*/
+#endif /* OS390 and OS400 */
+ // {sfb} When formatting with a percent instance, numbers very close to
+ // DBL_MAX will fail the round trip. This is because:
+ // 1) Format the double into a string --> INF% (since 100 * double > DBL_MAX)
+ // 2) Parse the string into a double --> INF
+ // 3) Re-format the double --> INF%
+ // 4) The strings are equal, so that works.
+ // 5) Calculate the proportional error --> INF, so the test will fail
+ // I'll get around this by dividing by the multiplier to make sure
+ // the double will stay in range.
+ //if(fmt->getMultipler() == 1)
+ if(fmt->getDynamicClassID() == DecimalFormat::getStaticClassID())
+ {
+#if !defined(OS390) && !defined(OS400)
+ /* DBL_MAX/2 is here because randomDouble does a *2 in the math */
+ test(fmt, randomDouble(DBL_MAX/2.0) / ((DecimalFormat*)fmt)->getMultiplier());
+#elif IEEE_754
+ test(fmt, randomDouble(1e75) / ((DecimalFormat*)fmt)->getMultiplier());
+#else
+ test(fmt, randomDouble(1e65) / ((DecimalFormat*)fmt)->getMultiplier()); /*OS390*/
+#endif
+ }
+
+#if defined XP_MAC || defined __alpha__ || defined U_OSF
+// These machines don't support denormalized doubles,
+// so the low-end range doesn't match Windows
+ test(fmt, randomDouble(1e-292));
+#elif defined(OS390) || defined(OS400)
+# if IEEE_754
+ test(fmt, randomDouble(1e-78)); /*OS390 and OS400*/
+# endif
+#else
+ test(fmt, randomDouble(1e-323));
+#endif /* OS390 and OS400*/
+#if !defined(OS390) && !defined(OS400)
+ test(fmt, randomDouble(1e-100));
+#elif IEEE_754
+ test(fmt, randomDouble(1e-78)); /*OS390 and OS400*/
+#endif /* OS390 and OS400*/
+ }
+}
+
+void
+NumberFormatRoundTripTest::test(NumberFormat *fmt, double value)
+{
+ test(fmt, Formattable(value));
+}
+
+void
+NumberFormatRoundTripTest::test(NumberFormat *fmt, int32_t value)
+{
+ test(fmt, Formattable(value));
+}
+
+void
+NumberFormatRoundTripTest::test(NumberFormat *fmt, const Formattable& value)
+{
+ fmt->setMaximumFractionDigits(999);
+
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString s, s2, temp;
+ if(isDouble(value))
+ s = fmt->format(value.getDouble(), s);
+ else
+ s = fmt->format(value.getLong(), s);
+
+ Formattable n;
+ UBool show = verbose;
+ if(DEBUG)
+ logln(/*value.getString(temp) +*/ " F> " + escape(s));
+
+ fmt->parse(s, n, status);
+ failure(status, "fmt->parse");
+ if(DEBUG)
+ logln(escape(s) + " P> " /*+ n.getString(temp)*/);
+
+ if(isDouble(n))
+ s2 = fmt->format(n.getDouble(), s2);
+ else
+ s2 = fmt->format(n.getLong(), s2);
+
+ if(DEBUG)
+ logln(/*n.getString(temp) +*/ " F> " + escape(s2));
+
+ if(STRING_COMPARE) {
+ if (s != s2) {
+ errln("*** STRING ERROR \"" + escape(s) + "\" != \"" + escape(s2) + "\"");
+ show = TRUE;
+ }
+ }
+
+ if(EXACT_NUMERIC_COMPARE) {
+ if(value != n) {
+ errln("*** NUMERIC ERROR");
+ show = TRUE;
+ }
+ }
+ else {
+ // Compute proportional error
+ double error = proportionalError(value, n);
+
+ if(error > MAX_ERROR) {
+ errln(UnicodeString("*** NUMERIC ERROR ") + error);
+ show = TRUE;
+ }
+
+ if (error > max_numeric_error)
+ max_numeric_error = error;
+ if (error < min_numeric_error)
+ min_numeric_error = error;
+ }
+
+ if (show) {
+ errln(/*value.getString(temp) +*/ typeOf(value, temp) + " F> " +
+ escape(s) + " P> " +
+ /*n.getString(temp) +*/ typeOf(n, temp) + " F> " +
+ escape(s2));
+ }
+}
+
+double
+NumberFormatRoundTripTest::proportionalError(const Formattable& a, const Formattable& b)
+{
+ double aa,bb;
+
+ if(isDouble(a))
+ aa = a.getDouble();
+ else
+ aa = a.getLong();
+
+ if(isDouble(b))
+ bb = b.getDouble();
+ else
+ bb = b.getLong();
+
+ double error = aa - bb;
+ if(aa != 0 && bb != 0)
+ error /= aa;
+
+ return uprv_fabs(error);
+}
+
+UnicodeString&
+NumberFormatRoundTripTest::typeOf(const Formattable& n, UnicodeString& result)
+{
+ if(n.getType() == Formattable::kLong) {
+ result = UnicodeString(" Long");
+ }
+ else if(n.getType() == Formattable::kDouble) {
+ result = UnicodeString(" Double");
+ }
+ else if(n.getType() == Formattable::kString) {
+ result = UnicodeString(" UnicodeString");
+ UnicodeString temp;
+ }
+
+ return result;
+}
+
+
+UnicodeString&
+NumberFormatRoundTripTest::escape(UnicodeString& s)
+{
+ UnicodeString copy(s);
+ s.remove();
+ for(int i = 0; i < copy.length(); ++i) {
+ UChar c = copy[i];
+ if(c < 0x00FF)
+ s += c;
+ else {
+ s += "+U";
+ char temp[16];
+ sprintf(temp, "%4X", c); // might not work
+ s += temp;
+ }
+ }
+ return s;
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */