Ruby 4.0.0dev (2025-12-06 revision 0346206d3eab2a8e659be0dd52aea6fc7b0ebb06)
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 "internal/compilers.h" /* for FLEX_ARY_LEN */
13#include <stddef.h> /* for size_t */
14
15#ifdef HAVE_SYS_TYPES_H
16# include <sys/types.h> /* for ssize_t (note: on Windows ssize_t is */
17#endif /* `#define`d in ruby/config.h) */
18
19#include "ruby/internal/stdbool.h" /* for bool */
20#include "ruby/ruby.h" /* for struct RBasic */
21
22#ifndef BDIGIT
23# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
24# define BDIGIT unsigned int
25# define SIZEOF_BDIGIT SIZEOF_INT
26# define BDIGIT_DBL unsigned LONG_LONG
27# define BDIGIT_DBL_SIGNED LONG_LONG
28# define PRI_BDIGIT_PREFIX ""
29# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
30# elif SIZEOF_INT*2 <= SIZEOF_LONG
31# define BDIGIT unsigned int
32# define SIZEOF_BDIGIT SIZEOF_INT
33# define BDIGIT_DBL unsigned long
34# define BDIGIT_DBL_SIGNED long
35# define PRI_BDIGIT_PREFIX ""
36# define PRI_BDIGIT_DBL_PREFIX "l"
37# elif SIZEOF_SHORT*2 <= SIZEOF_LONG
38# define BDIGIT unsigned short
39# define SIZEOF_BDIGIT SIZEOF_SHORT
40# define BDIGIT_DBL unsigned long
41# define BDIGIT_DBL_SIGNED long
42# define PRI_BDIGIT_PREFIX "h"
43# define PRI_BDIGIT_DBL_PREFIX "l"
44# else
45# define BDIGIT unsigned short
46# define SIZEOF_BDIGIT (SIZEOF_LONG/2)
47# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG
48# define BDIGIT_DBL unsigned long
49# define BDIGIT_DBL_SIGNED long
50# define PRI_BDIGIT_PREFIX "h"
51# define PRI_BDIGIT_DBL_PREFIX "l"
52# endif
53#endif
54
55#ifndef SIZEOF_ACTUAL_BDIGIT
56# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT
57#endif
58
59#ifdef PRI_BDIGIT_PREFIX
60# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
61# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
62# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
63# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
64# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
65# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
66#endif
67
68#ifdef PRI_BDIGIT_DBL_PREFIX
69# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
70# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
71# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
72# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
73# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
74# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
75#endif
76
77#define RBIGNUM(obj) ((struct RBignum *)(obj))
78#define BIGNUM_SIGN_BIT FL_USER1
79#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2)
80
81/* This is likely more bits than we need today and will also need adjustment if
82 * we change GC slot sizes.
83 */
84#define BIGNUM_EMBED_LEN_NUMBITS 9
85#define BIGNUM_EMBED_LEN_MASK \
86 (RUBY_FL_USER11 | RUBY_FL_USER10 | RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | \
87 RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3)
88#define BIGNUM_EMBED_LEN_SHIFT \
89 (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */
90#define BIGNUM_EMBED_LEN_MAX (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT)
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 /* This is a length 1 array because:
108 * 1. GCC has a bug that does not optimize C flexible array members
109 * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
110 * 2. Zero length arrays are not supported by all compilers
111 */
112 BDIGIT ary[1];
113 } as;
114};
115
116/* bignum.c */
117extern const char ruby_digitmap[];
118double rb_big_fdiv_double(VALUE x, VALUE y);
119VALUE rb_big_uminus(VALUE x);
120VALUE rb_big_hash(VALUE);
121VALUE rb_big_odd_p(VALUE);
122VALUE rb_big_even_p(VALUE);
123size_t rb_big_size(VALUE);
124VALUE rb_integer_float_cmp(VALUE x, VALUE y);
125VALUE rb_integer_float_eq(VALUE x, VALUE y);
126VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception);
127VALUE rb_big_comp(VALUE x);
128VALUE rb_big_aref(VALUE x, VALUE y);
129VALUE rb_big_aref2(VALUE num, VALUE beg, VALUE len);
130VALUE rb_big_abs(VALUE x);
131VALUE rb_big_size_m(VALUE big);
132VALUE rb_big_bit_length(VALUE big);
133VALUE rb_big_remainder(VALUE x, VALUE y);
134VALUE rb_big_gt(VALUE x, VALUE y);
135VALUE rb_big_ge(VALUE x, VALUE y);
136VALUE rb_big_lt(VALUE x, VALUE y);
137VALUE rb_big_le(VALUE x, VALUE y);
138VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num);
139VALUE rb_big_isqrt(VALUE n);
140static inline bool BIGNUM_SIGN(VALUE b);
141static inline bool BIGNUM_POSITIVE_P(VALUE b);
142static inline bool BIGNUM_NEGATIVE_P(VALUE b);
143static inline void BIGNUM_SET_SIGN(VALUE b, bool sign);
144static inline void BIGNUM_NEGATE(VALUE b);
145static inline size_t BIGNUM_LEN(VALUE b);
146static inline BDIGIT *BIGNUM_DIGITS(VALUE b);
147static inline int BIGNUM_LENINT(VALUE b);
148static inline bool BIGNUM_EMBED_P(VALUE b);
149
150RUBY_SYMBOL_EXPORT_BEGIN
151/* bignum.c (export) */
152VALUE rb_big_mul_normal(VALUE x, VALUE y);
153VALUE rb_big_mul_balance(VALUE x, VALUE y);
154VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
155VALUE rb_big_mul_toom3(VALUE x, VALUE y);
156VALUE rb_big_sq_fast(VALUE x);
157VALUE rb_big_divrem_normal(VALUE x, VALUE y);
158VALUE rb_big2str_poweroftwo(VALUE x, int base);
159VALUE rb_big2str_generic(VALUE x, int base);
160VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck);
161VALUE rb_str2big_normal(VALUE arg, int base, int badcheck);
162VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck);
163#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
164VALUE rb_big_mul_gmp(VALUE x, VALUE y);
165VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
166VALUE rb_big2str_gmp(VALUE x, int base);
167VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
168#endif
169VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
170RUBY_SYMBOL_EXPORT_END
171
172#if HAVE_LONG_LONG
173VALUE rb_ull2big(unsigned LONG_LONG n);
174VALUE rb_ll2big(LONG_LONG n);
175#endif
176
177#if defined(HAVE_INT128_T)
178VALUE rb_uint128t2big(uint128_t n);
179VALUE rb_int128t2big(int128_t n);
180#endif
181
182/* sign: positive:1, negative:0 */
183static inline bool
184BIGNUM_SIGN(VALUE b)
185{
186 return FL_TEST_RAW(b, BIGNUM_SIGN_BIT);
187}
188
189static inline bool
190BIGNUM_POSITIVE_P(VALUE b)
191{
192 return BIGNUM_SIGN(b);
193}
194
195static inline bool
196BIGNUM_NEGATIVE_P(VALUE b)
197{
198 return ! BIGNUM_POSITIVE_P(b);
199}
200
201static inline void
202BIGNUM_SET_SIGN(VALUE b, bool sign)
203{
204 if (sign) {
205 FL_SET_RAW(b, BIGNUM_SIGN_BIT);
206 }
207 else {
208 FL_UNSET_RAW(b, BIGNUM_SIGN_BIT);
209 }
210}
211
212static inline void
213BIGNUM_NEGATE(VALUE b)
214{
215 FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT);
216}
217
218static inline size_t
219BIGNUM_LEN(VALUE b)
220{
221 if (! BIGNUM_EMBED_P(b)) {
222 return RBIGNUM(b)->as.heap.len;
223 }
224 else {
225 size_t ret = RBASIC(b)->flags;
226 ret &= BIGNUM_EMBED_LEN_MASK;
227 ret >>= BIGNUM_EMBED_LEN_SHIFT;
228 return ret;
229 }
230}
231
232static inline int
233BIGNUM_LENINT(VALUE b)
234{
235 return rb_long2int(BIGNUM_LEN(b));
236}
237
238/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
239static inline BDIGIT *
240BIGNUM_DIGITS(VALUE b)
241{
242 if (BIGNUM_EMBED_P(b)) {
243 return RBIGNUM(b)->as.ary;
244 }
245 else {
246 return RBIGNUM(b)->as.heap.digits;
247 }
248}
249
250static inline bool
251BIGNUM_EMBED_P(VALUE b)
252{
253 return FL_TEST_RAW(b, BIGNUM_EMBED_FLAG);
254}
255
256#endif /* INTERNAL_BIGNUM_H */
#define LONG_LONG
Definition long_long.h:38
#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