Merge branch 'bigint-embed' of https://github.com/dearblue/mruby into bigint-embed

This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-10-10 22:31:55 +09:00
2 changed files with 551 additions and 336 deletions
File diff suppressed because it is too large Load Diff
+75 -1
View File
@@ -46,6 +46,8 @@ typedef int64_t mp_dbl_limb_signed;
#define MPZ_DIG_SIZE 32
#endif
#define RBIGINT_EMBED_SIZE_MAX ((sizeof(void*) * 3) / sizeof(mp_limb))
typedef struct _mpz_t {
mp_limb *p;
short sn;
@@ -54,10 +56,82 @@ typedef struct _mpz_t {
struct RBigint {
MRB_OBJECT_HEADER;
mpz_t mp;
union {
mpz_t heap;
mp_limb ary[RBIGINT_EMBED_SIZE_MAX];
} as;
};
#define RBIGINT(v) ((struct RBigint*)mrb_ptr(v))
/*
* flags of struct RBigint
*
* 6..: UNUSED
* 4..5: sign flags
* 00: negative (<--> -1)
* 01: zero (<--> 0)
* 10: positive (<--> +1)
* 11: UNUSED
* 0..3: size of embedded array; 15 means used with heap
*/
#define RBIGINT_EMBED_SIZE_MASK 0x0f
#define RBIGINT_EMBED_SIZE_OVER RBIGINT_EMBED_SIZE_MASK
#define RBIGINT_EMBED_SIZE_SHIFT 0
#define RBIGINT_EMBED_SIGN_MASK 0x03
#define RBIGINT_EMBED_SIGN_SHIFT 4
#define RBIGINT_ARY(m) (RBIGINT_EMBED_P(m) ? RBIGINT_EMBED_ARY(m) : RBIGINT_HEAP_ARY(m))
#define RBIGINT_SIGN(m) (RBIGINT_EMBED_P(m) ? RBIGINT_EMBED_SIGN(m) : RBIGINT_HEAP_SIGN(m))
#define RBIGINT_SIZE(m) (RBIGINT_EMBED_P(m) ? RBIGINT_EMBED_SIZE(m) : RBIGINT_HEAP_SIZE(m))
#define RBIGINT_SET_SIGN(m, s) do { \
if (RBIGINT_EMBED_P(m)) { \
RBIGINT_SET_EMBED_SIGN(m, s); \
} \
else { \
RBIGINT_SET_HEAP_SIGN(m, s); \
} \
} while (0)
#define RBIGINT_SET_SIZE(m, s) do { \
if (RBIGINT_EMBED_P(m)) { \
RBIGINT_SET_EMBED_SIZE(m, s); \
} \
else { \
RBIGINT_SET_HEAP_SIZE(m, s); \
} \
} while (0)
#define RBIGINT_HEAP_ARY(m) ((m)->as.heap.p)
#define RBIGINT_HEAP_SIGN(m) ((m)->as.heap.sn)
#define RBIGINT_HEAP_SIZE(m) ((m)->as.heap.sz)
#define RBIGINT_SET_HEAP(m) do { \
(m)->flags |= RBIGINT_EMBED_SIZE_OVER << RBIGINT_EMBED_SIZE_SHIFT; \
} while (0)
#define RBIGINT_SET_HEAP_SIGN(m, s) do { \
(m)->as.heap.sn = (s); \
} while (0)
#define RBIGINT_SET_HEAP_SIZE(m, s) do { \
(m)->as.heap.sz = (s); \
} while (0)
#define RBIGINT_EMBED_P(m) ((((m)->flags >> RBIGINT_EMBED_SIZE_SHIFT) & RBIGINT_EMBED_SIZE_MASK) < RBIGINT_EMBED_SIZE_OVER)
#define RBIGINT_EMBED_ARY(m) ((m)->as.ary)
#define RBIGINT_EMBED_SIGN(m) ((short)(((m)->flags >> RBIGINT_EMBED_SIGN_SHIFT) & RBIGINT_EMBED_SIGN_MASK) - 1)
#define RBIGINT_EMBED_SIZE(m) (size_t)(((m)->flags >> RBIGINT_EMBED_SIZE_SHIFT) & RBIGINT_EMBED_SIZE_MASK)
#define RBIGINT_SET_EMBED_ZERO(m) do { \
(m)->flags &= ~(RBIGINT_EMBED_SIZE_MASK << RBIGINT_EMBED_SIZE_SHIFT); \
} while (0)
#define RBIGINT_SET_EMBED_SIGN(m, s) do { \
(m)->flags = ((((s) + 1) & RBIGINT_EMBED_SIGN_MASK) << RBIGINT_EMBED_SIGN_SHIFT) | \
((m)->flags & ~(RBIGINT_EMBED_SIGN_MASK << RBIGINT_EMBED_SIGN_SHIFT)); \
} while (0)
#define RBIGINT_SET_EMBED_SIZE(m, s) do { \
size_t s_tmp = (s); \
mrb_assert((s_tmp) <= RBIGINT_EMBED_SIZE_MAX); \
RBIGINT_SET_EMBED_ZERO(m); \
(m)->flags |= (s_tmp) << RBIGINT_EMBED_SIZE_SHIFT; \
} while (0)
mrb_static_assert_object_size(struct RBigint);
#endif /* MRUBY_BIGINT_H */