]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/nmfmtrt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2004, 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
= 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
)
48 if(U_FAILURE(status
)) {
49 errln(UnicodeString("FAIL: ") + msg
+ " failed, error " + u_errorName(status
));
57 NumberFormatRoundTripTest::randLong()
59 // Assume 8-bit (or larger) rand values. Also assume
60 // that the system rand() function is very poor, which it always is.
63 char* poke
= (char*)&d
;
64 for (i
=0; i
< sizeof(uint32_t); ++i
)
66 poke
[i
] = (char)(rand() & 0xFF);
72 * Return a random value from -range..+range.
75 NumberFormatRoundTripTest::randomDouble(double range
)
77 double a
= randFraction();
78 return (2.0 * range
* a
) - range
;
82 NumberFormatRoundTripTest::start()
84 // test(NumberFormat.getInstance(new Locale("sr", "", "")));
86 UErrorCode status
= U_ZERO_ERROR
;
88 NumberFormat
*fmt
= NULL
;
90 logln("Default Locale");
92 fmt
= NumberFormat::createInstance(status
);
93 failure(status
, "NumberFormat::createInstance");
97 fmt
= NumberFormat::createCurrencyInstance(status
);
98 failure(status
, "NumberFormat::createCurrencyInstance");
102 fmt
= NumberFormat::createPercentInstance(status
);
103 failure(status
, "NumberFormat::createPercentInstance");
108 int32_t locCount
= 0;
109 const Locale
*loc
= NumberFormat::getAvailableLocales(locCount
);
113 logln("Quick mode: only testing first 5 Locales");
115 for(int i
= 0; i
< locCount
; ++i
) {
117 logln(loc
[i
].getDisplayName(name
));
119 fmt
= NumberFormat::createInstance(loc
[i
], status
);
120 failure(status
, "NumberFormat::createInstance");
124 fmt
= NumberFormat::createCurrencyInstance(loc
[i
], status
);
125 failure(status
, "NumberFormat::createCurrencyInstance");
129 fmt
= NumberFormat::createPercentInstance(loc
[i
], status
);
130 failure(status
, "NumberFormat::createPercentInstance");
135 logln(UnicodeString("Numeric error ") + min_numeric_error
+ " to " + max_numeric_error
);
140 NumberFormatRoundTripTest::test(NumberFormat
*fmt
)
142 #if IEEE_754 && !defined(OS400)
143 test(fmt
, uprv_getNaN());
144 test(fmt
, uprv_getInfinity());
145 test(fmt
, -uprv_getInfinity());
148 test(fmt
, (int32_t)500);
149 test(fmt
, (int32_t)0);
150 test(fmt
, (int32_t)-0);
152 double negZero
= 0.0; negZero
/= -1.0;
154 test(fmt
, 9223372036854775808.0);
155 test(fmt
, -9223372036854775809.0);
157 for(int i
= 0; i
< 10; ++i
) {
158 test(fmt
, randomDouble(1));
159 test(fmt
, randomDouble(10000));
160 test(fmt
, uprv_floor((randomDouble(10000))));
161 test(fmt
, randomDouble(1e50
));
162 test(fmt
, randomDouble(1e-50));
163 #if !defined(OS390) && !defined(OS400)
164 test(fmt
, randomDouble(1e100
));
166 test(fmt
, randomDouble(1e75
)); /*OS390 and OS400*/
167 #endif /* OS390 and OS400 */
168 // {sfb} When formatting with a percent instance, numbers very close to
169 // DBL_MAX will fail the round trip. This is because:
170 // 1) Format the double into a string --> INF% (since 100 * double > DBL_MAX)
171 // 2) Parse the string into a double --> INF
172 // 3) Re-format the double --> INF%
173 // 4) The strings are equal, so that works.
174 // 5) Calculate the proportional error --> INF, so the test will fail
175 // I'll get around this by dividing by the multiplier to make sure
176 // the double will stay in range.
177 //if(fmt->getMultipler() == 1)
178 if(fmt
->getDynamicClassID() == DecimalFormat::getStaticClassID())
180 #if !defined(OS390) && !defined(OS400)
181 /* DBL_MAX/2 is here because randomDouble does a *2 in the math */
182 test(fmt
, randomDouble(DBL_MAX
/2.0) / ((DecimalFormat
*)fmt
)->getMultiplier());
184 test(fmt
, randomDouble(1e75
) / ((DecimalFormat
*)fmt
)->getMultiplier());
186 test(fmt
, randomDouble(1e65
) / ((DecimalFormat
*)fmt
)->getMultiplier()); /*OS390*/
190 #if defined XP_MAC || defined __alpha__ || defined U_OSF
191 // These machines don't support denormalized doubles,
192 // so the low-end range doesn't match Windows
193 test(fmt
, randomDouble(1e-292));
194 #elif defined(OS390) || defined(OS400)
196 test(fmt
, randomDouble(1e-78)); /*OS390 and OS400*/
199 test(fmt
, randomDouble(1e-323));
200 #endif /* OS390 and OS400*/
201 #if !defined(OS390) && !defined(OS400)
202 test(fmt
, randomDouble(1e-100));
204 test(fmt
, randomDouble(1e-78)); /*OS390 and OS400*/
205 #endif /* OS390 and OS400*/
210 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, double value
)
212 test(fmt
, Formattable(value
));
216 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, int32_t value
)
218 test(fmt
, Formattable(value
));
222 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, const Formattable
& value
)
224 fmt
->setMaximumFractionDigits(999);
226 UErrorCode status
= U_ZERO_ERROR
;
227 UnicodeString s
, s2
, temp
;
229 s
= fmt
->format(value
.getDouble(), s
);
231 s
= fmt
->format(value
.getLong(), s
);
234 UBool show
= verbose
;
236 logln(/*value.getString(temp) +*/ " F> " + escape(s
));
238 fmt
->parse(s
, n
, status
);
239 failure(status
, "fmt->parse");
241 logln(escape(s
) + " P> " /*+ n.getString(temp)*/);
244 s2
= fmt
->format(n
.getDouble(), s2
);
246 s2
= fmt
->format(n
.getLong(), s2
);
249 logln(/*n.getString(temp) +*/ " F> " + escape(s2
));
253 errln("*** STRING ERROR \"" + escape(s
) + "\" != \"" + escape(s2
) + "\"");
258 if(EXACT_NUMERIC_COMPARE
) {
260 errln("*** NUMERIC ERROR");
265 // Compute proportional error
266 double error
= proportionalError(value
, n
);
268 if(error
> MAX_ERROR
) {
269 errln(UnicodeString("*** NUMERIC ERROR ") + error
);
273 if (error
> max_numeric_error
)
274 max_numeric_error
= error
;
275 if (error
< min_numeric_error
)
276 min_numeric_error
= error
;
280 errln(/*value.getString(temp) +*/ typeOf(value
, temp
) + " F> " +
282 /*n.getString(temp) +*/ typeOf(n
, temp
) + " F> " +
288 NumberFormatRoundTripTest::proportionalError(const Formattable
& a
, const Formattable
& b
)
302 double error
= aa
- bb
;
303 if(aa
!= 0 && bb
!= 0)
306 return uprv_fabs(error
);
310 NumberFormatRoundTripTest::typeOf(const Formattable
& n
, UnicodeString
& result
)
312 if(n
.getType() == Formattable::kLong
) {
313 result
= UnicodeString(" Long");
315 else if(n
.getType() == Formattable::kDouble
) {
316 result
= UnicodeString(" Double");
318 else if(n
.getType() == Formattable::kString
) {
319 result
= UnicodeString(" UnicodeString");
328 NumberFormatRoundTripTest::escape(UnicodeString
& s
)
330 UnicodeString
copy(s
);
332 for(int i
= 0; i
< copy
.length(); ++i
) {
339 sprintf(temp
, "%4X", c
); // might not work
346 #endif /* #if !UCONFIG_NO_FORMATTING */