]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/nmfmtrt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2015, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ***********************************************************************/
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
13 #include "unicode/dcfmtsym.h"
14 #include "unicode/decimfmt.h"
15 #include "unicode/locid.h"
19 #include <stdio.h> // for sprintf
22 // *****************************************************************************
23 // class NumberFormatRoundTripTest
24 // *****************************************************************************
26 UBool
NumberFormatRoundTripTest::verbose
= FALSE
;
27 UBool
NumberFormatRoundTripTest::STRING_COMPARE
= TRUE
;
28 UBool
NumberFormatRoundTripTest::EXACT_NUMERIC_COMPARE
= FALSE
;
29 UBool
NumberFormatRoundTripTest::DEBUG_VAR
= FALSE
;
30 double NumberFormatRoundTripTest::MAX_ERROR
= 1e-14;
31 double NumberFormatRoundTripTest::max_numeric_error
= 0.0;
32 double NumberFormatRoundTripTest::min_numeric_error
= 1.0;
34 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;
36 void NumberFormatRoundTripTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
38 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRoundTripTest");
41 default: name
= ""; break;
46 NumberFormatRoundTripTest::failure(UErrorCode status
, const char* msg
, UBool possibleDataError
)
48 if(U_FAILURE(status
)) {
49 if (possibleDataError
) {
50 dataerrln(UnicodeString("FAIL: ") + msg
+ " failed, error " + u_errorName(status
));
52 errln(UnicodeString("FAIL: ") + msg
+ " failed, error " + u_errorName(status
));
61 NumberFormatRoundTripTest::randLong()
63 // Assume 8-bit (or larger) rand values. Also assume
64 // that the system rand() function is very poor, which it always is.
67 char* poke
= (char*)&d
;
68 for (i
=0; i
< sizeof(uint32_t); ++i
)
70 poke
[i
] = (char)(rand() & 0xFF);
76 * Return a random value from -range..+range.
79 NumberFormatRoundTripTest::randomDouble(double range
)
81 double a
= randFraction();
82 return (2.0 * range
* a
) - range
;
86 NumberFormatRoundTripTest::start()
88 // test(NumberFormat.getInstance(new Locale("sr", "", "")));
90 UErrorCode status
= U_ZERO_ERROR
;
92 NumberFormat
*fmt
= NULL
;
94 logln("Default Locale");
96 fmt
= NumberFormat::createInstance(status
);
97 if (!failure(status
, "NumberFormat::createInstance", TRUE
)){
102 fmt
= NumberFormat::createCurrencyInstance(status
);
103 if (!failure(status
, "NumberFormat::createCurrencyInstance", TRUE
)){
108 fmt
= NumberFormat::createPercentInstance(status
);
109 if (!failure(status
, "NumberFormat::createPercentInstance", TRUE
)){
115 int32_t locCount
= 0;
116 const Locale
*loc
= NumberFormat::getAvailableLocales(locCount
);
120 logln("Quick mode: only testing first 5 Locales");
122 for(int i
= 0; i
< locCount
; ++i
) {
124 logln(loc
[i
].getDisplayName(name
));
126 fmt
= NumberFormat::createInstance(loc
[i
], status
);
127 failure(status
, "NumberFormat::createInstance");
131 fmt
= NumberFormat::createCurrencyInstance(loc
[i
], status
);
132 failure(status
, "NumberFormat::createCurrencyInstance");
136 fmt
= NumberFormat::createPercentInstance(loc
[i
], status
);
137 failure(status
, "NumberFormat::createPercentInstance");
142 logln(UnicodeString("Numeric error ") + min_numeric_error
+ " to " + max_numeric_error
);
147 NumberFormatRoundTripTest::test(NumberFormat
*fmt
)
149 #if IEEE_754 && U_PLATFORM != U_PF_OS400
150 test(fmt
, uprv_getNaN());
151 test(fmt
, uprv_getInfinity());
152 test(fmt
, -uprv_getInfinity());
155 test(fmt
, (int32_t)500);
156 test(fmt
, (int32_t)0);
157 test(fmt
, (int32_t)-0);
159 double negZero
= 0.0; negZero
/= -1.0;
161 test(fmt
, 9223372036854775808.0);
162 test(fmt
, -9223372036854775809.0);
164 for(int i
= 0; i
< 10; ++i
) {
165 test(fmt
, randomDouble(1));
166 test(fmt
, randomDouble(10000));
167 test(fmt
, uprv_floor((randomDouble(10000))));
168 test(fmt
, randomDouble(1e50
));
169 test(fmt
, randomDouble(1e-50));
170 #if !(U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400)
171 test(fmt
, randomDouble(1e100
));
173 test(fmt
, randomDouble(1e75
));
174 #endif /* OS390 and OS400 */
175 // {sfb} When formatting with a percent instance, numbers very close to
176 // DBL_MAX will fail the round trip. This is because:
177 // 1) Format the double into a string --> INF% (since 100 * double > DBL_MAX)
178 // 2) Parse the string into a double --> INF
179 // 3) Re-format the double --> INF%
180 // 4) The strings are equal, so that works.
181 // 5) Calculate the proportional error --> INF, so the test will fail
182 // I'll get around this by dividing by the multiplier to make sure
183 // the double will stay in range.
184 //if(fmt->getMultipler() == 1)
185 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(fmt
);
188 #if !(U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400)
189 /* DBL_MAX/2 is here because randomDouble does a *2 in the math */
190 test(fmt
, randomDouble(DBL_MAX
/2.0) / df
->getMultiplier());
192 test(fmt
, randomDouble(1e75
) / df
->getMultiplier());
194 test(fmt
, randomDouble(1e65
) / df
->getMultiplier());
198 #if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(__alpha__) || defined(U_OSF)
199 // These machines and compilers don't fully support denormalized doubles,
200 test(fmt
, randomDouble(1e-292));
201 test(fmt
, randomDouble(1e-100));
202 #elif U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
203 // i5/OS (OS/400) throws exceptions on denormalized numbers
205 test(fmt
, randomDouble(1e-78));
206 test(fmt
, randomDouble(1e-78));
207 // #else we're using something like the old z/OS floating point.
210 // This is a normal machine that can support IEEE754 denormalized doubles without throwing an error.
211 test(fmt
, randomDouble(DBL_MIN
)); /* Usually 2.2250738585072014e-308 */
212 test(fmt
, randomDouble(1e-100));
218 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, double value
)
220 test(fmt
, Formattable(value
));
224 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, int32_t value
)
226 test(fmt
, Formattable(value
));
230 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, const Formattable
& value
)
232 fmt
->setMaximumFractionDigits(999);
233 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(fmt
);
235 df
->setRoundingIncrement(0.0);
237 UErrorCode status
= U_ZERO_ERROR
;
238 UnicodeString s
, s2
, temp
;
240 s
= fmt
->format(value
.getDouble(), s
);
242 s
= fmt
->format(value
.getLong(), s
);
245 UBool show
= verbose
;
247 logln(/*value.getString(temp) +*/ " F> " + escape(s
));
249 fmt
->parse(s
, n
, status
);
250 failure(status
, "fmt->parse");
252 logln(escape(s
) + " P> " /*+ n.getString(temp)*/);
255 s2
= fmt
->format(n
.getDouble(), s2
);
257 s2
= fmt
->format(n
.getLong(), s2
);
260 logln(/*n.getString(temp) +*/ " F> " + escape(s2
));
264 errln("*** STRING ERROR \"" + escape(s
) + "\" != \"" + escape(s2
) + "\"");
269 if(EXACT_NUMERIC_COMPARE
) {
271 errln("*** NUMERIC ERROR");
276 // Compute proportional error
277 double error
= proportionalError(value
, n
);
279 if(error
> MAX_ERROR
) {
280 errln(UnicodeString("*** NUMERIC ERROR ") + error
);
284 if (error
> max_numeric_error
)
285 max_numeric_error
= error
;
286 if (error
< min_numeric_error
)
287 min_numeric_error
= error
;
291 errln(/*value.getString(temp) +*/ typeOf(value
, temp
) + " F> " +
292 escape(s
) + " P> " + (n
.getType() == Formattable::kDouble
? n
.getDouble() : (double)n
.getLong())
293 /*n.getString(temp) */ + typeOf(n
, temp
) + " F> " +
299 NumberFormatRoundTripTest::proportionalError(const Formattable
& a
, const Formattable
& b
)
313 double error
= aa
- bb
;
314 if(aa
!= 0 && bb
!= 0)
317 return uprv_fabs(error
);
321 NumberFormatRoundTripTest::typeOf(const Formattable
& n
, UnicodeString
& result
)
323 if(n
.getType() == Formattable::kLong
) {
324 result
= UnicodeString(" Long");
326 else if(n
.getType() == Formattable::kDouble
) {
327 result
= UnicodeString(" Double");
329 else if(n
.getType() == Formattable::kString
) {
330 result
= UnicodeString(" UnicodeString");
339 NumberFormatRoundTripTest::escape(UnicodeString
& s
)
341 UnicodeString
copy(s
);
343 for(int i
= 0; i
< copy
.length(); ++i
) {
350 sprintf(temp
, "%4X", c
); // might not work
357 #endif /* #if !UCONFIG_NO_FORMATTING */