typedef struct big_integer {
uint64_t* data;
size_t data_length;
} big_integer;
static size_t DIGITS_PER_UINT64 = 18;
static uint64_t MODULO = 1000000000000000000L;
big_integer* big_integer_create(const char* number_text)
{
size_t integer_text_length = strlen(number_text);
size_t data_length = integer_text_length / DIGITS_PER_UINT64 +
(integer_text_length % DIGITS_PER_UINT64 != 0 ? 1 : 0);
uint64_t* data = calloc(data_length, sizeof(uint64_t));
size_t chars_loaded = 0;
size_t data_index = 0;
uint64_t sum = 0;
uint64_t factor = 1;
for (int i = integer_text_length - 1; i >= 0; --i)
{
const char character = number_text[i];
sum += factor * (character - '0');
factor *= 10;
if (++chars_loaded % DIGITS_PER_UINT64 == 0)
{
data[data_index++] = sum;
sum = 0;
factor = 1;
}
}
if (chars_loaded % DIGITS_PER_UINT64 != 0)
{
data[data_index] = sum;
}
big_integer* result = malloc(sizeof *result);
result->data = data;
result->data_length = data_length;
return result;
}
void big_integer_free(big_integer* big_int)
{
free(big_int->data);
free(big_int);
}
void big_integer_print(big_integer* big_int, FILE* file)
{
int start_index = (int) big_int->data_length - 1;
if (big_int->data[start_index] == 0)
{
--start_index;
if (start_index >= 0)
{
fprintf(file, "%llu", big_int->data[start_index]);
}
for (int i = start_index - 1; i >= 0; --i)
{
fprintf(file, "%018llu", big_int->data[i]);
}
}
else
{
fprintf(file, "%llu", big_int->data[start_index--]);
for (int i = start_index; i >= 0; --i)
{
fprintf(file, "%018llu", big_int->data[i]);
}
}
}
big_integer* big_integer_copy(big_integer* big_int)
{
big_integer* ret = malloc(sizeof *ret);
uint64_t* data = malloc(big_int->data_length * sizeof(uint64_t));
ret->data_length = big_int->data_length;
ret->data = data;
memcpy(data, big_int->data, big_int->data_length * sizeof(uint64_t));
return ret;
}
big_integer* big_integer_add(big_integer* a, big_integer* b)
{
size_t a_length = a->data_length;
size_t b_length = b->data_length;
size_t data_length = MAX(a_length, b_length) + 1;
uint64_t* data = calloc(data_length, sizeof(uint64_t));
size_t end_index = MIN(a_length, b_length);
int index = 0;
uint64_t carry = 0;
big_integer* result = malloc(sizeof *result);
while (index != end_index)
{
uint64_t tmp = a->data[index] + b->data[index] + carry;
if (tmp >= MODULO)
{
carry = 1;
data[index] = tmp % MODULO;
}
else
{
carry = 0;
data[index] = tmp;
}
++index;
}
while (index < a_length)
{
uint64_t tmp = a->data[index] + carry;
if (tmp >= MODULO)
{
carry = 1;
data[index++] = tmp % MODULO;
}
else
{
carry = 0;
data[index++] = tmp;
}
}
while (index < b_length)
{
uint64_t tmp = b->data[index] + carry;
if (tmp >= MODULO)
{
carry = 1;
data[index++] = tmp % MODULO;
}
else
{
carry = 0;
data[index++] = tmp;
}
}
if (carry > 0) {
data[data_length - 1] = 1;
}
result->data = data;
result->data_length = data_length;
return result;
}
If I count creation and freeing the big integers, your program is faster by the factor of 2. HoweverNow, when I measured onlyrun my demo program (see the addition operationsGist above) with -O3 optimization flag, I got following figures:get something like
time elapsed: 21.34501515, total time: 1.4847 coderodde time: 0.27092157, total time: 1.2360
Note I have updated the code once again in the linked gist. Make sure you are up-to-date.