1/*
2 *******************************************************************************
3 * Copyright (C) 1996-2012, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7
8#include "unicode/utypes.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12#include "itrbnf.h"
13
14#include "unicode/umachine.h"
15
16#include "unicode/tblcoll.h"
17#include "unicode/coleitr.h"
18#include "unicode/ures.h"
19#include "unicode/ustring.h"
20#include "unicode/decimfmt.h"
21#include "unicode/udata.h"
22#include "testutil.h"
23
24//#include "llong.h"
25
26#include <string.h>
27
28// import com.ibm.text.RuleBasedNumberFormat;
29// import com.ibm.test.TestFmwk;
30
31// import java.util.Locale;
32// import java.text.NumberFormat;
33
34// current macro not in icu1.8.1
35#define TESTCASE(id,test)             \
36    case id:                          \
37        name = #test;                 \
38        if (exec) {                   \
39            logln(#test "---");       \
40            logln();                  \
41            test();                   \
42        }                             \
43        break
44
45void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/)
46{
47    if (exec) logln("TestSuite RuleBasedNumberFormat");
48    switch (index) {
49#if U_HAVE_RBNF
50        TESTCASE(0, TestEnglishSpellout);
51        TESTCASE(1, TestOrdinalAbbreviations);
52        TESTCASE(2, TestDurations);
53        TESTCASE(3, TestSpanishSpellout);
54        TESTCASE(4, TestFrenchSpellout);
55        TESTCASE(5, TestSwissFrenchSpellout);
56        TESTCASE(6, TestItalianSpellout);
57        TESTCASE(7, TestGermanSpellout);
58        TESTCASE(8, TestThaiSpellout);
59        TESTCASE(9, TestAPI);
60        TESTCASE(10, TestFractionalRuleSet);
61        TESTCASE(11, TestSwedishSpellout);
62        TESTCASE(12, TestBelgianFrenchSpellout);
63        TESTCASE(13, TestSmallValues);
64        TESTCASE(14, TestLocalizations);
65        TESTCASE(15, TestAllLocales);
66        TESTCASE(16, TestHebrewFraction);
67        TESTCASE(17, TestPortugueseSpellout);
68        TESTCASE(18, TestMultiplierSubstitution);
69        TESTCASE(19, TestSetDecimalFormatSymbols);
70#else
71        TESTCASE(0, TestRBNFDisabled);
72#endif
73    default:
74        name = "";
75        break;
76    }
77}
78
79#if U_HAVE_RBNF
80
81void IntlTestRBNF::TestHebrewFraction() {
82
83    // this is the expected output for 123.45, with no '<' in it.
84    UChar text1[] = {
85        0x05de, 0x05d0, 0x05d4, 0x0020,
86        0x05e2, 0x05e9, 0x05e8, 0x05d9, 0x05dd, 0x0020,
87        0x05d5, 0x05e9, 0x05dc, 0x05d5, 0x05e9, 0x0020,
88        0x05e0, 0x05e7, 0x05d5, 0x05d3, 0x05d4, 0x0020,
89        0x05d0, 0x05e8, 0x05d1, 0x05e2, 0x0020,
90        0x05d7, 0x05de, 0x05e9, 0x0000,
91    };
92    UChar text2[] = {
93        0x05DE, 0x05D0, 0x05D4, 0x0020,
94        0x05E2, 0x05E9, 0x05E8, 0x05D9, 0x05DD, 0x0020,
95        0x05D5, 0x05E9, 0x05DC, 0x05D5, 0x05E9, 0x0020,
96        0x05E0, 0x05E7, 0x05D5, 0x05D3, 0x05D4, 0x0020,
97        0x05D0, 0x05E4, 0x05E1, 0x0020,
98        0x05D0, 0x05E4, 0x05E1, 0x0020,
99        0x05D0, 0x05E8, 0x05D1, 0x05E2, 0x0020,
100        0x05D7, 0x05DE, 0x05E9, 0x0000,
101    };
102    UErrorCode status = U_ZERO_ERROR;
103    RuleBasedNumberFormat* formatter = new RuleBasedNumberFormat(URBNF_SPELLOUT, "he_IL", status);
104    if (status == U_MISSING_RESOURCE_ERROR || status == U_FILE_ACCESS_ERROR) {
105        errcheckln(status, "Failed in constructing RuleBasedNumberFormat - %s", u_errorName(status));
106        delete formatter;
107        return;
108    }
109    UnicodeString result;
110    Formattable parseResult;
111    ParsePosition pp(0);
112    {
113        UnicodeString expected(text1);
114        formatter->format(123.45, result);
115        if (result != expected) {
116            errln((UnicodeString)"expected '" + TestUtility::hex(expected) + "'\nbut got: '" + TestUtility::hex(result) + "'");
117        } else {
118//            formatter->parse(result, parseResult, pp);
119//            if (parseResult.getDouble() != 123.45) {
120//                errln("expected 123.45 but got: %g", parseResult.getDouble());
121//            }
122        }
123    }
124    {
125        UnicodeString expected(text2);
126        result.remove();
127        formatter->format(123.0045, result);
128        if (result != expected) {
129            errln((UnicodeString)"expected '" + TestUtility::hex(expected) + "'\nbut got: '" + TestUtility::hex(result) + "'");
130        } else {
131            pp.setIndex(0);
132//            formatter->parse(result, parseResult, pp);
133//            if (parseResult.getDouble() != 123.0045) {
134//                errln("expected 123.0045 but got: %g", parseResult.getDouble());
135//            }
136        }
137    }
138    delete formatter;
139}
140
141void
142IntlTestRBNF::TestAPI() {
143  // This test goes through the APIs that were not tested before.
144  // These tests are too small to have separate test classes/functions
145
146  UErrorCode status = U_ZERO_ERROR;
147  RuleBasedNumberFormat* formatter
148      = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status);
149  if (status == U_MISSING_RESOURCE_ERROR || status == U_FILE_ACCESS_ERROR) {
150    dataerrln("Unable to create formatter. - %s", u_errorName(status));
151    delete formatter;
152    return;
153  }
154
155  logln("RBNF API test starting");
156  // test clone
157  {
158    logln("Testing Clone");
159    RuleBasedNumberFormat* rbnfClone = (RuleBasedNumberFormat *)formatter->clone();
160    if(rbnfClone != NULL) {
161      if(!(*rbnfClone == *formatter)) {
162        errln("Clone should be semantically equivalent to the original!");
163      }
164      delete rbnfClone;
165    } else {
166      errln("Cloning failed!");
167    }
168  }
169
170  // test assignment
171  {
172    logln("Testing assignment operator");
173    RuleBasedNumberFormat assignResult(URBNF_SPELLOUT, Locale("es", "ES", ""), status);
174    assignResult = *formatter;
175    if(!(assignResult == *formatter)) {
176      errln("Assignment result should be semantically equivalent to the original!");
177    }
178  }
179
180  // test rule constructor
181  {
182    logln("Testing rule constructor");
183    LocalUResourceBundlePointer en(ures_open(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf", "en", &status));
184    if(U_FAILURE(status)) {
185      errln("Unable to access resource bundle with data!");
186    } else {
187      int32_t ruleLen = 0;
188      int32_t len = 0;
189      LocalUResourceBundlePointer rbnfRules(ures_getByKey(en.getAlias(), "RBNFRules", NULL, &status));
190      LocalUResourceBundlePointer ruleSets(ures_getByKey(rbnfRules.getAlias(), "SpelloutRules", NULL, &status));
191      UnicodeString desc;
192      while (ures_hasNext(ruleSets.getAlias())) {
193           const UChar* currentString = ures_getNextString(ruleSets.getAlias(), &len, NULL, &status);
194           ruleLen += len;
195           desc.append(currentString);
196      }
197
198      const UChar *spelloutRules = desc.getTerminatedBuffer();
199
200      if(U_FAILURE(status) || ruleLen == 0 || spelloutRules == NULL) {
201        errln("Unable to access the rules string!");
202      } else {
203        UParseError perror;
204        RuleBasedNumberFormat ruleCtorResult(spelloutRules, Locale::getUS(), perror, status);
205        if(!(ruleCtorResult == *formatter)) {
206          errln("Formatter constructed from the original rules should be semantically equivalent to the original!");
207        }
208
209        // Jitterbug 4452, for coverage
210        RuleBasedNumberFormat nf(spelloutRules, (UnicodeString)"", Locale::getUS(), perror, status);
211        if(!(nf == *formatter)) {
212          errln("Formatter constructed from the original rules should be semantically equivalent to the original!");
213        }
214      }
215    }
216  }
217
218  // test getRules
219  {
220    logln("Testing getRules function");
221    UnicodeString rules = formatter->getRules();
222    UParseError perror;
223    RuleBasedNumberFormat fromRulesResult(rules, Locale::getUS(), perror, status);
224
225    if(!(fromRulesResult == *formatter)) {
226      errln("Formatter constructed from rules obtained by getRules should be semantically equivalent to the original!");
227    }
228  }
229
230
231  {
232    logln("Testing copy constructor");
233    RuleBasedNumberFormat copyCtorResult(*formatter);
234    if(!(copyCtorResult == *formatter)) {
235      errln("Copy constructor result result should be semantically equivalent to the original!");
236    }
237  }
238
239#if !UCONFIG_NO_COLLATION
240  // test ruleset names
241  {
242    logln("Testing getNumberOfRuleSetNames, getRuleSetName and format using rule set names");
243    int32_t noOfRuleSetNames = formatter->getNumberOfRuleSetNames();
244    if(noOfRuleSetNames == 0) {
245      errln("Number of rule set names should be more than zero");
246    }
247    UnicodeString ruleSetName;
248    int32_t i = 0;
249    int32_t intFormatNum = 34567;
250    double doubleFormatNum = 893411.234;
251    logln("number of rule set names is %i", noOfRuleSetNames);
252    for(i = 0; i < noOfRuleSetNames; i++) {
253      FieldPosition pos1, pos2;
254      UnicodeString intFormatResult, doubleFormatResult;
255      Formattable intParseResult, doubleParseResult;
256
257      ruleSetName = formatter->getRuleSetName(i);
258      log("Rule set name %i is ", i);
259      log(ruleSetName);
260      logln(". Format results are: ");
261      intFormatResult = formatter->format(intFormatNum, ruleSetName, intFormatResult, pos1, status);
262      doubleFormatResult = formatter->format(doubleFormatNum, ruleSetName, doubleFormatResult, pos2, status);
263      if(U_FAILURE(status)) {
264        errln("Format using a rule set failed");
265        break;
266      }
267      logln(intFormatResult);
268      logln(doubleFormatResult);
269      formatter->setLenient(TRUE);
270      formatter->parse(intFormatResult, intParseResult, status);
271      formatter->parse(doubleFormatResult, doubleParseResult, status);
272
273      logln("Parse results for lenient = TRUE, %i, %f", intParseResult.getLong(), doubleParseResult.getDouble());
274
275      formatter->setLenient(FALSE);
276      formatter->parse(intFormatResult, intParseResult, status);
277      formatter->parse(doubleFormatResult, doubleParseResult, status);
278
279      logln("Parse results for lenient = FALSE, %i, %f", intParseResult.getLong(), doubleParseResult.getDouble());
280
281      if(U_FAILURE(status)) {
282        errln("Error during parsing");
283      }
284
285      intFormatResult = formatter->format(intFormatNum, "BLABLA", intFormatResult, pos1, status);
286      if(U_SUCCESS(status)) {
287        errln("Using invalid rule set name should have failed");
288        break;
289      }
290      status = U_ZERO_ERROR;
291      doubleFormatResult = formatter->format(doubleFormatNum, "TRUC", doubleFormatResult, pos2, status);
292      if(U_SUCCESS(status)) {
293        errln("Using invalid rule set name should have failed");
294        break;
295      }
296      status = U_ZERO_ERROR;
297    }
298    status = U_ZERO_ERROR;
299  }
300#endif
301
302  // test API
303  UnicodeString expected("four point five","");
304  logln("Testing format(double)");
305  UnicodeString result;
306  formatter->format(4.5,result);
307  if(result != expected) {
308      errln("Formatted 4.5, expected " + expected + " got " + result);
309  } else {
310      logln("Formatted 4.5, expected " + expected + " got " + result);
311  }
312  result.remove();
313  expected = "four";
314  formatter->format((int32_t)4,result);
315  if(result != expected) {
316      errln("Formatted 4, expected " + expected + " got " + result);
317  } else {
318      logln("Formatted 4, expected " + expected + " got " + result);
319  }
320
321  result.remove();
322  FieldPosition pos;
323  formatter->format((int64_t)4, result, pos, status = U_ZERO_ERROR);
324  if(result != expected) {
325      errln("Formatted 4 int64_t, expected " + expected + " got " + result);
326  } else {
327      logln("Formatted 4 int64_t, expected " + expected + " got " + result);
328  }
329
330  //Jitterbug 4452, for coverage
331  result.remove();
332  FieldPosition pos2;
333  formatter->format((int64_t)4, formatter->getRuleSetName(0), result, pos2, status = U_ZERO_ERROR);
334  if(result != expected) {
335      errln("Formatted 4 int64_t, expected " + expected + " got " + result);
336  } else {
337      logln("Formatted 4 int64_t, expected " + expected + " got " + result);
338  }
339
340  // clean up
341  logln("Cleaning up");
342  delete formatter;
343}
344
345void IntlTestRBNF::TestFractionalRuleSet()
346{
347    UnicodeString fracRules(
348        "%main:\n"
349               // this rule formats the number if it's 1 or more.  It formats
350               // the integral part using a DecimalFormat ("#,##0" puts
351               // thousands separators in the right places) and the fractional
352               // part using %%frac.  If there is no fractional part, it
353               // just shows the integral part.
354        "    x.0: <#,##0<[ >%%frac>];\n"
355               // this rule formats the number if it's between 0 and 1.  It
356               // shows only the fractional part (0.5 shows up as "1/2," not
357               // "0 1/2")
358        "    0.x: >%%frac>;\n"
359        // the fraction rule set.  This works the same way as the one in the
360        // preceding example: We multiply the fractional part of the number
361        // being formatted by each rule's base value and use the rule that
362        // produces the result closest to 0 (or the first rule that produces 0).
363        // Since we only provide rules for the numbers from 2 to 10, we know
364        // we'll get a fraction with a denominator between 2 and 10.
365        // "<0<" causes the numerator of the fraction to be formatted
366        // using numerals
367        "%%frac:\n"
368        "    2: 1/2;\n"
369        "    3: <0</3;\n"
370        "    4: <0</4;\n"
371        "    5: <0</5;\n"
372        "    6: <0</6;\n"
373        "    7: <0</7;\n"
374        "    8: <0</8;\n"
375        "    9: <0</9;\n"
376        "   10: <0</10;\n");
377
378    // mondo hack
379    int len = fracRules.length();
380    int change = 2;
381    for (int i = 0; i < len; ++i) {
382        UChar ch = fracRules.charAt(i);
383        if (ch == '\n') {
384            change = 2; // change ok
385        } else if (ch == ':') {
386            change = 1; // change, but once we hit a non-space char, don't change
387        } else if (ch == ' ') {
388            if (change != 0) {
389                fracRules.setCharAt(i, (UChar)0x200e);
390            }
391        } else {
392            if (change == 1) {
393                change = 0;
394            }
395        }
396    }
397
398    UErrorCode status = U_ZERO_ERROR;
399    UParseError perror;
400    RuleBasedNumberFormat formatter(fracRules, Locale::getEnglish(), perror, status);
401    if (U_FAILURE(status)) {
402        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
403    } else {
404        static const char* const testData[][2] = {
405            { "0", "0" },
406            { ".1", "1/10" },
407            { ".11", "1/9" },
408            { ".125", "1/8" },
409            { ".1428", "1/7" },
410            { ".1667", "1/6" },
411            { ".2", "1/5" },
412            { ".25", "1/4" },
413            { ".333", "1/3" },
414            { ".5", "1/2" },
415            { "1.1", "1 1/10" },
416            { "2.11", "2 1/9" },
417            { "3.125", "3 1/8" },
418            { "4.1428", "4 1/7" },
419            { "5.1667", "5 1/6" },
420            { "6.2", "6 1/5" },
421            { "7.25", "7 1/4" },
422            { "8.333", "8 1/3" },
423            { "9.5", "9 1/2" },
424            { ".2222", "2/9" },
425            { ".4444", "4/9" },
426            { ".5555", "5/9" },
427            { "1.2856", "1 2/7" },
428            { NULL, NULL }
429        };
430       doTest(&formatter, testData, FALSE); // exact values aren't parsable from fractions
431    }
432}
433
434#if 0
435#define LLAssert(a) \
436  if (!(a)) errln("FAIL: " #a)
437
438void IntlTestRBNF::TestLLongConstructors()
439{
440    logln("Testing constructors");
441
442    // constant (shouldn't really be public)
443    LLAssert(llong(llong::kD32).asDouble() == llong::kD32);
444
445    // internal constructor (shouldn't really be public)
446    LLAssert(llong(0, 1).asDouble() == 1);
447    LLAssert(llong(1, 0).asDouble() == llong::kD32);
448    LLAssert(llong((uint32_t)-1, (uint32_t)-1).asDouble() == -1);
449
450    // public empty constructor
451    LLAssert(llong().asDouble() == 0);
452
453    // public int32_t constructor
454    LLAssert(llong((int32_t)0).asInt() == (int32_t)0);
455    LLAssert(llong((int32_t)1).asInt() == (int32_t)1);
456    LLAssert(llong((int32_t)-1).asInt() == (int32_t)-1);
457    LLAssert(llong((int32_t)0x7fffffff).asInt() == (int32_t)0x7fffffff);
458    LLAssert(llong((int32_t)0xffffffff).asInt() == (int32_t)-1);
459    LLAssert(llong((int32_t)0x80000000).asInt() == (int32_t)0x80000000);
460
461    // public int16_t constructor
462    LLAssert(llong((int16_t)0).asInt() == (int16_t)0);
463    LLAssert(llong((int16_t)1).asInt() == (int16_t)1);
464    LLAssert(llong((int16_t)-1).asInt() == (int16_t)-1);
465    LLAssert(llong((int16_t)0x7fff).asInt() == (int16_t)0x7fff);
466    LLAssert(llong((int16_t)0xffff).asInt() == (int16_t)0xffff);
467    LLAssert(llong((int16_t)0x8000).asInt() == (int16_t)0x8000);
468
469    // public int8_t constructor
470    LLAssert(llong((int8_t)0).asInt() == (int8_t)0);
471    LLAssert(llong((int8_t)1).asInt() == (int8_t)1);
472    LLAssert(llong((int8_t)-1).asInt() == (int8_t)-1);
473    LLAssert(llong((int8_t)0x7f).asInt() == (int8_t)0x7f);
474    LLAssert(llong((int8_t)0xff).asInt() == (int8_t)0xff);
475    LLAssert(llong((int8_t)0x80).asInt() == (int8_t)0x80);
476
477    // public uint16_t constructor
478    LLAssert(llong((uint16_t)0).asUInt() == (uint16_t)0);
479    LLAssert(llong((uint16_t)1).asUInt() == (uint16_t)1);
480    LLAssert(llong((uint16_t)-1).asUInt() == (uint16_t)-1);
481    LLAssert(llong((uint16_t)0x7fff).asUInt() == (uint16_t)0x7fff);
482    LLAssert(llong((uint16_t)0xffff).asUInt() == (uint16_t)0xffff);
483    LLAssert(llong((uint16_t)0x8000).asUInt() == (uint16_t)0x8000);
484
485    // public uint32_t constructor
486    LLAssert(llong((uint32_t)0).asUInt() == (uint32_t)0);
487    LLAssert(llong((uint32_t)1).asUInt() == (uint32_t)1);
488    LLAssert(llong((uint32_t)-1).asUInt() == (uint32_t)-1);
489    LLAssert(llong((uint32_t)0x7fffffff).asUInt() == (uint32_t)0x7fffffff);
490    LLAssert(llong((uint32_t)0xffffffff).asUInt() == (uint32_t)-1);
491    LLAssert(llong((uint32_t)0x80000000).asUInt() == (uint32_t)0x80000000);
492
493    // public double constructor
494    LLAssert(llong((double)0).asDouble() == (double)0);
495    LLAssert(llong((double)1).asDouble() == (double)1);
496    LLAssert(llong((double)0x7fffffff).asDouble() == (double)0x7fffffff);
497    LLAssert(llong((double)0x80000000).asDouble() == (double)0x80000000);
498    LLAssert(llong((double)0x80000001).asDouble() == (double)0x80000001);
499
500    // can't access uprv_maxmantissa, so fake it
501    double maxmantissa = (llong((int32_t)1) << 40).asDouble();
502    LLAssert(llong(maxmantissa).asDouble() == maxmantissa);
503    LLAssert(llong(-maxmantissa).asDouble() == -maxmantissa);
504
505    // copy constructor
506    LLAssert(llong(llong(0, 1)).asDouble() == 1);
507    LLAssert(llong(llong(1, 0)).asDouble() == llong::kD32);
508    LLAssert(llong(llong(-1, (uint32_t)-1)).asDouble() == -1);
509
510    // asInt - test unsigned to signed narrowing conversion
511    LLAssert(llong((uint32_t)-1).asInt() == (int32_t)0x7fffffff);
512    LLAssert(llong(-1, 0).asInt() == (int32_t)0x80000000);
513
514    // asUInt - test signed to unsigned narrowing conversion
515    LLAssert(llong((int32_t)-1).asUInt() == (uint32_t)-1);
516    LLAssert(llong((int32_t)0x80000000).asUInt() == (uint32_t)0x80000000);
517
518    // asDouble already tested
519
520}
521
522void IntlTestRBNF::TestLLongSimpleOperators()
523{
524    logln("Testing simple operators");
525
526    // operator==
527    LLAssert(llong() == llong(0, 0));
528    LLAssert(llong(1,0) == llong(1, 0));
529    LLAssert(llong(0,1) == llong(0, 1));
530
531    // operator!=
532    LLAssert(llong(1,0) != llong(1,1));
533    LLAssert(llong(0,1) != llong(1,1));
534    LLAssert(llong(0xffffffff,0xffffffff) != llong(0x7fffffff, 0xffffffff));
535
536    // unsigned >
537    LLAssert(llong((int32_t)-1).ugt(llong(0x7fffffff, 0xffffffff)));
538
539    // unsigned <
540    LLAssert(llong(0x7fffffff, 0xffffffff).ult(llong((int32_t)-1)));
541
542    // unsigned >=
543    LLAssert(llong((int32_t)-1).uge(llong(0x7fffffff, 0xffffffff)));
544    LLAssert(llong((int32_t)-1).uge(llong((int32_t)-1)));
545
546    // unsigned <=
547    LLAssert(llong(0x7fffffff, 0xffffffff).ule(llong((int32_t)-1)));
548    LLAssert(llong((int32_t)-1).ule(llong((int32_t)-1)));
549
550    // operator>
551    LLAssert(llong(1, 1) > llong(1, 0));
552    LLAssert(llong(0, 0x80000000) > llong(0, 0x7fffffff));
553    LLAssert(llong(0x80000000, 1) > llong(0x80000000, 0));
554    LLAssert(llong(1, 0) > llong(0, 0x7fffffff));
555    LLAssert(llong(1, 0) > llong(0, 0xffffffff));
556    LLAssert(llong(0, 0) > llong(0x80000000, 1));
557
558    // operator<
559    LLAssert(llong(1, 0) < llong(1, 1));
560    LLAssert(llong(0, 0x7fffffff) < llong(0, 0x80000000));
561    LLAssert(llong(0x80000000, 0) < llong(0x80000000, 1));
562    LLAssert(llong(0, 0x7fffffff) < llong(1, 0));
563    LLAssert(llong(0, 0xffffffff) < llong(1, 0));
564    LLAssert(llong(0x80000000, 1) < llong(0, 0));
565
566    // operator>=
567    LLAssert(llong(1, 1) >= llong(1, 0));
568    LLAssert(llong(0, 0x80000000) >= llong(0, 0x7fffffff));
569    LLAssert(llong(0x80000000, 1) >= llong(0x80000000, 0));
570    LLAssert(llong(1, 0) >= llong(0, 0x7fffffff));
571    LLAssert(llong(1, 0) >= llong(0, 0xffffffff));
572    LLAssert(llong(0, 0) >= llong(0x80000000, 1));
573    LLAssert(llong() >= llong(0, 0));
574    LLAssert(llong(1,0) >= llong(1, 0));
575    LLAssert(llong(0,1) >= llong(0, 1));
576
577    // operator<=
578    LLAssert(llong(1, 0) <= llong(1, 1));
579    LLAssert(llong(0, 0x7fffffff) <= llong(0, 0x80000000));
580    LLAssert(llong(0x80000000, 0) <= llong(0x80000000, 1));
581    LLAssert(llong(0, 0x7fffffff) <= llong(1, 0));
582    LLAssert(llong(0, 0xffffffff) <= llong(1, 0));
583    LLAssert(llong(0x80000000, 1) <= llong(0, 0));
584    LLAssert(llong() <= llong(0, 0));
585    LLAssert(llong(1,0) <= llong(1, 0));
586    LLAssert(llong(0,1) <= llong(0, 1));
587
588    // operator==(int32)
589    LLAssert(llong() == (int32_t)0);
590    LLAssert(llong(0,1) == (int32_t)1);
591
592    // operator!=(int32)
593    LLAssert(llong(1,0) != (int32_t)0);
594    LLAssert(llong(0,1) != (int32_t)2);
595    LLAssert(llong(0,0xffffffff) != (int32_t)-1);
596
597    llong negOne(0xffffffff, 0xffffffff);
598
599    // operator>(int32)
600    LLAssert(llong(0, 0x80000000) > (int32_t)0x7fffffff);
601    LLAssert(negOne > (int32_t)-2);
602    LLAssert(llong(1, 0) > (int32_t)0x7fffffff);
603    LLAssert(llong(0, 0) > (int32_t)-1);
604
605    // operator<(int32)
606    LLAssert(llong(0, 0x7ffffffe) < (int32_t)0x7fffffff);
607    LLAssert(llong(0xffffffff, 0xfffffffe) < (int32_t)-1);
608
609    // operator>=(int32)
610    LLAssert(llong(0, 0x80000000) >= (int32_t)0x7fffffff);
611    LLAssert(negOne >= (int32_t)-2);
612    LLAssert(llong(1, 0) >= (int32_t)0x7fffffff);
613    LLAssert(llong(0, 0) >= (int32_t)-1);
614    LLAssert(llong() >= (int32_t)0);
615    LLAssert(llong(0,1) >= (int32_t)1);
616
617    // operator<=(int32)
618    LLAssert(llong(0, 0x7ffffffe) <= (int32_t)0x7fffffff);
619    LLAssert(llong(0xffffffff, 0xfffffffe) <= (int32_t)-1);
620    LLAssert(llong() <= (int32_t)0);
621    LLAssert(llong(0,1) <= (int32_t)1);
622
623    // operator=
624    LLAssert((llong(2,3) = llong((uint32_t)-1)).asUInt() == (uint32_t)-1);
625
626    // operator <<=
627    LLAssert((llong(1, 1) <<= 0) ==  llong(1, 1));
628    LLAssert((llong(1, 1) <<= 31) == llong(0x80000000, 0x80000000));
629    LLAssert((llong(1, 1) <<= 32) == llong(1, 0));
630    LLAssert((llong(1, 1) <<= 63) == llong(0x80000000, 0));
631    LLAssert((llong(1, 1) <<= 64) == llong(1, 1)); // only lower 6 bits are used
632    LLAssert((llong(1, 1) <<= -1) == llong(0x80000000, 0)); // only lower 6 bits are used
633
634    // operator <<
635    LLAssert((llong((int32_t)1) << 5).asUInt() == 32);
636
637    // operator >>= (sign extended)
638    LLAssert((llong(0x7fffa0a0, 0xbcbcdfdf) >>= 16) == llong(0x7fff,0xa0a0bcbc));
639    LLAssert((llong(0x8000789a, 0xbcde0000) >>= 16) == llong(0xffff8000,0x789abcde));
640    LLAssert((llong(0x80000000, 0) >>= 63) == llong(0xffffffff, 0xffffffff));
641    LLAssert((llong(0x80000000, 0) >>= 47) == llong(0xffffffff, 0xffff0000));
642    LLAssert((llong(0x80000000, 0x80000000) >> 64) == llong(0x80000000, 0x80000000)); // only lower 6 bits are used
643    LLAssert((llong(0x80000000, 0) >>= -1) == llong(0xffffffff, 0xffffffff)); // only lower 6 bits are used
644
645    // operator >> sign extended)
646    LLAssert((llong(0x8000789a, 0xbcde0000) >> 16) == llong(0xffff8000,0x789abcde));
647
648    // ushr (right shift without sign extension)
649    LLAssert(llong(0x7fffa0a0, 0xbcbcdfdf).ushr(16) == llong(0x7fff,0xa0a0bcbc));
650    LLAssert(llong(0x8000789a, 0xbcde0000).ushr(16) == llong(0x00008000,0x789abcde));
651    LLAssert(llong(0x80000000, 0).ushr(63) == llong(0, 1));
652    LLAssert(llong(0x80000000, 0).ushr(47) == llong(0, 0x10000));
653    LLAssert(llong(0x80000000, 0x80000000).ushr(64) == llong(0x80000000, 0x80000000)); // only lower 6 bits are used
654    LLAssert(llong(0x80000000, 0).ushr(-1) == llong(0, 1)); // only lower 6 bits are used
655
656    // operator&(llong)
657    LLAssert((llong(0x55555555, 0x55555555) & llong(0xaaaaffff, 0xffffaaaa)) == llong(0x00005555, 0x55550000));
658
659    // operator|(llong)
660    LLAssert((llong(0x55555555, 0x55555555) | llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffffff, 0xffffffff));
661
662    // operator^(llong)
663    LLAssert((llong(0x55555555, 0x55555555) ^ llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffaaaa, 0xaaaaffff));
664
665    // operator&(uint32)
666    LLAssert((llong(0x55555555, 0x55555555) & (uint32_t)0xffffaaaa) == llong(0, 0x55550000));
667
668    // operator|(uint32)
669    LLAssert((llong(0x55555555, 0x55555555) | (uint32_t)0xffffaaaa) == llong(0x55555555, 0xffffffff));
670
671    // operator^(uint32)
672    LLAssert((llong(0x55555555, 0x55555555) ^ (uint32_t)0xffffaaaa) == llong(0x55555555, 0xaaaaffff));
673
674    // operator~
675    LLAssert(~llong(0x55555555, 0x55555555) == llong(0xaaaaaaaa, 0xaaaaaaaa));
676
677    // operator&=(llong)
678    LLAssert((llong(0x55555555, 0x55555555) &= llong(0xaaaaffff, 0xffffaaaa)) == llong(0x00005555, 0x55550000));
679
680    // operator|=(llong)
681    LLAssert((llong(0x55555555, 0x55555555) |= llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffffff, 0xffffffff));
682
683    // operator^=(llong)
684    LLAssert((llong(0x55555555, 0x55555555) ^= llong(0xaaaaffff, 0xffffaaaa)) == llong(0xffffaaaa, 0xaaaaffff));
685
686    // operator&=(uint32)
687    LLAssert((llong(0x55555555, 0x55555555) &= (uint32_t)0xffffaaaa) == llong(0, 0x55550000));
688
689    // operator|=(uint32)
690    LLAssert((llong(0x55555555, 0x55555555) |= (uint32_t)0xffffaaaa) == llong(0x55555555, 0xffffffff));
691
692    // operator^=(uint32)
693    LLAssert((llong(0x55555555, 0x55555555) ^= (uint32_t)0xffffaaaa) == llong(0x55555555, 0xaaaaffff));
694
695    // prefix inc
696    LLAssert(llong(1, 0) == ++llong(0,0xffffffff));
697
698    // prefix dec
699    LLAssert(llong(0,0xffffffff) == --llong(1, 0));
700
701    // postfix inc
702    {
703        llong n(0, 0xffffffff);
704        LLAssert(llong(0, 0xffffffff) == n++);
705        LLAssert(llong(1, 0) == n);
706    }
707
708    // postfix dec
709    {
710        llong n(1, 0);
711        LLAssert(llong(1, 0) == n--);
712        LLAssert(llong(0, 0xffffffff) == n);
713    }
714
715    // unary minus
716    LLAssert(llong(0, 0) == -llong(0, 0));
717    LLAssert(llong(0xffffffff, 0xffffffff) == -llong(0, 1));
718    LLAssert(llong(0, 1) == -llong(0xffffffff, 0xffffffff));
719    LLAssert(llong(0x7fffffff, 0xffffffff) == -llong(0x80000000, 1));
720    LLAssert(llong(0x80000000, 0) == -llong(0x80000000, 0)); // !!! we don't handle overflow
721
722    // operator-=
723    {
724        llong n;
725        LLAssert((n -= llong(0, 1)) == llong(0xffffffff, 0xffffffff));
726        LLAssert(n == llong(0xffffffff, 0xffffffff));
727
728        n = llong(1, 0);
729        LLAssert((n -= llong(0, 1)) == llong(0, 0xffffffff));
730        LLAssert(n == llong(0, 0xffffffff));
731    }
732
733    // operator-
734    {
735        llong n;
736        LLAssert((n - llong(0, 1)) == llong(0xffffffff, 0xffffffff));
737        LLAssert(n == llong(0, 0));
738
739        n = llong(1, 0);
740        LLAssert((n - llong(0, 1)) == llong(0, 0xffffffff));
741        LLAssert(n == llong(1, 0));
742    }
743
744    // operator+=
745    {
746        llong n(0xffffffff, 0xffffffff);
747        LLAssert((n += llong(0, 1)) == llong(0, 0));
748        LLAssert(n == llong(0, 0));
749
750        n = llong(0, 0xffffffff);
751        LLAssert((n += llong(0, 1)) == llong(1, 0));
752        LLAssert(n == llong(1, 0));
753    }
754
755    // operator+
756    {
757        llong n(0xffffffff, 0xffffffff);
758        LLAssert((n + llong(0, 1)) == llong(0, 0));
759        LLAssert(n == llong(0xffffffff, 0xffffffff));
760
761        n = llong(0, 0xffffffff);
762        LLAssert((n + llong(0, 1)) == llong(1, 0));
763        LLAssert(n == llong(0, 0xffffffff));
764    }
765
766}
767
768void IntlTestRBNF::TestLLong()
769{
770    logln("Starting TestLLong");
771
772    TestLLongConstructors();
773
774    TestLLongSimpleOperators();
775
776    logln("Testing operator*=, operator*");
777
778    // operator*=, operator*
779    // small and large values, positive, &NEGative, zero
780    // also test commutivity
781    {
782        const llong ZERO;
783        const llong ONE(0, 1);
784        const llong NEG_ONE((int32_t)-1);
785        const llong THREE(0, 3);
786        const llong NEG_THREE((int32_t)-3);
787        const llong TWO_TO_16(0, 0x10000);
788        const llong NEG_TWO_TO_16 = -TWO_TO_16;
789        const llong TWO_TO_32(1, 0);
790        const llong NEG_TWO_TO_32 = -TWO_TO_32;
791
792        const llong NINE(0, 9);
793        const llong NEG_NINE = -NINE;
794
795        const llong TWO_TO_16X3(0, 0x00030000);
796        const llong NEG_TWO_TO_16X3 = -TWO_TO_16X3;
797
798        const llong TWO_TO_32X3(3, 0);
799        const llong NEG_TWO_TO_32X3 = -TWO_TO_32X3;
800
801        const llong TWO_TO_48(0x10000, 0);
802        const llong NEG_TWO_TO_48 = -TWO_TO_48;
803
804        const int32_t VALUE_WIDTH = 9;
805        const llong* values[VALUE_WIDTH] = {
806            &ZERO, &ONE, &NEG_ONE, &THREE, &NEG_THREE, &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_32, &NEG_TWO_TO_32
807        };
808
809        const llong* answers[VALUE_WIDTH*VALUE_WIDTH] = {
810            &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO, &ZERO,
811            &ZERO, &ONE,  &NEG_ONE, &THREE, &NEG_THREE,  &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_32, &NEG_TWO_TO_32,
812            &ZERO, &NEG_ONE, &ONE, &NEG_THREE, &THREE, &NEG_TWO_TO_16, &TWO_TO_16, &NEG_TWO_TO_32, &TWO_TO_32,
813            &ZERO, &THREE, &NEG_THREE, &NINE, &NEG_NINE, &TWO_TO_16X3, &NEG_TWO_TO_16X3, &TWO_TO_32X3, &NEG_TWO_TO_32X3,
814            &ZERO, &NEG_THREE, &THREE, &NEG_NINE, &NINE, &NEG_TWO_TO_16X3, &TWO_TO_16X3, &NEG_TWO_TO_32X3, &TWO_TO_32X3,
815            &ZERO, &TWO_TO_16, &NEG_TWO_TO_16, &TWO_TO_16X3, &NEG_TWO_TO_16X3, &TWO_TO_32, &NEG_TWO_TO_32, &TWO_TO_48, &NEG_TWO_TO_48,
816            &ZERO, &NEG_TWO_TO_16, &TWO_TO_16, &NEG_TWO_TO_16X3, &TWO_TO_16X3, &NEG_TWO_TO_32, &TWO_TO_32, &NEG_TWO_TO_48, &TWO_TO_48,
817            &ZERO, &TWO_TO_32, &NEG_TWO_TO_32, &TWO_TO_32X3, &NEG_TWO_TO_32X3, &TWO_TO_48, &NEG_TWO_TO_48, &ZERO, &ZERO,
818            &ZERO, &NEG_TWO_TO_32, &TWO_TO_32, &NEG_TWO_TO_32X3, &TWO_TO_32X3, &NEG_TWO_TO_48, &TWO_TO_48, &ZERO, &ZERO
819        };
820
821        for (int i = 0; i < VALUE_WIDTH; ++i) {
822            for (int j = 0; j < VALUE_WIDTH; ++j) {
823                llong lhs = *values[i];
824                llong rhs = *values[j];
825                llong ans = *answers[i*VALUE_WIDTH + j];
826
827                llong n = lhs;
828
829                LLAssert((n *= rhs) == ans);
830                LLAssert(n == ans);
831
832                n = lhs;
833                LLAssert((n * rhs) == ans);
834                LLAssert(n == lhs);
835            }
836        }
837    }
838
839    logln("Testing operator/=, operator/");
840    // operator/=, operator/
841    // test num = 0, div = 0, pos/neg, > 2^32, div > num
842    {
843        const llong ZERO;
844        const llong ONE(0, 1);
845        const llong NEG_ONE = -ONE;
846        const llong MAX(0x7fffffff, 0xffffffff);
847        const llong MIN(0x80000000, 0);
848        const llong TWO(0, 2);
849        const llong NEG_TWO = -TWO;
850        const llong FIVE(0, 5);
851        const llong NEG_FIVE = -FIVE;
852        const llong TWO_TO_32(1, 0);
853        const llong NEG_TWO_TO_32 = -TWO_TO_32;
854        const llong TWO_TO_32d5 = llong(TWO_TO_32.asDouble()/5.0);
855        const llong NEG_TWO_TO_32d5 = -TWO_TO_32d5;
856        const llong TWO_TO_32X5 = TWO_TO_32 * FIVE;
857        const llong NEG_TWO_TO_32X5 = -TWO_TO_32X5;
858
859        const llong* tuples[] = { // lhs, rhs, ans
860            &ZERO, &ZERO, &ZERO,
861            &ONE, &ZERO,&MAX,
862            &NEG_ONE, &ZERO, &MIN,
863            &ONE, &ONE, &ONE,
864            &ONE, &NEG_ONE, &NEG_ONE,
865            &NEG_ONE, &ONE, &NEG_ONE,
866            &NEG_ONE, &NEG_ONE, &ONE,
867            &FIVE, &TWO, &TWO,
868            &FIVE, &NEG_TWO, &NEG_TWO,
869            &NEG_FIVE, &TWO, &NEG_TWO,
870            &NEG_FIVE, &NEG_TWO, &TWO,
871            &TWO, &FIVE, &ZERO,
872            &TWO, &NEG_FIVE, &ZERO,
873            &NEG_TWO, &FIVE, &ZERO,
874            &NEG_TWO, &NEG_FIVE, &ZERO,
875            &TWO_TO_32, &TWO_TO_32, &ONE,
876            &TWO_TO_32, &NEG_TWO_TO_32, &NEG_ONE,
877            &NEG_TWO_TO_32, &TWO_TO_32, &NEG_ONE,
878            &NEG_TWO_TO_32, &NEG_TWO_TO_32, &ONE,
879            &TWO_TO_32, &FIVE, &TWO_TO_32d5,
880            &TWO_TO_32, &NEG_FIVE, &NEG_TWO_TO_32d5,
881            &NEG_TWO_TO_32, &FIVE, &NEG_TWO_TO_32d5,
882            &NEG_TWO_TO_32, &NEG_FIVE, &TWO_TO_32d5,
883            &TWO_TO_32X5, &FIVE, &TWO_TO_32,
884            &TWO_TO_32X5, &NEG_FIVE, &NEG_TWO_TO_32,
885            &NEG_TWO_TO_32X5, &FIVE, &NEG_TWO_TO_32,
886            &NEG_TWO_TO_32X5, &NEG_FIVE, &TWO_TO_32,
887            &TWO_TO_32X5, &TWO_TO_32, &FIVE,
888            &TWO_TO_32X5, &NEG_TWO_TO_32, &NEG_FIVE,
889            &NEG_TWO_TO_32X5, &NEG_TWO_TO_32, &FIVE,
890            &NEG_TWO_TO_32X5, &TWO_TO_32, &NEG_FIVE
891        };
892        const int TUPLE_WIDTH = 3;
893        const int TUPLE_COUNT = (int)(sizeof(tuples)/sizeof(tuples[0]))/TUPLE_WIDTH;
894        for (int i = 0; i < TUPLE_COUNT; ++i) {
895            const llong lhs = *tuples[i*TUPLE_WIDTH+0];
896            const llong rhs = *tuples[i*TUPLE_WIDTH+1];
897            const llong ans = *tuples[i*TUPLE_WIDTH+2];
898
899            llong n = lhs;
900            if (!((n /= rhs) == ans)) {
901                errln("fail: (n /= rhs) == ans");
902            }
903            LLAssert(n == ans);
904
905            n = lhs;
906            LLAssert((n / rhs) == ans);
907            LLAssert(n == lhs);
908        }
909    }
910
911    logln("Testing operator%%=, operator%%");
912    //operator%=, operator%
913    {
914        const llong ZERO;
915        const llong ONE(0, 1);
916        const llong TWO(0, 2);
917        const llong THREE(0,3);
918        const llong FOUR(0, 4);
919        const llong FIVE(0, 5);
920        const llong SIX(0, 6);
921
922        const llong NEG_ONE = -ONE;
923        const llong NEG_TWO = -TWO;
924        const llong NEG_THREE = -THREE;
925        const llong NEG_FOUR = -FOUR;
926        const llong NEG_FIVE = -FIVE;
927        const llong NEG_SIX = -SIX;
928
929        const llong NINETY_NINE(0, 99);
930        const llong HUNDRED(0, 100);
931        const llong HUNDRED_ONE(0, 101);
932
933        const llong BIG(0x12345678, 0x9abcdef0);
934        const llong BIG_FIVE(BIG * FIVE);
935        const llong BIG_FIVEm1 = BIG_FIVE - ONE;
936        const llong BIG_FIVEp1 = BIG_FIVE + ONE;
937
938        const llong* tuples[] = {
939            &ZERO, &FIVE, &ZERO,
940            &ONE, &FIVE, &ONE,
941            &TWO, &FIVE, &TWO,
942            &THREE, &FIVE, &THREE,
943            &FOUR, &FIVE, &FOUR,
944            &FIVE, &FIVE, &ZERO,
945            &SIX, &FIVE, &ONE,
946            &ZERO, &NEG_FIVE, &ZERO,
947            &ONE, &NEG_FIVE, &ONE,
948            &TWO, &NEG_FIVE, &TWO,
949            &THREE, &NEG_FIVE, &THREE,
950            &FOUR, &NEG_FIVE, &FOUR,
951            &FIVE, &NEG_FIVE, &ZERO,
952            &SIX, &NEG_FIVE, &ONE,
953            &NEG_ONE, &FIVE, &NEG_ONE,
954            &NEG_TWO, &FIVE, &NEG_TWO,
955            &NEG_THREE, &FIVE, &NEG_THREE,
956            &NEG_FOUR, &FIVE, &NEG_FOUR,
957            &NEG_FIVE, &FIVE, &ZERO,
958            &NEG_SIX, &FIVE, &NEG_ONE,
959            &NEG_ONE, &NEG_FIVE, &NEG_ONE,
960            &NEG_TWO, &NEG_FIVE, &NEG_TWO,
961            &NEG_THREE, &NEG_FIVE, &NEG_THREE,
962            &NEG_FOUR, &NEG_FIVE, &NEG_FOUR,
963            &NEG_FIVE, &NEG_FIVE, &ZERO,
964            &NEG_SIX, &NEG_FIVE, &NEG_ONE,
965            &NINETY_NINE, &FIVE, &FOUR,
966            &HUNDRED, &FIVE, &ZERO,
967            &HUNDRED_ONE, &FIVE, &ONE,
968            &BIG_FIVEm1, &FIVE, &FOUR,
969            &BIG_FIVE, &FIVE, &ZERO,
970            &BIG_FIVEp1, &FIVE, &ONE
971        };
972        const int TUPLE_WIDTH = 3;
973        const int TUPLE_COUNT = (int)(sizeof(tuples)/sizeof(tuples[0]))/TUPLE_WIDTH;
974        for (int i = 0; i < TUPLE_COUNT; ++i) {
975            const llong lhs = *tuples[i*TUPLE_WIDTH+0];
976            const llong rhs = *tuples[i*TUPLE_WIDTH+1];
977            const llong ans = *tuples[i*TUPLE_WIDTH+2];
978
979            llong n = lhs;
980            if (!((n %= rhs) == ans)) {
981                errln("fail: (n %= rhs) == ans");
982            }
983            LLAssert(n == ans);
984
985            n = lhs;
986            LLAssert((n % rhs) == ans);
987            LLAssert(n == lhs);
988        }
989    }
990
991    logln("Testing pow");
992    // pow
993    LLAssert(llong(0, 0).pow(0) == llong(0, 0));
994    LLAssert(llong(0, 0).pow(2) == llong(0, 0));
995    LLAssert(llong(0, 2).pow(0) == llong(0, 1));
996    LLAssert(llong(0, 2).pow(2) == llong(0, 4));
997    LLAssert(llong(0, 2).pow(32) == llong(1, 0));
998    LLAssert(llong(0, 5).pow(10) == llong((double)5.0 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5));
999
1000    // absolute value
1001    {
1002        const llong n(0xffffffff,0xffffffff);
1003        LLAssert(n.abs() == llong(0, 1));
1004    }
1005
1006#ifdef RBNF_DEBUG
1007    logln("Testing atoll");
1008    // atoll
1009    const char empty[] = "";
1010    const char zero[] = "0";
1011    const char neg_one[] = "-1";
1012    const char neg_12345[] = "-12345";
1013    const char big1[] = "123456789abcdef0";
1014    const char big2[] = "fFfFfFfFfFfFfFfF";
1015    LLAssert(llong::atoll(empty) == llong(0, 0));
1016    LLAssert(llong::atoll(zero) == llong(0, 0));
1017    LLAssert(llong::atoll(neg_one) == llong(0xffffffff, 0xffffffff));
1018    LLAssert(llong::atoll(neg_12345) == -llong(0, 12345));
1019    LLAssert(llong::atoll(big1, 16) == llong(0x12345678, 0x9abcdef0));
1020    LLAssert(llong::atoll(big2, 16) == llong(0xffffffff, 0xffffffff));
1021#endif
1022
1023    // u_atoll
1024    const UChar uempty[] = { 0 };
1025    const UChar uzero[] = { 0x30, 0 };
1026    const UChar uneg_one[] = { 0x2d, 0x31, 0 };
1027    const UChar uneg_12345[] = { 0x2d, 0x31, 0x32, 0x33, 0x34, 0x35, 0 };
1028    const UChar ubig1[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0 };
1029    const UChar ubig2[] = { 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0x66, 0x46, 0 };
1030    LLAssert(llong::utoll(uempty) == llong(0, 0));
1031    LLAssert(llong::utoll(uzero) == llong(0, 0));
1032    LLAssert(llong::utoll(uneg_one) == llong(0xffffffff, 0xffffffff));
1033    LLAssert(llong::utoll(uneg_12345) == -llong(0, 12345));
1034    LLAssert(llong::utoll(ubig1, 16) == llong(0x12345678, 0x9abcdef0));
1035    LLAssert(llong::utoll(ubig2, 16) == llong(0xffffffff, 0xffffffff));
1036
1037#ifdef RBNF_DEBUG
1038    logln("Testing lltoa");
1039    // lltoa
1040    {
1041        char buf[64]; // ascii
1042        LLAssert((llong(0, 0).lltoa(buf, (uint32_t)sizeof(buf)) == 1) && (strcmp(buf, zero) == 0));
1043        LLAssert((llong(0xffffffff, 0xffffffff).lltoa(buf, (uint32_t)sizeof(buf)) == 2) && (strcmp(buf, neg_one) == 0));
1044        LLAssert(((-llong(0, 12345)).lltoa(buf, (uint32_t)sizeof(buf)) == 6) && (strcmp(buf, neg_12345) == 0));
1045        LLAssert((llong(0x12345678, 0x9abcdef0).lltoa(buf, (uint32_t)sizeof(buf), 16) == 16) && (strcmp(buf, big1) == 0));
1046    }
1047#endif
1048
1049    logln("Testing u_lltoa");
1050    // u_lltoa
1051    {
1052        UChar buf[64];
1053        LLAssert((llong(0, 0).lltou(buf, (uint32_t)sizeof(buf)) == 1) && (u_strcmp(buf, uzero) == 0));
1054        LLAssert((llong(0xffffffff, 0xffffffff).lltou(buf, (uint32_t)sizeof(buf)) == 2) && (u_strcmp(buf, uneg_one) == 0));
1055        LLAssert(((-llong(0, 12345)).lltou(buf, (uint32_t)sizeof(buf)) == 6) && (u_strcmp(buf, uneg_12345) == 0));
1056        LLAssert((llong(0x12345678, 0x9abcdef0).lltou(buf, (uint32_t)sizeof(buf), 16) == 16) && (u_strcmp(buf, ubig1) == 0));
1057    }
1058}
1059
1060/* if 0 */
1061#endif
1062
1063void
1064IntlTestRBNF::TestEnglishSpellout()
1065{
1066    UErrorCode status = U_ZERO_ERROR;
1067    RuleBasedNumberFormat* formatter
1068        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status);
1069    if (U_FAILURE(status)) {
1070        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1071    } else {
1072        static const char* const testData[][2] = {
1073            { "1", "one" },
1074            { "2", "two" },
1075            { "15", "fifteen" },
1076            { "20", "twenty" },
1077            { "23", "twenty-three" },
1078            { "73", "seventy-three" },
1079            { "88", "eighty-eight" },
1080            { "100", "one hundred" },
1081            { "106", "one hundred six" },
1082            { "127", "one hundred twenty-seven" },
1083            { "200", "two hundred" },
1084            { "579", "five hundred seventy-nine" },
1085            { "1,000", "one thousand" },
1086            { "2,000", "two thousand" },
1087            { "3,004", "three thousand four" },
1088            { "4,567", "four thousand five hundred sixty-seven" },
1089            { "15,943", "fifteen thousand nine hundred forty-three" },
1090            { "2,345,678", "two million three hundred forty-five thousand six hundred seventy-eight" },
1091            { "-36", "minus thirty-six" },
1092            { "234.567", "two hundred thirty-four point five six seven" },
1093            { NULL, NULL}
1094        };
1095
1096        doTest(formatter, testData, TRUE);
1097
1098#if !UCONFIG_NO_COLLATION
1099        formatter->setLenient(TRUE);
1100        static const char* lpTestData[][2] = {
1101            { "fifty-7", "57" },
1102            { " fifty-7", "57" },
1103            { "  fifty-7", "57" },
1104            { "2 thousand six    HUNDRED fifty-7", "2,657" },
1105            { "fifteen hundred and zero", "1,500" },
1106            { "FOurhundred     thiRTY six", "436" },
1107            { NULL, NULL}
1108        };
1109        doLenientParseTest(formatter, lpTestData);
1110#endif
1111    }
1112    delete formatter;
1113}
1114
1115void
1116IntlTestRBNF::TestOrdinalAbbreviations()
1117{
1118    UErrorCode status = U_ZERO_ERROR;
1119    RuleBasedNumberFormat* formatter
1120        = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale::getUS(), status);
1121
1122    if (U_FAILURE(status)) {
1123        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1124    } else {
1125        static const char* const testData[][2] = {
1126            { "1", "1st" },
1127            { "2", "2nd" },
1128            { "3", "3rd" },
1129            { "4", "4th" },
1130            { "7", "7th" },
1131            { "10", "10th" },
1132            { "11", "11th" },
1133            { "13", "13th" },
1134            { "20", "20th" },
1135            { "21", "21st" },
1136            { "22", "22nd" },
1137            { "23", "23rd" },
1138            { "24", "24th" },
1139            { "33", "33rd" },
1140            { "102", "102nd" },
1141            { "312", "312th" },
1142            { "12,345", "12,345th" },
1143            { NULL, NULL}
1144        };
1145
1146        doTest(formatter, testData, FALSE);
1147    }
1148    delete formatter;
1149}
1150
1151void
1152IntlTestRBNF::TestDurations()
1153{
1154    UErrorCode status = U_ZERO_ERROR;
1155    RuleBasedNumberFormat* formatter
1156        = new RuleBasedNumberFormat(URBNF_DURATION, Locale::getUS(), status);
1157
1158    if (U_FAILURE(status)) {
1159        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1160    } else {
1161        static const char* const testData[][2] = {
1162            { "3,600", "1:00:00" },     //move me and I fail
1163            { "0", "0 sec." },
1164            { "1", "1 sec." },
1165            { "24", "24 sec." },
1166            { "60", "1:00" },
1167            { "73", "1:13" },
1168            { "145", "2:25" },
1169            { "666", "11:06" },
1170            //            { "3,600", "1:00:00" },
1171            { "3,740", "1:02:20" },
1172            { "10,293", "2:51:33" },
1173            { NULL, NULL}
1174        };
1175
1176        doTest(formatter, testData, TRUE);
1177
1178#if !UCONFIG_NO_COLLATION
1179        formatter->setLenient(TRUE);
1180        static const char* lpTestData[][2] = {
1181            { "2-51-33", "10,293" },
1182            { NULL, NULL}
1183        };
1184        doLenientParseTest(formatter, lpTestData);
1185#endif
1186    }
1187    delete formatter;
1188}
1189
1190void
1191IntlTestRBNF::TestSpanishSpellout()
1192{
1193    UErrorCode status = U_ZERO_ERROR;
1194    RuleBasedNumberFormat* formatter
1195        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("es", "ES", ""), status);
1196
1197    if (U_FAILURE(status)) {
1198        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1199    } else {
1200        static const char* const testData[][2] = {
1201            { "1", "uno" },
1202            { "6", "seis" },
1203            { "16", "diecis\\u00e9is" },
1204            { "20", "veinte" },
1205            { "24", "veinticuatro" },
1206            { "26", "veintis\\u00e9is" },
1207            { "73", "setenta y tres" },
1208            { "88", "ochenta y ocho" },
1209            { "100", "cien" },
1210            { "106", "ciento seis" },
1211            { "127", "ciento veintisiete" },
1212            { "200", "doscientos" },
1213            { "579", "quinientos setenta y nueve" },
1214            { "1,000", "mil" },
1215            { "2,000", "dos mil" },
1216            { "3,004", "tres mil cuatro" },
1217            { "4,567", "cuatro mil quinientos sesenta y siete" },
1218            { "15,943", "quince mil novecientos cuarenta y tres" },
1219            { "2,345,678", "dos millones trescientos cuarenta y cinco mil seiscientos setenta y ocho"},
1220            { "-36", "menos treinta y seis" },
1221            { "234.567", "doscientos treinta y cuatro coma cinco seis siete" },
1222            { NULL, NULL}
1223        };
1224
1225        doTest(formatter, testData, TRUE);
1226    }
1227    delete formatter;
1228}
1229
1230void
1231IntlTestRBNF::TestFrenchSpellout()
1232{
1233    UErrorCode status = U_ZERO_ERROR;
1234    RuleBasedNumberFormat* formatter
1235        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getFrance(), status);
1236
1237    if (U_FAILURE(status)) {
1238        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1239    } else {
1240        static const char* const testData[][2] = {
1241            { "1", "un" },
1242            { "15", "quinze" },
1243            { "20", "vingt" },
1244            { "21", "vingt-et-un" },
1245            { "23", "vingt-trois" },
1246            { "62", "soixante-deux" },
1247            { "70", "soixante-dix" },
1248            { "71", "soixante-et-onze" },
1249            { "73", "soixante-treize" },
1250            { "80", "quatre-vingts" },
1251            { "88", "quatre-vingt-huit" },
1252            { "100", "cent" },
1253            { "106", "cent-six" },
1254            { "127", "cent-vingt-sept" },
1255            { "200", "deux-cents" },
1256            { "579", "cinq-cent-soixante-dix-neuf" },
1257            { "1,000", "mille" },
1258            { "1,123", "mille-cent-vingt-trois" },
1259            { "1,594", "mille-cinq-cent-quatre-vingt-quatorze" },
1260            { "2,000", "deux-mille" },
1261            { "3,004", "trois-mille-quatre" },
1262            { "4,567", "quatre-mille-cinq-cent-soixante-sept" },
1263            { "15,943", "quinze-mille-neuf-cent-quarante-trois" },
1264            { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-six-cent-soixante-dix-huit" },
1265            { "-36", "moins trente-six" },
1266            { "234.567", "deux-cent-trente-quatre virgule cinq six sept" },
1267            { NULL, NULL}
1268        };
1269
1270        doTest(formatter, testData, TRUE);
1271
1272#if !UCONFIG_NO_COLLATION
1273        formatter->setLenient(TRUE);
1274        static const char* lpTestData[][2] = {
1275            { "trente-et-un", "31" },
1276            { "un cent quatre vingt dix huit", "198" },
1277            { NULL, NULL}
1278        };
1279        doLenientParseTest(formatter, lpTestData);
1280#endif
1281    }
1282    delete formatter;
1283}
1284
1285static const char* const swissFrenchTestData[][2] = {
1286    { "1", "un" },
1287    { "15", "quinze" },
1288    { "20", "vingt" },
1289    { "21", "vingt-et-un" },
1290    { "23", "vingt-trois" },
1291    { "62", "soixante-deux" },
1292    { "70", "septante" },
1293    { "71", "septante-et-un" },
1294    { "73", "septante-trois" },
1295    { "80", "huitante" },
1296    { "88", "huitante-huit" },
1297    { "100", "cent" },
1298    { "106", "cent-six" },
1299    { "127", "cent-vingt-sept" },
1300    { "200", "deux-cents" },
1301    { "579", "cinq-cent-septante-neuf" },
1302    { "1,000", "mille" },
1303    { "1,123", "mille-cent-vingt-trois" },
1304    { "1,594", "mille-cinq-cent-nonante-quatre" },
1305    { "2,000", "deux-mille" },
1306    { "3,004", "trois-mille-quatre" },
1307    { "4,567", "quatre-mille-cinq-cent-soixante-sept" },
1308    { "15,943", "quinze-mille-neuf-cent-quarante-trois" },
1309    { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-six-cent-septante-huit" },
1310    { "-36", "moins trente-six" },
1311    { "234.567", "deux-cent-trente-quatre virgule cinq six sept" },
1312    { NULL, NULL}
1313};
1314
1315void
1316IntlTestRBNF::TestSwissFrenchSpellout()
1317{
1318    UErrorCode status = U_ZERO_ERROR;
1319    RuleBasedNumberFormat* formatter
1320        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "CH", ""), status);
1321
1322    if (U_FAILURE(status)) {
1323        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1324    } else {
1325        doTest(formatter, swissFrenchTestData, TRUE);
1326    }
1327    delete formatter;
1328}
1329
1330static const char* const belgianFrenchTestData[][2] = {
1331    { "1", "un" },
1332    { "15", "quinze" },
1333    { "20", "vingt" },
1334    { "21", "vingt-et-un" },
1335    { "23", "vingt-trois" },
1336    { "62", "soixante-deux" },
1337    { "70", "septante" },
1338    { "71", "septante-et-un" },
1339    { "73", "septante-trois" },
1340    { "80", "quatre-vingts" },
1341    { "88", "quatre-vingt-huit" },
1342    { "90", "nonante" },
1343    { "91", "nonante-et-un" },
1344    { "95", "nonante-cinq" },
1345    { "100", "cent" },
1346    { "106", "cent-six" },
1347    { "127", "cent-vingt-sept" },
1348    { "200", "deux-cents" },
1349    { "579", "cinq-cent-septante-neuf" },
1350    { "1,000", "mille" },
1351    { "1,123", "mille-cent-vingt-trois" },
1352    { "1,594", "mille-cinq-cent-nonante-quatre" },
1353    { "2,000", "deux-mille" },
1354    { "3,004", "trois-mille-quatre" },
1355    { "4,567", "quatre-mille-cinq-cent-soixante-sept" },
1356    { "15,943", "quinze-mille-neuf-cent-quarante-trois" },
1357    { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-six-cent-septante-huit" },
1358    { "-36", "moins trente-six" },
1359    { "234.567", "deux-cent-trente-quatre virgule cinq six sept" },
1360    { NULL, NULL}
1361};
1362
1363
1364void
1365IntlTestRBNF::TestBelgianFrenchSpellout()
1366{
1367    UErrorCode status = U_ZERO_ERROR;
1368    RuleBasedNumberFormat* formatter
1369        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "BE", ""), status);
1370
1371    if (U_FAILURE(status)) {
1372        errcheckln(status, "rbnf status: 0x%x (%s)\n", status, u_errorName(status));
1373        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1374    } else {
1375        // Belgian french should match Swiss french.
1376        doTest(formatter, belgianFrenchTestData, TRUE);
1377    }
1378    delete formatter;
1379}
1380
1381void
1382IntlTestRBNF::TestItalianSpellout()
1383{
1384    UErrorCode status = U_ZERO_ERROR;
1385    RuleBasedNumberFormat* formatter
1386        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getItalian(), status);
1387
1388    if (U_FAILURE(status)) {
1389        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1390    } else {
1391        static const char* const testData[][2] = {
1392            { "1", "uno" },
1393            { "15", "quindici" },
1394            { "20", "venti" },
1395            { "23", "venti\\u00ADtr\\u00E9" },
1396            { "73", "settanta\\u00ADtr\\u00E9" },
1397            { "88", "ottant\\u00ADotto" },
1398            { "100", "cento" },
1399            { "101", "cento\\u00ADuno" },
1400            { "103", "cento\\u00ADtr\\u00E9" },
1401            { "106", "cento\\u00ADsei" },
1402            { "108", "cent\\u00ADotto" },
1403            { "127", "cento\\u00ADventi\\u00ADsette" },
1404            { "181", "cent\\u00ADottant\\u00ADuno" },
1405            { "200", "due\\u00ADcento" },
1406            { "579", "cinque\\u00ADcento\\u00ADsettanta\\u00ADnove" },
1407            { "1,000", "mille" },
1408            { "2,000", "due\\u00ADmila" },
1409            { "3,004", "tre\\u00ADmila\\u00ADquattro" },
1410            { "4,567", "quattro\\u00ADmila\\u00ADcinque\\u00ADcento\\u00ADsessanta\\u00ADsette" },
1411            { "15,943", "quindici\\u00ADmila\\u00ADnove\\u00ADcento\\u00ADquaranta\\u00ADtr\\u00E9" },
1412            { "-36", "meno trenta\\u00ADsei" },
1413            { "234.567", "due\\u00ADcento\\u00ADtrenta\\u00ADquattro virgola cinque sei sette" },
1414            { NULL, NULL}
1415        };
1416
1417        doTest(formatter, testData, TRUE);
1418    }
1419    delete formatter;
1420}
1421
1422void
1423IntlTestRBNF::TestPortugueseSpellout()
1424{
1425    UErrorCode status = U_ZERO_ERROR;
1426    RuleBasedNumberFormat* formatter
1427        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("pt","BR",""), status);
1428
1429    if (U_FAILURE(status)) {
1430        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1431    } else {
1432        static const char* const testData[][2] = {
1433            { "1", "um" },
1434            { "15", "quinze" },
1435            { "20", "vinte" },
1436            { "23", "vinte e tr\\u00EAs" },
1437            { "73", "setenta e tr\\u00EAs" },
1438            { "88", "oitenta e oito" },
1439            { "100", "cem" },
1440            { "106", "cento e seis" },
1441            { "108", "cento e oito" },
1442            { "127", "cento e vinte e sete" },
1443            { "181", "cento e oitenta e um" },
1444            { "200", "duzentos" },
1445            { "579", "quinhentos e setenta e nove" },
1446            { "1,000", "mil" },
1447            { "2,000", "dois mil" },
1448            { "3,004", "tr\\u00EAs mil e quatro" },
1449            { "4,567", "quatro mil e quinhentos e sessenta e sete" },
1450            { "15,943", "quinze mil e novecentos e quarenta e tr\\u00EAs" },
1451            { "-36", "menos trinta e seis" },
1452            { "234.567", "duzentos e trinta e quatro v\\u00EDrgula cinco seis sete" },
1453            { NULL, NULL}
1454        };
1455
1456        doTest(formatter, testData, TRUE);
1457    }
1458    delete formatter;
1459}
1460void
1461IntlTestRBNF::TestGermanSpellout()
1462{
1463    UErrorCode status = U_ZERO_ERROR;
1464    RuleBasedNumberFormat* formatter
1465        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getGermany(), status);
1466
1467    if (U_FAILURE(status)) {
1468        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1469    } else {
1470        static const char* const testData[][2] = {
1471            { "1", "eins" },
1472            { "15", "f\\u00fcnfzehn" },
1473            { "20", "zwanzig" },
1474            { "23", "drei\\u00ADund\\u00ADzwanzig" },
1475            { "73", "drei\\u00ADund\\u00ADsiebzig" },
1476            { "88", "acht\\u00ADund\\u00ADachtzig" },
1477            { "100", "ein\\u00ADhundert" },
1478            { "106", "ein\\u00ADhundert\\u00ADsechs" },
1479            { "127", "ein\\u00ADhundert\\u00ADsieben\\u00ADund\\u00ADzwanzig" },
1480            { "200", "zwei\\u00ADhundert" },
1481            { "579", "f\\u00fcnf\\u00ADhundert\\u00ADneun\\u00ADund\\u00ADsiebzig" },
1482            { "1,000", "ein\\u00ADtausend" },
1483            { "2,000", "zwei\\u00ADtausend" },
1484            { "3,004", "drei\\u00ADtausend\\u00ADvier" },
1485            { "4,567", "vier\\u00ADtausend\\u00ADf\\u00fcnf\\u00ADhundert\\u00ADsieben\\u00ADund\\u00ADsechzig" },
1486            { "15,943", "f\\u00fcnfzehn\\u00ADtausend\\u00ADneun\\u00ADhundert\\u00ADdrei\\u00ADund\\u00ADvierzig" },
1487            { "2,345,678", "zwei Millionen drei\\u00ADhundert\\u00ADf\\u00fcnf\\u00ADund\\u00ADvierzig\\u00ADtausend\\u00ADsechs\\u00ADhundert\\u00ADacht\\u00ADund\\u00ADsiebzig" },
1488            { NULL, NULL}
1489        };
1490
1491        doTest(formatter, testData, TRUE);
1492
1493#if !UCONFIG_NO_COLLATION
1494        formatter->setLenient(TRUE);
1495        static const char* lpTestData[][2] = {
1496            { "ein Tausend sechs Hundert fuenfunddreissig", "1,635" },
1497            { NULL, NULL}
1498        };
1499        doLenientParseTest(formatter, lpTestData);
1500#endif
1501    }
1502    delete formatter;
1503}
1504
1505void
1506IntlTestRBNF::TestThaiSpellout()
1507{
1508    UErrorCode status = U_ZERO_ERROR;
1509    RuleBasedNumberFormat* formatter
1510        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("th"), status);
1511
1512    if (U_FAILURE(status)) {
1513        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1514    } else {
1515        static const char* const testData[][2] = {
1516            { "0", "\\u0e28\\u0e39\\u0e19\\u0e22\\u0e4c" },
1517            { "1", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07" },
1518            { "10", "\\u0e2a\\u0e34\\u0e1a" },
1519            { "11", "\\u0e2a\\u0e34\\u0e1a\\u200b\\u0e40\\u0e2d\\u0e47\\u0e14" },
1520            { "21", "\\u0e22\\u0e35\\u0e48\\u200b\\u0e2a\\u0e34\\u0e1a\\u200b\\u0e40\\u0e2d\\u0e47\\u0e14" },
1521            { "101", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07\\u200b\\u0e23\\u0e49\\u0e2d\\u0e22\\u200b\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07" },
1522            { "1.234", "\\u0e2b\\u0e19\\u0e36\\u0e48\\u0e07\\u200b\\u0e08\\u0e38\\u0e14\\u200b\\u0e2a\\u0e2d\\u0e07\\u0e2a\\u0e32\\u0e21\\u0e2a\\u0e35\\u0e48" },
1523            { NULL, NULL}
1524        };
1525
1526        doTest(formatter, testData, TRUE);
1527    }
1528    delete formatter;
1529}
1530
1531void
1532IntlTestRBNF::TestSwedishSpellout()
1533{
1534    UErrorCode status = U_ZERO_ERROR;
1535    RuleBasedNumberFormat* formatter
1536        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("sv"), status);
1537
1538    if (U_FAILURE(status)) {
1539        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1540    } else {
1541        static const char* testDataDefault[][2] = {
1542            { "101", "ett\\u00adhundra\\u00adett" },
1543            { "123", "ett\\u00adhundra\\u00adtjugo\\u00adtre" },
1544            { "1,001", "et\\u00adtusen ett" },
1545            { "1,100", "et\\u00adtusen ett\\u00adhundra" },
1546            { "1,101", "et\\u00adtusen ett\\u00adhundra\\u00adett" },
1547            { "1,234", "et\\u00adtusen tv\\u00e5\\u00adhundra\\u00adtrettio\\u00adfyra" },
1548            { "10,001", "tio\\u00adtusen ett" },
1549            { "11,000", "elva\\u00adtusen" },
1550            { "12,000", "tolv\\u00adtusen" },
1551            { "20,000", "tjugo\\u00adtusen" },
1552            { "21,000", "tjugo\\u00adet\\u00adtusen" },
1553            { "21,001", "tjugo\\u00adet\\u00adtusen ett" },
1554            { "200,000", "tv\\u00e5\\u00adhundra\\u00adtusen" },
1555            { "201,000", "tv\\u00e5\\u00adhundra\\u00adet\\u00adtusen" },
1556            { "200,200", "tv\\u00e5\\u00adhundra\\u00adtusen tv\\u00e5\\u00adhundra" },
1557            { "2,002,000", "tv\\u00e5 miljoner tv\\u00e5\\u00adtusen" },
1558            { "12,345,678", "tolv miljoner tre\\u00adhundra\\u00adfyrtio\\u00adfem\\u00adtusen sex\\u00adhundra\\u00adsjuttio\\u00ad\\u00e5tta" },
1559            { "123,456.789", "ett\\u00adhundra\\u00adtjugo\\u00adtre\\u00adtusen fyra\\u00adhundra\\u00adfemtio\\u00adsex komma sju \\u00e5tta nio" },
1560            { "-12,345.678", "minus tolv\\u00adtusen tre\\u00adhundra\\u00adfyrtio\\u00adfem komma sex sju \\u00e5tta" },
1561            { NULL, NULL }
1562        };
1563        doTest(formatter, testDataDefault, TRUE);
1564
1565          static const char* testDataNeutrum[][2] = {
1566              { "101", "ett\\u00adhundra\\u00adett" },
1567              { "1,001", "et\\u00adtusen ett" },
1568              { "1,101", "et\\u00adtusen ett\\u00adhundra\\u00adett" },
1569              { "10,001", "tio\\u00adtusen ett" },
1570              { "21,001", "tjugo\\u00adet\\u00adtusen ett" },
1571              { NULL, NULL }
1572          };
1573
1574          formatter->setDefaultRuleSet("%spellout-cardinal-neuter", status);
1575          if (U_SUCCESS(status)) {
1576          logln("        testing spellout-cardinal-neuter rules");
1577          doTest(formatter, testDataNeutrum, TRUE);
1578          }
1579          else {
1580          errln("Can't test spellout-cardinal-neuter rules");
1581          }
1582
1583        static const char* testDataYear[][2] = {
1584            { "101", "ett\\u00adhundra\\u00adett" },
1585            { "900", "nio\\u00adhundra" },
1586            { "1,001", "et\\u00adtusen ett" },
1587            { "1,100", "elva\\u00adhundra" },
1588            { "1,101", "elva\\u00adhundra\\u00adett" },
1589            { "1,234", "tolv\\u00adhundra\\u00adtrettio\\u00adfyra" },
1590            { "2,001", "tjugo\\u00adhundra\\u00adett" },
1591            { "10,001", "tio\\u00adtusen ett" },
1592            { NULL, NULL }
1593        };
1594
1595        status = U_ZERO_ERROR;
1596        formatter->setDefaultRuleSet("%spellout-numbering-year", status);
1597        if (U_SUCCESS(status)) {
1598            logln("testing year rules");
1599            doTest(formatter, testDataYear, TRUE);
1600        }
1601        else {
1602            errln("Can't test year rules");
1603        }
1604
1605    }
1606    delete formatter;
1607}
1608
1609void
1610IntlTestRBNF::TestSmallValues()
1611{
1612    UErrorCode status = U_ZERO_ERROR;
1613    RuleBasedNumberFormat* formatter
1614        = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("en_US"), status);
1615
1616    if (U_FAILURE(status)) {
1617        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1618    } else {
1619        static const char* const testDataDefault[][2] = {
1620        { "0.001", "zero point zero zero one" },
1621        { "0.0001", "zero point zero zero zero one" },
1622        { "0.00001", "zero point zero zero zero zero one" },
1623        { "0.000001", "zero point zero zero zero zero zero one" },
1624        { "0.0000001", "zero point zero zero zero zero zero zero one" },
1625        { "0.00000001", "zero point zero zero zero zero zero zero zero one" },
1626        { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" },
1627        { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" },
1628        { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" },
1629        { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" },
1630        { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" },
1631        { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
1632        { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
1633        { "10,000,000.001", "ten million point zero zero one" },
1634        { "10,000,000.0001", "ten million point zero zero zero one" },
1635        { "10,000,000.00001", "ten million point zero zero zero zero one" },
1636        { "10,000,000.000001", "ten million point zero zero zero zero zero one" },
1637        { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" },
1638//        { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" },
1639//        { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" },
1640        { "10,000,000", "ten million" },
1641//        { "1,234,567,890.0987654", "one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety point zero nine eight seven six five four" },
1642//        { "123,456,789.9876543", "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine point nine eight seven six five four three" },
1643//        { "12,345,678.87654321", "twelve million, three hundred and forty-five thousand, six hundred and seventy-eight point eight seven six five four three two one" },
1644        { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" },
1645        { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" },
1646        { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" },
1647        { "1,234.4321", "one thousand two hundred thirty-four point four three two one" },
1648        { "123.321", "one hundred twenty-three point three two one" },
1649        { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" },
1650        { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" },
1651        { NULL, NULL }
1652        };
1653
1654        doTest(formatter, testDataDefault, TRUE);
1655
1656        delete formatter;
1657    }
1658}
1659
1660void
1661IntlTestRBNF::TestLocalizations(void)
1662{
1663    int i;
1664    UnicodeString rules("%main:0:no;1:some;100:a lot;1000:tons;\n"
1665        "%other:0:nada;1:yah, some;100:plenty;1000:more'n you'll ever need");
1666
1667    UErrorCode status = U_ZERO_ERROR;
1668    UParseError perror;
1669    RuleBasedNumberFormat formatter(rules, perror, status);
1670    if (U_FAILURE(status)) {
1671        errcheckln(status, "FAIL: could not construct formatter - %s", u_errorName(status));
1672    } else {
1673        {
1674            static const char* const testData[][2] = {
1675                { "0", "nada" },
1676                { "5", "yah, some" },
1677                { "423", "plenty" },
1678                { "12345", "more'n you'll ever need" },
1679                { NULL, NULL }
1680            };
1681            doTest(&formatter, testData, FALSE);
1682        }
1683
1684        {
1685            UnicodeString loc("<<%main, %other>,<en, Main, Other>,<fr, leMain, leOther>,<de, 'das Main', 'etwas anderes'>>");
1686            static const char* const testData[][2] = {
1687                { "0", "no" },
1688                { "5", "some" },
1689                { "423", "a lot" },
1690                { "12345", "tons" },
1691                { NULL, NULL }
1692            };
1693            RuleBasedNumberFormat formatter0(rules, loc, perror, status);
1694            if (U_FAILURE(status)) {
1695                errln("failed to build second formatter");
1696            } else {
1697                doTest(&formatter0, testData, FALSE);
1698
1699                {
1700                // exercise localization info
1701                    Locale locale0("en__VALLEY@turkey=gobblegobble");
1702                    Locale locale1("de_DE_FOO");
1703                    Locale locale2("ja_JP");
1704                    UnicodeString name = formatter0.getRuleSetName(0);
1705                    if ( formatter0.getRuleSetDisplayName(0, locale0) == "Main"
1706                      && formatter0.getRuleSetDisplayName(0, locale1) == "das Main"
1707                      && formatter0.getRuleSetDisplayName(0, locale2) == "%main"
1708                      && formatter0.getRuleSetDisplayName(name, locale0) == "Main"
1709                      && formatter0.getRuleSetDisplayName(name, locale1) == "das Main"
1710                      && formatter0.getRuleSetDisplayName(name, locale2) == "%main"){
1711                          logln("getRuleSetDisplayName tested");
1712                    }else {
1713                        errln("failed to getRuleSetDisplayName");
1714                    }
1715                }
1716
1717                for (i = 0; i < formatter0.getNumberOfRuleSetDisplayNameLocales(); ++i) {
1718                    Locale locale = formatter0.getRuleSetDisplayNameLocale(i, status);
1719                    if (U_SUCCESS(status)) {
1720                        for (int j = 0; j < formatter0.getNumberOfRuleSetNames(); ++j) {
1721                            UnicodeString name = formatter0.getRuleSetName(j);
1722                            UnicodeString lname = formatter0.getRuleSetDisplayName(j, locale);
1723                            UnicodeString msg = locale.getName();
1724                            msg.append(": ");
1725                            msg.append(name);
1726                            msg.append(" = ");
1727                            msg.append(lname);
1728                            logln(msg);
1729                        }
1730                    }
1731                }
1732            }
1733        }
1734
1735        {
1736            static const char* goodLocs[] = {
1737                "", // zero-length ok, same as providing no localization data
1738                "<<>>", // no public rule sets ok
1739                "<<%main>>", // no localizations ok
1740                "<<%main,>,<en, Main,>>", // comma before close angle ok
1741                "<<%main>,<en, ',<>\" '>>", // quotes everything until next quote
1742                "<<%main>,<'en', \"it's ok\">>", // double quotes work too
1743                "  \n <\n  <\n  %main\n  >\n  , \t <\t   en\t  ,  \tfoo \t\t > \n\n >  \n ", // Pattern_White_Space ok
1744           };
1745            int32_t goodLocsLen = sizeof(goodLocs)/sizeof(goodLocs[0]);
1746
1747            static const char* badLocs[] = {
1748                " ", // non-zero length
1749                "<>", // empty array
1750                "<", // unclosed outer array
1751                "<<", // unclosed inner array
1752                "<<,>>", // unexpected comma
1753                "<<''>>", // empty string
1754                "  x<<%main>>", // first non space char not open angle bracket
1755                "<%main>", // missing inner array
1756                "<<%main %other>>", // elements missing separating commma (spaces must be quoted)
1757                "<<%main><en, Main>>", // arrays missing separating comma
1758                "<<%main>,<en, main, foo>>", // too many elements in locale data
1759                "<<%main>,<en>>", // too few elements in locale data
1760                "<<<%main>>>", // unexpected open angle
1761                "<<%main<>>>", // unexpected open angle
1762                "<<%main, %other>,<en,,>>", // implicit empty strings
1763                "<<%main>,<en,''>>", // empty string
1764                "<<%main>, < en, '>>", // unterminated quote
1765                "<<%main>, < en, \"<>>", // unterminated quote
1766                "<<%main\">>", // quote in string
1767                "<<%main'>>", // quote in string
1768                "<<%main<>>", // open angle in string
1769                "<<%main>> x", // extra non-space text at end
1770
1771            };
1772            int32_t badLocsLen = sizeof(badLocs)/sizeof(badLocs[0]);
1773
1774            for (i = 0; i < goodLocsLen; ++i) {
1775                logln("[%d] '%s'", i, goodLocs[i]);
1776                UErrorCode status = U_ZERO_ERROR;
1777                UnicodeString loc(goodLocs[i]);
1778                RuleBasedNumberFormat fmt(rules, loc, perror, status);
1779                if (U_FAILURE(status)) {
1780                    errln("Failed parse of good localization string: '%s'", goodLocs[i]);
1781                }
1782            }
1783
1784            for (i = 0; i < badLocsLen; ++i) {
1785                logln("[%d] '%s'", i, badLocs[i]);
1786                UErrorCode status = U_ZERO_ERROR;
1787                UnicodeString loc(badLocs[i]);
1788                RuleBasedNumberFormat fmt(rules, loc, perror, status);
1789                if (U_SUCCESS(status)) {
1790                    errln("Successful parse of bad localization string: '%s'", badLocs[i]);
1791                }
1792            }
1793        }
1794    }
1795}
1796
1797void
1798IntlTestRBNF::TestAllLocales()
1799{
1800    const char* names[] = {
1801        " (spellout) ",
1802        " (ordinal)  ",
1803        " (duration) "
1804    };
1805    double numbers[] = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};
1806
1807    // RBNF parse is extremely slow when lenient option is enabled.
1808    // For non-exhaustive mode, we only test a few locales.
1809    const char* parseLocales[] = {"en_US", "nl_NL", "be", NULL};
1810
1811
1812    int32_t count = 0;
1813    const Locale* locales = Locale::getAvailableLocales(count);
1814    for (int i = 0; i < count; ++i) {
1815        const Locale* loc = &locales[i];
1816        UBool testParse = TRUE;
1817        if (quick) {
1818            testParse = FALSE;
1819            for (int k = 0; parseLocales[k] != NULL; k++) {
1820                if (strcmp(loc->getLanguage(), parseLocales[k]) == 0) {
1821                    testParse = TRUE;
1822                    break;
1823                }
1824            }
1825        }
1826
1827        for (int j = 0; j < 3; ++j) {
1828            UErrorCode status = U_ZERO_ERROR;
1829            RuleBasedNumberFormat* f = new RuleBasedNumberFormat((URBNFRuleSetTag)j, *loc, status);
1830            if (U_FAILURE(status)) {
1831                errln(UnicodeString(loc->getName()) + names[j]
1832                    + "ERROR could not instantiate -> " + u_errorName(status));
1833                continue;
1834            }
1835#if !UCONFIG_NO_COLLATION
1836            for (unsigned int numidx = 0; numidx < sizeof(numbers)/sizeof(double); numidx++) {
1837                double n = numbers[numidx];
1838                UnicodeString str;
1839                f->format(n, str);
1840
1841                logln(UnicodeString(loc->getName()) + names[j]
1842                    + "success: " + n + " -> " + str);
1843
1844                if (testParse) {
1845                    // We do not validate the result in this test case,
1846                    // because there are cases which do not round trip by design.
1847                    Formattable num;
1848
1849                    // regular parse
1850                    status = U_ZERO_ERROR;
1851                    f->setLenient(FALSE);
1852                    f->parse(str, num, status);
1853                    if (U_FAILURE(status)) {
1854                        //TODO: We need to fix parse problems - see #6895 / #6896
1855                        if (status == U_INVALID_FORMAT_ERROR) {
1856                            logln(UnicodeString(loc->getName()) + names[j]
1857                                + "WARNING could not parse '" + str + "' -> " + u_errorName(status));
1858                        } else {
1859                             errln(UnicodeString(loc->getName()) + names[j]
1860                                + "ERROR could not parse '" + str + "' -> " + u_errorName(status));
1861                       }
1862                    }
1863                    // lenient parse
1864                    status = U_ZERO_ERROR;
1865                    f->setLenient(TRUE);
1866                    f->parse(str, num, status);
1867                    if (U_FAILURE(status)) {
1868                        //TODO: We need to fix parse problems - see #6895 / #6896
1869                        if (status == U_INVALID_FORMAT_ERROR) {
1870                            logln(UnicodeString(loc->getName()) + names[j]
1871                                + "WARNING could not parse(lenient) '" + str + "' -> " + u_errorName(status));
1872                        } else {
1873                            errln(UnicodeString(loc->getName()) + names[j]
1874                                + "ERROR could not parse(lenient) '" + str + "' -> " + u_errorName(status));
1875                        }
1876                    }
1877                }
1878            }
1879#endif
1880            delete f;
1881        }
1882    }
1883}
1884
1885void
1886IntlTestRBNF::TestMultiplierSubstitution(void) {
1887  UnicodeString rules("=#,##0=;1,000,000: <##0.###< million;");
1888  UErrorCode status = U_ZERO_ERROR;
1889  UParseError parse_error;
1890  RuleBasedNumberFormat *rbnf =
1891    new RuleBasedNumberFormat(rules, Locale::getUS(), parse_error, status);
1892  if (U_SUCCESS(status)) {
1893    UnicodeString res;
1894    FieldPosition pos;
1895    double n = 1234000.0;
1896    rbnf->format(n, res, pos);
1897    delete rbnf;
1898
1899    UnicodeString expected = UNICODE_STRING_SIMPLE("1.234 million");
1900    if (expected != res) {
1901      UnicodeString msg = "Expected: ";
1902      msg.append(expected);
1903      msg.append(" but got ");
1904      msg.append(res);
1905      errln(msg);
1906    }
1907  }
1908}
1909
1910void
1911IntlTestRBNF::TestSetDecimalFormatSymbols() {
1912    UErrorCode status = U_ZERO_ERROR;
1913
1914    RuleBasedNumberFormat rbnf(URBNF_ORDINAL, Locale::getEnglish(), status);
1915    if (U_FAILURE(status)) {
1916        dataerrln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
1917        return;
1918    }
1919
1920    DecimalFormatSymbols dfs(Locale::getEnglish(), status);
1921    if (U_FAILURE(status)) {
1922        errln("Unable to create DecimalFormatSymbols - " + UnicodeString(u_errorName(status)));
1923        return;
1924    }
1925
1926    UnicodeString expected[] = {
1927            UnicodeString("1,001st"),
1928            UnicodeString("1&001st")
1929    };
1930
1931    double number = 1001;
1932
1933    UnicodeString result;
1934
1935    rbnf.format(number, result);
1936    if (result != expected[0]) {
1937        errln("Format Error - Got: " + result + " Expected: " + expected[0]);
1938    }
1939
1940    result.remove();
1941
1942    /* Set new symbol for testing */
1943    dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, UnicodeString("&"), TRUE);
1944    rbnf.setDecimalFormatSymbols(dfs);
1945
1946    rbnf.format(number, result);
1947    if (result != expected[1]) {
1948        errln("Format Error - Got: " + result + " Expected: " + expected[1]);
1949    }
1950}
1951
1952
1953void
1954IntlTestRBNF::doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing)
1955{
1956  // man, error reporting would be easier with printf-style syntax for unicode string and formattable
1957
1958    UErrorCode status = U_ZERO_ERROR;
1959    DecimalFormatSymbols dfs("en", status);
1960    // NumberFormat* decFmt = NumberFormat::createInstance(Locale::getUS(), status);
1961    DecimalFormat decFmt("#,###.################", dfs, status);
1962    if (U_FAILURE(status)) {
1963        errcheckln(status, "FAIL: could not create NumberFormat - %s", u_errorName(status));
1964    } else {
1965        for (int i = 0; testData[i][0]; ++i) {
1966            const char* numString = testData[i][0];
1967            const char* expectedWords = testData[i][1];
1968
1969            log("[%i] %s = ", i, numString);
1970            Formattable expectedNumber;
1971            decFmt.parse(numString, expectedNumber, status);
1972            if (U_FAILURE(status)) {
1973                errln("FAIL: decFmt could not parse %s", numString);
1974                break;
1975            } else {
1976                UnicodeString actualString;
1977                FieldPosition pos;
1978                formatter->format(expectedNumber, actualString/* , pos*/, status);
1979                if (U_FAILURE(status)) {
1980                    UnicodeString msg = "Fail: formatter could not format ";
1981                    decFmt.format(expectedNumber, msg, status);
1982                    errln(msg);
1983                    break;
1984                } else {
1985                    UnicodeString expectedString = UnicodeString(expectedWords, -1, US_INV).unescape();
1986                    if (actualString != expectedString) {
1987                        UnicodeString msg = "FAIL: check failed for ";
1988                        decFmt.format(expectedNumber, msg, status);
1989                        msg.append(", expected ");
1990                        msg.append(expectedString);
1991                        msg.append(" but got ");
1992                        msg.append(actualString);
1993                        errln(msg);
1994                        break;
1995                    } else {
1996                        logln(actualString);
1997                        if (testParsing) {
1998                            Formattable parsedNumber;
1999                            formatter->parse(actualString, parsedNumber, status);
2000                            if (U_FAILURE(status)) {
2001                                UnicodeString msg = "FAIL: formatter could not parse ";
2002                                msg.append(actualString);
2003                                msg.append(" status code: " );
2004                                msg.append(u_errorName(status));
2005                                errln(msg);
2006                                break;
2007                            } else {
2008                                if (parsedNumber != expectedNumber) {
2009                                    UnicodeString msg = "FAIL: parse failed for ";
2010                                    msg.append(actualString);
2011                                    msg.append(", expected ");
2012                                    decFmt.format(expectedNumber, msg, status);
2013                                    msg.append(", but got ");
2014                                    decFmt.format(parsedNumber, msg, status);
2015                                    errln(msg);
2016                                    break;
2017                                }
2018                            }
2019                        }
2020                    }
2021                }
2022            }
2023        }
2024    }
2025}
2026
2027void
2028IntlTestRBNF::doLenientParseTest(RuleBasedNumberFormat* formatter, const char* testData[][2])
2029{
2030    UErrorCode status = U_ZERO_ERROR;
2031    NumberFormat* decFmt = NumberFormat::createInstance(Locale::getUS(), status);
2032    if (U_FAILURE(status)) {
2033        errcheckln(status, "FAIL: could not create NumberFormat - %s", u_errorName(status));
2034    } else {
2035        for (int i = 0; testData[i][0]; ++i) {
2036            const char* spelledNumber = testData[i][0]; // spelled-out number
2037            const char* asciiUSNumber = testData[i][1]; // number as ascii digits formatted for US locale
2038
2039            UnicodeString spelledNumberString = UnicodeString(spelledNumber).unescape();
2040            Formattable actualNumber;
2041            formatter->parse(spelledNumberString, actualNumber, status);
2042            if (U_FAILURE(status)) {
2043                UnicodeString msg = "FAIL: formatter could not parse ";
2044                msg.append(spelledNumberString);
2045                errln(msg);
2046                break;
2047            } else {
2048                // I changed the logic of this test somewhat from Java-- instead of comparing the
2049                // strings, I compare the Formattables.  Hmmm, but the Formattables don't compare,
2050                // so change it back.
2051
2052                UnicodeString asciiUSNumberString = asciiUSNumber;
2053                Formattable expectedNumber;
2054                decFmt->parse(asciiUSNumberString, expectedNumber, status);
2055                if (U_FAILURE(status)) {
2056                    UnicodeString msg = "FAIL: decFmt could not parse ";
2057                    msg.append(asciiUSNumberString);
2058                    errln(msg);
2059                    break;
2060                } else {
2061                    UnicodeString actualNumberString;
2062                    UnicodeString expectedNumberString;
2063                    decFmt->format(actualNumber, actualNumberString, status);
2064                    decFmt->format(expectedNumber, expectedNumberString, status);
2065                    if (actualNumberString != expectedNumberString) {
2066                        UnicodeString msg = "FAIL: parsing";
2067                        msg.append(asciiUSNumberString);
2068                        msg.append("\n");
2069                        msg.append("  lenient parse failed for ");
2070                        msg.append(spelledNumberString);
2071                        msg.append(", expected ");
2072                        msg.append(expectedNumberString);
2073                        msg.append(", but got ");
2074                        msg.append(actualNumberString);
2075                        errln(msg);
2076                        break;
2077                    }
2078                }
2079            }
2080        }
2081        delete decFmt;
2082    }
2083}
2084
2085/* U_HAVE_RBNF */
2086#else
2087
2088void
2089IntlTestRBNF::TestRBNFDisabled() {
2090    errln("*** RBNF currently disabled on this platform ***\n");
2091}
2092
2093/* U_HAVE_RBNF */
2094#endif
2095
2096#endif /* #if !UCONFIG_NO_FORMATTING */
2097