Files
datum/docs/bigint.md
Marco Cetica a02f2dff40
All checks were successful
clang-build / clang-build (push) Successful in 41s
gcc-build / gcc-build (push) Successful in 19s
Added Knuth's "Algorithm D" from TAOCP "Seminumerical algorithms"
2026-02-25 17:13:49 +01:00

94 lines
4.1 KiB
Markdown

# BigInt Technical Details
In this document you can find a quick overview of the technical
aspects (internal design, memory layout, etc.) of the `BigInt` data structure.
`BigInt` is a data type for arbitrary precision arithmetic that supports addition,
subtraction, multiplication, division and modulo operations on signed integers of unlimited size. Internally, it uses
the `Vector` data structure to represent big numbers using the following layout:
```
Number: 2485795518678991171206065
Internally: [ 171206065, 518678991, 2485795 ]
/ | \
/ | \
digit[0] digit[1] digit[2]
(LSB) (MSB)
```
That is, each element of the vector stores 9 digits in base $10^9$ using
**little-endian order**. Each such digits can therefore store values from `0` up to
`999,999,999`.
This scheme maps to the following structure:
```c
typedef struct {
vector_t *digits;
bool is_negative;
} bigint_t;
```
where the `digits` array stores the representation in base $10^9$ of the big integer
and the boolean `is_negative` variable denotes its sign.
The `BigInt` data structure supports the following methods:
- `bigint_result_t bigint_from_int(value)`: creates a big integer from a primitive `int` type;
- `bigint_result_t bigint_from_string(string_num)`: creates a big integer from a C string;
- `bigint_result_t bigint_to_string(number)`: converts a big integer to a C string;
- `bigint_result_t bigint_clone(number)`: clones a big integer;
- `bigint_result_t bigint_compare(x, y)`: compares two big integers, returning either `-1`, `0` or `1` if the first is less than, equal than or greater than the second, respectively;
- `bigint_result_t bigint_add(x, y)`: adds two big integers together in $\mathcal{O}(n)$;
- `bigint_result_t bigint_sub(x, y)`: subtracts two big integers in $\mathcal{O}(n)$;
- `bigint_result_t bigint_prod(x, y)`: multiplies two big integers using Karatsuba's algorithm in $\mathcal{O}(n^{1.585})$;
- `bigint_result_t bigint_divmod(x, y)`: divides two big integers using _Knuth's Algorithm D_ in $\mathcal{O}(n \times m)$ where $n$ and $m$ are the number of base-10^9
parts/limbs in the divisor and the quotient, respectively. This method returns both the quotient and the remainder;
- `bigint_result_t bigint_mod(x, y)`: calls `bigint_divmod`, discards the quotient and yields the remainder;
- `bigint_result_t bigint_destroy(number)`: deletes the big number;
- `bigint_result_t bigint_printf(format, ...)`: `printf` wrapper that introduces the `%B` placeholder to print big numbers. It supports variadic parameters.
As you can see from the previous function signatures, methods that operate on the
`BigInt` data type return a custom type called `bigint_result_t` which is defined as
follows:
```c
typedef enum {
BIGINT_OK = 0x0,
BIGINT_ERR_ALLOCATE,
BIGINT_ERR_DIV_BY_ZERO,
BIGINT_ERR_INVALID
} bigint_status_t;
typedef struct {
bigint_t *quotient;
bigint_t *remainder;
} div_result_t;
typedef struct {
bigint_status_t status;
uint8_t message[RESULT_MSG_SIZE];
union {
bigint_t *number;
div_result_t division;
int8_t compare_status;
char *string_num;
} value;
} bigint_result_t;
```
Each method that returns such type indicates whether the operation was successful or not
by setting the `status` field and by providing a descriptive message on the `message`
field. If the operation was successful (that is, `status == BIGINT_OK`), you can either
move on with the rest of the program or read the returned value from the sum data type.
Of course, you can choose to ignore the return value (if you're brave enough :D) as
illustrated on the first part of the README.
The sum data type (i.e., the `value` union) defines four different variables. Each
of them has an unique scope as described below:
- `number`: result of arithmetical, cloning and creating functions;
- `division`: result of `bigint_divmod`;
- `compare_status`: result of `bigint_compare`;
- `string_num`: result of `bigint_to_string`.