aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/libmaxint/include/maxint.h
blob: 66c5b849206cd27537fbcfb095578da9511f71f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

#define MI_NEG 1
#define MI_POS 0

#define MI_BIT(a,n) ((mi_ul) ((a) >> (n)) & 1)
#define MI_BITA(a,m,n) ((mi_ul) ((a)[(n) / (m)] >> ((n) % (m))) & 1)

#define MI_UL_BYTES (sizeof(mi_ul))
#define MI_UL_BITS  (8 * sizeof(mi_ul))

#define MI_ULS_BYTES (sizeof(mi_uls))
#define MI_ULS_BITS (8 * sizeof(mi_uls))

#define MI_ABS(x) ((mi_ul) ((x) > 0 ? (x) : -(x)))
#define MI_SIGN(x) ((x) >= 0 ? MI_POS : MI_NEG)
#define MI_TO_SIGN(x) ((x)->sign == MI_POS ? 1 : -1)

#define MI_INIT ((struct maxint) { \
	.data = NULL,   \
	.size = 0,      \
	.cap = 0,       \
	.sign = MI_POS, \
})

/* unsigned underlying type */
typedef uint64_t mi_ul;
typedef int64_t mi_uls;

enum {
	MI_OK,
	MI_ERR_OOM,
	MI_ERR_INVAL,
};

struct maxint {
	mi_ul *data;
	size_t size, cap;
	int sign;
};

/* void mi_init(struct maxint *m); */
void mi_deinit(struct maxint *m);

/* struct maxint *mi_imm(struct maxint *storage, mi_ul tmp, int sign); */

int mi_set(struct maxint *m1, const struct maxint *m2);
int mi_setv(struct maxint *m, mi_ul v, int sign);
int mi_setstr(struct maxint *m, const char *str,
	const char **end, const char *alph);

int mi_resize(struct maxint *m, size_t size);

static inline mi_ul mi_cast_ul(const struct maxint *m);
static inline mi_uls mi_cast_uls(const struct maxint *m);

bool mi_zero(const struct maxint *m);

size_t mi_lastset(const struct maxint *m);

ssize_t mi_str(const struct maxint *m, char *buf, size_t buflen,
	mi_ul base, const char *alph, size_t zfill);
ssize_t mi_hex(const struct maxint *m, char *buf, size_t buflen,
	bool capital, size_t zfill);
ssize_t mi_dec(const struct maxint *m, char *buf, size_t buflen, size_t zfill);
ssize_t mi_bin(const struct maxint *m, char *buf, size_t buflen, size_t zfill);

/* mi_add: o1 = i1 + i2
 * allowed: o1 == i1 */
int mi_add(struct maxint *o1, const struct maxint *i1, const struct maxint *i2);

/* mi_sub: o1 = i1 - i2
 * allowed: o1 == i1 */
int mi_sub(struct maxint *o1, const struct maxint *i1, const struct maxint *i2);

/* mi_shl: o1 = i1 << shift
 * allowed: o1 == i1 */
int mi_shl(struct maxint *o1, const struct maxint *i1, size_t shift);

/* mi_shr: o1 = i1 >> shift
 * allowed: o1 == i1 */
int mi_shr(struct maxint *o1, const struct maxint *i1, size_t shift);

/* mi_mul: o1 = i1 * i2
 * allowed: o1 == i1 */
int mi_mul(struct maxint *o1, const struct maxint *i1, const struct maxint *i2);

/* mi_div: o1 = i1 / i2, o2 = i1 % i2
 * allowed: o1 == i1 */
int mi_div(struct maxint *o1, struct maxint *o2,
	const struct maxint *i1, const struct maxint *i2);

/* mi_swap: o1 <=> o2 */
void mi_swap(struct maxint *o1, struct maxint *o2);

/* mi_gcm: o1 = gcm(i1, i2)
 * allowed: o1 == i1 */
int mi_gcm(struct maxint *o1, const struct maxint *i1, const struct maxint *i2);

/* mi_lcm: o1 = lcm(i1, i2)
 * allowed: o1 == i1 */
int mi_lcm(struct maxint *o1, const struct maxint *i1, const struct maxint *i2);

/* mi_cmp: (i1 < i2) => -1 | (i1 == i2) => 0 | (i1 < i2) => 1 */
int mi_cmp(const struct maxint *i1, const struct maxint *i2);

static inline void
mi_init(struct maxint *m)
{
	m->data = NULL;
	m->size = 0;
	m->cap = 0;
	m->sign = MI_POS;
}

static inline struct maxint *
mi_imm(struct maxint *mi_tmp, mi_ul *ul_tmp, mi_ul imm, int sign)
{
	mi_tmp->sign = sign;
	if (mi_tmp->data) {
		mi_tmp->data[0] = imm;
	} else {
		*ul_tmp = imm;
		mi_tmp->data = ul_tmp;
	}
	mi_tmp->size = 1;
	return mi_tmp;
}

static inline mi_ul
mi_cast_ul(const struct maxint *m)
{
	return m->data[0];
}

static inline mi_uls
mi_cast_uls(const struct maxint *m)
{
	mi_uls val;
	mi_ul mask;

	mask = (((mi_ul) 1) << (MI_ULS_BITS - 1)) - 1;
	val = (mi_uls) (m->data[0] & mask);

	return val * MI_TO_SIGN(m);;
}