Lolly 1.4.28
Loading...
Searching...
No Matches
numeral.cpp
Go to the documentation of this file.
1
2/******************************************************************************
3 * MODULE : numberal.hpp
4 * DESCRIPTION:
5 * COPYRIGHT : (C) 2013 Francois Poulain
6 * 2023 Darcy Shen
7 *******************************************************************************
8 * This software falls under the GNU general public license version 3 or later.
9 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
10 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ******************************************************************************/
12
13#include "numeral.hpp"
14#include "analyze.hpp"
15
16namespace lolly {
17namespace data {
18static const string roman_ones[10] = {"", "i", "ii", "iii", "iv",
19 "v", "vi", "vii", "viii", "ix"};
20static const string roman_tens[10] = {"", "x", "xx", "xxx", "xl",
21 "l", "lx", "lxx", "lxxx", "xc"};
22static const string roman_hundreds[10]= {"", "c", "cc", "ccc", "cd",
23 "d", "dc", "dcc", "dccc", "cm"};
24static const string roman_thousands[4]= {"", "m", "mm", "mmm"};
25
26// 0 should not be used as index of this array, or bug occurs. because digit 0
27// is handled specially according to position of digit.
28static const string chars_han[10]= {"?", "一", "二", "三", "四",
29 "五", "六", "七", "八", "九"};
30
31static const char* hex_string= "0123456789ABCDEF";
32
33string
35 if (nr == 0) return "o";
36 if (nr > 3999 || nr < -3999) return "?";
37 if (nr < 0) return "-" * to_roman (-nr);
38 return roman_thousands[(nr / 1000) % 10] * roman_hundreds[(nr / 100) % 10] *
39 roman_tens[(nr / 10) % 10] * roman_ones[nr % 10];
40}
41
42string
44 return upcase_all (to_roman (nr));
45}
46
47string
49 short thousand= (nr % 10000) / 1000, hundred= (nr % 1000) / 100,
50 ten= (nr % 100) / 10, one= nr % 10;
51 short cases= (leading_zero << 4) | ((thousand == 0) << 3) |
52 ((hundred == 0) << 2) | ((ten == 0) << 1) | (one == 0);
53 switch (cases) {
54 case 0x0:
55 case 0x10:
56 return chars_han[thousand] * "千" * chars_han[hundred] * "百" *
57 chars_han[ten] * "十" * chars_han[one];
58 case 0x1:
59 case 0x11:
60 return chars_han[thousand] * "千" * chars_han[hundred] * "百" *
61 chars_han[ten] * "十";
62 case 0x2:
63 case 0x12:
64 return chars_han[thousand] * "千" * chars_han[hundred] * "百零" *
66 case 0x3:
67 case 0x13:
68 return chars_han[thousand] * "千" * chars_han[hundred] * "百";
69 case 0x4:
70 case 0x14:
71 return chars_han[thousand] * "千零" * chars_han[ten] * "十" *
73 case 0x5:
74 case 0x15:
75 return chars_han[thousand] * "千零" * chars_han[ten] * "十";
76 case 0x6:
77 case 0x16:
78 return chars_han[thousand] * "千零" * chars_han[one];
79 case 0x7:
80 case 0x17:
81 return chars_han[thousand] * "千";
82 case 0x8:
83 return chars_han[hundred] * "百" * chars_han[ten] * "十" * chars_han[one];
84 case 0x18:
85 return "零" * chars_han[hundred] * "百" * chars_han[ten] * "十" *
87 case 0x9:
88 return chars_han[hundred] * "百" * chars_han[ten] * "十";
89 case 0x19:
90 return "零" * chars_han[hundred] * "百" * chars_han[ten] * "十";
91 case 0xA:
92 return chars_han[hundred] * "百零" * chars_han[one];
93 case 0x1A:
94 return "零" * chars_han[hundred] * "百零" * chars_han[one];
95 case 0xB:
96 return chars_han[hundred] * "百";
97 case 0x1B:
98 return "零" * chars_han[hundred] * "百";
99 case 0xC:
100 if (ten == 1) {
101 return "十" * chars_han[one];
102 }
103 else {
104 return chars_han[ten] * "十" * chars_han[one];
105 }
106 case 0x1C:
107 return "零" * chars_han[ten] * "十" * chars_han[one];
108 case 0xD:
109 if (ten == 1) {
110 return "十";
111 }
112 else {
113 return chars_han[ten] * "十";
114 }
115 case 0x1D:
116 return "零" * chars_han[ten] * "十";
117 case 0xE:
118 return chars_han[one];
119 case 0x1E:
120 return "零" * chars_han[one];
121 case 0xF:
122 case 0x1F:
123 return "";
124 default:
125 return "?" * as_string (cases);
126 }
127}
128
129string
131 if (nr == 0) return "零";
132 if (nr == 0x80000000) return "负二十一亿四千七百四十八万三千六百四十八";
133 if (nr < 0) return "负" * to_hanzi (-nr);
134 if (nr >= 100000000) {
135 return hanzi_sub (nr / 100000000, false) * "亿" *
136 hanzi_sub ((nr / 10000) % 10000, true) * "万" *
137 hanzi_sub (nr % 10000, true);
138 }
139 if (nr >= 10000) {
140 return hanzi_sub (nr / 10000, false) * "万" * hanzi_sub (nr % 10000, true);
141 }
142 return hanzi_sub (nr, false);
143}
144
145string
147 uint8_t i_low = i & 15;
148 uint8_t i_high= i >> 4;
150}
151
152string
154 return locase_all (to_padded_Hex (i));
155}
156
157/**
158 * @brief Handle positive number separately to avoid unnecessary check of sign.
159 * string is passed into the function as reference, thus no reference counting
160 * is performed.
161 * @tparam T unsigned integral type is expected.
162 */
163template <typename T>
165 void>
166to_Hex_positive (T i, string& s) {
167 if (i >= 16) {
168 to_Hex_positive (i >> 4, s);
169 }
170 s << hex_string[i & 15];
171}
172
173string
175 if (i == INT32_MIN) return "-80000000";
176 if (i < 0) {
177 string result ("-");
179 return result;
180 }
181 else {
182 string result;
184 return result;
185 };
186}
187
188string
190 return locase_all (to_Hex (i));
191}
192
193string
195 intptr_t i= (intptr_t) ptr;
196 if (i < 0) {
197 string result ("-");
198 to_Hex_positive ((uintptr_t) (-i), result);
199 return result;
200 }
201 else {
202 string result;
203 to_Hex_positive ((uintptr_t) (i), result);
204 return result;
205 };
206}
207
208string
210 return locase_all (to_Hex (ptr));
211}
212
213int
214from_hex (string s) {
215 int i, n= N (s), res= 0;
216 if ((n > 0) && (s[0] == '-')) return -from_hex (s (1, n));
217 for (i= 0; i < n; i++) {
218 res= res << 4;
219 if (is_digit (s[i])) res+= (int) (s[i] - '0');
220 if ((s[i] >= 'A') && (s[i] <= 'F')) res+= (int) (s[i] + 10 - 'A');
221 if ((s[i] >= 'a') && (s[i] <= 'f')) res+= (int) (s[i] + 10 - 'a');
222 }
223 return res;
224}
225
226/**
227 * @brief Handle positive number separately to avoid unnecessary check of sign.
228 * string is passed into the function as reference, thus no reference counting
229 * is performed.
230 * Because length of string s is known here, use index instead of appending
231 * operator can avoid cost of reallocation. Firstly a string of given length is
232 * constructed, then digits is filled according to index rather than appending
233 * to the tail.
234 * @tparam T unsigned integral type is expected.
235 */
236template <unsigned int cur, typename T>
238 void>
239as_hexadecimal_sub (T i, string& s) {
240 if constexpr (cur > 0) {
241 as_hexadecimal_sub<cur - 1> (i >> 4, s);
242 }
243 s[cur]= hex_string[i & 15];
244}
245
246string
247as_hexadecimal (int i, int len) {
248 string result (len);
249 switch (len) {
250 case 1:
251 as_hexadecimal_sub<0> ((unsigned int) i, result);
252 break;
253 case 2:
254 as_hexadecimal_sub<1> ((unsigned int) i, result);
255 break;
256 case 3:
257 as_hexadecimal_sub<2> ((unsigned int) i, result);
258 break;
259 case 4:
260 as_hexadecimal_sub<3> ((unsigned int) i, result);
261 break;
262 case 5:
263 as_hexadecimal_sub<4> ((unsigned int) i, result);
264 break;
265 case 6:
266 as_hexadecimal_sub<5> ((unsigned int) i, result);
267 break;
268 case 7:
269 as_hexadecimal_sub<6> ((unsigned int) i, result);
270 break;
271 case 8:
272 as_hexadecimal_sub<7> ((unsigned int) i, result);
273 break;
274 case 9:
275 as_hexadecimal_sub<8> ((unsigned int) i, result);
276 break;
277 case 10:
278 as_hexadecimal_sub<9> ((unsigned int) i, result);
279 break;
280 case 11:
281 as_hexadecimal_sub<10> ((unsigned int) i, result);
282 break;
283 case 12:
284 as_hexadecimal_sub<11> ((unsigned int) i, result);
285 break;
286 case 13:
287 as_hexadecimal_sub<12> ((unsigned int) i, result);
288 break;
289 case 14:
290 as_hexadecimal_sub<13> ((unsigned int) i, result);
291 break;
292 case 15:
293 as_hexadecimal_sub<14> ((unsigned int) i, result);
294 break;
295 case 16:
296 as_hexadecimal_sub<15> ((unsigned int) i, result);
297 break;
298 default:
299 TM_FAILED ("len is too large");
300 break;
301 }
302 return result;
303}
304
305string
307 string result;
309 return result;
310}
311
312string
314 string res ((int) (N (bin) * 2));
315 int cur= 0;
316 for (unsigned char ch : bin) {
317 res[cur] = hex_string[ch >> 4];
318 res[cur + 1]= hex_string[ch & 0x0f];
319 cur+= 2;
320 }
321 return res;
322}
323
324} // namespace data
325} // namespace lolly
string locase_all(string s)
Converts all uppercase characters in a string to lowercase.
Definition analyze.cpp:137
string upcase_all(string s)
Converts all lowercase characters in a string to uppercase.
Definition analyze.cpp:127
bool is_digit(char c)
Definition analyze.hpp:37
void * pointer
Definition basic.hpp:24
#define TM_FAILED(msg)
Macro used to throw an exception with a specified error message.
Definition basic.hpp:93
The list class represents a linked list.
Definition list.hpp:48
list(T item)
Construct a new list object with a single item.
Definition list.hpp:137
string to_hex(int32_t i)
Definition numeral.cpp:189
string binary_to_hexadecimal(string bin)
Converts a binary stream to its hexadecimal represention.
Definition numeral.cpp:313
string uint32_to_Hex(uint32_t i)
Converts an unsigned integer to a hexadecimal string.
Definition numeral.cpp:306
std::enable_if_t< std::conjunction_v< std::is_integral< T >, std::is_unsigned< T > >, void > to_Hex_positive(T i, string &s)
Handle positive number separately to avoid unnecessary check of sign. string is passed into the funct...
Definition numeral.cpp:166
string to_hanzi(int32_t nr)
Generates a Chinese numeral for a given integer.
Definition numeral.cpp:130
string to_roman(int32_t nr)
Generates a Roman numeral string for an integer.
Definition numeral.cpp:34
string as_hexadecimal(int i, int len)
Converts an unsigned integer to a hexadecimal string with a fixed length.
Definition numeral.cpp:247
static const string roman_thousands[4]
Definition numeral.cpp:24
static const string roman_ones[10]
Definition numeral.cpp:18
string hanzi_sub(int16_t nr, bool leading_zero)
Definition numeral.cpp:48
static const string roman_tens[10]
Definition numeral.cpp:20
string to_padded_hex(uint8_t i)
Converts an 8-bit unsigned integer to a fixed-length (2) hex string.
Definition numeral.cpp:153
string to_Roman(int32_t nr)
Generates an uppercase Roman numeral string for an integer.
Definition numeral.cpp:43
int N(lolly_tree< T > t)
static const string chars_han[10]
Definition numeral.cpp:28
static const string roman_hundreds[10]
Definition numeral.cpp:22
static const char * hex_string
Definition numeral.cpp:31
int from_hex(string s)
Converts a hexadecimal string to an integer.
Definition numeral.cpp:214
string to_Hex(int32_t i)
Definition numeral.cpp:174
string to_padded_Hex(uint8_t i)
Definition numeral.cpp:146
std::enable_if_t< std::conjunction_v< std::is_integral< T >, std::is_unsigned< T > >, void > as_hexadecimal_sub(T i, string &s)
Handle positive number separately to avoid unnecessary check of sign. string is passed into the funct...
Definition numeral.cpp:239
string as_string(int16_t i)
Definition string.cpp:272