Ruby 3.5.0dev (2025-08-02 revision 30a20bc166bc37acd7dcb3788686df149c7f428a)
bignum.h
1#ifndef INTERNAL_BIGNUM_H /*-*-C-*-vi:se ft=c:*/
2#define INTERNAL_BIGNUM_H
11#include "ruby/internal/config.h" /* for HAVE_LIBGMP */
12#include <stddef.h> /* for size_t */
13
14#ifdef HAVE_SYS_TYPES_H
15# include <sys/types.h> /* for ssize_t (note: on Windows ssize_t is */
16#endif /* `#define`d in ruby/config.h) */
17
18#include "ruby/internal/stdbool.h" /* for bool */
19#include "ruby/ruby.h" /* for struct RBasic */
20
21#ifndef BDIGIT
22# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
23# define BDIGIT unsigned int
24# define SIZEOF_BDIGIT SIZEOF_INT
25# define BDIGIT_DBL unsigned LONG_LONG
26# define BDIGIT_DBL_SIGNED LONG_LONG
27# define PRI_BDIGIT_PREFIX ""
28# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
29# elif SIZEOF_INT*2 <= SIZEOF_LONG
30# define BDIGIT unsigned int
31# define SIZEOF_BDIGIT SIZEOF_INT
32# define BDIGIT_DBL unsigned long
33# define BDIGIT_DBL_SIGNED long
34# define PRI_BDIGIT_PREFIX ""
35# define PRI_BDIGIT_DBL_PREFIX "l"
36# elif SIZEOF_SHORT*2 <= SIZEOF_LONG
37# define BDIGIT unsigned short
38# define SIZEOF_BDIGIT SIZEOF_SHORT
39# define BDIGIT_DBL unsigned long
40# define BDIGIT_DBL_SIGNED long
41# define PRI_BDIGIT_PREFIX "h"
42# define PRI_BDIGIT_DBL_PREFIX "l"
43# else
44# define BDIGIT unsigned short
45# define SIZEOF_BDIGIT (SIZEOF_LONG/2)
46# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG
47# define BDIGIT_DBL unsigned long
48# define BDIGIT_DBL_SIGNED long
49# define PRI_BDIGIT_PREFIX "h"
50# define PRI_BDIGIT_DBL_PREFIX "l"
51# endif
52#endif
53
54#ifndef SIZEOF_ACTUAL_BDIGIT
55# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT
56#endif
57
58#ifdef PRI_BDIGIT_PREFIX
59# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
60# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
61# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
62# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
63# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
64# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
65#endif
66
67#ifdef PRI_BDIGIT_DBL_PREFIX
68# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
69# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
70# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
71# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
72# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
73# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
74#endif
75
76#define RBIGNUM(obj) ((struct RBignum *)(obj))
77#define BIGNUM_SIGN_BIT FL_USER1
78#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2)
79#define BIGNUM_EMBED_LEN_NUMBITS 3
80#define BIGNUM_EMBED_LEN_MASK \
81 (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT)
82#define BIGNUM_EMBED_LEN_SHIFT \
83 (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */
84#ifndef BIGNUM_EMBED_LEN_MAX
85# if (SIZEOF_VALUE*RBIMPL_RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1
86# define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RBIMPL_RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT)
87# else
88# define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1)
89# endif
90#endif
91
92enum rb_int_parse_flags {
93 RB_INT_PARSE_SIGN = 0x01,
94 RB_INT_PARSE_UNDERSCORE = 0x02,
95 RB_INT_PARSE_PREFIX = 0x04,
96 RB_INT_PARSE_ALL = 0x07,
97 RB_INT_PARSE_DEFAULT = 0x07,
98};
99
100struct RBignum {
101 struct RBasic basic;
102 union {
103 struct {
104 size_t len;
105 BDIGIT *digits;
106 } heap;
107 BDIGIT ary[BIGNUM_EMBED_LEN_MAX];
108 } as;
109};
110
111/* bignum.c */
112extern const char ruby_digitmap[];
113double rb_big_fdiv_double(VALUE x, VALUE y);
114VALUE rb_big_uminus(VALUE x);
115VALUE rb_big_hash(VALUE);
116VALUE rb_big_odd_p(VALUE);
117VALUE rb_big_even_p(VALUE);
118size_t rb_big_size(VALUE);
119VALUE rb_integer_float_cmp(VALUE x, VALUE y);
120VALUE rb_integer_float_eq(VALUE x, VALUE y);
121VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception);
122VALUE rb_big_comp(VALUE x);
123VALUE rb_big_aref(VALUE x, VALUE y);
124VALUE rb_big_aref2(VALUE num, VALUE beg, VALUE len);
125VALUE rb_big_abs(VALUE x);
126VALUE rb_big_size_m(VALUE big);
127VALUE rb_big_bit_length(VALUE big);
128VALUE rb_big_remainder(VALUE x, VALUE y);
129VALUE rb_big_gt(VALUE x, VALUE y);
130VALUE rb_big_ge(VALUE x, VALUE y);
131VALUE rb_big_lt(VALUE x, VALUE y);
132VALUE rb_big_le(VALUE x, VALUE y);
133VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num);
134VALUE rb_big_isqrt(VALUE n);
135static inline bool BIGNUM_SIGN(VALUE b);
136static inline bool BIGNUM_POSITIVE_P(VALUE b);
137static inline bool BIGNUM_NEGATIVE_P(VALUE b);
138static inline void BIGNUM_SET_SIGN(VALUE b, bool sign);
139static inline void BIGNUM_NEGATE(VALUE b);
140static inline size_t BIGNUM_LEN(VALUE b);
141static inline BDIGIT *BIGNUM_DIGITS(VALUE b);
142static inline int BIGNUM_LENINT(VALUE b);
143static inline bool BIGNUM_EMBED_P(VALUE b);
144
145RUBY_SYMBOL_EXPORT_BEGIN
146/* bignum.c (export) */
147VALUE rb_big_mul_normal(VALUE x, VALUE y);
148VALUE rb_big_mul_balance(VALUE x, VALUE y);
149VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
150VALUE rb_big_mul_toom3(VALUE x, VALUE y);
151VALUE rb_big_sq_fast(VALUE x);
152VALUE rb_big_divrem_normal(VALUE x, VALUE y);
153VALUE rb_big2str_poweroftwo(VALUE x, int base);
154VALUE rb_big2str_generic(VALUE x, int base);
155VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck);
156VALUE rb_str2big_normal(VALUE arg, int base, int badcheck);
157VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck);
158#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
159VALUE rb_big_mul_gmp(VALUE x, VALUE y);
160VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
161VALUE rb_big2str_gmp(VALUE x, int base);
162VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
163#endif
164VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
165RUBY_SYMBOL_EXPORT_END
166
167#if defined(HAVE_INT128_T)
168VALUE rb_int128t2big(int128_t n);
169#endif
170
171/* sign: positive:1, negative:0 */
172static inline bool
173BIGNUM_SIGN(VALUE b)
174{
175 return FL_TEST_RAW(b, BIGNUM_SIGN_BIT);
176}
177
178static inline bool
179BIGNUM_POSITIVE_P(VALUE b)
180{
181 return BIGNUM_SIGN(b);
182}
183
184static inline bool
185BIGNUM_NEGATIVE_P(VALUE b)
186{
187 return ! BIGNUM_POSITIVE_P(b);
188}
189
190static inline void
191BIGNUM_SET_SIGN(VALUE b, bool sign)
192{
193 if (sign) {
194 FL_SET_RAW(b, BIGNUM_SIGN_BIT);
195 }
196 else {
197 FL_UNSET_RAW(b, BIGNUM_SIGN_BIT);
198 }
199}
200
201static inline void
202BIGNUM_NEGATE(VALUE b)
203{
204 FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT);
205}
206
207static inline size_t
208BIGNUM_LEN(VALUE b)
209{
210 if (! BIGNUM_EMBED_P(b)) {
211 return RBIGNUM(b)->as.heap.len;
212 }
213 else {
214 size_t ret = RBASIC(b)->flags;
215 ret &= BIGNUM_EMBED_LEN_MASK;
216 ret >>= BIGNUM_EMBED_LEN_SHIFT;
217 return ret;
218 }
219}
220
221static inline int
222BIGNUM_LENINT(VALUE b)
223{
224 return rb_long2int(BIGNUM_LEN(b));
225}
226
227/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
228static inline BDIGIT *
229BIGNUM_DIGITS(VALUE b)
230{
231 if (BIGNUM_EMBED_P(b)) {
232 return RBIGNUM(b)->as.ary;
233 }
234 else {
235 return RBIGNUM(b)->as.heap.digits;
236 }
237}
238
239static inline bool
240BIGNUM_EMBED_P(VALUE b)
241{
242 return FL_TEST_RAW(b, BIGNUM_EMBED_FLAG);
243}
244
245#endif /* INTERNAL_BIGNUM_H */
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:133
#define FL_REVERSE_RAW
Old name of RB_FL_REVERSE_RAW.
Definition fl_type.h:127
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:131
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:129
int len
Length of the buffer.
Definition io.h:8
#define rb_long2int
Just another name of rb_long2int_inline.
Definition long.h:62
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
C99 shim for <stdbool.h>
Ruby object's base components.
Definition rbasic.h:69
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40