Ruby: include/ruby/internal/arithmetic/long.h Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

long.h
Go to the documentation of this file.
1#ifndef RBIMPL_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_ARITHMETIC_LONG_H
31#include "ruby/internal/config.h"
32#include "ruby/internal/arithmetic/fixnum.h" /* FIXABLE */
33#include "ruby/internal/arithmetic/intptr_t.h" /* rb_int2big etc.*/
34#include "ruby/internal/assume.h"
35#include "ruby/internal/attr/artificial.h"
36#include "ruby/internal/attr/cold.h"
37#include "ruby/internal/attr/const.h"
38#include "ruby/internal/attr/constexpr.h"
39#include "ruby/internal/attr/noreturn.h"
40#include "ruby/internal/cast.h"
41#include "ruby/internal/dllexport.h"
42#include "ruby/internal/special_consts.h" /* FIXNUM_FLAG */
43#include "ruby/internal/value.h"
44#include "ruby/assert.h"
45
46#define FIX2LONG RB_FIX2LONG
47#define FIX2ULONG RB_FIX2ULONG
48#define INT2FIX RB_INT2FIX
49#define LONG2FIX RB_INT2FIX
50#define LONG2NUM RB_LONG2NUM
51#define NUM2LONG RB_NUM2LONG
52#define NUM2ULONG RB_NUM2ULONG
53#define RB_FIX2LONG rb_fix2long
54#define RB_FIX2ULONG rb_fix2ulong
55#define RB_LONG2FIX RB_INT2FIX
56#define RB_LONG2NUM rb_long2num_inline
57#define RB_NUM2LONG rb_num2long_inline
58#define RB_NUM2ULONG rb_num2ulong_inline
59#define RB_ULONG2NUM rb_ulong2num_inline
60#define ULONG2NUM RB_ULONG2NUM
61#define rb_fix_new RB_INT2FIX
62#define rb_long2int rb_long2int_inline
63
65#define RB_INT2FIX RB_INT2FIX
68 RBIMPL_SYMBOL_EXPORT_BEGIN()
69
70 RBIMPL_ATTR_NORETURN()
71 RBIMPL_ATTR_COLD()
72void rb_out_of_int(SIGNED_VALUE num);
73
74long rb_num2long(VALUE num);
75unsigned long rb_num2ulong(VALUE num);
76 RBIMPL_SYMBOL_EXPORT_END()
77
78 RBIMPL_ATTR_CONST_UNLESS_DEBUG()
79 RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
80 RBIMPL_ATTR_ARTIFICIAL()
81static inline VALUE
82RB_INT2FIX(long i)
83{
84 RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(i));
85
86 /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully
87 * defined. Also it can be compiled into a single LEA instruction. */
88 const unsigned long j = i;
89 const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG;
90 const long l = k;
91 const SIGNED_VALUE m = l; /* Sign extend */
92 const VALUE n = m;
93
94 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n));
95 return n;
96}
97
98static inline int
99rb_long2int_inline(long n)
100{
101 int i = RBIMPL_CAST((int)n);
102
103 if /* constexpr */ (sizeof(long) <= sizeof(int)) {
104 RBIMPL_ASSUME(i == n);
105 }
106
107 if (i != n)
108 rb_out_of_int(n);
109
110 return i;
111}
112
113 RBIMPL_ATTR_CONST_UNLESS_DEBUG()
114 RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
115static inline long
116rbimpl_fix2long_by_idiv(VALUE x)
117{
118 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
119
120 /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because
121 * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1
122 * below. */
123 const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG;
124 const SIGNED_VALUE z = y / 2;
125 const long w = RBIMPL_CAST((long)z);
126
127 RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w));
128 return w;
129}
130
131 RBIMPL_ATTR_CONST_UNLESS_DEBUG()
132 RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
133static inline long
134rbimpl_fix2long_by_shift(VALUE x)
135{
136 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
137
138 /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this
139 * is noticeably faster than above. */
140 const SIGNED_VALUE y = x;
141 const SIGNED_VALUE z = y >> 1;
142 const long w = RBIMPL_CAST((long)z);
143
144 RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w));
145 return w;
146}
147
148 RBIMPL_ATTR_CONST()
149 RBIMPL_ATTR_CONSTEXPR(CXX11)
150static inline bool
151rbimpl_right_shift_is_arithmetic_p(void)
152{
153 return (-1 >> 1) == -1;
154}
155
156 RBIMPL_ATTR_CONST_UNLESS_DEBUG()
157 RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
158static inline long
159rb_fix2long(VALUE x)
160{
161 if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) {
162 return rbimpl_fix2long_by_shift(x);
163 }
164 else {
165 return rbimpl_fix2long_by_idiv(x);
166 }
167}
168
169 RBIMPL_ATTR_CONST_UNLESS_DEBUG()
170 RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
171static inline unsigned long
172rb_fix2ulong(VALUE x)
173{
174 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
175 return rb_fix2long(x);
176}
177
178static inline long
179rb_num2long_inline(VALUE x)
180{
181 if (RB_FIXNUM_P(x))
182 return RB_FIX2LONG(x);
183 else
184 return rb_num2long(x);
185}
186
187static inline unsigned long
188rb_num2ulong_inline(VALUE x)
189{
190 /* This (negative fixnum would become a large unsigned long while negative
191 * bignum is an exception) has been THE behaviour of NUM2ULONG since the
192 * beginning. It is strange, but we can no longer change how it works at
193 * this moment. We have to get by with it. See also:
194 * https://bugs.ruby-lang.org/issues/9089 */
195 if (RB_FIXNUM_P(x))
196 return RB_FIX2ULONG(x);
197 else
198 return rb_num2ulong(x);
199}
200
201static inline VALUE
202rb_long2num_inline(long v)
203{
204 if (RB_FIXABLE(v))
205 return RB_LONG2FIX(v);
206 else
207 return rb_int2big(v);
208}
209
210static inline VALUE
211rb_ulong2num_inline(unsigned long v)
212{
213 if (RB_POSFIXABLE(v))
214 return RB_LONG2FIX(v);
215 else
216 return rb_uint2big(v);
217}
218
227#if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14
228# /* C++ can write constexpr as enum values. */
229
230#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
231# undef INT2FIX
232# define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG)
233
234#else
235# undef INT2FIX
236# define INT2FIX(i) \
237 __builtin_choose_expr( \
238 __builtin_constant_p(i), \
239 RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \
240 RB_INT2FIX(i))
241#endif
244#endif /* RBIMPL_ARITHMETIC_LONG_H */
artificial.h
Defines RBIMPL_ATTR_ARTIFICIAL.
RBIMPL_ATTR_ARTIFICIAL
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition: artificial.h:43
assert.h
RBIMPL_ASSERT_OR_ASSUME
#define RBIMPL_ASSERT_OR_ASSUME(expr)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition: assert.h:229
rb_int2big
VALUE rb_int2big(intptr_t n)
Definition: bignum.c:3186
rb_uint2big
VALUE rb_uint2big(uintptr_t n)
Definition: bignum.c:3164
cast.h
Defines RBIMPL_CAST.
cold.h
Defines RBIMPL_ATTR_COLD.
RBIMPL_ATTR_COLD
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition: cold.h:34
const.h
Defines RBIMPL_ATTR_CONST.
RBIMPL_ATTR_CONST
#define RBIMPL_ATTR_CONST()
Wraps (or simulates) __attribute__((const))
Definition: const.h:36
RBIMPL_ATTR_CONST_UNLESS_DEBUG
#define RBIMPL_ATTR_CONST_UNLESS_DEBUG()
Enables RBIMPL_ATTR_CONST iff.
Definition: const.h:41
constexpr.h
RBIMPL_ATTR_CONSTEXPR.
RBIMPL_ATTR_CONSTEXPR
#define RBIMPL_ATTR_CONSTEXPR(_)
Wraps (or simulates) C++11 constexpr.
Definition: constexpr.h:75
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG
#define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_)
Enables RBIMPL_ATTR_CONSTEXPR iff.
Definition: constexpr.h:80
dllexport.h
Tewaking visibility of C variables/functions.
RBIMPL_SYMBOL_EXPORT_END
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition: dllexport.h:86
RBIMPL_SYMBOL_EXPORT_BEGIN
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition: dllexport.h:77
num
big_t * num
Definition: enough.c:232
fixnum.h
Handling of integers formerly known as Fixnums.
RB_FIXABLE
#define RB_FIXABLE(_)
Definition: fixnum.h:40
RB_POSFIXABLE
#define RB_POSFIXABLE(_)
Definition: fixnum.h:38
config.h
Thin wrapper to ruby/config.h.
assume.h
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
RBIMPL_ASSUME
#define RBIMPL_ASSUME(_)
Wraps (or simulates) __builtin_unreachable.
Definition: assume.h:79
intptr_t.h
Arithmetic conversion between C's intptr_t and Ruby's.
long
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
RB_FIX2ULONG
#define RB_FIX2ULONG
Definition: long.h:54
RB_FIX2LONG
#define RB_FIX2LONG
Definition: long.h:53
rb_out_of_int
void rb_out_of_int(SIGNED_VALUE num)
Definition: numeric.c:2969
rb_num2long
long rb_num2long(VALUE num)
Definition: numeric.c:2894
RB_LONG2FIX
#define RB_LONG2FIX
Definition: long.h:55
rb_num2ulong
unsigned long rb_num2ulong(VALUE num)
Definition: numeric.c:2963
noreturn.h
Defines RBIMPL_ATTR_NORETURN.
RBIMPL_ATTR_NORETURN
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]]
Definition: noreturn.h:38
special_consts.h
Defines enum ruby_special_consts.
RUBY_FIXNUM_FLAG
@ RUBY_FIXNUM_FLAG
Definition: special_consts.h:92
value.h
Defines VALUE and ID.
VALUE
unsigned long VALUE
Definition: value.h:38
SIGNED_VALUE
#define SIGNED_VALUE
Definition: value.h:40