]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/format/RbnfTest.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / dev / test / format / RbnfTest.java
1 //##header J2SE15
2 /*
3  *******************************************************************************
4  * Copyright (C) 1996-2009, International Business Machines Corporation and    *
5  * others. All Rights Reserved.                                                *
6  *******************************************************************************
7  */
8 package com.ibm.icu.dev.test.format;
9
10 import java.math.BigInteger;
11 import java.text.DecimalFormat;
12 import java.text.NumberFormat;
13 import java.text.ParseException;
14 import java.util.Locale;
15 import java.util.Random;
16
17 import com.ibm.icu.dev.test.TestFmwk;
18 import com.ibm.icu.text.RuleBasedNumberFormat;
19 import com.ibm.icu.util.ULocale;
20
21 public class RbnfTest extends TestFmwk {
22     public static void main(String[] args) {
23         RbnfTest test = new RbnfTest();
24
25         try {
26             test.run(args);
27         }
28         catch (Throwable e) {
29             System.out.println("Entire test failed because of exception: "
30                                + e.toString());
31             e.printStackTrace();
32         }
33     }
34
35     static String fracRules = 
36         "%main:\n" +
37         // this rule formats the number if it's 1 or more.  It formats
38         // the integral part using a DecimalFormat ("#,##0" puts
39         // thousands separators in the right places) and the fractional
40         // part using %%frac.  If there is no fractional part, it
41         // just shows the integral part.
42         "    x.0: <#,##0<[ >%%frac>];\n" +
43         // this rule formats the number if it's between 0 and 1.  It
44         // shows only the fractional part (0.5 shows up as "1/2," not
45         // "0 1/2")
46         "    0.x: >%%frac>;\n" +
47         // the fraction rule set.  This works the same way as the one in the
48         // preceding example: We multiply the fractional part of the number
49         // being formatted by each rule's base value and use the rule that
50         // produces the result closest to 0 (or the first rule that produces 0).
51         // Since we only provide rules for the numbers from 2 to 10, we know
52         // we'll get a fraction with a denominator between 2 and 10.
53         // "<0<" causes the numerator of the fraction to be formatted
54         // using numerals
55         "%%frac:\n" +
56         "    2: 1/2;\n" +
57         "    3: <0</3;\n" +
58         "    4: <0</4;\n" +
59         "    5: <0</5;\n" +
60         "    6: <0</6;\n" +
61         "    7: <0</7;\n" +
62         "    8: <0</8;\n" +
63         "    9: <0</9;\n" +
64         "   10: <0</10;\n";
65
66     static {
67         // mondo hack
68     char[] fracRulesArr = fracRules.toCharArray();
69         int len = fracRulesArr.length;
70         int change = 2;
71         for (int i = 0; i < len; ++i) {
72             char ch = fracRulesArr[i];
73             if (ch == '\n') {
74                 change = 2; // change ok
75             } else if (ch == ':') {
76                 change = 1; // change, but once we hit a non-space char, don't change
77             } else if (ch == ' ') {
78                 if (change != 0) {
79                     fracRulesArr[i] = (char)0x200e;
80                 }
81             } else {
82                 if (change == 1) {
83                     change = 0;
84                 }
85             }
86         }
87     fracRules = new String(fracRulesArr);
88     }
89
90     static final String durationInSecondsRules =
91         // main rule set for formatting with words
92         "%with-words:\n"
93         // take care of singular and plural forms of "second"
94         + "    0 seconds; 1 second; =0= seconds;\n"
95         // use %%min to format values greater than 60 seconds
96         + "    60/60: <%%min<[, >>];\n"
97         // use %%hr to format values greater than 3,600 seconds
98         // (the ">>>" below causes us to see the number of minutes
99         // when when there are zero minutes)
100         + "    3600/60: <%%hr<[, >>>];\n"
101         // this rule set takes care of the singular and plural forms
102         // of "minute"
103         + "%%min:\n"
104         + "    0 minutes; 1 minute; =0= minutes;\n"
105         // this rule set takes care of the singular and plural forms
106         // of "hour"
107         + "%%hr:\n"
108         + "    0 hours; 1 hour; =0= hours;\n"
109
110         // main rule set for formatting in numerals
111         + "%in-numerals:\n"
112         // values below 60 seconds are shown with "sec."
113         + "    =0= sec.;\n"
114         // higher values are shown with colons: %%min-sec is used for
115         // values below 3,600 seconds...
116         + "    60: =%%min-sec=;\n"
117         // ...and %%hr-min-sec is used for values of 3,600 seconds
118         // and above
119         + "    3600: =%%hr-min-sec=;\n"
120         // this rule causes values of less than 10 minutes to show without
121         // a leading zero
122         + "%%min-sec:\n"
123         + "    0: :=00=;\n"
124         + "    60/60: <0<>>;\n"
125         // this rule set is used for values of 3,600 or more.  Minutes are always
126         // shown, and always shown with two digits
127         + "%%hr-min-sec:\n"
128         + "    0: :=00=;\n"
129         + "    60/60: <00<>>;\n"
130         + "    3600/60: <#,##0<:>>>;\n"
131         // the lenient-parse rules allow several different characters to be used
132         // as delimiters between hours, minutes, and seconds
133         + "%%lenient-parse:\n"
134         + "    & : = . = ' ' = -;\n";
135
136     public void TestCoverage() {
137         // extra calls to boost coverage numbers
138         RuleBasedNumberFormat fmt0 = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);
139         RuleBasedNumberFormat fmt1 = (RuleBasedNumberFormat)fmt0.clone();
140         RuleBasedNumberFormat fmt2 = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);
141         if (!fmt0.equals(fmt0)) {
142             errln("self equality fails");
143         }
144         if (!fmt0.equals(fmt1)) {
145             errln("clone equality fails");
146         }
147         if (!fmt0.equals(fmt2)) {
148             errln("duplicate equality fails");
149         }
150         String str = fmt0.toString();
151         logln(str);
152
153         RuleBasedNumberFormat fmt3 =  new RuleBasedNumberFormat(durationInSecondsRules);
154
155         if (fmt0.equals(fmt3)) {
156             errln("nonequal fails");
157         }
158         if (!fmt3.equals(fmt3)) {
159             errln("self equal 2 fails");
160         }
161         str = fmt3.toString();
162         logln(str);
163
164         String[] names = fmt3.getRuleSetNames();
165
166         try {
167             fmt3.setDefaultRuleSet(null);
168             fmt3.setDefaultRuleSet("%%foo");
169             errln("sdrf %%foo didn't fail");
170         }
171         catch (Exception e) {
172             logln("Got the expected exception");
173         }
174
175         try {
176             fmt3.setDefaultRuleSet("%bogus");
177             errln("sdrf %bogus didn't fail");
178         }
179         catch (Exception e) {
180             logln("Got the expected exception");
181         }
182
183         try {
184             str = fmt3.format(2.3, names[0]);
185             logln(str);
186             str = fmt3.format(2.3, "%%foo");
187             errln("format double %%foo didn't fail");
188         }
189         catch (Exception e) {
190             logln("Got the expected exception");
191         }
192
193         try {
194             str = fmt3.format(123L, names[0]);
195             logln(str);
196             str = fmt3.format(123L, "%%foo");
197             errln("format double %%foo didn't fail");
198         }
199         catch (Exception e) {
200             logln("Got the expected exception");
201         }
202
203         RuleBasedNumberFormat fmt4 = new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);
204         RuleBasedNumberFormat fmt5 = new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);
205         str = fmt4.toString();
206         logln(str);
207         if (!fmt4.equals(fmt5)) {
208             errln("duplicate 2 equality failed");
209         }
210         str = fmt4.format(123L);
211         logln(str);
212         try {
213             Number num = fmt4.parse(str);
214             logln(num.toString());
215         }
216         catch (Exception e) {
217             errln("parse caught exception");
218         }
219
220         str = fmt4.format(.000123);
221         logln(str);
222         try {
223             Number num = fmt4.parse(str);
224             logln(num.toString());
225         }
226         catch (Exception e) {
227             errln("parse caught exception");
228         }
229
230         str = fmt4.format(456.000123);
231         logln(str);
232         try {
233             Number num = fmt4.parse(str);
234             logln(num.toString());
235         }
236         catch (Exception e) {
237             errln("parse caught exception");
238         }
239     }
240
241     public void TestUndefinedSpellout() {
242         Locale greek = new Locale("el", "", "");
243         RuleBasedNumberFormat[] formatters = {
244             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.SPELLOUT),
245             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.ORDINAL),
246             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.DURATION),
247         };
248
249         String[] data = {
250             "0",
251             "1",
252             "15",
253             "20",
254             "23",
255             "73",
256             "88",
257             "100",
258             "106",
259             "127",
260             "200",
261             "579",
262             "1,000",
263             "2,000",
264             "3,004",
265             "4,567",
266             "15,943",
267             "105,000",
268             "2,345,678",
269             "-36",
270             "-36.91215",
271             "234.56789"
272         };
273
274         NumberFormat decFormat = NumberFormat.getInstance(Locale.US);
275         for (int j = 0; j < formatters.length; ++j) {
276             com.ibm.icu.text.NumberFormat formatter = formatters[j];
277             logln("formatter[" + j + "]");
278             for (int i = 0; i < data.length; ++i) {
279                 try {
280                     String result = formatter.format(decFormat.parse(data[i]));
281                     logln("[" + i + "] " + data[i] + " ==> " + result);
282                 }
283                 catch (Exception e) {
284                     errln("formatter[" + j + "], data[" + i + "] " + data[i] + " threw exception " + e.getMessage());
285                 }
286             }
287         }
288     }
289
290     /**
291      * Perform a simple spot check on the English spellout rules
292      */
293     public void TestEnglishSpellout() {
294         RuleBasedNumberFormat formatter
295             = new RuleBasedNumberFormat(Locale.US,
296                                         RuleBasedNumberFormat.SPELLOUT);
297         String[][] testData = {
298             { "1", "one" },
299             { "15", "fifteen" },
300             { "20", "twenty" },
301             { "23", "twenty-three" },
302             { "73", "seventy-three" },
303             { "88", "eighty-eight" },
304             { "100", "one hundred" },
305             { "106", "one hundred six" },
306             { "127", "one hundred twenty-seven" },
307             { "200", "two hundred" },
308             { "579", "five hundred seventy-nine" },
309             { "1,000", "one thousand" },
310             { "2,000", "two thousand" },
311             { "3,004", "three thousand four" },
312             { "4,567", "four thousand five hundred sixty-seven" },
313             { "15,943", "fifteen thousand nine hundred forty-three" },
314             { "2,345,678", "two million three hundred forty-five "
315               + "thousand six hundred seventy-eight" },
316             { "-36", "minus thirty-six" },
317             { "234.567", "two hundred thirty-four point five six seven" }
318         };
319
320         doTest(formatter, testData, true);
321
322         formatter.setLenientParseMode(true);
323         String[][] lpTestData = {
324             { "FOurhundred     thiRTY six", "436" },
325             // test spaces before fifty-7 causing lenient parse match of "fifty-" to " fifty"
326             // leaving "-7" for remaining parse, resulting in 2643 as the parse result.
327             { "fifty-7", "57" },
328             { " fifty-7", "57" },
329             { "  fifty-7", "57" },
330             { "2 thousand six HUNDRED   fifty-7", "2,657" },
331             { "fifteen hundred and zero", "1,500" }
332         };
333         doLenientParseTest(formatter, lpTestData);
334     }
335
336     /**
337      * Perform a simple spot check on the English ordinal-abbreviation rules
338      */
339     public void TestOrdinalAbbreviations() {
340         RuleBasedNumberFormat formatter
341             = new RuleBasedNumberFormat(Locale.US,
342                                         RuleBasedNumberFormat.ORDINAL);
343         String[][] testData = {
344             { "1", "1\u02e2\u1d57" },
345             { "2", "2\u207f\u1d48" },
346             { "3", "3\u02b3\u1d48" },
347             { "4", "4\u1d57\u02b0" },
348             { "7", "7\u1d57\u02b0" },
349             { "10", "10\u1d57\u02b0" },
350             { "11", "11\u1d57\u02b0" },
351             { "13", "13\u1d57\u02b0" },
352             { "20", "20\u1d57\u02b0" },
353             { "21", "21\u02e2\u1d57" },
354             { "22", "22\u207f\u1d48" },
355             { "23", "23\u02b3\u1d48" },
356             { "24", "24\u1d57\u02b0" },
357             { "33", "33\u02b3\u1d48" },
358             { "102", "102\u207f\u1d48" },
359             { "312", "312\u1d57\u02b0" },
360             { "12,345", "12,345\u1d57\u02b0" }
361         };
362
363         doTest(formatter, testData, false);
364     }
365
366     /**
367      * Perform a simple spot check on the duration-formatting rules
368      */
369     public void TestDurations() {
370         RuleBasedNumberFormat formatter
371             = new RuleBasedNumberFormat(Locale.US,
372                                         RuleBasedNumberFormat.DURATION);
373         String[][] testData = {
374             { "3,600", "1:00:00" },             //move me and I fail
375             { "0", "0 sec." },
376             { "1", "1 sec." },
377             { "24", "24 sec." },
378             { "60", "1:00" },
379             { "73", "1:13" },
380             { "145", "2:25" },
381             { "666", "11:06" },
382             //            { "3,600", "1:00:00" },
383             { "3,740", "1:02:20" },
384             { "10,293", "2:51:33" }
385         };
386
387         doTest(formatter, testData, true);
388
389         formatter.setLenientParseMode(true);
390         String[][] lpTestData = {
391             { "2-51-33", "10,293" }
392         };
393         doLenientParseTest(formatter, lpTestData);
394     }
395
396     /**
397      * Perform a simple spot check on the Spanish spellout rules
398      */
399     public void TestSpanishSpellout() {
400         RuleBasedNumberFormat formatter
401             = new RuleBasedNumberFormat(new Locale("es", "es",
402                                                    ""), RuleBasedNumberFormat.SPELLOUT);
403         String[][] testData = {
404             { "1", "uno" },
405             { "6", "seis" },
406             { "16", "diecis\u00e9is" },
407             { "20", "veinte" },
408             { "24", "veinticuatro" },
409             { "26", "veintis\u00e9is" },
410             { "73", "setenta y tres" },
411             { "88", "ochenta y ocho" },
412             { "100", "cien" },
413             { "106", "ciento seis" },
414             { "127", "ciento veintisiete" },
415             { "200", "doscientos" },
416             { "579", "quinientos setenta y nueve" },
417             { "1,000", "mil" },
418             { "2,000", "dos mil" },
419             { "3,004", "tres mil cuatro" },
420             { "4,567", "cuatro mil quinientos sesenta y siete" },
421             { "15,943", "quince mil novecientos cuarenta y tres" },
422             { "2,345,678", "dos millones trescientos cuarenta y cinco mil "
423               + "seiscientos setenta y ocho"},
424             { "-36", "menos treinta y seis" },
425             { "234.567", "doscientos treinta y cuatro coma cinco seis siete" }
426         };
427
428         doTest(formatter, testData, true);
429     }
430
431     /**
432      * Perform a simple spot check on the French spellout rules
433      */
434     public void TestFrenchSpellout() {
435         RuleBasedNumberFormat formatter
436             = new RuleBasedNumberFormat(Locale.FRANCE,
437                                         RuleBasedNumberFormat.SPELLOUT);
438         String[][] testData = {
439             { "1", "un" },
440             { "15", "quinze" },
441             { "20", "vingt" },
442             { "21", "vingt-et-un" },
443             { "23", "vingt-trois" },
444             { "62", "soixante-deux" },
445             { "70", "soixante-dix" },
446             { "71", "soixante-et-onze" },
447             { "73", "soixante-treize" },
448             { "80", "quatre-vingts" },
449             { "88", "quatre-vingt-huit" },
450             { "100", "cent" },
451             { "106", "cent-six" },
452             { "127", "cent-vingt-sept" },
453             { "200", "deux-cents" },
454             { "579", "cinq-cent-soixante-dix-neuf" },
455             { "1,000", "mille" },
456             { "1,123", "mille-cent-vingt-trois" },
457             { "1,594", "mille-cinq-cent-quatre-vingt-quatorze" },
458             { "2,000", "deux-mille" },
459             { "3,004", "trois-mille-quatre" },
460             { "4,567", "quatre-mille-cinq-cent-soixante-sept" },
461             { "15,943", "quinze-mille-neuf-cent-quarante-trois" },
462             { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-"
463               + "six-cent-soixante-dix-huit" },
464             { "-36", "moins trente-six" },
465             { "234.567", "deux-cent-trente-quatre virgule cinq six sept" }
466         };
467
468         doTest(formatter, testData, true);
469
470         formatter.setLenientParseMode(true);
471         String[][] lpTestData = {
472             { "trente-et-un", "31" },
473             { "un cent quatre vingt dix huit", "198" }
474         };
475         doLenientParseTest(formatter, lpTestData);
476     }
477
478     /**
479      * Perform a simple spot check on the Swiss French spellout rules
480      */
481     public void TestSwissFrenchSpellout() {
482         RuleBasedNumberFormat formatter
483             = new RuleBasedNumberFormat(new Locale("fr", "CH",
484                                                    ""), RuleBasedNumberFormat.SPELLOUT);
485         String[][] testData = {
486             { "1", "un" },
487             { "15", "quinze" },
488             { "20", "vingt" },
489             { "21", "vingt-et-un" },
490             { "23", "vingt-trois" },
491             { "62", "soixante-deux" },
492             { "70", "septante" },
493             { "71", "septante-et-un" },
494             { "73", "septante-trois" },
495             { "80", "huitante" },
496             { "88", "huitante-huit" },
497             { "100", "cent" },
498             { "106", "cent-six" },
499             { "127", "cent-vingt-sept" },
500             { "200", "deux-cents" },
501             { "579", "cinq-cent-septante-neuf" },
502             { "1,000", "mille" },
503             { "1,123", "mille-cent-vingt-trois" },
504             { "1,594", "mille-cinq-cent-nonante-quatre" },
505             { "2,000", "deux-mille" },
506             { "3,004", "trois-mille-quatre" },
507             { "4,567", "quatre-mille-cinq-cent-soixante-sept" },
508             { "15,943", "quinze-mille-neuf-cent-quarante-trois" },
509             { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-"
510               + "six-cent-septante-huit" },
511             { "-36", "moins trente-six" },
512             { "234.567", "deux-cent-trente-quatre virgule cinq six sept" }
513         };
514
515         doTest(formatter, testData, true);
516     }
517
518     /**
519      * Perform a simple spot check on the Italian spellout rules
520      */
521     public void TestItalianSpellout() {
522         RuleBasedNumberFormat formatter
523             = new RuleBasedNumberFormat(Locale.ITALIAN,
524                                         RuleBasedNumberFormat.SPELLOUT);
525         String[][] testData = {
526             { "1", "uno" },
527             { "15", "quindici" },
528             { "20", "venti" },
529             { "23", "venti\u00ADtr\u00E9" },
530             { "73", "settanta\u00ADtr\u00E9" },
531             { "88", "ottant\u00ADotto" },
532             { "100", "cento" },
533             { "106", "cento\u00ADsei" },
534             { "108", "cent\u00ADotto" },
535             { "127", "cento\u00ADventi\u00ADsette" },
536             { "181", "cent\u00ADottant\u00ADuno" },
537             { "200", "due\u00ADcento" },
538             { "579", "cinque\u00ADcento\u00ADsettanta\u00ADnove" },
539             { "1,000", "mille" },
540             { "2,000", "due\u00ADmila" },
541             { "3,004", "tre\u00ADmila\u00ADquattro" },
542             { "4,567", "quattro\u00ADmila\u00ADcinque\u00ADcento\u00ADsessanta\u00ADsette" },
543             { "15,943", "quindici\u00ADmila\u00ADnove\u00ADcento\u00ADquaranta\u00ADtr\u00E9" },
544             { "-36", "meno trenta\u00ADsei" },
545             { "234.567", "due\u00ADcento\u00ADtrenta\u00ADquattro virgola cinque sei sette" }
546         };
547
548         doTest(formatter, testData, true);
549     }
550
551     /**
552      * Perform a simple spot check on the German spellout rules
553      */
554     public void TestGermanSpellout() {
555         RuleBasedNumberFormat formatter
556             = new RuleBasedNumberFormat(Locale.GERMANY,
557                                         RuleBasedNumberFormat.SPELLOUT);
558         String[][] testData = {
559             { "1", "eins" },
560             { "15", "f\u00fcnfzehn" },
561             { "20", "zwanzig" },
562             { "23", "drei\u00ADund\u00ADzwanzig" },
563             { "73", "drei\u00ADund\u00ADsiebzig" },
564             { "88", "acht\u00ADund\u00ADachtzig" },
565             { "100", "ein\u00ADhundert" },
566             { "106", "ein\u00ADhundert\u00ADsechs" },
567             { "127", "ein\u00ADhundert\u00ADsieben\u00ADund\u00ADzwanzig" },
568             { "200", "zwei\u00ADhundert" },
569             { "579", "f\u00fcnf\u00ADhundert\u00ADneun\u00ADund\u00ADsiebzig" },
570             { "1,000", "ein\u00ADtausend" },
571             { "2,000", "zwei\u00ADtausend" },
572             { "3,004", "drei\u00ADtausend\u00ADvier" },
573             { "4,567", "vier\u00ADtausend\u00ADf\u00fcnf\u00ADhundert\u00ADsieben\u00ADund\u00ADsechzig" },
574             { "15,943", "f\u00fcnfzehn\u00ADtausend\u00ADneun\u00ADhundert\u00ADdrei\u00ADund\u00ADvierzig" },
575             { "2,345,678", "zwei Millionen drei\u00ADhundert\u00ADf\u00fcnf\u00ADund\u00ADvierzig\u00ADtausend\u00AD"
576               + "sechs\u00ADhundert\u00ADacht\u00ADund\u00ADsiebzig" }
577         };
578
579         doTest(formatter, testData, true);
580
581         formatter.setLenientParseMode(true);
582         String[][] lpTestData = {
583             { "ein Tausend sechs Hundert fuenfunddreissig", "1,635" }
584         };
585         doLenientParseTest(formatter, lpTestData);
586     }
587
588     /**
589      * Perform a simple spot check on the Thai spellout rules
590      */
591     public void TestThaiSpellout() {
592         RuleBasedNumberFormat formatter
593             = new RuleBasedNumberFormat(new Locale("th", "TH", ""),
594                                         RuleBasedNumberFormat.SPELLOUT);
595         String[][] testData = {
596             { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },
597             { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },
598             { "10", "\u0e2a\u0e34\u0e1a" },
599             { "11", "\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" },
600             { "21", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" },
601             { "101", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e2b\u0e19\u0e36\u0e48\u0e07" },
602             { "1.234", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e2d\u0e07\u0e2a\u0e32\u0e21\u0e2a\u0e35\u0e48" },
603             { "21.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
604             { "22.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e2d\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
605             { "23.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
606             { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },
607             { "12,345.678", "\u0E2B\u0E19\u0E36\u0E48\u0E07\u200b\u0E2B\u0E21\u0E37\u0E48\u0E19\u200b\u0E2A\u0E2D\u0E07\u200b\u0E1E\u0E31\u0E19\u200b\u0E2A\u0E32\u0E21\u200b\u0E23\u0E49\u0E2D\u0E22\u200b\u0E2A\u0E35\u0E48\u200b\u0E2A\u0E34\u0E1A\u200b\u0E2B\u0E49\u0E32\u200b\u0E08\u0E38\u0E14\u200b\u0E2B\u0E01\u0E40\u0E08\u0E47\u0E14\u0E41\u0E1B\u0E14" },
608         };
609
610         doTest(formatter, testData, true);
611
612         /*
613           formatter.setLenientParseMode(true);
614           String[][] lpTestData = {
615           { "ein Tausend sechs Hundert fuenfunddreissig", "1,635" }
616           };
617           doLenientParseTest(formatter, lpTestData);
618         */
619     }
620
621     public void TestFractionalRuleSet() {
622
623
624         RuleBasedNumberFormat formatter =
625             new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);
626
627         String[][] testData = {
628             { "0", "0" },
629             { "1", "1" },
630             { "10", "10" },
631             { ".1", "1/10" },
632             { ".11", "1/9" },
633             { ".125", "1/8" },
634             { ".1428", "1/7" },
635             { ".1667", "1/6" },
636             { ".2", "1/5" },
637             { ".25", "1/4" },
638             { ".333", "1/3" },
639             { ".5", "1/2" },
640             { "1.1", "1 1/10" },
641             { "2.11", "2 1/9" },
642             { "3.125", "3 1/8" },
643             { "4.1428", "4 1/7" },
644             { "5.1667", "5 1/6" },
645             { "6.2", "6 1/5" },
646             { "7.25", "7 1/4" },
647             { "8.333", "8 1/3" },
648             { "9.5", "9 1/2" },
649             { ".2222", "2/9" },
650             { ".4444", "4/9" },
651             { ".5555", "5/9" },
652             { "1.2856", "1 2/7" }
653         };
654         doTest(formatter, testData, false); // exact values aren't parsable from fractions
655     }
656
657     public void TestSwedishSpellout()
658     {
659         Locale locale = new Locale("sv", "", "");
660         RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);
661
662         String[][] testDataDefault = {
663             { "101", "ett\u00ADhundra\u00ADett" },
664             { "123", "ett\u00ADhundra\u00ADtjugo\u00ADtre" },
665             { "1,001", "ettusen ett" },
666             { "1,100", "ettusen ett\u00ADhundra" },
667             { "1,101", "ettusen ett\u00ADhundra\u00ADett" },
668             { "1,234", "ettusen tv\u00e5\u00ADhundra\u00ADtrettio\u00ADfyra" },
669             { "10,001", "tio\u00ADtusen ett" },
670             { "11,000", "elva\u00ADtusen" },
671             { "12,000", "tolv\u00ADtusen" },
672             { "20,000", "tjugo-tusen" },
673             { "21,000", "tjugo\u00ADett-tusen" },
674             { "21,001", "tjugo\u00ADett-tusen ett" },
675             { "200,000", "tv\u00e5\u00ADhundra-tusen" },
676             { "201,000", "tv\u00e5\u00ADhundra\u00ADett-tusen" },
677             { "200,200", "tv\u00e5\u00ADhundra-tusen tv\u00e5\u00ADhundra" },
678             { "2,002,000", "tv\u00e5 miljoner tv\u00e5\u00ADtusen" },
679             { "12,345,678", "tolv miljoner tre\u00ADhundra\u00ADfyrtio\u00ADfem-tusen sex\u00ADhundra\u00ADsjuttio\u00AD\u00e5tta" },
680             { "123,456.789", "ett\u00ADhundra\u00ADtjugo\u00ADtre-tusen fyra\u00ADhundra\u00ADfemtio\u00ADsex komma sju \u00e5tta nio" },
681             { "-12,345.678", "minus tolv\u00ADtusen tre\u00ADhundra\u00ADfyrtio\u00ADfem komma sex sju \u00e5tta" }
682         };
683
684         logln("testing default rules");
685         doTest(formatter, testDataDefault, true);
686
687         String[][] testDataNeutrum = {
688             { "101", "ett\u00adhundra\u00aden" },
689             { "1,001", "ettusen en" },
690             { "1,101", "ettusen ett\u00adhundra\u00aden" },
691             { "10,001", "tio\u00adtusen en" },
692             { "21,001", "tjugo\u00aden\u00adtusen en" }
693         };
694
695         formatter.setDefaultRuleSet("%spellout-cardinal-neutre");
696         logln("testing neutrum rules");
697         doTest(formatter, testDataNeutrum, true);
698
699         String[][] testDataYear = {
700             { "101", "ett\u00adhundra\u00adett" },
701             { "900", "nio\u00adhundra" },
702             { "1,001", "ettusen ett" },
703             { "1,100", "elva\u00adhundra" },
704             { "1,101", "elva\u00adhundra\u00adett" },
705             { "1,234", "tolv\u00adhundra\u00adtrettio\u00adfyra" },
706             { "2,001", "tjugo\u00adhundra\u00adett" },
707             { "10,001", "tio\u00adtusen ett" }
708         };
709
710         formatter.setDefaultRuleSet("%spellout-numbering-year");
711         logln("testing year rules");
712         doTest(formatter, testDataYear, true);
713     }
714
715     public void TestBigNumbers() {
716         BigInteger bigI = new BigInteger("1234567890", 10);
717         StringBuffer buf = new StringBuffer();
718         RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);
719         fmt.format(bigI, buf, null);
720         logln("big int: " + buf.toString());
721
722 //#if defined(FOUNDATION10)
723 //#else
724         buf.setLength(0);
725         java.math.BigDecimal bigD = new java.math.BigDecimal(bigI);
726         fmt.format(bigD, buf, null);
727         logln("big dec: " + buf.toString());
728 //#endif
729     }
730
731   public void TestTrailingSemicolon() {
732     String thaiRules = 
733         "%default:\n" +
734         "  -x: \u0e25\u0e1a>>;\n" +
735         "  x.x: <<\u0e08\u0e38\u0e14>>>;\n" +
736         "  \u0e28\u0e39\u0e19\u0e22\u0e4c; \u0e2b\u0e19\u0e36\u0e48\u0e07; \u0e2a\u0e2d\u0e07; \u0e2a\u0e32\u0e21;\n" +
737         "  \u0e2a\u0e35\u0e48; \u0e2b\u0e49\u0e32; \u0e2b\u0e01; \u0e40\u0e08\u0e47\u0e14; \u0e41\u0e1b\u0e14;\n" +
738         "  \u0e40\u0e01\u0e49\u0e32; \u0e2a\u0e34\u0e1a; \u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14;\n" +
739         "  \u0e2a\u0e34\u0e1a\u0e2a\u0e2d\u0e07; \u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21;\n" +
740         "  \u0e2a\u0e34\u0e1a\u0e2a\u0e35\u0e48; \u0e2a\u0e34\u0e1a\u0e2b\u0e49\u0e32;\n" +
741         "  \u0e2a\u0e34\u0e1a\u0e2b\u0e01; \u0e2a\u0e34\u0e1a\u0e40\u0e08\u0e47\u0e14;\n" +
742         "  \u0e2a\u0e34\u0e1a\u0e41\u0e1b\u0e14; \u0e2a\u0e34\u0e1a\u0e40\u0e01\u0e49\u0e32;\n" +
743         "  20: \u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
744         "  30: \u0e2a\u0e32\u0e21\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
745         "  40: \u0e2a\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
746         "  50: \u0e2b\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
747         "  60: \u0e2b\u0e01\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
748         "  70: \u0e40\u0e08\u0e47\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
749         "  80: \u0e41\u0e1b\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
750         "  90: \u0e40\u0e01\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +
751         "  100: <<\u0e23\u0e49\u0e2d\u0e22[>>];\n" +
752         "  1000: <<\u0e1e\u0e31\u0e19[>>];\n" +
753         "  10000: <<\u0e2b\u0e21\u0e37\u0e48\u0e19[>>];\n" +
754         "  100000: <<\u0e41\u0e2a\u0e19[>>];\n" +
755         "  1,000,000: <<\u0e25\u0e49\u0e32\u0e19[>>];\n" +
756         "  1,000,000,000: <<\u0e1e\u0e31\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n" +
757         "  1,000,000,000,000: <<\u0e25\u0e49\u0e32\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n" +
758         "  1,000,000,000,000,000: =#,##0=;\n" +
759         "%%alt-ones:\n" +
760         "  \u0e28\u0e39\u0e19\u0e22\u0e4c;\n" +
761         "  \u0e40\u0e2d\u0e47\u0e14;\n" +
762         "  =%default=;\n ; ;; ";
763
764         RuleBasedNumberFormat formatter
765             = new RuleBasedNumberFormat(thaiRules, new Locale("th", "TH", ""));
766
767         String[][] testData = {
768             { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },
769             { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },
770             { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }
771         };
772         
773         doTest(formatter, testData, true);
774     }
775
776     public void TestSmallValues() {
777     String[][] testData = {
778         { "0.001", "zero point zero zero one" },
779         { "0.0001", "zero point zero zero zero one" },
780         { "0.00001", "zero point zero zero zero zero one" },
781         { "0.000001", "zero point zero zero zero zero zero one" },
782         { "0.0000001", "zero point zero zero zero zero zero zero one" },
783         { "0.00000001", "zero point zero zero zero zero zero zero zero one" },
784         { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" },
785         { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" },
786         { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" },
787         { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" },
788         { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" },
789         { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
790         { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" },
791         { "10,000,000.001", "ten million point zero zero one" },
792         { "10,000,000.0001", "ten million point zero zero zero one" },
793         { "10,000,000.00001", "ten million point zero zero zero zero one" },
794         { "10,000,000.000001", "ten million point zero zero zero zero zero one" },
795         { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" },
796         { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" },
797         { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" },
798         { "10,000,000", "ten million" },
799         { "1,234,567,890.0987654", "one billion two hundred thirty-four million five hundred sixty-seven thousand eight hundred ninety point zero nine eight seven six five four" },
800         { "123,456,789.9876543", "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine point nine eight seven six five four three" },
801         { "12,345,678.87654321", "twelve million three hundred forty-five thousand six hundred seventy-eight point eight seven six five four three two one" },
802         { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" },
803         { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" },
804         { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" },
805         { "1,234.4321", "one thousand two hundred thirty-four point four three two one" },
806         { "123.321", "one hundred twenty-three point three two one" },
807         { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" },
808         { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" },
809     };
810
811     RuleBasedNumberFormat formatter
812         = new RuleBasedNumberFormat(Locale.US, RuleBasedNumberFormat.SPELLOUT);
813     doTest(formatter, testData, true);
814     }
815
816     public void TestRuleSetDisplayName() {
817         ULocale.setDefault(ULocale.US);
818         String[][] localizations = new String[][] {
819             /* public rule sets*/
820             {"%simplified", "%default", "%ordinal"},
821             /* display names in "en_US" locale*/
822             {"en_US", "Simplified", "Default", "Ordinal"},
823             /* display names in "zh_Hans" locale*/
824             {"zh_Hans", "\u7B80\u5316", "\u7F3A\u7701",  "\u5E8F\u5217"},
825             /* display names in a fake locale*/
826             {"foo_Bar_BAZ", "Simplified", "Default", "Ordinal"}
827         };
828         
829         //Construct RuleBasedNumberFormat by rule sets and localizations list
830         RuleBasedNumberFormat formatter
831             = new RuleBasedNumberFormat(ukEnglish, localizations, ULocale.US);
832         RuleBasedNumberFormat f2= new RuleBasedNumberFormat(ukEnglish, localizations);
833         assertTrue("Check the two formatters' equality", formatter.equals(f2));        
834
835         //get displayName by name
836         String[] ruleSetNames = formatter.getRuleSetNames();
837         for (int i=0; i<ruleSetNames.length; i++) {
838             logln("Rule set name: " + ruleSetNames[i]);
839             String RSName_defLoc = formatter.getRuleSetDisplayName(ruleSetNames[i]);
840             assertEquals("Display name in default locale", localizations[1][i+1], RSName_defLoc);
841             String RSName_loc = formatter.getRuleSetDisplayName(ruleSetNames[i], ULocale.CHINA);
842             assertEquals("Display name in Chinese", localizations[2][i+1], RSName_loc);
843         }
844                 
845         // getDefaultRuleSetName
846         String defaultRS = formatter.getDefaultRuleSetName();
847         //you know that the default rule set is %simplified according to rule sets string ukEnglish
848         assertEquals("getDefaultRuleSetName", "%simplified", defaultRS);
849         
850         //get locales of localizations
851         ULocale[] locales = formatter.getRuleSetDisplayNameLocales();
852         for (int i=0; i<locales.length; i++) {
853             logln(locales[i].getName());
854         }
855         
856         //get displayNames
857         String[] RSNames_defLoc = formatter.getRuleSetDisplayNames();
858         for (int i=0; i<RSNames_defLoc.length; i++) {
859             assertEquals("getRuleSetDisplayNames in default locale", localizations[1][i+1], RSNames_defLoc[i]);
860         }
861         
862         String[] RSNames_loc = formatter.getRuleSetDisplayNames(ULocale.UK);
863         for (int i=0; i<RSNames_loc.length; i++) {
864             assertEquals("getRuleSetDisplayNames in English", localizations[1][i+1], RSNames_loc[i]);
865         }    
866         
867         RSNames_loc = formatter.getRuleSetDisplayNames(ULocale.CHINA);
868         for (int i=0; i<RSNames_loc.length; i++) {
869             assertEquals("getRuleSetDisplayNames in Chinese", localizations[2][i+1], RSNames_loc[i]);
870         }        
871
872         RSNames_loc = formatter.getRuleSetDisplayNames(new ULocale("foo_Bar_BAZ"));
873         for (int i=0; i<RSNames_loc.length; i++) {
874             assertEquals("getRuleSetDisplayNames in fake locale", localizations[3][i+1], RSNames_loc[i]);
875         }              
876     }
877
878     public void TestAllLocales() {
879         StringBuffer errors = null;
880         ULocale[] locales = ULocale.getAvailableLocales();
881         String[] names = {
882             " (spellout) ",
883             " (ordinal)  ",
884             " (duration) "
885         };
886         double[] numbers = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};
887         Random r = null;
888
889         // RBNF parse is extremely slow when lenient option is enabled.
890         // For non-exhaustive mode, we only test a few locales.
891         // "nl_NL", "be" had crash problem reported by #6534
892         String[] parseLocales = {"en_US", "nl_NL", "be"};
893
894         for (int i = 0; i < locales.length; ++i) {
895             ULocale loc = locales[i];
896             int count = numbers.length;
897             boolean testParse = true;
898             if (getInclusion() <= 5) {
899                 testParse = false;
900                 for (int k = 0; k < parseLocales.length; k++) {
901                     if (loc.toString().equals(parseLocales[k])) {
902                         testParse = true;
903                         break;
904                     }
905                 }
906             } else {
907                 //RBNF parse is too slow.  Increase count only for debugging purpose for now.
908                 //count = 100;
909             }
910
911             for (int j = 0; j < 3; ++j) {
912                 RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(loc, j+1);
913
914                 for (int c = 0; c < count; c++) {
915                     double n;
916                     if (c < numbers.length) {
917                         n = numbers[c];
918                     } else {
919                         if (r == null) {
920                             r = createRandom();
921                         }
922                         n = ((int)(r.nextInt(10000) - 3000)) / 16d;
923                     }
924
925                     String s = fmt.format(n);
926                     logln(loc.getName() + names[j] + "success format: " + n + " -> " + s);
927
928                     if (testParse) {
929                         // We do not validate the result in this test case,
930                         // because there are cases which do not round trip by design.
931                         try {
932                             // non-lenient parse
933                             fmt.setLenientParseMode(false);
934                             Number num = fmt.parse(s);
935                             logln(loc.getName() + names[j] + "success parse: " + s + " -> " + num);
936
937                             // lenient parse
938                             fmt.setLenientParseMode(true);
939                             num = fmt.parse(s);
940                             logln(loc.getName() + names[j] + "success parse (lenient): " + s + " -> " + num);
941                         } catch (ParseException pe) {
942                             String msg = loc.getName() + names[j] + "ERROR:" + pe.getMessage();
943                             logln(msg);
944                             if (errors == null) {
945                                 errors = new StringBuffer();
946                             }
947                             errors.append("\n" + msg);
948                         }
949                     }
950                 }
951             }
952         }
953         if (errors != null) {
954             //TODO: We need to fix parse problems - see #6895 / #6896
955             //errln(errors.toString());
956             logln(errors.toString());
957         }
958     }
959
960     void doTest(RuleBasedNumberFormat formatter, String[][] testData,
961                 boolean testParsing) {
962     //        NumberFormat decFmt = NumberFormat.getInstance(Locale.US);
963     NumberFormat decFmt = new DecimalFormat("#,###.################");
964         try {
965             for (int i = 0; i < testData.length; i++) {
966                 String number = testData[i][0];
967                 String expectedWords = testData[i][1];
968                 logln("test[" + i + "] number: " + number + " target: " + expectedWords);
969                 Number num = decFmt.parse(number);
970                 String actualWords = formatter.format(num);
971
972                 if (!actualWords.equals(expectedWords)) {
973                     errln("Spot check format failed: for " + number + ", expected\n    "
974                           + expectedWords + ", but got\n    " +
975                           actualWords);
976                 }
977                 else if (testParsing) {
978                     String actualNumber = decFmt.format(formatter
979                                                         .parse(actualWords));
980
981                     if (!actualNumber.equals(number)) {
982                         errln("Spot check parse failed: for " + actualWords +
983                               ", expected " + number + ", but got " +
984                               actualNumber);
985                     }
986                 }
987             }
988         }
989         catch (Throwable e) {
990             e.printStackTrace();
991             errln("Test failed with exception: " + e.toString());
992         }
993     }
994
995     void doLenientParseTest(RuleBasedNumberFormat formatter,
996                             String[][] testData) {
997         NumberFormat decFmt = NumberFormat.getInstance(Locale.US);
998
999         try {
1000             for (int i = 0; i < testData.length; i++) {
1001                 String words = testData[i][0];
1002                 String expectedNumber = testData[i][1];
1003                 String actualNumber = decFmt.format(formatter.parse(words));
1004
1005                 if (!actualNumber.equals(expectedNumber)) {
1006                     errln("Lenient-parse spot check failed: for "
1007                           + words + ", expected " + expectedNumber
1008                           + ", but got " + actualNumber);
1009                 }
1010             }
1011         }
1012         catch (Throwable e) {
1013             errln("Test failed with exception: " + e.toString());
1014             e.printStackTrace();
1015         }
1016     }
1017
1018
1019     /**
1020      * Spellout rules for U.K. English.  
1021      * I borrow the rule sets for TestRuleSetDisplayName()
1022      */
1023     public static final String ukEnglish =
1024         "%simplified:\n"
1025         + "    -x: minus >>;\n"
1026         + "    x.x: << point >>;\n"
1027         + "    zero; one; two; three; four; five; six; seven; eight; nine;\n"
1028         + "    ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
1029         + "        seventeen; eighteen; nineteen;\n"
1030         + "    20: twenty[->>];\n"
1031         + "    30: thirty[->>];\n"
1032         + "    40: forty[->>];\n"
1033         + "    50: fifty[->>];\n"
1034         + "    60: sixty[->>];\n"
1035         + "    70: seventy[->>];\n"
1036         + "    80: eighty[->>];\n"
1037         + "    90: ninety[->>];\n"
1038         + "    100: << hundred[ >>];\n"
1039         + "    1000: << thousand[ >>];\n"
1040         + "    1,000,000: << million[ >>];\n"
1041         + "    1,000,000,000,000: << billion[ >>];\n"
1042         + "    1,000,000,000,000,000: =#,##0=;\n"
1043         + "%alt-teens:\n"
1044         + "    =%simplified=;\n"
1045         + "    1000>: <%%alt-hundreds<[ >>];\n"
1046         + "    10,000: =%simplified=;\n"
1047         + "    1,000,000: << million[ >%simplified>];\n"
1048         + "    1,000,000,000,000: << billion[ >%simplified>];\n"
1049         + "    1,000,000,000,000,000: =#,##0=;\n"
1050         + "%%alt-hundreds:\n"
1051         + "    0: SHOULD NEVER GET HERE!;\n"
1052         + "    10: <%simplified< thousand;\n"
1053         + "    11: =%simplified= hundred>%%empty>;\n"
1054         + "%%empty:\n"
1055         + "    0:;"
1056         + "%ordinal:\n"
1057         + "    zeroth; first; second; third; fourth; fifth; sixth; seventh;\n"
1058         + "        eighth; ninth;\n"
1059         + "    tenth; eleventh; twelfth; thirteenth; fourteenth;\n"
1060         + "        fifteenth; sixteenth; seventeenth; eighteenth;\n"
1061         + "        nineteenth;\n"
1062         + "    twentieth; twenty->>;\n"
1063         + "    30: thirtieth; thirty->>;\n"
1064         + "    40: fortieth; forty->>;\n"
1065         + "    50: fiftieth; fifty->>;\n"
1066         + "    60: sixtieth; sixty->>;\n"
1067         + "    70: seventieth; seventy->>;\n"
1068         + "    80: eightieth; eighty->>;\n"
1069         + "    90: ninetieth; ninety->>;\n"
1070         + "    100: <%simplified< hundredth; <%simplified< hundred >>;\n"
1071         + "    1000: <%simplified< thousandth; <%simplified< thousand >>;\n"
1072         + "    1,000,000: <%simplified< millionth; <%simplified< million >>;\n"
1073         + "    1,000,000,000,000: <%simplified< billionth;\n"
1074         + "        <%simplified< billion >>;\n"
1075         + "    1,000,000,000,000,000: =#,##0=;"
1076         + "%default:\n"
1077         + "    -x: minus >>;\n"
1078         + "    x.x: << point >>;\n"
1079         + "    =%simplified=;\n"
1080         + "    100: << hundred[ >%%and>];\n"
1081         + "    1000: << thousand[ >%%and>];\n"
1082         + "    100,000>>: << thousand[>%%commas>];\n"
1083         + "    1,000,000: << million[>%%commas>];\n"
1084         + "    1,000,000,000,000: << billion[>%%commas>];\n"
1085         + "    1,000,000,000,000,000: =#,##0=;\n"
1086         + "%%and:\n"
1087         + "    and =%default=;\n"
1088         + "    100: =%default=;\n"
1089         + "%%commas:\n"
1090         + "    ' and =%default=;\n"
1091         + "    100: , =%default=;\n"
1092         + "    1000: , <%default< thousand, >%default>;\n"
1093         + "    1,000,000: , =%default=;"
1094         + "%%lenient-parse:\n"
1095         + "    & ' ' , ',' ;\n";
1096
1097 }
1098