]> www.ginac.de Git - cln.git/blob - src/real/format-output/cl_fmt_cardinal.cc
2685f47e4f68a1a1e9cce7c3cf3f37f6d10895dc
[cln.git] / src / real / format-output / cl_fmt_cardinal.cc
1 // format_cardinal().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_format.h"
8
9
10 // Implementation.
11
12 #include "cl_integer.h"
13 #include "cl_integer_io.h"
14 #include "cl_abort.h"
15
16 static const char * const cl_format_ones [20] = {
17         NULL,
18         "one",
19         "two",
20         "three",
21         "four",
22         "five",
23         "six",
24         "seven",
25         "eight",
26         "nine",
27         "ten",
28         "eleven",
29         "twelve",
30         "thirteen",
31         "fourteen",
32         "fifteen",
33         "sixteen",
34         "seventeen",
35         "eighteen",
36         "nineteen",
37 };
38
39 // gibt eine ganze Zahl >0, <1000 im Klartext auf englisch auf den stream aus.
40 // (arg=0 -> gibt nichts aus.)
41 static void format_small_cardinal (cl_ostream stream, uintL arg)
42 {
43         var uintL hundreds = floor(arg,100);
44         var uintL tens_and_ones = arg % 100;
45         if (hundreds > 0) {
46                 fprint(stream,cl_format_ones[hundreds]);
47                 fprint(stream," hundred");
48         }
49         if (tens_and_ones > 0) {
50                 if (hundreds > 0)
51                         fprint(stream," and ");
52                 var uintL tens = floor(tens_and_ones,10);
53                 var uintL ones = tens_and_ones % 10;
54                 if (tens < 2)
55                         fprint(stream,cl_format_ones[tens_and_ones]);
56                 else {
57                         fprint(stream,cl_format_tens[tens]);
58                         if (ones > 0) {
59                                 fprintchar(stream,'-');
60                                 fprint(stream,cl_format_ones[ones]);
61                         }
62                 }
63         }
64 }
65
66 void format_cardinal (cl_ostream stream, const cl_I& argument)
67 {
68         if (zerop(argument))
69                 fprint(stream,"zero");
70         else {
71                 var cl_I arg = argument;
72                 if (minusp(arg)) {
73                         fprint(stream,"minus ");
74                         arg = -arg;
75                 }
76                 // amerikanisch (billion=10^9)
77                 static const char * const illions[] = {
78                         "",
79                         " thousand",
80                         " million",
81                         " billion",
82                         " trillion",
83                         " quadrillion",
84                         " quintillion",
85                         " sextillion",
86                         " septillion",
87                         " octillion",
88                         " nonillion",
89                         " decillion",
90                         " undecillion",
91                         " duodecillion",
92                         " tredecillion",
93                         " quattuordecillion",
94                         " quindecillion",
95                         " sexdecillion",
96                         " septendecillion",
97                         " octodecillion",
98                         " novemdecillion",
99                         " vigintillion",
100                         NULL
101                 };
102                 var uintL small_pieces [sizeof(illions)/sizeof(illions[0])];
103                 // Let the recursion begin.
104                 var const char * const * illion_ptr = &illions[0];
105                 var uintL * small_piece_ptr = &small_pieces[0];
106                 do {
107                         if (*illion_ptr == NULL) {
108                                 fprint(cl_stderr, "format_cardinal: argument too large: ");
109                                 fprint(cl_stderr, argument);
110                                 fprint(cl_stderr, "\n");
111                                 cl_abort();
112                         }
113                         var cl_I_div_t div = floor2(arg,1000);
114                         var const cl_I& thousands = div.quotient;
115                         var uintL small = cl_I_to_UL(div.remainder);
116                         illion_ptr++;
117                         *small_piece_ptr++ = small;
118                         arg = thousands;
119                 } while (arg > 0);
120                 // Roll back the recursion.
121                 var cl_boolean first_piece = cl_true;
122                 do {
123                         var uintL small = *--small_piece_ptr;
124                         var const char * illion = *--illion_ptr;
125                         if (small > 0) {
126                                 if (!first_piece)
127                                         fprint(stream,", ");
128                                 format_small_cardinal(stream,small);
129                                 fprint(stream,illion);
130                                 first_piece = cl_false;
131                         }
132                 } until (illion_ptr == &illions[0]);
133         }
134 }