Ruby 4.1.0dev (2026-10-30 revision 7704181e64db25a20de9d5e89ff9661af4fd1820)
len_t.h
Go to the documentation of this file.
1#ifndef RBIMPL_ARITHMETIC_LEN_T_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_ARITHMETIC_LEN_T_H
23#include "ruby/internal/config.h"
27#include "ruby/internal/cast.h"
28#include "ruby/internal/value.h"
29
30#define FIX2LEN RB_FIX2LEN
31#define FIX2ULEN RB_FIX2ULEN
32#define LEN2FIX RB_LEN2FIX
33#define LEN2NUM RB_LEN2NUM
34#define NUM2LEN RB_NUM2LEN
35#define ULEN2NUM RB_ULEN2NUM
36#define NUM2ULEN RB_NUM2ULEN
37#define rb_len2int rb_len2int_inline
38#define rb_len2long rb_len2long_inline
40#if SIZEOF_RB_LEN_T > SIZEOF_LONG
41# define RB_LEN2NUM RB_LL2NUM
42# define RB_NUM2LEN RB_NUM2LL
43# define RB_ULEN2NUM RB_ULL2NUM
44# define RB_NUM2ULEN RB_NUM2ULL
45#else
47# define RB_LEN2NUM RB_LONG2NUM
48
50# define RB_NUM2LEN RB_NUM2LONG
51
53# define RB_ULEN2NUM RB_ULONG2NUM
54
56# define RB_NUM2ULEN RB_NUM2ULONG
57#endif
58
59#define RB_FIX2LEN rb_fix2len
60#define RB_FIX2ULEN rb_fix2ulen
61
72static inline VALUE
74{
76
77 /* :NOTE: rb_ulen_t should be same as VALUE. */
78 const rb_ulen_t j = RBIMPL_CAST((rb_ulen_t)i);
79 const rb_ulen_t k = (j << 1) + RUBY_FIXNUM_FLAG;
80 const rb_len_t l = RBIMPL_CAST((rb_len_t)k);
81 const SIGNED_VALUE m = l; /* Sign extend */
82 const VALUE n = RBIMPL_CAST((VALUE)m);
83
85 return n;
86}
87
97static inline VALUE
99{
100 return rb_len2fix(i);
101}
102
115static inline rb_len_t
116rbimpl_fix2len_by_idiv(VALUE x)
117{
119
120 /* :NOTE: VALUE should be same size as `rb_len_t`. (x-1)/2 never overflows
121 * because RB_FIXNUM_P(x) holds. Also it has no portability issue like
122 * y>>1 below. */
123 const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)(x - RUBY_FIXNUM_FLAG));
124 const SIGNED_VALUE z = y / 2;
125 const rb_len_t w = RBIMPL_CAST((rb_len_t)z);
126
128 return w;
129}
130
143static inline rb_len_t
144rbimpl_fix2len_by_shift(VALUE x)
145{
147
148 /* :NOTE: VALUE should be same size as `rb_len_t`. If right shift is
149 * arithmetic, this is noticeably faster than above. */
150 const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)x);
151 const SIGNED_VALUE z = y >> 1;
152 const rb_len_t w = RBIMPL_CAST((rb_len_t)z);
153
155 return w;
156}
157
167static const bool rbimpl_right_shift_is_arithmetic_p = (-1 >> 1) == -1;
168
178static inline rb_len_t
180{
181 if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p) {
182 return rbimpl_fix2len_by_shift(x);
183 }
184 else {
185 return rbimpl_fix2len_by_idiv(x);
186 }
187}
188
199static inline rb_ulen_t
201{
203 return RBIMPL_CAST((rb_ulen_t)rb_fix2len(x));
204}
205
213static inline int
215{
216 int i = RBIMPL_CAST((int)n);
217
218 if /* constexpr */ (sizeof(rb_len_t) <= sizeof(int)) {
219 RBIMPL_ASSUME(i == n);
220 }
221
222 if (i != n)
223 rb_out_of_int(n);
224
225 return i;
226}
227
235static inline long
237{
238 long l = RBIMPL_CAST((long)n);
239
240 if /* constexpr */ (sizeof(rb_len_t) <= sizeof(long)) {
241 RBIMPL_ASSUME(l == n);
242 }
243
244 if (l != n)
246
247 return l;
248}
249
257static inline long
259{
260 return rb_len2long(rb_fix2len(x));
261}
262
271static inline unsigned long
273{
274 return RBIMPL_CAST((unsigned long)rb_fix2ulen(x));
275}
276
277#endif /* RBIMPL_ARITHMETIC_LEN_T_H */
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition artificial.h:43
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
#define RBIMPL_ATTR_CONST_UNLESS_DEBUG()
Enables RBIMPL_ATTR_CONST if and only if.
Definition const.h:41
#define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_)
Enables RBIMPL_ATTR_CONSTEXPR if and only if.
Definition constexpr.h:79
#define RB_FIXABLE(_)
Checks if the passed value is in range of fixnum.
Definition fixnum.h:52
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
#define RBIMPL_ASSUME(_)
Wraps (or simulates) __builtin_unreachable.
Definition assume.h:76
Arithmetic conversion between C's long long and Ruby's.
static VALUE RB_INT2FIX(long i)
Converts a C's long into an instance of rb_cInteger.
Definition len_t.h:98
static VALUE rb_len2fix(rb_len_t i)
Converts a rb_len_t into an instance of rb_cInteger.
Definition len_t.h:73
static int rb_len2int_inline(rb_len_t n)
Checks if int can hold the given integer.
Definition len_t.h:214
static long rb_fix2long(VALUE x)
Converts a Fixnum into C's long.
Definition len_t.h:258
#define rb_len2long
Just another name of rb_len2long_inline.
Definition len_t.h:38
static rb_len_t rb_fix2len(VALUE x)
Converts a Fixnum into rb_len_t.
Definition len_t.h:179
static long rb_len2long_inline(rb_len_t n)
Checks if long can hold the given integer.
Definition len_t.h:236
static rb_ulen_t rb_fix2ulen(VALUE x)
Converts a Fixnum into rb_ulen_t.
Definition len_t.h:200
static unsigned long rb_fix2ulong(VALUE x)
Converts a Fixnum into C's unsigned long.
Definition len_t.h:272
Arithmetic conversion between C's long and Ruby's.
void rb_out_of_int(SIGNED_VALUE num)
This is an utility function to raise an rb_eRangeError.
Definition numeric.c:3191
void rb_out_of_long(SIGNED_VALUE num)
This is an utility function to raise an rb_eRangeError.
Definition numeric.c:3198
static bool RB_FIXNUM_P(VALUE obj)
Checks if the given object is a so-called Fixnum.
@ RUBY_FIXNUM_FLAG
Flag to denote a fixnum.
Defines VALUE and ID.
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
Definition value.h:142
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition value.h:63
unsigned long rb_ulen_t
An unsigned integer type that has the same width with rb_len_t.
Definition value.h:145
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40