#pragma once #include #include #include #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);; }