7#define INTEGER_EXTRACT(integer, length_variable, values_variable) \ 
    8    if ((integer)->values == NULL) { \ 
   10        values_variable = &(integer)->value; \ 
   12        length_variable = (integer)->length; \ 
   13        values_variable = (integer)->values; \ 
   23    uint32_t *left_values;
 
   24    INTEGER_EXTRACT(left, left_length, left_values)
 
   27    uint32_t *right_values;
 
   28    INTEGER_EXTRACT(right, right_length, right_values)
 
   30    size_t length = left_length < right_length ? right_length : left_length;
 
   31    uint32_t *values = (uint32_t *) 
xmalloc(
sizeof(uint32_t) * (length + 1));
 
   32    if (values == NULL) 
return;
 
   35    for (
size_t index = 0; index < length; index++) {
 
   36        uint64_t sum = carry + (index < left_length ? left_values[index] : 0) + (index < right_length ? right_values[index] : 0);
 
   37        values[index] = (uint32_t) (sum % base);
 
   42        values[length] = (uint32_t) carry;
 
   46    *destination = (
pm_integer_t) { length, values, 0, 
false };
 
   58    INTEGER_EXTRACT(a, a_length, a_values)
 
   62    INTEGER_EXTRACT(b, b_length, b_values)
 
   66    INTEGER_EXTRACT(c, c_length, c_values)
 
   68    uint32_t *values = (uint32_t*) 
xmalloc(
sizeof(uint32_t) * a_length);
 
   71    for (
size_t index = 0; index < a_length; index++) {
 
   75            (index < b_length ? b_values[index] : 0) -
 
   76            (index < c_length ? c_values[index] : 0)
 
   80            values[index] = (uint32_t) sub;
 
   83            sub += 2 * (int64_t) base;
 
   84            values[index] = (uint32_t) ((uint64_t) sub % base);
 
   85            carry = sub / (int64_t) base - 2;
 
   89    while (a_length > 1 && values[a_length - 1] == 0) a_length--;
 
   90    *destination = (
pm_integer_t) { a_length, values, 0, 
false };
 
  100    uint32_t *left_values;
 
  101    INTEGER_EXTRACT(left, left_length, left_values)
 
  104    uint32_t *right_values;
 
  105    INTEGER_EXTRACT(right, right_length, right_values)
 
  107    if (left_length > right_length) {
 
  108        size_t temporary_length = left_length;
 
  109        left_length = right_length;
 
  110        right_length = temporary_length;
 
  112        uint32_t *temporary_values = left_values;
 
  113        left_values = right_values;
 
  114        right_values = temporary_values;
 
  117    if (left_length <= 10) {
 
  118        size_t length = left_length + right_length;
 
  119        uint32_t *values = (uint32_t *) 
xcalloc(length, 
sizeof(uint32_t));
 
  120        if (values == NULL) 
return;
 
  122        for (
size_t left_index = 0; left_index < left_length; left_index++) {
 
  124            for (
size_t right_index = 0; right_index < right_length; right_index++) {
 
  125                uint64_t product = (uint64_t) left_values[left_index] * right_values[right_index] + values[left_index + right_index] + carry;
 
  126                values[left_index + right_index] = (uint32_t) (product % base);
 
  127                carry = (uint32_t) (product / base);
 
  129            values[left_index + right_length] = carry;
 
  132        while (length > 1 && values[length - 1] == 0) length--;
 
  133        *destination = (
pm_integer_t) { length, values, 0, 
false };
 
  137    if (left_length * 2 <= right_length) {
 
  138        uint32_t *values = (uint32_t *) 
xcalloc(left_length + right_length, 
sizeof(uint32_t));
 
  140        for (
size_t start_offset = 0; start_offset < right_length; start_offset += left_length) {
 
  141            size_t end_offset = start_offset + left_length;
 
  142            if (end_offset > right_length) end_offset = right_length;
 
  146                .values = left_values,
 
  152                .
length = end_offset - start_offset,
 
  153                .values = right_values + start_offset,
 
  159            karatsuba_multiply(&product, &sliced_left, &sliced_right, base);
 
  162            for (
size_t index = 0; index < product.
length; index++) {
 
  163                uint64_t sum = (uint64_t) values[start_offset + index] + product.
values[index] + carry;
 
  164                values[start_offset + index] = (uint32_t) (sum % base);
 
  165                carry = (uint32_t) (sum / base);
 
  168            if (carry > 0) values[start_offset + product.
length] += carry;
 
  172        *destination = (
pm_integer_t) { left_length + right_length, values, 0, 
false };
 
  176    size_t half = left_length / 2;
 
  178    pm_integer_t x1 = { left_length - half, left_values + half, 0, 
false };
 
  180    pm_integer_t y1 = { right_length - half, right_values + half, 0, 
false };
 
  183    karatsuba_multiply(&z0, &x0, &y0, base);
 
  186    karatsuba_multiply(&z2, &x1, &y1, base);
 
  191    big_add(&x01, &x0, &x1, base);
 
  194    big_add(&y01, &y0, &y1, base);
 
  197    karatsuba_multiply(&xy, &x01, &y01, base);
 
  200    big_sub2(&z1, &xy, &z0, &z2, base);
 
  202    size_t length = left_length + right_length;
 
  203    uint32_t *values = (uint32_t*) 
xcalloc(length, 
sizeof(uint32_t));
 
  205    assert(z0.
values != NULL);
 
  206    memcpy(values, z0.
values, 
sizeof(uint32_t) * z0.
length);
 
  208    assert(z2.
values != NULL);
 
  209    memcpy(values + 2 * half, z2.
values, 
sizeof(uint32_t) * z2.
length);
 
  212    for(
size_t index = 0; index < z1.
length; index++) {
 
  213        uint64_t sum = (uint64_t) carry + values[index + half] + z1.
values[index];
 
  214        values[index + half] = (uint32_t) (sum % base);
 
  215        carry = (uint32_t) (sum / base);
 
  218    for(
size_t index = half + z1.
length; carry > 0; index++) {
 
  219        uint64_t sum = (uint64_t) carry + values[index];
 
  220        values[index] = (uint32_t) (sum % base);
 
  221        carry = (uint32_t) (sum / base);
 
  224    while (length > 1 && values[length - 1] == 0) length--;
 
  232    *destination = (
pm_integer_t) { length, values, 0, 
false };
 
  242static const int8_t pm_integer_parse_digit_values[256] = {
 
  244    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  245    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  246    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  247     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, 
 
  248    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  249    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  0, 
 
  250    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  251    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  252    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  253    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  254    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  255    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  256    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  257    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  258    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  259    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
 
  266pm_integer_parse_digit(
const uint8_t character) {
 
  267    int8_t value = pm_integer_parse_digit_values[character];
 
  268    assert(value != -1 && 
"invalid digit");
 
  270    return (uint8_t) value;
 
  278pm_integer_from_uint64(
pm_integer_t *integer, uint64_t value, uint64_t base) {
 
  280        integer->
value = (uint32_t) value;
 
  285    uint64_t length_value = value;
 
  286    while (length_value > 0) {
 
  288        length_value /= base;
 
  291    uint32_t *values = (uint32_t *) 
xmalloc(
sizeof(uint32_t) * length);
 
  292    if (values == NULL) 
return;
 
  294    for (
size_t value_index = 0; value_index < length; value_index++) {
 
  295        values[value_index] = (uint32_t) (value % base);
 
  310    if (integer->
values == NULL) {
 
  318    if (integer->
length > 1) {
 
  322    uint32_t value = integer->
values[0];
 
  323    bool negative = integer->
negative && value != 0;
 
  326    *integer = (
pm_integer_t) { .
values = NULL, .value = value, .length = 0, .negative = negative };
 
  334pm_integer_convert_base(
pm_integer_t *destination, 
const pm_integer_t *source, uint64_t base_from, uint64_t base_to) {
 
  335    size_t source_length;
 
  336    const uint32_t *source_values;
 
  337    INTEGER_EXTRACT(source, source_length, source_values)
 
  339    size_t bigints_length = (source_length + 1) / 2;
 
  340    assert(bigints_length > 0);
 
  343    if (bigints == NULL) 
return;
 
  345    for (
size_t index = 0; index < source_length; index += 2) {
 
  346        uint64_t value = source_values[index] + base_from * (index + 1 < source_length ? source_values[index + 1] : 0);
 
  347        pm_integer_from_uint64(&bigints[index / 2], value, base_to);
 
  351    pm_integer_from_uint64(&base, base_from, base_to);
 
  353    while (bigints_length > 1) {
 
  355        karatsuba_multiply(&next_base, &base, &base, base_to);
 
  360        size_t next_length = (bigints_length + 1) / 2;
 
  363        for (
size_t bigints_index = 0; bigints_index < bigints_length; bigints_index += 2) {
 
  364            if (bigints_index + 1 == bigints_length) {
 
  365                next_bigints[bigints_index / 2] = bigints[bigints_index];
 
  368                karatsuba_multiply(&multiplied, &base, &bigints[bigints_index + 1], base_to);
 
  370                big_add(&next_bigints[bigints_index / 2], &bigints[bigints_index], &multiplied, base_to);
 
  378        bigints = next_bigints;
 
  379        bigints_length = next_length;
 
  382    *destination = bigints[0];
 
  384    pm_integer_normalize(destination);
 
  390#undef INTEGER_EXTRACT 
  396pm_integer_parse_powof2(
pm_integer_t *integer, uint32_t base, 
const uint8_t *digits, 
size_t digits_length) {
 
  398    while (base > (uint32_t) (1 << bit)) bit++;
 
  400    size_t length = (digits_length * bit + 31) / 32;
 
  401    uint32_t *values = (uint32_t *) 
xcalloc(length, 
sizeof(uint32_t));
 
  403    for (
size_t digit_index = 0; digit_index < digits_length; digit_index++) {
 
  404        size_t bit_position = bit * (digits_length - digit_index - 1);
 
  405        uint32_t value = digits[digit_index];
 
  407        size_t index = bit_position / 32;
 
  408        size_t shift = bit_position % 32;
 
  410        values[index] |= value << shift;
 
  411        if (32 - shift < bit) values[index + 1] |= value >> (32 - shift);
 
  414    while (length > 1 && values[length - 1] == 0) length--;
 
  415    *integer = (
pm_integer_t) { .
length = length, .values = values, .value = 0, .negative = 
false };
 
  416    pm_integer_normalize(integer);
 
  423pm_integer_parse_decimal(
pm_integer_t *integer, 
const uint8_t *digits, 
size_t digits_length) {
 
  424    const size_t batch = 9;
 
  425    size_t length = (digits_length + batch - 1) / batch;
 
  427    uint32_t *values = (uint32_t *) 
xcalloc(length, 
sizeof(uint32_t));
 
  430    for (
size_t digits_index = 0; digits_index < digits_length; digits_index++) {
 
  431        value = value * 10 + digits[digits_index];
 
  433        size_t reverse_index = digits_length - digits_index - 1;
 
  434        if (reverse_index % batch == 0) {
 
  435            values[reverse_index / batch] = value;
 
  441    pm_integer_convert_base(integer, &((
pm_integer_t) { .length = length, .values = values,  .value = 0, .negative = 
false }), 1000000000, ((uint64_t) 1 << 32));
 
  449pm_integer_parse_big(
pm_integer_t *integer, uint32_t multiplier, 
const uint8_t *start, 
const uint8_t *end) {
 
  451    uint8_t *digits = 
xmalloc(
sizeof(uint8_t) * (
size_t) (end - start));
 
  452    size_t digits_length = 0;
 
  454    for (; start < end; start++) {
 
  455        if (*start == 
'_') 
continue;
 
  456        digits[digits_length++] = pm_integer_parse_digit(*start);
 
  460    if (multiplier == 10) {
 
  461        pm_integer_parse_decimal(integer, digits, digits_length);
 
  463        pm_integer_parse_powof2(integer, multiplier, digits, digits_length);
 
  478    if (*start == 
'+') start++;
 
  481    uint32_t multiplier = 10;
 
  484            while (*start == 
'0') start++; 
 
  492            if (*start == 
'_' || *start == 
'o' || *start == 
'O') start++; 
 
  496            if (*start == 
'0' && (end - start) > 1) start += 2; 
 
  503            if (*start == 
'0' && (end - start) > 1) {
 
  505                    case '_': start += 2; multiplier = 8; 
break;
 
  506                    case '0': 
case '1': 
case '2': 
case '3': 
case '4': 
case '5': 
case '6': 
case '7': start++; multiplier = 8; 
break;
 
  507                    case 'b': 
case 'B': start += 2; multiplier = 2; 
break;
 
  508                    case 'o': 
case 'O': start += 2; multiplier = 8; 
break;
 
  509                    case 'd': 
case 'D': start += 2; 
break;
 
  510                    case 'x': 
case 'X': start += 2; multiplier = 16; 
break;
 
  511                    default: assert(
false && 
"unreachable"); 
break;
 
  519    if (start >= end) 
return;
 
  521    const uint8_t *cursor = start;
 
  522    uint64_t value = (uint64_t) pm_integer_parse_digit(*cursor++);
 
  524    for (; cursor < end; cursor++) {
 
  525        if (*cursor == 
'_') 
continue;
 
  526        value = value * multiplier + (uint64_t) pm_integer_parse_digit(*cursor);
 
  528        if (value > UINT32_MAX) {
 
  531            pm_integer_parse_big(integer, multiplier, start, end);
 
  536    integer->
value = (uint32_t) value;
 
 
  547    int negative = left->
negative ? -1 : 1;
 
  550        if (left->
value < right->
value) 
return -1 * negative;
 
  551        if (left->
value > right->
value) 
return 1 * negative;
 
  558    for (
size_t index = 0; index < left->
length; index++) {
 
  559        size_t value_index = left->
length - index - 1;
 
  560        uint32_t left_value = left->
values[value_index];
 
  561        uint32_t right_value = right->
values[value_index];
 
  563        if (left_value < right_value) 
return -1 * negative;
 
  564        if (left_value > right_value) 
return 1 * negative;
 
 
  581        denominator->
length != 0 ||
 
  583        numerator->
value == 0 ||
 
  585        denominator->
value == 1
 
  589    uint32_t divisor = numerator->
value;
 
  590    uint32_t remainder = denominator->
value;
 
  592    while (remainder != 0) {
 
  593        uint32_t temporary = remainder;
 
  594        remainder = divisor % remainder;
 
  599    numerator->
value /= divisor;
 
  600    denominator->
value /= divisor;
 
 
  609        pm_buffer_append_byte(buffer, 
'-');
 
  614    if (integer->
values == NULL) {
 
  615        pm_buffer_append_format(buffer, 
"%" PRIu32, integer->
value);
 
  621    if (integer->
length == 2) {
 
  622        const uint64_t value = ((uint64_t) integer->
values[0]) | ((uint64_t) integer->
values[1] << 32);
 
  623        pm_buffer_append_format(buffer, 
"%" PRIu64, value);
 
  629    pm_integer_convert_base(&converted, integer, (uint64_t) 1 << 32, 1000000000);
 
  631    if (converted.
values == NULL) {
 
  632        pm_buffer_append_format(buffer, 
"%" PRIu32, converted.
value);
 
  638    size_t digits_length = converted.
length * 9;
 
  639    char *digits = 
xcalloc(digits_length, 
sizeof(
char));
 
  640    if (digits == NULL) 
return;
 
  643    for (
size_t value_index = 0; value_index < converted.
length; value_index++) {
 
  644        uint32_t value = converted.
values[value_index];
 
  646        for (
size_t digit_index = 0; digit_index < 9; digit_index++) {
 
  647            digits[digits_length - 9 * value_index - digit_index - 1] = (char) (
'0' + value % 10);
 
  652    size_t start_offset = 0;
 
  653    while (start_offset < digits_length - 1 && digits[start_offset] == 
'0') start_offset++;
 
  656    pm_buffer_append_string(buffer, digits + start_offset, digits_length - start_offset);
 
 
#define xfree
Old name of ruby_xfree.
#define xmalloc
Old name of ruby_xmalloc.
#define xcalloc
Old name of ruby_xcalloc.
PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer)
Free the internal memory of an integer.
PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer)
Convert an integer to a decimal string.
This module provides functions for working with arbitrary-sized integers.
pm_integer_base_t
An enum controlling the base of an integer.
@ PM_INTEGER_BASE_DEFAULT
The default decimal base, with no prefix.
@ PM_INTEGER_BASE_BINARY
The binary base, indicated by a 0b or 0B prefix.
@ PM_INTEGER_BASE_DECIMAL
The decimal base, indicated by a 0d, 0D, or empty prefix.
@ PM_INTEGER_BASE_HEXADECIMAL
The hexadecimal base, indicated by a 0x or 0X prefix.
@ PM_INTEGER_BASE_OCTAL
The octal base, indicated by a 0, 0o, or 0O prefix.
@ PM_INTEGER_BASE_UNKNOWN
An unknown base, in which case pm_integer_parse will derive it based on the content of the string.
#define PRISM_EXPORTED_FUNCTION
By default, we compile with -fvisibility=hidden.
A pm_buffer_t is a simple memory buffer that stores data in a contiguous block of memory.
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.