1#include "prism/internal/integer.h"
3#include "prism/internal/allocator.h"
4#include "prism/internal/buffer.h"
28#define INTEGER_EXTRACT(integer, length_variable, values_variable) \
29 if ((integer)->values == NULL) { \
30 length_variable = 1; \
31 values_variable = &(integer)->value; \
33 length_variable = (integer)->length; \
34 values_variable = (integer)->values; \
44 uint32_t *left_values;
45 INTEGER_EXTRACT(left, left_length, left_values)
48 uint32_t *right_values;
49 INTEGER_EXTRACT(right, right_length, right_values)
51 size_t length = left_length < right_length ? right_length : left_length;
52 uint32_t *values = (uint32_t *)
xmalloc(
sizeof(uint32_t) * (length + 1));
53 if (values == NULL)
return;
56 for (
size_t index = 0; index < length; index++) {
57 uint64_t sum = carry + (index < left_length ? left_values[index] : 0) + (index < right_length ? right_values[index] : 0);
58 values[index] = (uint32_t) (sum % base);
63 values[length] = (uint32_t) carry;
67 *destination = (
pm_integer_t) { length, values, 0,
false };
79 INTEGER_EXTRACT(a, a_length, a_values)
83 INTEGER_EXTRACT(b, b_length, b_values)
87 INTEGER_EXTRACT(c, c_length, c_values)
89 uint32_t *values = (uint32_t*)
xmalloc(
sizeof(uint32_t) * a_length);
92 for (
size_t index = 0; index < a_length; index++) {
96 (index < b_length ? b_values[index] : 0) -
97 (index < c_length ? c_values[index] : 0)
101 values[index] = (uint32_t) sub;
104 sub += 2 * (int64_t) base;
105 values[index] = (uint32_t) ((uint64_t) sub % base);
106 carry = sub / (int64_t) base - 2;
110 while (a_length > 1 && values[a_length - 1] == 0) a_length--;
111 *destination = (
pm_integer_t) { a_length, values, 0,
false };
121 uint32_t *left_values;
122 INTEGER_EXTRACT(left, left_length, left_values)
125 uint32_t *right_values;
126 INTEGER_EXTRACT(right, right_length, right_values)
128 if (left_length > right_length) {
129 size_t temporary_length = left_length;
130 left_length = right_length;
131 right_length = temporary_length;
133 uint32_t *temporary_values = left_values;
134 left_values = right_values;
135 right_values = temporary_values;
138 if (left_length <= 10) {
139 size_t length = left_length + right_length;
140 uint32_t *values = (uint32_t *)
xcalloc(length,
sizeof(uint32_t));
141 if (values == NULL)
return;
143 for (
size_t left_index = 0; left_index < left_length; left_index++) {
145 for (
size_t right_index = 0; right_index < right_length; right_index++) {
146 uint64_t product = (uint64_t) left_values[left_index] * right_values[right_index] + values[left_index + right_index] + carry;
147 values[left_index + right_index] = (uint32_t) (product % base);
148 carry = (uint32_t) (product / base);
150 values[left_index + right_length] = carry;
153 while (length > 1 && values[length - 1] == 0) length--;
154 *destination = (
pm_integer_t) { length, values, 0,
false };
158 if (left_length * 2 <= right_length) {
159 uint32_t *values = (uint32_t *)
xcalloc(left_length + right_length,
sizeof(uint32_t));
161 for (
size_t start_offset = 0; start_offset < right_length; start_offset += left_length) {
162 size_t end_offset = start_offset + left_length;
163 if (end_offset > right_length) end_offset = right_length;
167 .values = left_values,
173 .
length = end_offset - start_offset,
174 .values = right_values + start_offset,
180 karatsuba_multiply(&product, &sliced_left, &sliced_right, base);
183 for (
size_t index = 0; index < product.
length; index++) {
184 uint64_t sum = (uint64_t) values[start_offset + index] + product.
values[index] + carry;
185 values[start_offset + index] = (uint32_t) (sum % base);
186 carry = (uint32_t) (sum / base);
189 if (carry > 0) values[start_offset + product.
length] += carry;
190 pm_integer_free(&product);
193 *destination = (
pm_integer_t) { left_length + right_length, values, 0,
false };
197 size_t half = left_length / 2;
199 pm_integer_t x1 = { left_length - half, left_values + half, 0,
false };
201 pm_integer_t y1 = { right_length - half, right_values + half, 0,
false };
204 karatsuba_multiply(&z0, &x0, &y0, base);
207 karatsuba_multiply(&z2, &x1, &y1, base);
212 big_add(&x01, &x0, &x1, base);
215 big_add(&y01, &y0, &y1, base);
218 karatsuba_multiply(&xy, &x01, &y01, base);
221 big_sub2(&z1, &xy, &z0, &z2, base);
223 size_t length = left_length + right_length;
224 uint32_t *values = (uint32_t*)
xcalloc(length,
sizeof(uint32_t));
226 assert(z0.
values != NULL);
227 memcpy(values, z0.
values,
sizeof(uint32_t) * z0.
length);
229 assert(z2.
values != NULL);
230 memcpy(values + 2 * half, z2.
values,
sizeof(uint32_t) * z2.
length);
233 for(
size_t index = 0; index < z1.
length; index++) {
234 uint64_t sum = (uint64_t) carry + values[index + half] + z1.
values[index];
235 values[index + half] = (uint32_t) (sum % base);
236 carry = (uint32_t) (sum / base);
239 for(
size_t index = half + z1.
length; carry > 0; index++) {
240 uint64_t sum = (uint64_t) carry + values[index];
241 values[index] = (uint32_t) (sum % base);
242 carry = (uint32_t) (sum / base);
245 while (length > 1 && values[length - 1] == 0) length--;
246 pm_integer_free(&z0);
247 pm_integer_free(&z1);
248 pm_integer_free(&z2);
249 pm_integer_free(&x01);
250 pm_integer_free(&y01);
251 pm_integer_free(&xy);
253 *destination = (
pm_integer_t) { length, values, 0,
false };
263static const int8_t pm_integer_parse_digit_values[256] = {
265 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
266 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
267 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
268 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
269 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
270 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
271 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
272 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
275 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
276 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
277 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
278 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
279 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
280 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
287pm_integer_parse_digit(
const uint8_t character) {
288 int8_t value = pm_integer_parse_digit_values[character];
289 assert(value != -1 &&
"invalid digit");
291 return (uint8_t) value;
299pm_integer_from_uint64(
pm_integer_t *integer, uint64_t value, uint64_t base) {
301 integer->
value = (uint32_t) value;
306 uint64_t length_value = value;
307 while (length_value > 0) {
309 length_value /= base;
312 uint32_t *values = (uint32_t *)
xmalloc(
sizeof(uint32_t) * length);
313 if (values == NULL)
return;
315 for (
size_t value_index = 0; value_index < length; value_index++) {
316 values[value_index] = (uint32_t) (value % base);
331 if (integer->
values == NULL) {
339 if (integer->
length > 1) {
343 uint32_t value = integer->
values[0];
344 bool negative = integer->
negative && value != 0;
346 pm_integer_free(integer);
347 *integer = (
pm_integer_t) { .
values = NULL, .value = value, .length = 0, .negative = negative };
355pm_integer_convert_base(
pm_integer_t *destination,
const pm_integer_t *source, uint64_t base_from, uint64_t base_to) {
356 size_t source_length;
357 const uint32_t *source_values;
358 INTEGER_EXTRACT(source, source_length, source_values)
360 size_t bigints_length = (source_length + 1) / 2;
361 assert(bigints_length > 0);
364 if (bigints == NULL)
return;
366 for (
size_t index = 0; index < source_length; index += 2) {
367 uint64_t value = source_values[index] + base_from * (index + 1 < source_length ? source_values[index + 1] : 0);
368 pm_integer_from_uint64(&bigints[index / 2], value, base_to);
372 pm_integer_from_uint64(&base, base_from, base_to);
374 while (bigints_length > 1) {
376 karatsuba_multiply(&next_base, &base, &base, base_to);
378 pm_integer_free(&base);
381 size_t next_length = (bigints_length + 1) / 2;
384 for (
size_t bigints_index = 0; bigints_index < bigints_length; bigints_index += 2) {
385 if (bigints_index + 1 == bigints_length) {
386 next_bigints[bigints_index / 2] = bigints[bigints_index];
389 karatsuba_multiply(&multiplied, &base, &bigints[bigints_index + 1], base_to);
391 big_add(&next_bigints[bigints_index / 2], &bigints[bigints_index], &multiplied, base_to);
392 pm_integer_free(&bigints[bigints_index]);
393 pm_integer_free(&bigints[bigints_index + 1]);
394 pm_integer_free(&multiplied);
398 xfree_sized(bigints, bigints_length *
sizeof(
pm_integer_t));
399 bigints = next_bigints;
400 bigints_length = next_length;
403 *destination = bigints[0];
405 pm_integer_normalize(destination);
407 xfree_sized(bigints, bigints_length *
sizeof(
pm_integer_t));
408 pm_integer_free(&base);
411#undef INTEGER_EXTRACT
417pm_integer_parse_powof2(
pm_integer_t *integer, uint32_t base,
const uint8_t *digits,
size_t digits_length) {
419 while (base > (uint32_t) (1 << bit)) bit++;
421 size_t length = (digits_length * bit + 31) / 32;
422 uint32_t *values = (uint32_t *)
xcalloc(length,
sizeof(uint32_t));
424 for (
size_t digit_index = 0; digit_index < digits_length; digit_index++) {
425 size_t bit_position = bit * (digits_length - digit_index - 1);
426 uint32_t value = digits[digit_index];
428 size_t index = bit_position / 32;
429 size_t shift = bit_position % 32;
431 values[index] |= value << shift;
432 if (32 - shift < bit) values[index + 1] |= value >> (32 - shift);
435 while (length > 1 && values[length - 1] == 0) length--;
436 *integer = (
pm_integer_t) { .
length = length, .values = values, .value = 0, .negative =
false };
437 pm_integer_normalize(integer);
444pm_integer_parse_decimal(
pm_integer_t *integer,
const uint8_t *digits,
size_t digits_length) {
445 const size_t batch = 9;
446 const size_t length = (digits_length + batch - 1) / batch;
448 uint32_t *values = (uint32_t *)
xcalloc(length,
sizeof(uint32_t));
451 for (
size_t digits_index = 0; digits_index < digits_length; digits_index++) {
452 value = value * 10 + digits[digits_index];
454 size_t reverse_index = digits_length - digits_index - 1;
455 if (reverse_index % batch == 0) {
456 values[reverse_index / batch] = value;
462 pm_integer_convert_base(integer, &((
pm_integer_t) { .length = length, .values = values, .value = 0, .negative =
false }), 1000000000, ((uint64_t) 1 << 32));
463 xfree_sized(values, length *
sizeof(uint32_t));
470pm_integer_parse_big(
pm_integer_t *integer, uint32_t multiplier,
const uint8_t *start,
const uint8_t *end) {
472 const size_t digits_capa =
sizeof(uint8_t) * (
size_t) (end - start);
473 uint8_t *digits =
xmalloc(digits_capa);
474 size_t digits_length = 0;
476 for (; start < end; start++) {
477 if (*start ==
'_')
continue;
478 digits[digits_length++] = pm_integer_parse_digit(*start);
482 if (multiplier == 10) {
483 pm_integer_parse_decimal(integer, digits, digits_length);
485 pm_integer_parse_powof2(integer, multiplier, digits, digits_length);
488 xfree_sized(digits, digits_capa);
497pm_integer_parse(
pm_integer_t *integer, pm_integer_base_t base,
const uint8_t *start,
const uint8_t *end) {
500 if (*start ==
'+') start++;
503 uint32_t multiplier = 10;
505 case PM_INTEGER_BASE_DEFAULT:
506 while (start < end && *start ==
'0') start++;
508 case PM_INTEGER_BASE_BINARY:
512 case PM_INTEGER_BASE_OCTAL:
514 if (*start ==
'_' || *start ==
'o' || *start ==
'O') start++;
517 case PM_INTEGER_BASE_DECIMAL:
518 if (*start ==
'0' && (end - start) > 1) start += 2;
520 case PM_INTEGER_BASE_HEXADECIMAL:
524 case PM_INTEGER_BASE_UNKNOWN:
525 if (*start ==
'0' && (end - start) > 1) {
527 case '_': start += 2; multiplier = 8;
break;
528 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': start++; multiplier = 8;
break;
529 case 'b':
case 'B': start += 2; multiplier = 2;
break;
530 case 'o':
case 'O': start += 2; multiplier = 8;
break;
531 case 'd':
case 'D': start += 2;
break;
532 case 'x':
case 'X': start += 2; multiplier = 16;
break;
533 default: assert(
false &&
"unreachable");
break;
541 if (start >= end)
return;
543 const uint8_t *cursor = start;
544 uint64_t value = (uint64_t) pm_integer_parse_digit(*cursor++);
546 for (; cursor < end; cursor++) {
547 if (*cursor ==
'_')
continue;
548 value = value * multiplier + (uint64_t) pm_integer_parse_digit(*cursor);
550 if (value > UINT32_MAX) {
553 pm_integer_parse_big(integer, multiplier, start, end);
558 integer->
value = (uint32_t) value;
569 int negative = left->
negative ? -1 : 1;
572 if (left->
value < right->
value)
return -1 * negative;
573 if (left->
value > right->
value)
return 1 * negative;
580 for (
size_t index = 0; index < left->
length; index++) {
581 size_t value_index = left->
length - index - 1;
582 uint32_t left_value = left->
values[value_index];
583 uint32_t right_value = right->
values[value_index];
585 if (left_value < right_value)
return -1 * negative;
586 if (left_value > right_value)
return 1 * negative;
603 denominator->
length != 0 ||
605 numerator->
value == 0 ||
607 denominator->
value == 1
611 uint32_t divisor = numerator->
value;
612 uint32_t remainder = denominator->
value;
614 while (remainder != 0) {
615 uint32_t temporary = remainder;
616 remainder = divisor % remainder;
621 numerator->
value /= divisor;
622 denominator->
value /= divisor;
631 pm_buffer_append_byte(buffer,
'-');
636 if (integer->
values == NULL) {
637 pm_buffer_append_format(buffer,
"%" PRIu32, integer->
value);
643 if (integer->
length == 2) {
644 const uint64_t value = ((uint64_t) integer->
values[0]) | ((uint64_t) integer->
values[1] << 32);
645 pm_buffer_append_format(buffer,
"%" PRIu64, value);
651 pm_integer_convert_base(&converted, integer, (uint64_t) 1 << 32, 1000000000);
653 if (converted.
values == NULL) {
654 pm_buffer_append_format(buffer,
"%" PRIu32, converted.
value);
655 pm_integer_free(&converted);
660 const size_t digits_length = converted.
length * 9;
661 char *digits =
xcalloc(digits_length,
sizeof(
char));
662 if (digits == NULL)
return;
665 for (
size_t value_index = 0; value_index < converted.
length; value_index++) {
666 uint32_t value = converted.
values[value_index];
668 for (
size_t digit_index = 0; digit_index < 9; digit_index++) {
669 digits[digits_length - 9 * value_index - digit_index - 1] = (char) (
'0' + value % 10);
674 size_t start_offset = 0;
675 while (start_offset < digits_length - 1 && digits[start_offset] ==
'0') start_offset++;
678 pm_buffer_append_string(buffer, digits + start_offset, digits_length - start_offset);
679 xfree_sized(digits,
sizeof(
char) * digits_length);
680 pm_integer_free(&converted);
#define xfree
Old name of ruby_xfree.
#define xmalloc
Old name of ruby_xmalloc.
#define xcalloc
Old name of ruby_xcalloc.
A structure represents an arbitrary-sized integer.
size_t length
The number of allocated values.
uint32_t value
Embedded value for small integer.
uint32_t * values
List of 32-bit integers.
bool negative
Whether or not the integer is negative.