66namespace cp_algo ::math {
77 enum base_v {
88 x10 = uint64_t (1e18 ),
9- x16 = 0
9+ x16 = uint64_t ( 0 )
1010 };
1111 template <base_v base = x10>
1212 struct bigint {
@@ -46,6 +46,13 @@ namespace cp_algo::math {
4646 d_ptr[i] -= o_ptr[i] + carry;
4747 carry = d_ptr[i] >= base;
4848 d_ptr[i] += carry ? uint64_t (base) : 0 ;
49+ } else if constexpr (base == x16) {
50+ auto sub = o_ptr[i] + carry;
51+ auto new_carry = sub ? (d_ptr[i] < sub) : carry;
52+ d_ptr[i] -= sub;
53+ carry = new_carry;
54+ } else {
55+ static_assert (base == x10 || base == x16, " Unsupported base" );
4956 }
5057 }
5158 if (carry) {
@@ -80,11 +87,18 @@ namespace cp_algo::math {
8087 d_ptr[i] += o_ptr[i] + carry;
8188 carry = d_ptr[i] >= base;
8289 d_ptr[i] -= carry ? uint64_t (base) : 0 ;
90+ } else if constexpr (base == x16) {
91+ auto add = o_ptr[i] + carry;
92+ auto new_carry = add ? (d_ptr[i] >= -add) : carry;
93+ d_ptr[i] += add;
94+ carry = new_carry;
95+ } else {
96+ static_assert (base == x10 || base == x16, " Unsupported base" );
8397 }
8498 }
8599 if (carry) {
86100 N = size (digits);
87- for (; i < N && d_ptr[i] == base - 1 ; i++) {
101+ for (; i < N && d_ptr[i] == uint64_t ( base) - 1 ; i++) {
88102 d_ptr[i] = 0 ;
89103 }
90104 if (i < N) {
@@ -104,10 +118,10 @@ namespace cp_algo::math {
104118 size_t len = size (s);
105119 assert (len > 0 );
106120 constexpr auto digit_length = base == x10 ? 18 : base == x16 ? 16 : 0 ;
121+ constexpr auto sub_base = base == x10 ? 10 : base == x16 ? 16 : 0 ;
107122 size_t num_digits = (len + digit_length - 1 ) / digit_length;
108123 digits.resize (num_digits);
109124 size_t i = len;
110- constexpr auto sub_base = base == x10 ? 10 : base == x16 ? 16 : 0 ;
111125 for (size_t j = 0 ; j < num_digits - 1 ; j++) {
112126 std::from_chars (s.data () + i - digit_length, s.data () + i, digits[j], sub_base);
113127 i -= digit_length;
@@ -140,11 +154,28 @@ namespace cp_algo::math {
140154 if (empty (x.digits )) {
141155 return out << ' 0' ;
142156 }
143- if constexpr (base == x10) {
144- out << x.digits .back ();
145- for (auto d: x.digits | std::views::reverse | std::views::drop (1 )) {
146- out << std::string (18 - size (std::to_string (d)), ' 0' ) << d;
157+ constexpr auto digit_length = base == x10 ? 18 : base == x16 ? 16 : 0 ;
158+ constexpr auto sub_base = base == x10 ? 10 : base == x16 ? 16 : 0 ;
159+ char buf[20 ];
160+ auto [ptr, ec] = std::to_chars (buf, buf + sizeof (buf), x.digits .back (), sub_base);
161+ if constexpr (base == x16) {
162+ for (char * p = buf; p != ptr; ++p) {
163+ *p = (char )std::toupper (*p);
164+ }
165+ }
166+ buf[ptr - buf] = 0 ;
167+ out << buf;
168+ for (auto d: x.digits | std::views::reverse | std::views::drop (1 )) {
169+ auto [ptr, ec] = std::to_chars (buf, buf + sizeof (buf), d, sub_base);
170+ if constexpr (base == x16) {
171+ for (char * p = buf; p != ptr; ++p) {
172+ *p = (char )std::toupper (*p);
173+ }
147174 }
175+ auto len = ptr - buf;
176+ out << std::string (digit_length - len, ' 0' );
177+ buf[len] = 0 ;
178+ out << buf;
148179 }
149180 return out;
150181 }
0 commit comments