HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
unicode_plural.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
10#pragma once
11
12#include "../utility/module.hpp"
13#include "../i18n/module.hpp"
14#include <concepts>
15#include <array>
16#include <cstdint>
17#include <cstddef>
18
19namespace hi { inline namespace v1 {
20
23enum class plurality_value : uint8_t {
26 zero = 0,
27
30 one = 1,
31
34 two = 2,
35
38 few = 3,
39
42 many = 4,
43
46 other = 5
47};
48
51enum class plurality_mask : uint8_t {
54 zero = 1 << to_underlying(plurality_value::zero),
55
58 one = 1 << to_underlying(plurality_value::one),
59
62 two = 1 << to_underlying(plurality_value::two),
63
66 few = 1 << to_underlying(plurality_value::few),
67
70 many = 1 << to_underlying(plurality_value::many),
71
74 other = 1 << to_underlying(plurality_value::other),
75};
76
79[[nodiscard]] constexpr plurality_mask operator|(plurality_mask const& lhs, plurality_mask const& rhs) noexcept
80{
81 return static_cast<plurality_mask>(to_underlying(lhs) | to_underlying(rhs));
82}
83
86struct plurality {
87 plurality_value value;
88 plurality_mask mask;
89
90 constexpr plurality(plurality_value value, plurality_mask mask) noexcept : value(value), mask(mask)
91 {
92 // Check if the value uses only bits that are set in the mask.
93 hi_axiom(not to_bool(to_underlying(value) & ~to_underlying(mask)));
94 }
95
103 [[nodiscard]] constexpr size_t index(size_t n) const noexcept
104 {
105 hi_assert(n != 0);
106
107 hilet value_as_mask = (1 << (to_underlying(value) + 1)) - 1;
108 // Get the index based on the number of '1' bits that are set from the
109 // plurality position to lsb.
110 hilet i = std::popcount(narrow_cast<uint8_t>(value_as_mask & to_underlying(mask))) - 1;
111 if (i < n) {
112 return i;
113 } else {
114 return n - 1;
115 }
116 }
117};
118
119namespace detail {
120
128 unsigned long long n = 0;
129
132 unsigned long long f = 0;
133
136 unsigned long long t = 0;
137
140 uint8_t i = 0;
141
144 uint8_t v = 0;
145
148 uint8_t w = 0;
149
152 uint8_t c = 0;
153
154 constexpr plural_operand(std::integral auto value) noexcept : n(std::abs(value)), i(narrow_cast<uint8_t>(decimal_width(value))) {}
155};
156
157// Each of the rules can be shared by multiple languages. Each rule will be named
158// after the first language in alphabetical order.
159
160// clang-format off
161[[nodiscard]] constexpr plurality cardinal_plural_bambara(plural_operand) noexcept
162{
164}
165
166[[nodiscard]] constexpr plurality cardinal_plural_cebuano(plural_operand op) noexcept
167{
168 hilet value = [&] {
169 if (
170 (op.v == 0 and op.i >= 1 and op.i <= 3) or
171 (op.v == 0 and op.i % 10 != 4 and op.i % 10 != 6 and op.i % 10 != 9) or
172 (op.v != 0 and op.f % 10 != 4 and op.f % 10 != 6 and op.f % 10 != 9)) {
174 } else {
176 }
177 }();
178
180}
181
182[[nodiscard]] constexpr plurality cardinal_plural_central_atlas_tamazight(plural_operand op) noexcept
183{
184 hilet value = [&] {
185 if (op.n == 0 or op.n == 1 or (op.n >= 11 and op.n <= 99)) {
187 } else {
189 }
190 }();
191
193}
194
195[[nodiscard]] constexpr plurality cardinal_plural_icelandic(plural_operand op) noexcept
196{
197 hilet value = [&] {
198 if ((op.t == 0 and op.i % 10 == 1 and op.i % 100 != 11) or op.t != 0) {
200 } else {
202 }
203 }();
204
206}
207
208[[nodiscard]] constexpr plurality cardinal_plural_akan(plural_operand op) noexcept
209{
210 hilet value = [&] {
211 if (op.n == 0 or op.n == 1) {
213 } else {
215 }
216 }();
217
219}
220
221[[nodiscard]] constexpr plurality cardinal_plural_afrikaans(plural_operand op) noexcept
222{
223 hilet value = [&] {
224 if (op.n == 1) {
226 } else {
228 }
229 }();
230
232}
233
234[[nodiscard]] constexpr plurality cardinal_plural_latvian(plural_operand op) noexcept
235{
236 hilet value = [&] {
237 if (
238 op.n == 0 or
239 (op.n % 100 >= 11 and op.n % 100 <= 19) or
240 (op.v == 2 and op.f % 100 >= 11 and op.f % 100 <= 19)) {
242 } else if (
243 (op.n % 10 == 1 and op.n % 100 != 11) or
244 (op.v == 2 and op.f % 10 == 1 and op.f % 100 != 11) or
245 (op.v != 2 and op.f % 10 == 1)) {
247 } else {
249 }
250 }();
251
253}
254
255[[nodiscard]] constexpr plurality cardinal_plural_colognian(plural_operand op) noexcept
256{
257 hilet value = [&] {
258 if (op.n == 0) {
260 } else if (op.n == 1) {
262 } else {
264 }
265 }();
266
268}
269
270[[nodiscard]] constexpr plurality cardinal_plural_inari_sami(plural_operand op) noexcept
271{
272 hilet value = [&] {
273 if (op.n == 1) {
275 } else if (op.n == 2) {
277 } else {
279 }
280 }();
281
283}
284
285[[nodiscard]] constexpr plurality cardinal_plural_belarusian(plural_operand op) noexcept
286{
287 hilet value = [&] {
288 if (op.n % 10 == 1 and op.n % 100 != 11) {
290 } else if (op.n % 10 >= 2 and op.n % 10 <= 4 and not (op.n % 100 >= 12 and op.n % 100 <= 14)) {
292 } else if (
293 op.n % 10 == 0 or
294 (op.n % 10 >= 5 and op.n % 10 <= 9) or
295 (op.n % 100 >= 11 and op.n % 100 <= 14)) {
297 } else {
299 }
300 }();
301
303}
304
305[[nodiscard]] constexpr plurality cardinal_plural_polish(plural_operand op) noexcept
306{
307 hilet value = [&] {
308 // The specification uses op.i (number of digits) instead of op.n (absolute value)
309 if (op.n == 1 and op.v == 0) {
311 } else if (op.v == 0 and (op.n % 10 >= 2 and op.n % 10 <= 4) and not (op.n % 100 >= 12 and op.n % 100 <= 14)) {
313 } else if (
314 (op.v == 0 and op.n != 1 and op.n % 10 >= 0 and op.n % 10 <= 1) or
315 (op.v == 0 and op.n % 10 >= 5 and op.n % 10 <= 9) or
316 (op.v == 0 and op.n % 100 >= 12 and op.n % 100 <= 14)) {
318 } else {
320 }
321 }();
322
324}
325
326[[nodiscard]] constexpr plurality cardinal_plural_lithuanian(plural_operand op) noexcept
327{
328 hilet value = [&] {
329 if (op.n % 10 == 1 and not (op.n % 100 >= 11 and op.n % 100 <= 19)) {
331 } else if (op.n % 10 >= 2 and op.n % 10 <= 9 and not (op.n % 100 >= 11 and op.n % 100 <= 19)) {
333 } else if (op.f != 0) {
335 } else {
337 }
338 }();
339
341}
342
343[[nodiscard]] constexpr plurality cardinal_plural_bosnian(plural_operand op) noexcept
344{
345 hilet value = [&] {
346 // The specification uses op.i (number of digits) instead of op.n (absolute value)
347 if (
348 (op.v == 0 and op.n % 10 == 1 and op.n % 100 != 11) or
349 (op.f % 10 == 1 and op.f % 100 != 11)) {
351 } else if (
352 (op.v == 0 and op.n % 10 >= 2 and op.n % 10 <= 4 and not (op.n % 100 >= 12 and op.n % 100 <= 14)) or
353 (op.f % 10 >= 2 and op.f % 10 <= 4 and not (op.f % 100 >= 12 and op.n % 100 <= 14))) {
355 } else {
357 }
358 }();
359
361}
362
363[[nodiscard]] constexpr plurality cardinal_plural_tachelhit(plural_operand op) noexcept
364{
365 hilet value = [&] {
366 if (op.i == 0 or op.n == 1) {
368 } else if (op.n >= 2 and op.n <= 10) {
370 } else {
372 }
373 }();
374
376}
377
378[[nodiscard]] constexpr plurality cardinal_plural_moldavian(plural_operand op) noexcept
379{
380 hilet value = [&] {
381 // The specification uses op.i (number of digits) for determining 'one'
382 // which is wrong.
383 if (op.n == 1 and op.v == 0) {
385 } else if (
386 op.v != 0 or
387 op.n == 0 or
388 (op.n % 100 >= 2 and op.n % 100 <= 19)) {
390 } else {
392 }
393 }();
394
396}
397
398[[nodiscard]] constexpr plurality cardinal_plural_czech(plural_operand op) noexcept
399{
400 hilet value = [&] {
401 // The specification uses op.i (number of digits) instead of
402 // op.n (absolute value).
403 if (op.n == 1 and op.v == 0) {
405 } else if (op.n >= 2 and op.n <= 4 and op.v == 0) {
407 } else if (op.v != 0) {
409 } else {
411 }
412 }();
413
415}
416
417[[nodiscard]] constexpr plurality cardinal_plural_manx(plural_operand op) noexcept
418{
419 hilet value = [&] {
420 // The specification uses op.i (number of digits) instead of
421 // op.n (absolute value).
422 if (op.v == 0 and op.n % 10 == 1) {
424 } else if (op.v == 0 and op.n % 10 == 2) {
426 } else if (op.v == 0 and (
427 op.n % 100 == 0 or op.n % 100 == 20 or op.n % 100 == 40 or op.n % 100 == 60 or op.n % 100 == 80)) {
429 } else if (op.v != 0) {
431 } else {
433 }
434 }();
435
437}
438
439[[nodiscard]] constexpr plurality cardinal_plural_scottish_gaelic(plural_operand op) noexcept
440{
441 hilet value = [&] {
442 if (op.n == 1 or op.n == 11) {
444 } else if (op.n == 2 or op.n == 12) {
446 } else if ((op.n >= 3 and op.n <= 10) or (op.n >= 13 and op.n <= 19)) {
448 } else {
450 }
451 }();
452
454}
455
456[[nodiscard]] constexpr plurality cardinal_plural_breton(plural_operand op) noexcept
457{
458 hilet value = [&] {
459 if (op.n % 10 == 1 and op.n % 100 != 11 and op.n % 100 != 71 and op.n % 100 != 91) {
461 } else if (op.n % 10 == 2 and op.n % 100 != 12 and op.n % 100 != 72 and op.n % 100 != 92) {
463 } else if (
464 (op.n % 10 == 3 or op.n % 10 == 4 or op.n % 10 == 9) and
465 (not (op.n % 100 >= 10 and op.n % 100 <= 19) and
466 not (op.n % 100 >= 70 and op.n % 100 <= 79) and
467 not (op.n % 100 >= 90 and op.n % 100 <= 99))) {
469 } else if (op.n != 0 and op.n % 1'000'000 == 0) {
471 } else {
473 }
474 }();
475
477}
478
479[[nodiscard]] constexpr plurality cardinal_plural_lower_sorbian(plural_operand op) noexcept
480{
481 hilet value = [&] {
482 // The specification use op.i (number of digits) instead of
483 // op.n (absolute value).
484 if (
485 (op.v == 0 and op.n % 100 == 1) or
486 op.f % 100 == 1) {
488 } else if (
489 (op.v == 0 and op.n % 100 == 2) or
490 op.f % 100 == 2) {
492 } else if (
493 (op.v == 0 and op.n % 100 >= 3 and op.n % 100 <= 4) or
494 (op.f % 100 >= 3 and op.f % 100 <= 4)) {
496 } else {
498 }
499 }();
500
502}
503
504[[nodiscard]] constexpr plurality cardinal_plural_hebrew(plural_operand op) noexcept
505{
506 hilet value = [&] {
507 // The specification use op.i (number of digits) instead of
508 // op.n (absolute value).
509 if (op.n == 1 and op.v == 0) {
511 } else if (op.n == 2 and op.v == 0) {
513 } else if (op.v == 0 and not (op.n >= 0 and op.n <= 10) and op.n % 10 == 0) {
515 } else {
517 }
518 }();
519
521}
522
523[[nodiscard]] constexpr plurality cardinal_plural_maltese(plural_operand op) noexcept
524{
525 hilet value = [&] {
526 if (op.n == 1) {
528 } else if (op.n == 0 or (op.n % 100 >= 2 and op.n % 100 <= 10)) {
530 } else if (op.n % 100 >= 11 and op.n % 100 <= 19) {
532 } else {
534 }
535 }();
536
538}
539
540[[nodiscard]] constexpr plurality cardinal_plural_irish(plural_operand op) noexcept
541{
542 hilet value = [&] {
543 if (op.n == 1) {
545 } else if (op.n == 2) {
547 } else if (op.n >= 3 and op.n <= 6) {
549 } else if (op.n >= 7 and op.n <= 10) {
551 } else {
553 }
554 }();
555
557}
558
559[[nodiscard]] constexpr plurality cardinal_plural_arabic(plural_operand op) noexcept
560{
561 hilet value = [&] {
562 if (op.n == 0) {
564 } else if (op.n == 1) {
566 } else if (op.n == 2) {
568 } else if (op.n % 100 >= 3 and op.n % 100 <= 10) {
570 } else if (op.n % 100 >= 11 and op.n % 100 <= 99) {
572 } else {
574 }
575 }();
576
577 return {
578 value,
581}
582
583[[nodiscard]] constexpr plurality cardinal_plural_welsh(plural_operand op) noexcept
584{
585 hilet value = [&] {
586 if (op.n == 0) {
588 } else if (op.n == 1) {
590 } else if (op.n == 2) {
592 } else if (op.n == 3) {
594 } else if (op.n == 6) {
596 } else {
598 }
599 }();
600
601 return {
602 value,
605 }
606
607[[nodiscard]] constexpr plurality cardinal_plural_cornish(plural_operand op) noexcept
608{
609 hilet value = [&] {
610 if (op.n == 0) {
612 } else if (op.n == 1) {
614 } else if (
615 op.n % 100 == 2 or
616 op.n % 100 == 22 or
617 op.n % 100 == 42 or
618 op.n % 100 == 62 or
619 op.n % 100 == 82 or
620 (op.n % 1'000 == 0 and (
621 (op.n % 100'000 >= 1'000 and op.n % 100'000 <= 20'000) or
622 op.n % 100'000 == 40'000 or
623 op.n % 100'000 == 60'000 or
624 op.n % 100'000 == 80'000)) or
625 (op.n != 0 and op.n % 1'000'000 == 100'000)) {
627 } else if (
628 op.n % 100 == 3 or
629 op.n % 100 == 23 or
630 op.n % 100 == 43 or
631 op.n % 100 == 63 or
632 op.n % 100 == 83) {
634 } else if (op.n != 1 and (
635 op.n % 100 == 1 or
636 op.n % 100 == 21 or
637 op.n % 100 == 41 or
638 op.n % 100 == 61 or
639 op.n % 100 == 81)) {
641 } else {
643 }
644 }();
645
646 return {
647 value,
650}
651// clang-format on
652
653using cardinal_plural_fptr = plurality (*)(plural_operand);
654
655[[nodiscard]] constexpr auto cardinal_plural_table_init() noexcept
656{
658
659 // Bambara, Burmese, Cantonese, Chinese, Dzongkha, Igbo, Indonesian,
660 // Japanese, Javanese, Kabuverdianu, Khmer, Korean, Koyraboro Senni, Lakota,
661 // Lao, Lojban, Makonde, Malay, N’Ko, Osage, Root, Sakha, Sango, Sichuan Yi,
662 // Sundanese, Thai, Tibetan, Tongan, Vietnamese, Wolof, Yoruba
663 for (auto& rule_ptr : r) {
664 rule_ptr = cardinal_plural_bambara;
665 }
666
667 // Cebuano, Filipino, Tagalog
668 r[iso_639{"ceb"}.intrinsic()] = cardinal_plural_cebuano;
669 r[iso_639{"fil"}.intrinsic()] = cardinal_plural_cebuano;
670 r[iso_639{"tl"}.intrinsic()] = cardinal_plural_cebuano;
671
672 // Central Atlas Tamazight
673 r[iso_639{"tzm"}.intrinsic()] = cardinal_plural_central_atlas_tamazight;
674
675 // Icelandic, Macedonian
676 r[iso_639{"is"}.intrinsic()] = cardinal_plural_icelandic;
677 r[iso_639{"mk"}.intrinsic()] = cardinal_plural_icelandic;
678
679 // Akan, Amharic, Armenian, Assamese, Bangla, Bihari, French, Fulah,
680 r[iso_639{"ak"}.intrinsic()] = cardinal_plural_akan;
681 r[iso_639{"am"}.intrinsic()] = cardinal_plural_akan;
682 r[iso_639{"hy"}.intrinsic()] = cardinal_plural_akan;
683 r[iso_639{"as"}.intrinsic()] = cardinal_plural_akan;
684 r[iso_639{"bn"}.intrinsic()] = cardinal_plural_akan;
685 r[iso_639{"bh"}.intrinsic()] = cardinal_plural_akan;
686 r[iso_639{"fr"}.intrinsic()] = cardinal_plural_akan;
687 r[iso_639{"ff"}.intrinsic()] = cardinal_plural_akan;
688 // Gujarati, Gun, Hindi, Kabyle, Kannada, Lingala, Malagasy, Northern Sotho,
689 r[iso_639{"gu"}.intrinsic()] = cardinal_plural_akan;
690 r[iso_639{"guw"}.intrinsic()] = cardinal_plural_akan;
691 r[iso_639{"hi"}.intrinsic()] = cardinal_plural_akan;
692 r[iso_639{"kab"}.intrinsic()] = cardinal_plural_akan;
693 r[iso_639{"kn"}.intrinsic()] = cardinal_plural_akan;
694 r[iso_639{"ln"}.intrinsic()] = cardinal_plural_akan;
695 r[iso_639{"mg"}.intrinsic()] = cardinal_plural_akan;
696 r[iso_639{"nso"}.intrinsic()] = cardinal_plural_akan;
697 // Persian, Portuguese, Punjabi, Sinhala, Tigrinya, Walloon, Zulu
698 r[iso_639{"fa"}.intrinsic()] = cardinal_plural_akan;
699 r[iso_639{"pt"}.intrinsic()] = cardinal_plural_akan;
700 r[iso_639{"pa"}.intrinsic()] = cardinal_plural_akan;
701 r[iso_639{"si"}.intrinsic()] = cardinal_plural_akan;
702 r[iso_639{"ti"}.intrinsic()] = cardinal_plural_akan;
703 r[iso_639{"wa"}.intrinsic()] = cardinal_plural_akan;
704 r[iso_639{"zu"}.intrinsic()] = cardinal_plural_akan;
705
706 // Afrikaans, Albanian, Aragonese, Asturian, Asu, Azerbaijani, Basque,
707 r[iso_639{"af"}.intrinsic()] = cardinal_plural_afrikaans;
708 r[iso_639{"sq"}.intrinsic()] = cardinal_plural_afrikaans;
709 r[iso_639{"an"}.intrinsic()] = cardinal_plural_afrikaans;
710 r[iso_639{"ast"}.intrinsic()] = cardinal_plural_afrikaans;
711 r[iso_639{"asa"}.intrinsic()] = cardinal_plural_afrikaans;
712 r[iso_639{"az"}.intrinsic()] = cardinal_plural_afrikaans;
713 r[iso_639{"eu"}.intrinsic()] = cardinal_plural_afrikaans;
714 // Bemba, Bena, Bodo, Bulgarian, Catalan, Central Kurdish, Chechen,
715 r[iso_639{"bem"}.intrinsic()] = cardinal_plural_afrikaans;
716 r[iso_639{"bez"}.intrinsic()] = cardinal_plural_afrikaans;
717 r[iso_639{"brx"}.intrinsic()] = cardinal_plural_afrikaans;
718 r[iso_639{"bg"}.intrinsic()] = cardinal_plural_afrikaans;
719 r[iso_639{"ca"}.intrinsic()] = cardinal_plural_afrikaans;
720 r[iso_639{"ckb"}.intrinsic()] = cardinal_plural_afrikaans;
721 r[iso_639{"ce"}.intrinsic()] = cardinal_plural_afrikaans;
722 // Cherokee, Chiga, Danish, Divehi, Dutch, English, Esperanto, Estonian,
723 r[iso_639{"chr"}.intrinsic()] = cardinal_plural_afrikaans;
724 r[iso_639{"cgg"}.intrinsic()] = cardinal_plural_afrikaans;
725 r[iso_639{"da"}.intrinsic()] = cardinal_plural_afrikaans;
726 r[iso_639{"dv"}.intrinsic()] = cardinal_plural_afrikaans;
727 r[iso_639{"nl"}.intrinsic()] = cardinal_plural_afrikaans;
728 r[iso_639{"en"}.intrinsic()] = cardinal_plural_afrikaans;
729 r[iso_639{"eo"}.intrinsic()] = cardinal_plural_afrikaans;
730 r[iso_639{"et"}.intrinsic()] = cardinal_plural_afrikaans;
731 // European Portuguese, Ewe, Faroese, Finnish, Friulian, Galician, Ganda,
732 //r[iso_639{"pt"}] = cardinal_plural_afrikaans;
733 r[iso_639{"ee"}.intrinsic()] = cardinal_plural_afrikaans;
734 r[iso_639{"fo"}.intrinsic()] = cardinal_plural_afrikaans;
735 r[iso_639{"fi"}.intrinsic()] = cardinal_plural_afrikaans;
736 r[iso_639{"fur"}.intrinsic()] = cardinal_plural_afrikaans;
737 r[iso_639{"gl"}.intrinsic()] = cardinal_plural_afrikaans;
738 r[iso_639{"lg"}.intrinsic()] = cardinal_plural_afrikaans;
739 // Georgian, German, Greek, Hausa, Hawaiian, Hungarian, Ido, Interlingua,
740 r[iso_639{"ka"}.intrinsic()] = cardinal_plural_afrikaans;
741 r[iso_639{"de"}.intrinsic()] = cardinal_plural_afrikaans;
742 r[iso_639{"el"}.intrinsic()] = cardinal_plural_afrikaans;
743 r[iso_639{"ha"}.intrinsic()] = cardinal_plural_afrikaans;
744 r[iso_639{"haw"}.intrinsic()] = cardinal_plural_afrikaans;
745 r[iso_639{"hu"}.intrinsic()] = cardinal_plural_afrikaans;
746 r[iso_639{"io"}.intrinsic()] = cardinal_plural_afrikaans;
747 r[iso_639{"ia"}.intrinsic()] = cardinal_plural_afrikaans;
748 // Italian, Jju, Kako, Kalaallisut, Kashmiri, Kazakh, Kurdish, Kyrgyz,
749 r[iso_639{"it"}.intrinsic()] = cardinal_plural_afrikaans;
750 r[iso_639{"kaj"}.intrinsic()] = cardinal_plural_afrikaans;
751 r[iso_639{"kkj"}.intrinsic()] = cardinal_plural_afrikaans;
752 r[iso_639{"kl"}.intrinsic()] = cardinal_plural_afrikaans;
753 r[iso_639{"ks"}.intrinsic()] = cardinal_plural_afrikaans;
754 r[iso_639{"kk"}.intrinsic()] = cardinal_plural_afrikaans;
755 r[iso_639{"ku"}.intrinsic()] = cardinal_plural_afrikaans;
756 r[iso_639{"ky"}.intrinsic()] = cardinal_plural_afrikaans;
757 // Luxembourgish, Machame, Malayalam, Marathi, Masai, Metaʼ, Mongolian,
758 r[iso_639{"lb"}.intrinsic()] = cardinal_plural_afrikaans;
759 r[iso_639{"jmc"}.intrinsic()] = cardinal_plural_afrikaans;
760 r[iso_639{"ml"}.intrinsic()] = cardinal_plural_afrikaans;
761 r[iso_639{"mr"}.intrinsic()] = cardinal_plural_afrikaans;
762 r[iso_639{"mas"}.intrinsic()] = cardinal_plural_afrikaans;
763 r[iso_639{"mgo"}.intrinsic()] = cardinal_plural_afrikaans;
764 r[iso_639{"mn"}.intrinsic()] = cardinal_plural_afrikaans;
765 // Nahuatl, Nepali, Ngiemboon, Ngomba, North Ndebele, Norwegian,
766 r[iso_639{"nah"}.intrinsic()] = cardinal_plural_afrikaans;
767 r[iso_639{"ne"}.intrinsic()] = cardinal_plural_afrikaans;
768 r[iso_639{"nnh"}.intrinsic()] = cardinal_plural_afrikaans;
769 r[iso_639{"jgo"}.intrinsic()] = cardinal_plural_afrikaans;
770 r[iso_639{"ns"}.intrinsic()] = cardinal_plural_afrikaans;
771 r[iso_639{"no"}.intrinsic()] = cardinal_plural_afrikaans;
772 // Norwegian Bokmål, Norwegian Nynorsk, Nyanja, Nyankole, Odia, Oromo,
773 r[iso_639{"nb"}.intrinsic()] = cardinal_plural_afrikaans;
774 r[iso_639{"nn"}.intrinsic()] = cardinal_plural_afrikaans;
775 r[iso_639{"ny"}.intrinsic()] = cardinal_plural_afrikaans;
776 r[iso_639{"nyn"}.intrinsic()] = cardinal_plural_afrikaans;
777 r[iso_639{"or"}.intrinsic()] = cardinal_plural_afrikaans;
778 r[iso_639{"om"}.intrinsic()] = cardinal_plural_afrikaans;
779 // Ossetic, Papiamento, Pashto, Romansh, Rombo, Rwa, Saho, Samburu,
780 r[iso_639{"os"}.intrinsic()] = cardinal_plural_afrikaans;
781 r[iso_639{"pap"}.intrinsic()] = cardinal_plural_afrikaans;
782 r[iso_639{"ps"}.intrinsic()] = cardinal_plural_afrikaans;
783 r[iso_639{"rm"}.intrinsic()] = cardinal_plural_afrikaans;
784 r[iso_639{"rof"}.intrinsic()] = cardinal_plural_afrikaans;
785 r[iso_639{"rwk"}.intrinsic()] = cardinal_plural_afrikaans;
786 r[iso_639{"ssy"}.intrinsic()] = cardinal_plural_afrikaans;
787 r[iso_639{"saq"}.intrinsic()] = cardinal_plural_afrikaans;
788 // Sardinian, Sena, Shambala, Shona, Sicilian, Sindhi, Soga, Somali,
789 r[iso_639{"sc"}.intrinsic()] = cardinal_plural_afrikaans;
790 r[iso_639{"seh"}.intrinsic()] = cardinal_plural_afrikaans;
791 r[iso_639{"ksb"}.intrinsic()] = cardinal_plural_afrikaans;
792 r[iso_639{"sn"}.intrinsic()] = cardinal_plural_afrikaans;
793 r[iso_639{"scn"}.intrinsic()] = cardinal_plural_afrikaans;
794 r[iso_639{"sd"}.intrinsic()] = cardinal_plural_afrikaans;
795 r[iso_639{"xog"}.intrinsic()] = cardinal_plural_afrikaans;
796 r[iso_639{"so"}.intrinsic()] = cardinal_plural_afrikaans;
797 // South Ndebele, Southern Kurdish, Southern Sotho, Spanish, Swahili,
798 r[iso_639{"nr"}.intrinsic()] = cardinal_plural_afrikaans;
799 r[iso_639{"sdh"}.intrinsic()] = cardinal_plural_afrikaans;
800 r[iso_639{"st"}.intrinsic()] = cardinal_plural_afrikaans;
801 r[iso_639{"es"}.intrinsic()] = cardinal_plural_afrikaans;
802 r[iso_639{"sw"}.intrinsic()] = cardinal_plural_afrikaans;
803 // Swati, Swedish, Swiss German, Syriac, Tamil, Telugu, Teso, Tigre,
804 r[iso_639{"ss"}.intrinsic()] = cardinal_plural_afrikaans;
805 r[iso_639{"sv"}.intrinsic()] = cardinal_plural_afrikaans;
806 r[iso_639{"gsw"}.intrinsic()] = cardinal_plural_afrikaans;
807 r[iso_639{"syr"}.intrinsic()] = cardinal_plural_afrikaans;
808 r[iso_639{"ta"}.intrinsic()] = cardinal_plural_afrikaans;
809 r[iso_639{"te"}.intrinsic()] = cardinal_plural_afrikaans;
810 r[iso_639{"teo"}.intrinsic()] = cardinal_plural_afrikaans;
811 r[iso_639{"tig"}.intrinsic()] = cardinal_plural_afrikaans;
812 // Tsonga, Tswana, Turkish, Turkmen, Tyap, Urdu, Uyghur, Uzbek, Venda,
813 r[iso_639{"ts"}.intrinsic()] = cardinal_plural_afrikaans;
814 r[iso_639{"tn"}.intrinsic()] = cardinal_plural_afrikaans;
815 r[iso_639{"tr"}.intrinsic()] = cardinal_plural_afrikaans;
816 r[iso_639{"tk"}.intrinsic()] = cardinal_plural_afrikaans;
817 r[iso_639{"kcg"}.intrinsic()] = cardinal_plural_afrikaans;
818 r[iso_639{"ur"}.intrinsic()] = cardinal_plural_afrikaans;
819 r[iso_639{"ug"}.intrinsic()] = cardinal_plural_afrikaans;
820 r[iso_639{"uz"}.intrinsic()] = cardinal_plural_afrikaans;
821 r[iso_639{"ve"}.intrinsic()] = cardinal_plural_afrikaans;
822 // Volapük, Vunjo, Walser, Western Frisian, Xhosa, Yiddish
823 r[iso_639{"vo"}.intrinsic()] = cardinal_plural_afrikaans;
824 r[iso_639{"vun"}.intrinsic()] = cardinal_plural_afrikaans;
825 r[iso_639{"wae"}.intrinsic()] = cardinal_plural_afrikaans;
826 r[iso_639{"fy"}.intrinsic()] = cardinal_plural_afrikaans;
827 r[iso_639{"xh"}.intrinsic()] = cardinal_plural_afrikaans;
828 r[iso_639{"ji"}.intrinsic()] = cardinal_plural_afrikaans;
829 r[iso_639{"yi"}.intrinsic()] = cardinal_plural_afrikaans; // Yiddish twice.
830
831 // Latvian, Prussian
832 r[iso_639{"lv"}.intrinsic()] = cardinal_plural_latvian;
833 r[iso_639{"prg"}.intrinsic()] = cardinal_plural_latvian;
834
835 // Colognian, Langi
836 r[iso_639{"ksh"}.intrinsic()] = cardinal_plural_colognian;
837 r[iso_639{"lag"}.intrinsic()] = cardinal_plural_colognian;
838
839 // Inari Sami, Inuktitut, Lule Sami, Nama, Northern Sami,
840 r[iso_639{"smn"}.intrinsic()] = cardinal_plural_inari_sami;
841 r[iso_639{"iu"}.intrinsic()] = cardinal_plural_inari_sami;
842 r[iso_639{"smj"}.intrinsic()] = cardinal_plural_inari_sami;
843 r[iso_639{"naq"}.intrinsic()] = cardinal_plural_inari_sami;
844 r[iso_639{"se"}.intrinsic()] = cardinal_plural_inari_sami;
845 // Sami languages [Other], Skolt Sami, Southern Sami
846 r[iso_639{"smi"}.intrinsic()] = cardinal_plural_inari_sami;
847 r[iso_639{"sms"}.intrinsic()] = cardinal_plural_inari_sami;
848 r[iso_639{"sma"}.intrinsic()] = cardinal_plural_inari_sami;
849
850 // Belarusian, Russian, Ukrainian
851 r[iso_639{"be"}.intrinsic()] = cardinal_plural_belarusian;
852 r[iso_639{"ru"}.intrinsic()] = cardinal_plural_belarusian;
853 r[iso_639{"uk"}.intrinsic()] = cardinal_plural_belarusian;
854
855 // Polish
856 r[iso_639{"pl"}.intrinsic()] = cardinal_plural_polish;
857
858 // Lithuanian
859 r[iso_639{"lt"}.intrinsic()] = cardinal_plural_lithuanian;
860
861 // Bosnian, Croatian, Serbian, Serbo-Croatian
862 r[iso_639{"bs"}.intrinsic()] = cardinal_plural_bosnian;
863 r[iso_639{"hr"}.intrinsic()] = cardinal_plural_bosnian;
864 r[iso_639{"sr"}.intrinsic()] = cardinal_plural_bosnian;
865 r[iso_639{"sh"}.intrinsic()] = cardinal_plural_bosnian;
866
867 // Tachelhit
868 r[iso_639{"shi"}.intrinsic()] = cardinal_plural_tachelhit;
869
870 // Moldavian, Romanian
871 r[iso_639{"mo"}.intrinsic()] = cardinal_plural_moldavian;
872 r[iso_639{"ro"}.intrinsic()] = cardinal_plural_moldavian;
873
874 // Czech, Slovak
875 r[iso_639{"cs"}.intrinsic()] = cardinal_plural_czech;
876 r[iso_639{"sk"}.intrinsic()] = cardinal_plural_czech;
877
878 // Manx
879 r[iso_639{"gv"}.intrinsic()] = cardinal_plural_manx;
880
881 // Scottish Gaelic
882 r[iso_639{"gd"}.intrinsic()] = cardinal_plural_scottish_gaelic;
883
884 // Breton
885 r[iso_639{"br"}.intrinsic()] = cardinal_plural_breton;
886
887 // Lower Sorbian, Slovenian, Upper Sorbian
888 r[iso_639{"dsb"}.intrinsic()] = cardinal_plural_lower_sorbian;
889 r[iso_639{"sl"}.intrinsic()] = cardinal_plural_lower_sorbian;
890 r[iso_639{"hsb"}.intrinsic()] = cardinal_plural_lower_sorbian;
891
892 // Hebrew
893 r[iso_639{"he"}.intrinsic()] = cardinal_plural_hebrew;
894
895 // Maltese
896 r[iso_639{"mt"}.intrinsic()] = cardinal_plural_maltese;
897
898 // Irish
899 r[iso_639{"ga"}.intrinsic()] = cardinal_plural_irish;
900
901 // Arabic, Najdi Arabic
902 r[iso_639{"ar"}.intrinsic()] = cardinal_plural_arabic;
903 r[iso_639{"ars"}.intrinsic()] = cardinal_plural_arabic;
904
905 // Welsh
906 r[iso_639{"cy"}.intrinsic()] = cardinal_plural_welsh;
907
908 // Cornish
909 r[iso_639{"kw"}.intrinsic()] = cardinal_plural_cornish;
910
911 return r;
912}
913
914constexpr auto cardinal_plural_table = cardinal_plural_table_init();
915
916} // namespace detail
917
924[[nodiscard]] constexpr plurality cardinal_plural(language_tag language, std::integral auto n) noexcept
925{
926 if (language == language_tag{"pt-PT"}) {
927 // Portuguese in Portugal is different from Portuguese spoken in
928 // other regions.
929 return cardinal_plural_afrikaans(detail::plural_operand(n));
930 }
931
932 hilet language_index = language.region.intrinsic();
933 hi_axiom_bounds(language_index, detail::cardinal_plural_table);
934 return detail::cardinal_plural_table[language_index](detail::plural_operand(n));
935}
936
944[[nodiscard]] constexpr size_t cardinal_plural(language_tag language, std::integral auto n, size_t size) noexcept
945{
946 return cardinal_plural(language, n).index(size);
947}
948
949}} // namespace hi::v1
950
#define hi_axiom_bounds(x,...)
Specify an axiom that the value is within bounds.
Definition assert.hpp:264
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
plurality_value
The plurality value of a cardinal or ordinal number.
Definition unicode_plural.hpp:23
@ other
Any other number, every language will have at least this.
@ few
The number is part of few, and this means something in the current language.
@ many
The number is part of many, and this means something in the current language.
@ two
The number was two, and this means something in the current language.
@ zero
The number was zero, and this means something in the current language.
@ one
The number was one, and this means something in the current language.
plurality_mask
A mask of plurality values that this language supports.
Definition unicode_plural.hpp:51
@ other
Any other number, every language will have at least this.
@ few
The number is part of few, and this means something in the current language.
@ many
The number is part of many, and this means something in the current language.
@ two
The number was two, and this means something in the current language.
@ zero
The number was zero, and this means something in the current language.
@ one
The number was one, and this means something in the current language.
constexpr plurality cardinal_plural(language_tag language, std::integral auto n) noexcept
Get plural information of a number in a given language.
Definition unicode_plural.hpp:924
Plurality of a number.
Definition unicode_plural.hpp:86
constexpr size_t index(size_t n) const noexcept
Get an index to select between translations.
Definition unicode_plural.hpp:103
The operand for the unicode-plural rules.
Definition unicode_plural.hpp:125
uint8_t i
Number of digits in the value.
Definition unicode_plural.hpp:140
unsigned long long f
Visible fraction digits with trailing zeros.
Definition unicode_plural.hpp:132
uint8_t c
Compact decimal exponent value.
Definition unicode_plural.hpp:152
unsigned long long t
Visible fraction digits without trailing zeros.
Definition unicode_plural.hpp:136
uint8_t w
Number of visible fraction digits without trailing zeros.
Definition unicode_plural.hpp:148
uint8_t v
Number of visible fraction digits with trailing zeros.
Definition unicode_plural.hpp:144
unsigned long long n
Absolute value.
Definition unicode_plural.hpp:128