]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/nmfmtrt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2007, 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 if (!failure(status
, "NumberFormat::createInstance")){
98 fmt
= NumberFormat::createCurrencyInstance(status
);
99 if (!failure(status
, "NumberFormat::createCurrencyInstance")){
104 fmt
= NumberFormat::createPercentInstance(status
);
105 if (!failure(status
, "NumberFormat::createPercentInstance")){
111 int32_t locCount
= 0;
112 const Locale
*loc
= NumberFormat::getAvailableLocales(locCount
);
116 logln("Quick mode: only testing first 5 Locales");
118 for(int i
= 0; i
< locCount
; ++i
) {
120 logln(loc
[i
].getDisplayName(name
));
122 fmt
= NumberFormat::createInstance(loc
[i
], status
);
123 failure(status
, "NumberFormat::createInstance");
127 fmt
= NumberFormat::createCurrencyInstance(loc
[i
], status
);
128 failure(status
, "NumberFormat::createCurrencyInstance");
132 fmt
= NumberFormat::createPercentInstance(loc
[i
], status
);
133 failure(status
, "NumberFormat::createPercentInstance");
138 logln(UnicodeString("Numeric error ") + min_numeric_error
+ " to " + max_numeric_error
);
143 NumberFormatRoundTripTest::test(NumberFormat
*fmt
)
145 #if IEEE_754 && !defined(OS400)
146 test(fmt
, uprv_getNaN());
147 test(fmt
, uprv_getInfinity());
148 test(fmt
, -uprv_getInfinity());
151 test(fmt
, (int32_t)500);
152 test(fmt
, (int32_t)0);
153 test(fmt
, (int32_t)-0);
155 double negZero
= 0.0; negZero
/= -1.0;
157 test(fmt
, 9223372036854775808.0);
158 test(fmt
, -9223372036854775809.0);
160 for(int i
= 0; i
< 10; ++i
) {
161 test(fmt
, randomDouble(1));
162 test(fmt
, randomDouble(10000));
163 test(fmt
, uprv_floor((randomDouble(10000))));
164 test(fmt
, randomDouble(1e50
));
165 test(fmt
, randomDouble(1e-50));
166 #if !defined(OS390) && !defined(OS400)
167 test(fmt
, randomDouble(1e100
));
169 test(fmt
, randomDouble(1e75
)); /*OS390 and OS400*/
170 #endif /* OS390 and OS400 */
171 // {sfb} When formatting with a percent instance, numbers very close to
172 // DBL_MAX will fail the round trip. This is because:
173 // 1) Format the double into a string --> INF% (since 100 * double > DBL_MAX)
174 // 2) Parse the string into a double --> INF
175 // 3) Re-format the double --> INF%
176 // 4) The strings are equal, so that works.
177 // 5) Calculate the proportional error --> INF, so the test will fail
178 // I'll get around this by dividing by the multiplier to make sure
179 // the double will stay in range.
180 //if(fmt->getMultipler() == 1)
181 if(fmt
->getDynamicClassID() == DecimalFormat::getStaticClassID())
183 #if !defined(OS390) && !defined(OS400)
184 /* DBL_MAX/2 is here because randomDouble does a *2 in the math */
185 test(fmt
, randomDouble(DBL_MAX
/2.0) / ((DecimalFormat
*)fmt
)->getMultiplier());
187 test(fmt
, randomDouble(1e75
) / ((DecimalFormat
*)fmt
)->getMultiplier());
189 test(fmt
, randomDouble(1e65
) / ((DecimalFormat
*)fmt
)->getMultiplier()); /*OS390*/
193 #if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(__alpha__) || defined(U_OSF)
194 // These machines and compilers don't fully support denormalized doubles,
195 test(fmt
, randomDouble(1e-292));
196 test(fmt
, randomDouble(1e-100));
197 #elif defined(OS390) || defined(OS400)
198 // i5/OS (OS400) throws exceptions on denormalized numbers
200 test(fmt
, randomDouble(1e-78));
201 test(fmt
, randomDouble(1e-78));
202 // #else we're using something like the old z/OS floating point.
205 // This is a normal machine that can support IEEE754 denormalized doubles without throwing an error.
206 test(fmt
, randomDouble(DBL_MIN
)); /* Usually 2.2250738585072014e-308 */
207 test(fmt
, randomDouble(1e-100));
213 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, double value
)
215 test(fmt
, Formattable(value
));
219 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, int32_t value
)
221 test(fmt
, Formattable(value
));
225 NumberFormatRoundTripTest::test(NumberFormat
*fmt
, const Formattable
& value
)
227 fmt
->setMaximumFractionDigits(999);
228 if(fmt
->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
229 ((DecimalFormat
*)fmt
)->setRoundingIncrement(0.0);
231 UErrorCode status
= U_ZERO_ERROR
;
232 UnicodeString s
, s2
, temp
;
234 s
= fmt
->format(value
.getDouble(), s
);
236 s
= fmt
->format(value
.getLong(), s
);
239 UBool show
= verbose
;
241 logln(/*value.getString(temp) +*/ " F> " + escape(s
));
243 fmt
->parse(s
, n
, status
);
244 failure(status
, "fmt->parse");
246 logln(escape(s
) + " P> " /*+ n.getString(temp)*/);
249 s2
= fmt
->format(n
.getDouble(), s2
);
251 s2
= fmt
->format(n
.getLong(), s2
);
254 logln(/*n.getString(temp) +*/ " F> " + escape(s2
));
258 errln("*** STRING ERROR \"" + escape(s
) + "\" != \"" + escape(s2
) + "\"");
263 if(EXACT_NUMERIC_COMPARE
) {
265 errln("*** NUMERIC ERROR");
270 // Compute proportional error
271 double error
= proportionalError(value
, n
);
273 if(error
> MAX_ERROR
) {
274 errln(UnicodeString("*** NUMERIC ERROR ") + error
);
278 if (error
> max_numeric_error
)
279 max_numeric_error
= error
;
280 if (error
< min_numeric_error
)
281 min_numeric_error
= error
;
285 errln(/*value.getString(temp) +*/ typeOf(value
, temp
) + " F> " +
286 escape(s
) + " P> " + (n
.getType() == Formattable::kDouble
? n
.getDouble() : (double)n
.getLong())
287 /*n.getString(temp) */ + typeOf(n
, temp
) + " F> " +
293 NumberFormatRoundTripTest::proportionalError(const Formattable
& a
, const Formattable
& b
)
307 double error
= aa
- bb
;
308 if(aa
!= 0 && bb
!= 0)
311 return uprv_fabs(error
);
315 NumberFormatRoundTripTest::typeOf(const Formattable
& n
, UnicodeString
& result
)
317 if(n
.getType() == Formattable::kLong
) {
318 result
= UnicodeString(" Long");
320 else if(n
.getType() == Formattable::kDouble
) {
321 result
= UnicodeString(" Double");
323 else if(n
.getType() == Formattable::kString
) {
324 result
= UnicodeString(" UnicodeString");
333 NumberFormatRoundTripTest::escape(UnicodeString
& s
)
335 UnicodeString
copy(s
);
337 for(int i
= 0; i
< copy
.length(); ++i
) {
344 sprintf(temp
, "%4X", c
); // might not work
351 #endif /* #if !UCONFIG_NO_FORMATTING */