diff options
author | Jonathan Kew <jfkthame@googlemail.com> | 2006-07-25 12:37:43 +0000 |
---|---|---|
committer | Jonathan Kew <jfkthame@googlemail.com> | 2006-07-25 12:37:43 +0000 |
commit | 10c60368cd42904bd991453f02b684ebe02ef915 (patch) | |
tree | c6fb06ccf22a81c80af08f79df1b436120703de4 /Build/source/libs/icu-xetex/test/intltest/nmfmtrt.cpp | |
parent | 4d8b2aac6036acbb6878236c27e2fb110dad8643 (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.cpp | 349 |
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 */ |