Merge pull request #1 from ceticamarco/bignum_experimental
Adding BigInt support
This commit is contained in:
19
.github/workflows/clang-build.yml
vendored
Normal file
19
.github/workflows/clang-build.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: clang-build
|
||||||
|
on: [push,pull_request,workflow_dispatch]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clang-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Clang
|
||||||
|
run: sudo apt update && sudo apt install -y clang
|
||||||
|
|
||||||
|
- name: Build Datum
|
||||||
|
run: |
|
||||||
|
make clean all CC=clang
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
./test_vector && ./test_map && ./test_bigint
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
name: datum
|
name: gcc-build
|
||||||
on:
|
on: [push,pull_request,workflow_dispatch]
|
||||||
push:
|
|
||||||
branch: [master]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
gcc-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build Datum
|
- name: Build Datum
|
||||||
run: |
|
run: |
|
||||||
make clean all
|
make clean all
|
||||||
|
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: |
|
run: |
|
||||||
./test_vector && ./test_map
|
./test_vector && ./test_map && ./test_bigint
|
||||||
10
Makefile
10
Makefile
@@ -10,13 +10,14 @@ TESTS_SRC = tests
|
|||||||
TARGET = usage
|
TARGET = usage
|
||||||
TEST_V_TARGET = test_vector
|
TEST_V_TARGET = test_vector
|
||||||
TEST_M_TARGET = test_map
|
TEST_M_TARGET = test_map
|
||||||
|
TEST_B_TARGET = test_bigint
|
||||||
|
|
||||||
LIB_OBJS = $(OBJ_DIR)/vector.o $(OBJ_DIR)/map.o
|
LIB_OBJS = $(OBJ_DIR)/vector.o $(OBJ_DIR)/map.o $(OBJ_DIR)/bigint.o
|
||||||
PROG_OBJS = $(OBJ_DIR)/usage.o
|
PROG_OBJS = $(OBJ_DIR)/usage.o
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET)
|
all: $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET) $(TEST_B_TARGET)
|
||||||
|
|
||||||
$(TARGET): $(PROG_OBJS) $(LIB_OBJS)
|
$(TARGET): $(PROG_OBJS) $(LIB_OBJS)
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
@@ -27,6 +28,9 @@ $(TEST_V_TARGET): $(OBJ_DIR)/test_vector.o $(OBJ_DIR)/vector.o
|
|||||||
$(TEST_M_TARGET): $(OBJ_DIR)/test_map.o $(OBJ_DIR)/map.o
|
$(TEST_M_TARGET): $(OBJ_DIR)/test_map.o $(OBJ_DIR)/map.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
$(TEST_B_TARGET): $(OBJ_DIR)/test_bigint.o $(OBJ_DIR)/bigint.o $(OBJ_DIR)/vector.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
@@ -40,4 +44,4 @@ $(OBJ_DIR):
|
|||||||
mkdir -p $(OBJ_DIR)
|
mkdir -p $(OBJ_DIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJ_DIR) $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET)
|
rm -rf $(OBJ_DIR) $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET) $(TEST_B_TARGET)
|
||||||
|
|||||||
40
README.md
40
README.md
@@ -2,7 +2,8 @@
|
|||||||
<h1>Datum</h1>
|
<h1>Datum</h1>
|
||||||
<h6><i>Collection of dynamic and generic data structures.</i></h6>
|
<h6><i>Collection of dynamic and generic data structures.</i></h6>
|
||||||
|
|
||||||
[](https://github.com/ceticamarco/datum/actions/workflows/datum.yml)
|
[](https://github.com/ceticamarco/datum/actions/workflows/gcc-build.yml)
|
||||||
|
[](https://github.com/ceticamarco/datum/actions/workflows/clang-build.yml)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Datum is a collection of dynamic and generic data structures implemented from scratch in C with no external dependencies beyond
|
Datum is a collection of dynamic and generic data structures implemented from scratch in C with no external dependencies beyond
|
||||||
@@ -10,11 +11,12 @@ the standard library. It currently features:
|
|||||||
|
|
||||||
- [**Vector**](/docs/vector.md): a growable, contiguous array of homogenous generic data types;
|
- [**Vector**](/docs/vector.md): a growable, contiguous array of homogenous generic data types;
|
||||||
- [**Map**](/docs/map.md): an associative array that handles generic heterogenous data types;
|
- [**Map**](/docs/map.md): an associative array that handles generic heterogenous data types;
|
||||||
|
- [**BigInt**](/docs/bigint.md): a data type for arbitrary large integers.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
At its simplest, you can use this library as follows:
|
At its simplest, you can use this library as follows:
|
||||||
|
|
||||||
### `Vector`'s usage
|
### `Vector` usage
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -51,7 +53,7 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### `Map`'s usage
|
### `Map` usage
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -95,6 +97,35 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `BigInt` usage
|
||||||
|
```c
|
||||||
|
#include "src/bigint.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile with: gcc -O3 main.c src/bigint.c src/vector.c
|
||||||
|
* Output: 20000! = 1819206320230345134827641...
|
||||||
|
* Time: 4.01s user 0.00s system 99% cpu 4.021 total
|
||||||
|
*/
|
||||||
|
int main(void) {
|
||||||
|
const int n = 20000;
|
||||||
|
bigint_t *fact = bigint_from_int(1).value.number;
|
||||||
|
|
||||||
|
for (int idx = 2; idx <= n; idx++) {
|
||||||
|
bigint_t *big_idx = bigint_from_int(idx).value.number;
|
||||||
|
bigint_t *partial_fact = bigint_prod(fact, big_idx).value.number;
|
||||||
|
|
||||||
|
bigint_destroy(fact);
|
||||||
|
bigint_destroy(big_idx);
|
||||||
|
fact = partial_fact;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_printf("%d! = %B\n", n, fact);
|
||||||
|
|
||||||
|
bigint_destroy(fact);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
For a more exhaustive example, refer to the `usage.c` file. There, you will find a program with proper error management
|
For a more exhaustive example, refer to the `usage.c` file. There, you will find a program with proper error management
|
||||||
and a sample usage for every available method. To run it, first issue the following command:
|
and a sample usage for every available method. To run it, first issue the following command:
|
||||||
|
|
||||||
@@ -109,12 +140,13 @@ For additional details about this library (internal design, memory
|
|||||||
management, data ownership, etc.) go to the [docs folder](/docs).
|
management, data ownership, etc.) go to the [docs folder](/docs).
|
||||||
|
|
||||||
## Unit tests
|
## Unit tests
|
||||||
Datum provides some unit tests for both the `Vector` and the `Map` data types. To run them, you can issue the following commands:
|
Datum provides some unit tests for `Vector`, `Map` and `BigInt`. To run them, you can issue the following commands:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ make clean all
|
$ make clean all
|
||||||
$ ./test_vector
|
$ ./test_vector
|
||||||
$ ./test_map
|
$ ./test_map
|
||||||
|
$ ./test_bigint
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ At the time being, this documentation includes the following pages:
|
|||||||
|
|
||||||
- [vector.md](vector.md): vector documentation;
|
- [vector.md](vector.md): vector documentation;
|
||||||
- [map.md](map.md): map documentation;
|
- [map.md](map.md): map documentation;
|
||||||
- [sort.md](sort.md): how to use the `vector_sort` method.
|
- [sort.md](sort.md): how to use the `vector_sort` method;
|
||||||
|
- [bigint.md](bigint.md): bigint documentation.
|
||||||
|
|||||||
92
docs/bigint.md
Normal file
92
docs/bigint.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# 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)`: create a big integer from a primitive `int` type;
|
||||||
|
- `bigint_result_t bigint_from_string(string_num)`: create a big integer from a C string;
|
||||||
|
- `bigint_result_t bigint_to_string(number)`: convert a big integer to a C string;
|
||||||
|
- `bigint_result_t bigint_clone(number)`: clone a big integer;
|
||||||
|
- `bigint_result_t bigint_compare(x, y)`: compare 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)`: add two big integers together in $\mathcal{O}(n)$;
|
||||||
|
- `bigint_result_t bigint_sub(x, y)`: subtract two big integers in $\mathcal{O}(n)$;
|
||||||
|
- `bigint_result_t bigint_prod(x, y)`: multiply two big integers using Karatsuba's algorithm in $\mathcal{O}(n^{1.585})$;
|
||||||
|
- `bigint_result_t bigint_divmod(x, y)`: divide two big integers using *long division* algorithm in $\mathcal{O}(n^2)$, returning both the quotient and the remainder;
|
||||||
|
- `bigint_result_t bigint_mod(x, y)`: computes modulo of two big integers using *long division* algorithm in $\mathcal{O}(n^2)$;
|
||||||
|
- `bigint_result_t bigint_destroy(number)`: delete 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 by 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 in 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`.
|
||||||
|
|
||||||
@@ -71,5 +71,5 @@ typedef struct {
|
|||||||
Each method that returns such type indicates whether the operation was successful or not by setting
|
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
|
the `status` field and by providing a descriptive message on the `message` field. If the operation was
|
||||||
successful (that is, `status == MAP_OK`), you can either move on with the rest of the program or read
|
successful (that is, `status == MAP_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
|
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
|
||||||
in the first part of the README.
|
in the first part of the README.
|
||||||
18
docs/sort.md
18
docs/sort.md
@@ -42,7 +42,7 @@ vector_order_t cmp_int_desc(const void *x, const void *y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compile with: gcc main.c src/vector.h
|
* Compile with: gcc main.c src/vector.c
|
||||||
* Output: Before sorting: -8 20 -10 125 34 9
|
* Output: Before sorting: -8 20 -10 125 34 9
|
||||||
* After sorting (ascending order): -10 -8 9 20 34 125
|
* After sorting (ascending order): -10 -8 9 20 34 125
|
||||||
* After sorting (descending order): 125 34 20 9 -8 -10
|
* After sorting (descending order): 125 34 20 9 -8 -10
|
||||||
@@ -55,9 +55,11 @@ int main(void) {
|
|||||||
vector_push(v, &values[idx]);
|
vector_push(v, &values[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t sz = vector_size(v);
|
||||||
|
|
||||||
// Print unsorted array
|
// Print unsorted array
|
||||||
printf("Before sorting: ");
|
printf("Before sorting: ");
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +68,7 @@ int main(void) {
|
|||||||
|
|
||||||
// Print sorted array
|
// Print sorted array
|
||||||
printf("\nAfter sorting (ascending order): ");
|
printf("\nAfter sorting (ascending order): ");
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ int main(void) {
|
|||||||
|
|
||||||
// Print sorted array
|
// Print sorted array
|
||||||
printf("\nAfter sorting (descending order): ");
|
printf("\nAfter sorting (descending order): ");
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
printf("%d ", *(int*)vector_get(v, idx).value.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +126,7 @@ vector_order_t cmp_person_by_name(const void *x, const void *y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compile with: gcc main.c src/vector.h
|
* Compile with: gcc main.c src/vector.c
|
||||||
* Output: Sort by age:
|
* Output: Sort by age:
|
||||||
* Name: Marco, Age: 25
|
* Name: Marco, Age: 25
|
||||||
* Name: Alice, Age: 28
|
* Name: Alice, Age: 28
|
||||||
@@ -149,9 +151,11 @@ int main(void) {
|
|||||||
// Sort array by age
|
// Sort array by age
|
||||||
vector_sort(employees, cmp_person_by_age);
|
vector_sort(employees, cmp_person_by_age);
|
||||||
|
|
||||||
|
const size_t sz = vector_size(employees);
|
||||||
|
|
||||||
// Print sorted array
|
// Print sorted array
|
||||||
printf("Sort by age:\n");
|
printf("Sort by age:\n");
|
||||||
for (size_t idx = 0; idx < vector_size(employees); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
Employee *p = (Employee*)vector_get(employees, idx).value.element;
|
Employee *p = (Employee*)vector_get(employees, idx).value.element;
|
||||||
printf("Name: %s, Age: %d\n", p->name, p->age);
|
printf("Name: %s, Age: %d\n", p->name, p->age);
|
||||||
}
|
}
|
||||||
@@ -161,7 +165,7 @@ int main(void) {
|
|||||||
|
|
||||||
// Print sorted array
|
// Print sorted array
|
||||||
printf("\nSort by name:\n");
|
printf("\nSort by name:\n");
|
||||||
for (size_t idx = 0; idx < vector_size(employees); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
Employee *p = (Employee*)vector_get(employees, idx).value.element;
|
Employee *p = (Employee*)vector_get(employees, idx).value.element;
|
||||||
printf("Name: %s, Age: %d\n", p->name, p->age);
|
printf("Name: %s, Age: %d\n", p->name, p->age);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Each method that returns such type indicates whether the operation was successfu
|
|||||||
by setting the `status` field and by providing a descriptive message on the `message`
|
by setting the `status` field and by providing a descriptive message on the `message`
|
||||||
field. If the operation was successful (that is, `status == VECTOR_OK`), you can either
|
field. If the operation was successful (that is, `status == VECTOR_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
|
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 in the first part of the README.
|
ignore the return value (if you're brave enough :D) as illustrated in the first part of the README.
|
||||||
|
|
||||||
The documentation for the `vector_sort(map, cmp)` method can be found
|
The documentation for the `vector_sort(map, cmp)` method can be found
|
||||||
in [the following document](/docs/sort.md).
|
in [the following document](/docs/sort.md).
|
||||||
1863
src/bigint.c
Normal file
1863
src/bigint.c
Normal file
File diff suppressed because it is too large
Load Diff
64
src/bigint.h
Normal file
64
src/bigint.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef BIGINT_H
|
||||||
|
#define BIGINT_H
|
||||||
|
|
||||||
|
#define RESULT_MSG_SIZE 64
|
||||||
|
|
||||||
|
// Numerical base (10^9)
|
||||||
|
#define BIGINT_BASE 1000000000
|
||||||
|
// Each digit stores values from 0 to 999,999,999
|
||||||
|
#define BIGINT_BASE_DIGITS 9
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BIGINT_OK = 0x0,
|
||||||
|
BIGINT_ERR_ALLOCATE,
|
||||||
|
BIGINT_ERR_DIV_BY_ZERO,
|
||||||
|
BIGINT_ERR_INVALID
|
||||||
|
} bigint_status_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vector_t *digits;
|
||||||
|
bool is_negative;
|
||||||
|
} bigint_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;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bigint_result_t bigint_from_int(long long value);
|
||||||
|
bigint_result_t bigint_from_string(const char *string_num);
|
||||||
|
bigint_result_t bigint_to_string(const bigint_t *number);
|
||||||
|
bigint_result_t bigint_clone(const bigint_t *number);
|
||||||
|
bigint_result_t bigint_compare(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_add(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_sub(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_prod(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_divmod(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_mod(const bigint_t *x, const bigint_t *y);
|
||||||
|
bigint_result_t bigint_destroy(bigint_t *number);
|
||||||
|
bigint_result_t bigint_printf(const char *format, ...);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#define SET_MSG(result, msg) \
|
#define SET_MSG(result, msg) \
|
||||||
snprintf((char *)result.message, RESULT_MSG_SIZE, msg)
|
do { \
|
||||||
|
snprintf((char *)(result).message, RESULT_MSG_SIZE, "%s", (const char *)msg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -35,7 +37,7 @@ uint64_t hash_key(const char *key) {
|
|||||||
*
|
*
|
||||||
* Returns a map_result_t data type containing a new hash map
|
* Returns a map_result_t data type containing a new hash map
|
||||||
*/
|
*/
|
||||||
map_result_t map_new() {
|
map_result_t map_new(void) {
|
||||||
map_result_t result = {0};
|
map_result_t result = {0};
|
||||||
|
|
||||||
map_t *map = malloc(sizeof(map_t));
|
map_t *map = malloc(sizeof(map_t));
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ typedef struct {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
map_result_t map_new();
|
map_result_t map_new(void);
|
||||||
map_result_t map_add(map_t *map, const char *key, void *value);
|
map_result_t map_add(map_t *map, const char *key, void *value);
|
||||||
map_result_t map_get(const map_t *map, const char *key);
|
map_result_t map_get(const map_t *map, const char *key);
|
||||||
map_result_t map_remove(map_t *map, const char *key);
|
map_result_t map_remove(map_t *map, const char *key);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#define SET_MSG(result, msg) \
|
#define SET_MSG(result, msg) \
|
||||||
snprintf((char *)result.message, RESULT_MSG_SIZE, msg)
|
do { \
|
||||||
|
snprintf((char *)(result).message, RESULT_MSG_SIZE, "%s", (const char *)msg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
381
tests/test_bigint.c
Normal file
381
tests/test_bigint.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
* Unit tests for BigInt data type
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEST(NAME) do { \
|
||||||
|
printf("Running test_%s...", #NAME); \
|
||||||
|
test_##NAME(); \
|
||||||
|
printf(" PASSED\n"); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "../src/bigint.h"
|
||||||
|
|
||||||
|
static void bigint_eq(const bigint_t *number, const char *expected) {
|
||||||
|
bigint_result_t exp_num_res = bigint_from_string(expected);
|
||||||
|
assert(exp_num_res.status == BIGINT_OK);
|
||||||
|
bigint_t *exp_num = exp_num_res.value.number;
|
||||||
|
|
||||||
|
bigint_result_t cmp_res = bigint_compare(number, exp_num);
|
||||||
|
assert(cmp_res.status == BIGINT_OK);
|
||||||
|
|
||||||
|
const int8_t cmp = cmp_res.value.compare_status;
|
||||||
|
assert(cmp == 0);
|
||||||
|
|
||||||
|
bigint_destroy(exp_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test creating big integers from int
|
||||||
|
void test_bigint_from_int(void) {
|
||||||
|
bigint_result_t res = bigint_from_int(0);
|
||||||
|
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "0");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
|
||||||
|
res = bigint_from_int(10);
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "10");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
|
||||||
|
res = bigint_from_int(-12345678900LL);
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "-12345678900");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test creating big integers from string
|
||||||
|
void test_bigint_from_string(void) {
|
||||||
|
bigint_result_t res = bigint_from_string("00000123");
|
||||||
|
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "123");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
|
||||||
|
res = bigint_from_string("-00000456789");
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "-456789");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sum between big integers
|
||||||
|
void test_bigint_add(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(123);
|
||||||
|
bigint_result_t y = bigint_from_int(456);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t sum = bigint_add(x.value.number, y.value.number);
|
||||||
|
assert(sum.status == BIGINT_OK);
|
||||||
|
bigint_eq(sum.value.number, "579");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(sum.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test difference between big numbers
|
||||||
|
void test_bigint_sub(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(456);
|
||||||
|
bigint_result_t y = bigint_from_int(123);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t diff = bigint_sub(x.value.number, y.value.number);
|
||||||
|
assert(diff.status == BIGINT_OK);
|
||||||
|
bigint_eq(diff.value.number, "333");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(diff.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test difference between big numbers with negative result
|
||||||
|
void test_bigint_sub_neg(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(123);
|
||||||
|
bigint_result_t y = bigint_from_int(456);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t diff = bigint_sub(x.value.number, y.value.number);
|
||||||
|
assert(diff.status == BIGINT_OK);
|
||||||
|
bigint_eq(diff.value.number, "-333");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(diff.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test difference between mixed big numbers
|
||||||
|
void test_bigint_sub_mixed(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(456);
|
||||||
|
bigint_result_t y = bigint_from_int(-123);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t diff = bigint_sub(x.value.number, y.value.number);
|
||||||
|
assert(diff.status == BIGINT_OK);
|
||||||
|
bigint_eq(diff.value.number, "579");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(diff.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test product between big numbers
|
||||||
|
void test_bigint_prod(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(1234);
|
||||||
|
bigint_result_t y = bigint_from_int(56789);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t prod = bigint_prod(x.value.number, y.value.number);
|
||||||
|
assert(prod.status == BIGINT_OK);
|
||||||
|
bigint_eq(prod.value.number, "70077626");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(prod.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test product between mixed negative big numbers
|
||||||
|
void test_bigint_prod_mixed(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-1234);
|
||||||
|
bigint_result_t y = bigint_from_int(56789);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t prod = bigint_prod(x.value.number, y.value.number);
|
||||||
|
assert(prod.status == BIGINT_OK);
|
||||||
|
bigint_eq(prod.value.number, "-70077626");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(prod.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test product between negative big numbers
|
||||||
|
void test_bigint_prod_neg(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-1234);
|
||||||
|
bigint_result_t y = bigint_from_int(-56789);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t prod = bigint_prod(x.value.number, y.value.number);
|
||||||
|
assert(prod.status == BIGINT_OK);
|
||||||
|
bigint_eq(prod.value.number, "70077626");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
bigint_destroy(prod.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test division between big numbers
|
||||||
|
void test_bigint_div(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(100);
|
||||||
|
bigint_result_t y = bigint_from_int(2);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t div = bigint_divmod(x.value.number, y.value.number);
|
||||||
|
assert(div.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_t* const quotient = div.value.division.quotient;
|
||||||
|
bigint_t* const remainder = div.value.division.remainder;
|
||||||
|
|
||||||
|
bigint_eq(quotient, "50");
|
||||||
|
bigint_eq(remainder, "0");
|
||||||
|
|
||||||
|
bigint_destroy(quotient);
|
||||||
|
bigint_destroy(remainder);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test division between big numbers with negative dividend
|
||||||
|
// This library follows C-style divison such that sign(remainder) = sign(dividend)
|
||||||
|
void test_bigint_div_dividend(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-100);
|
||||||
|
bigint_result_t y = bigint_from_int(3);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t div = bigint_divmod(x.value.number, y.value.number);
|
||||||
|
assert(div.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_t* const quotient = div.value.division.quotient;
|
||||||
|
bigint_t* const remainder = div.value.division.remainder;
|
||||||
|
|
||||||
|
bigint_eq(quotient, "-33");
|
||||||
|
bigint_eq(remainder, "-1");
|
||||||
|
|
||||||
|
bigint_destroy(quotient);
|
||||||
|
bigint_destroy(remainder);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test division between big numbers with negative divisor
|
||||||
|
// This library follows C-style divison such that sign(remainder) = sign(dividend)
|
||||||
|
void test_bigint_div_divisor(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(13);
|
||||||
|
bigint_result_t y = bigint_from_int(-4);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t div = bigint_divmod(x.value.number, y.value.number);
|
||||||
|
assert(div.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_t* const quotient = div.value.division.quotient;
|
||||||
|
bigint_t* const remainder = div.value.division.remainder;
|
||||||
|
|
||||||
|
bigint_eq(quotient, "-3");
|
||||||
|
bigint_eq(remainder, "1");
|
||||||
|
|
||||||
|
bigint_destroy(quotient);
|
||||||
|
bigint_destroy(remainder);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test division between big numbers with negative numbers
|
||||||
|
// This library follows C-style divison such that sign(remainder) = sign(dividend)
|
||||||
|
void test_bigint_div_neg(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-100);
|
||||||
|
bigint_result_t y = bigint_from_int(-3);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t div = bigint_divmod(x.value.number, y.value.number);
|
||||||
|
assert(div.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_t* const quotient = div.value.division.quotient;
|
||||||
|
bigint_t* const remainder = div.value.division.remainder;
|
||||||
|
|
||||||
|
bigint_eq(quotient, "33");
|
||||||
|
bigint_eq(remainder, "-1");
|
||||||
|
|
||||||
|
bigint_destroy(quotient);
|
||||||
|
bigint_destroy(remainder);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test division by zero
|
||||||
|
void test_bigint_div_by_zero(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-100);
|
||||||
|
bigint_result_t y = bigint_from_int(0);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK && y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t div = bigint_divmod(x.value.number, y.value.number);
|
||||||
|
assert(div.status == BIGINT_ERR_DIV_BY_ZERO);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cloning of big numbers
|
||||||
|
void test_bigint_clone(void) {
|
||||||
|
bigint_result_t x = bigint_from_string("0010101010");
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t cloned = bigint_clone(x.value.number);
|
||||||
|
assert(cloned.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_eq(cloned.value.number, "10101010");
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(cloned.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test comparison between equal numbers
|
||||||
|
void test_bigint_compare_eq(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(123);
|
||||||
|
bigint_result_t y = bigint_from_int(123);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK);
|
||||||
|
assert(y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t cmp_res = bigint_compare(x.value.number, y.value.number);
|
||||||
|
assert(cmp_res.status == BIGINT_OK);
|
||||||
|
|
||||||
|
const int8_t cmp = cmp_res.value.compare_status;
|
||||||
|
assert(cmp == 0);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test comparison between numbers (less than)
|
||||||
|
void test_bigint_compare_lt(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(-123);
|
||||||
|
bigint_result_t y = bigint_from_int(0);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK);
|
||||||
|
assert(y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t cmp_res = bigint_compare(x.value.number, y.value.number);
|
||||||
|
assert(cmp_res.status == BIGINT_OK);
|
||||||
|
|
||||||
|
const int8_t cmp = cmp_res.value.compare_status;
|
||||||
|
assert(cmp == -1);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test comparison between numbers (greater than)
|
||||||
|
void test_bigint_compare_gt(void) {
|
||||||
|
bigint_result_t x = bigint_from_int(123);
|
||||||
|
bigint_result_t y = bigint_from_int(-5);
|
||||||
|
|
||||||
|
assert(x.status == BIGINT_OK);
|
||||||
|
assert(y.status == BIGINT_OK);
|
||||||
|
|
||||||
|
bigint_result_t cmp_res = bigint_compare(x.value.number, y.value.number);
|
||||||
|
assert(cmp_res.status == BIGINT_OK);
|
||||||
|
|
||||||
|
const int8_t cmp = cmp_res.value.compare_status;
|
||||||
|
assert(cmp == 1);
|
||||||
|
|
||||||
|
bigint_destroy(x.value.number);
|
||||||
|
bigint_destroy(y.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("=== Running BigInt unit tests ===\n\n");
|
||||||
|
|
||||||
|
TEST(bigint_from_int);
|
||||||
|
TEST(bigint_from_string);
|
||||||
|
TEST(bigint_add);
|
||||||
|
TEST(bigint_sub);
|
||||||
|
TEST(bigint_sub_neg);
|
||||||
|
TEST(bigint_sub_mixed);
|
||||||
|
TEST(bigint_prod);
|
||||||
|
TEST(bigint_prod_mixed);
|
||||||
|
TEST(bigint_prod_neg);
|
||||||
|
TEST(bigint_div);
|
||||||
|
TEST(bigint_div_dividend);
|
||||||
|
TEST(bigint_div_divisor);
|
||||||
|
TEST(bigint_div_neg);
|
||||||
|
TEST(bigint_div_by_zero);
|
||||||
|
TEST(bigint_clone);
|
||||||
|
TEST(bigint_compare_eq);
|
||||||
|
TEST(bigint_compare_lt);
|
||||||
|
TEST(bigint_compare_gt);
|
||||||
|
|
||||||
|
printf("\n=== All tests passed ===\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "../src/map.h"
|
#include "../src/map.h"
|
||||||
|
|
||||||
// Create a new map
|
// Create a new map
|
||||||
void test_map_new() {
|
void test_map_new(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -27,7 +27,7 @@ void test_map_new() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add elements to map
|
// Add elements to map
|
||||||
void test_map_add() {
|
void test_map_add(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -47,7 +47,7 @@ void test_map_add() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add multiple elements to the map
|
// Add multiple elements to the map
|
||||||
void test_map_add_multiple() {
|
void test_map_add_multiple(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -68,7 +68,7 @@ void test_map_add_multiple() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get map element
|
// Get map element
|
||||||
void test_map_get() {
|
void test_map_get(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -85,7 +85,7 @@ void test_map_get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get non-existing key from map
|
// Get non-existing key from map
|
||||||
void test_map_get_invalid() {
|
void test_map_get_invalid(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -98,7 +98,7 @@ void test_map_get_invalid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map with heterogeneous types
|
// Map with heterogeneous types
|
||||||
void test_map_mixed() {
|
void test_map_mixed(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -126,7 +126,7 @@ void test_map_mixed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update existing map key
|
// Update existing map key
|
||||||
void test_map_update() {
|
void test_map_update(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -149,7 +149,7 @@ void test_map_update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove an element from map
|
// Remove an element from map
|
||||||
void test_map_remove() {
|
void test_map_remove(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -177,7 +177,7 @@ void test_map_remove() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove non-existing key from map
|
// Remove non-existing key from map
|
||||||
void test_map_remove_invalid() {
|
void test_map_remove_invalid(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -190,7 +190,7 @@ void test_map_remove_invalid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear the map
|
// Clear the map
|
||||||
void test_map_clear() {
|
void test_map_clear(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -212,7 +212,7 @@ void test_map_clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear empty map
|
// Clear empty map
|
||||||
void test_map_clear_empty() {
|
void test_map_clear_empty(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -226,7 +226,7 @@ void test_map_clear_empty() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Multiple operations in sequence (add, update, delete and clear)
|
// Multiple operations in sequence (add, update, delete and clear)
|
||||||
void test_map_sequence() {
|
void test_map_sequence(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -266,7 +266,7 @@ typedef struct {
|
|||||||
short age;
|
short age;
|
||||||
} Person;
|
} Person;
|
||||||
|
|
||||||
void test_map_struct() {
|
void test_map_struct(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
@@ -298,7 +298,7 @@ void test_map_struct() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test map capacity tracking
|
// Test map capacity tracking
|
||||||
void test_map_cap() {
|
void test_map_cap(void) {
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
|
|
||||||
assert(res.status == MAP_OK);
|
assert(res.status == MAP_OK);
|
||||||
|
|||||||
Binary file not shown.
@@ -15,7 +15,7 @@
|
|||||||
#include "../src/vector.h"
|
#include "../src/vector.h"
|
||||||
|
|
||||||
// Create a new vector
|
// Create a new vector
|
||||||
void test_vector_new() {
|
void test_vector_new(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -27,14 +27,14 @@ void test_vector_new() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a vector with zero capacity
|
// Create a vector with zero capacity
|
||||||
void test_vector_new_zcap() {
|
void test_vector_new_zcap(void) {
|
||||||
vector_result_t res = vector_new(0, sizeof(int));
|
vector_result_t res = vector_new(0, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_ERR_ALLOCATE);
|
assert(res.status == VECTOR_ERR_ALLOCATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push elements to vector
|
// Push elements to vector
|
||||||
void test_vector_push() {
|
void test_vector_push(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -54,7 +54,7 @@ void test_vector_push() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Trigger vector reallocation
|
// Trigger vector reallocation
|
||||||
void test_vector_push_realloc() {
|
void test_vector_push_realloc(void) {
|
||||||
vector_result_t res = vector_new(1, sizeof(int));
|
vector_result_t res = vector_new(1, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -72,7 +72,7 @@ void test_vector_push_realloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get vector elements
|
// Get vector elements
|
||||||
void test_vector_get() {
|
void test_vector_get(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -89,7 +89,7 @@ void test_vector_get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test out of bounds
|
// Test out of bounds
|
||||||
void test_vector_get_ofb() {
|
void test_vector_get_ofb(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -119,7 +119,7 @@ vector_order_t cmp_int_desc(const void *x, const void *y) {
|
|||||||
return cmp_int_asc(y, x);
|
return cmp_int_asc(y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_vector_sort_int_asc() {
|
void test_vector_sort_int_asc(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -134,7 +134,9 @@ void test_vector_sort_int_asc() {
|
|||||||
assert(sort_res.status == VECTOR_OK);
|
assert(sort_res.status == VECTOR_OK);
|
||||||
|
|
||||||
const int expected[] = { -7, 1, 4, 6, 12, 25, 25, 71 };
|
const int expected[] = { -7, 1, 4, 6, 12, 25, 25, 71 };
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
|
||||||
|
const size_t sz = vector_size(v);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
int *val = (int*)vector_get(v, idx).value.element;
|
int *val = (int*)vector_get(v, idx).value.element;
|
||||||
assert(*val == expected[idx]);
|
assert(*val == expected[idx]);
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,7 @@ void test_vector_sort_int_asc() {
|
|||||||
vector_destroy(v);
|
vector_destroy(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_vector_sort_int_desc() {
|
void test_vector_sort_int_desc(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -157,7 +159,9 @@ void test_vector_sort_int_desc() {
|
|||||||
assert(sort_res.status == VECTOR_OK);
|
assert(sort_res.status == VECTOR_OK);
|
||||||
|
|
||||||
const int expected[] = { 71, 25, 25, 12, 6, 4, 1, -7 };
|
const int expected[] = { 71, 25, 25, 12, 6, 4, 1, -7 };
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
|
||||||
|
const size_t sz = vector_size(v);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
int *val = (int*)vector_get(v, idx).value.element;
|
int *val = (int*)vector_get(v, idx).value.element;
|
||||||
assert(*val == expected[idx]);
|
assert(*val == expected[idx]);
|
||||||
}
|
}
|
||||||
@@ -183,7 +187,7 @@ vector_order_t cmp_string_desc(const void *x, const void *y) {
|
|||||||
return VECTOR_ORDER_EQ;
|
return VECTOR_ORDER_EQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_vector_sort_string() {
|
void test_vector_sort_string(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(char*));
|
vector_result_t res = vector_new(5, sizeof(char*));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -198,7 +202,9 @@ void test_vector_sort_string() {
|
|||||||
assert(sort_res.status == VECTOR_OK);
|
assert(sort_res.status == VECTOR_OK);
|
||||||
|
|
||||||
const char *expected[] = { "world!", "system-programming", "hello", "foo", "embedded", "bar"};
|
const char *expected[] = { "world!", "system-programming", "hello", "foo", "embedded", "bar"};
|
||||||
for (size_t idx = 0; idx < vector_size(v); idx++) {
|
|
||||||
|
const size_t sz = vector_size(v);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
const char *val = *(const char**)vector_get(v, idx).value.element;
|
const char *val = *(const char**)vector_get(v, idx).value.element;
|
||||||
assert(!strcmp(val, expected[idx]));
|
assert(!strcmp(val, expected[idx]));
|
||||||
}
|
}
|
||||||
@@ -234,7 +240,7 @@ vector_order_t cmp_person_by_name(const void *x, const void *y) {
|
|||||||
return VECTOR_ORDER_EQ;
|
return VECTOR_ORDER_EQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_vector_sort_struct_by_age() {
|
void test_vector_sort_struct_by_age(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(Person));
|
vector_result_t res = vector_new(5, sizeof(Person));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -257,7 +263,8 @@ void test_vector_sort_struct_by_age() {
|
|||||||
{ .name = "Bob", .age = 45 }
|
{ .name = "Bob", .age = 45 }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t idx = 0; idx < vector_size(people); idx++) {
|
const size_t sz = sizeof(expected) / sizeof(expected[0]);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
Person *p = (Person*)vector_get(people, idx).value.element;
|
Person *p = (Person*)vector_get(people, idx).value.element;
|
||||||
assert(!strcmp(p->name, expected[idx].name));
|
assert(!strcmp(p->name, expected[idx].name));
|
||||||
assert(p->age == expected[idx].age);
|
assert(p->age == expected[idx].age);
|
||||||
@@ -266,7 +273,7 @@ void test_vector_sort_struct_by_age() {
|
|||||||
vector_destroy(people);
|
vector_destroy(people);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_vector_sort_struct_by_name() {
|
void test_vector_sort_struct_by_name(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(Person));
|
vector_result_t res = vector_new(5, sizeof(Person));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -295,7 +302,8 @@ void test_vector_sort_struct_by_name() {
|
|||||||
{ .name = "Sophia", .age = 45 }
|
{ .name = "Sophia", .age = 45 }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t idx = 0; idx < vector_size(people); idx++) {
|
const size_t sz = vector_size(people);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
Person *p = (Person*)vector_get(people, idx).value.element;
|
Person *p = (Person*)vector_get(people, idx).value.element;
|
||||||
assert(!strcmp(p->name, expected[idx].name));
|
assert(!strcmp(p->name, expected[idx].name));
|
||||||
assert(p->age == expected[idx].age);
|
assert(p->age == expected[idx].age);
|
||||||
@@ -305,7 +313,7 @@ void test_vector_sort_struct_by_name() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set vector element
|
// Set vector element
|
||||||
void test_vector_set() {
|
void test_vector_set(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -324,7 +332,7 @@ void test_vector_set() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set vector element out of bounds
|
// Set vector element out of bounds
|
||||||
void test_vector_set_ofb() {
|
void test_vector_set_ofb(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -340,7 +348,7 @@ void test_vector_set_ofb() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pop element from vector
|
// Pop element from vector
|
||||||
void test_vector_pop() {
|
void test_vector_pop(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -361,7 +369,7 @@ void test_vector_pop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test pop element from empty vector
|
// Test pop element from empty vector
|
||||||
void test_vector_pop_empty() {
|
void test_vector_pop_empty(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -374,7 +382,7 @@ void test_vector_pop_empty() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear vector
|
// Clear vector
|
||||||
void test_vector_clear() {
|
void test_vector_clear(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(int));
|
vector_result_t res = vector_new(5, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -396,7 +404,7 @@ void test_vector_clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Multiple operations in sequence (push, set, pop and clear)
|
// Multiple operations in sequence (push, set, pop and clear)
|
||||||
void test_vector_sequence() {
|
void test_vector_sequence(void) {
|
||||||
vector_result_t res = vector_new(2, sizeof(int));
|
vector_result_t res = vector_new(2, sizeof(int));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -426,7 +434,7 @@ void test_vector_sequence() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vector with chars
|
// Vector with chars
|
||||||
void test_vector_char() {
|
void test_vector_char(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(char));
|
vector_result_t res = vector_new(5, sizeof(char));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
@@ -449,7 +457,7 @@ typedef struct {
|
|||||||
int y;
|
int y;
|
||||||
} Point;
|
} Point;
|
||||||
|
|
||||||
void test_vector_struct() {
|
void test_vector_struct(void) {
|
||||||
vector_result_t res = vector_new(5, sizeof(Point));
|
vector_result_t res = vector_new(5, sizeof(Point));
|
||||||
|
|
||||||
assert(res.status == VECTOR_OK);
|
assert(res.status == VECTOR_OK);
|
||||||
|
|||||||
119
usage.c
119
usage.c
@@ -20,10 +20,14 @@
|
|||||||
|
|
||||||
#include "src/vector.h"
|
#include "src/vector.h"
|
||||||
#include "src/map.h"
|
#include "src/map.h"
|
||||||
|
#include "src/bigint.h"
|
||||||
|
|
||||||
|
static int vector_usage(void);
|
||||||
|
static int map_usage(void);
|
||||||
|
static int bigint_usage(void);
|
||||||
|
|
||||||
static int vector_usage();
|
|
||||||
static int map_usage();
|
|
||||||
static vector_order_t cmp_int_asc(const void *x, const void *y);
|
static vector_order_t cmp_int_asc(const void *x, const void *y);
|
||||||
|
static vector_order_t cmp_int_desc(const void *x, const void *y);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
int st;
|
int st;
|
||||||
@@ -36,6 +40,11 @@ int main(void) {
|
|||||||
st = map_usage();
|
st = map_usage();
|
||||||
if (st) { return st; }
|
if (st) { return st; }
|
||||||
|
|
||||||
|
SEP(50);
|
||||||
|
|
||||||
|
st = bigint_usage();
|
||||||
|
if (st) { return st; }
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +62,7 @@ vector_order_t cmp_int_desc(const void *x, const void *y) {
|
|||||||
return cmp_int_asc(y, x);
|
return cmp_int_asc(y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vector_usage() {
|
int vector_usage(void) {
|
||||||
// Create a vector of 3 integers
|
// Create a vector of 3 integers
|
||||||
vector_result_t res = vector_new(3, sizeof(int));
|
vector_result_t res = vector_new(3, sizeof(int));
|
||||||
if (res.status != VECTOR_OK) {
|
if (res.status != VECTOR_OK) {
|
||||||
@@ -79,7 +88,8 @@ int vector_usage() {
|
|||||||
printf("Vector capacity (should be > 5): %zu\n\n", vector_capacity(vector));
|
printf("Vector capacity (should be > 5): %zu\n\n", vector_capacity(vector));
|
||||||
|
|
||||||
// Print the whole vector
|
// Print the whole vector
|
||||||
for (size_t idx = 0; idx < vector_size(vector); idx++) {
|
size_t sz = vector_size(vector);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
vector_result_t get_res = vector_get(vector, idx);
|
vector_result_t get_res = vector_get(vector, idx);
|
||||||
if (get_res.status != VECTOR_OK) {
|
if (get_res.status != VECTOR_OK) {
|
||||||
printf("Cannot retrieve vec[%zu]: %s\n", idx, get_res.message);
|
printf("Cannot retrieve vec[%zu]: %s\n", idx, get_res.message);
|
||||||
@@ -127,7 +137,9 @@ int vector_usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("Added new elements. Before sort: ");
|
printf("Added new elements. Before sort: ");
|
||||||
for (size_t idx = 0; idx < vector_size(vector); idx++) {
|
|
||||||
|
sz = vector_size(vector);
|
||||||
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
vector_result_t sort_get_res = vector_get(vector, idx);
|
vector_result_t sort_get_res = vector_get(vector, idx);
|
||||||
if (sort_get_res.status != VECTOR_OK) {
|
if (sort_get_res.status != VECTOR_OK) {
|
||||||
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
||||||
@@ -148,7 +160,7 @@ int vector_usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("After sort in ascending order: ");
|
printf("After sort in ascending order: ");
|
||||||
for (size_t idx = 0; idx < vector_size(vector); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
vector_result_t sort_get_res = vector_get(vector, idx);
|
vector_result_t sort_get_res = vector_get(vector, idx);
|
||||||
if (sort_get_res.status != VECTOR_OK) {
|
if (sort_get_res.status != VECTOR_OK) {
|
||||||
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
||||||
@@ -170,7 +182,7 @@ int vector_usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("After sort in descending order: ");
|
printf("After sort in descending order: ");
|
||||||
for (size_t idx = 0; idx < vector_size(vector); idx++) {
|
for (size_t idx = 0; idx < sz; idx++) {
|
||||||
vector_result_t sort_get_res = vector_get(vector, idx);
|
vector_result_t sort_get_res = vector_get(vector, idx);
|
||||||
if (sort_get_res.status != VECTOR_OK) {
|
if (sort_get_res.status != VECTOR_OK) {
|
||||||
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
printf("Cannot retrieve vec[%zu]: %s\n", idx, sort_get_res.message);
|
||||||
@@ -194,7 +206,7 @@ int vector_usage() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int map_usage() {
|
int map_usage(void) {
|
||||||
// Create a new map
|
// Create a new map
|
||||||
map_result_t res = map_new();
|
map_result_t res = map_new();
|
||||||
if (res.status != MAP_OK) {
|
if (res.status != MAP_OK) {
|
||||||
@@ -225,7 +237,7 @@ int map_usage() {
|
|||||||
|
|
||||||
// Print size and capacity
|
// Print size and capacity
|
||||||
printf("Map size (should be 2): %zu\n", map_size(map));
|
printf("Map size (should be 2): %zu\n", map_size(map));
|
||||||
printf("Map capacity (should be >=2): %zu\n\n", map_capacity(map));
|
printf("Map capacity (should be > 2): %zu\n\n", map_capacity(map));
|
||||||
|
|
||||||
// Retrieve keys
|
// Retrieve keys
|
||||||
map_result_t get_res = map_get(map, "x");
|
map_result_t get_res = map_get(map, "x");
|
||||||
@@ -282,6 +294,8 @@ int map_usage() {
|
|||||||
printf("Map cleared (size should be 0): %zu\n", map_size(map));
|
printf("Map cleared (size should be 0): %zu\n", map_size(map));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
// Delete the map
|
// Delete the map
|
||||||
map_result_t del_res = map_destroy(map);
|
map_result_t del_res = map_destroy(map);
|
||||||
if (del_res.status != MAP_OK) {
|
if (del_res.status != MAP_OK) {
|
||||||
@@ -292,3 +306,90 @@ int map_usage() {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bigint_usage(void) {
|
||||||
|
// Create two big integers
|
||||||
|
bigint_result_t x_res = bigint_from_string("123456789");
|
||||||
|
if (x_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while creating big number: %s\n", x_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_result_t y_res = bigint_from_string("987654321");
|
||||||
|
if (x_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while creating big number: %s\n", x_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_t *x = x_res.value.number;
|
||||||
|
bigint_t *y = y_res.value.number;
|
||||||
|
|
||||||
|
// Sum two big integers
|
||||||
|
bigint_result_t sum_res = bigint_add(x, y);
|
||||||
|
if (sum_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while summing two big numbers: %s\n", sum_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_t *sum = sum_res.value.number;
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
bigint_printf("123456789 + 987654321 (should be 1,111,111,110) = %B\n", sum);
|
||||||
|
|
||||||
|
// Subtract two big integers
|
||||||
|
bigint_result_t diff_res = bigint_sub(x, y);
|
||||||
|
if (diff_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while subtracting two big numbers: %s\n", diff_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_t *diff = diff_res.value.number;
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
bigint_printf("123456789 - 987654321 (should be -864,197,532) = %B\n", diff);
|
||||||
|
|
||||||
|
// Multiply two big integers
|
||||||
|
bigint_result_t prod_res = bigint_prod(x, y);
|
||||||
|
if (prod_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while multiplying two big numbers: %s\n", prod_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_t *prod = prod_res.value.number;
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
bigint_printf("123456789 * 987654321 (should be 121,932,631,112,635,269) = %B\n", prod);
|
||||||
|
|
||||||
|
bigint_t *a = bigint_from_string("457349545684946456456456567567").value.number;
|
||||||
|
bigint_t *b = bigint_from_string("43569678678678678678678432").value.number;
|
||||||
|
|
||||||
|
// Divide two big integers
|
||||||
|
bigint_result_t div_res = bigint_divmod(a, b);
|
||||||
|
if (div_res.status != BIGINT_OK) {
|
||||||
|
printf("Error while dividing two big numbers: %s\n", div_res.message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint_t *quotient = div_res.value.division.quotient;
|
||||||
|
bigint_t *remainder = div_res.value.division.remainder;
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
bigint_printf(
|
||||||
|
"457349545684946456456456567567 / 43569678678678678678678432 (should be 10,496) = %B\
|
||||||
|
\n457349545684946456456456567567 %% 43569678678678678678678432 (should be 42,198,273,535,045,045,047,745,295) = %B\n",
|
||||||
|
quotient, remainder);
|
||||||
|
|
||||||
|
// Destroy big numbers
|
||||||
|
bigint_destroy(x); bigint_destroy(y);
|
||||||
|
bigint_destroy(a); bigint_destroy(b);
|
||||||
|
bigint_destroy(sum); bigint_destroy(diff);
|
||||||
|
bigint_destroy(prod); bigint_destroy(quotient); bigint_destroy(remainder);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user