Ruby  3.4.0dev (2024-11-22 revision 37a72b0150ec36b4ea27175039afc28c62207b0c)
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"
40 #include "ruby/internal/cast.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
65 #define RB_INT2FIX RB_INT2FIX
69 
78 void rb_out_of_int(SIGNED_VALUE num);
79 
88 long rb_num2long(VALUE num);
89 
98 unsigned long rb_num2ulong(VALUE num);
100 
110 static inline VALUE
111 RB_INT2FIX(long i)
112 {
114 
115  /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully
116  * defined. Also it can be compiled into a single LEA instruction. */
117  const unsigned long j = RBIMPL_CAST((unsigned long)i);
118  const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG;
119  const long l = RBIMPL_CAST((long)k);
120  const SIGNED_VALUE m = l; /* Sign extend */
121  const VALUE n = RBIMPL_CAST((VALUE)m);
122 
124  return n;
125 }
126 
134 static inline int
136 {
137  int i = RBIMPL_CAST((int)n);
138 
139  if /* constexpr */ (sizeof(long) <= sizeof(int)) {
140  RBIMPL_ASSUME(i == n);
141  }
142 
143  if (i != n)
144  rb_out_of_int(n);
145 
146  return i;
147 }
148 
161 static inline long
162 rbimpl_fix2long_by_idiv(VALUE x)
163 {
165 
166  /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because
167  * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1
168  * below. */
169  const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)(x - RUBY_FIXNUM_FLAG));
170  const SIGNED_VALUE z = y / 2;
171  const long w = RBIMPL_CAST((long)z);
172 
174  return w;
175 }
176 
189 static inline long
190 rbimpl_fix2long_by_shift(VALUE x)
191 {
193 
194  /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this
195  * is noticeably faster than above. */
196  const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)x);
197  const SIGNED_VALUE z = y >> 1;
198  const long w = RBIMPL_CAST((long)z);
199 
201  return w;
202 }
203 
215 static inline bool
216 rbimpl_right_shift_is_arithmetic_p(void)
217 {
218  return (-1 >> 1) == -1;
219 }
220 
230 static inline long
232 {
233  if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) {
234  return rbimpl_fix2long_by_shift(x);
235  }
236  else {
237  return rbimpl_fix2long_by_idiv(x);
238  }
239 }
240 
251 static inline unsigned long
253 {
255  return RBIMPL_CAST((unsigned long)rb_fix2long(x));
256 }
257 
266 static inline long
268 {
269  if (RB_FIXNUM_P(x))
270  return RB_FIX2LONG(x);
271  else
272  return rb_num2long(x);
273 }
274 
292 static inline unsigned long
294 {
295  if (RB_FIXNUM_P(x))
296  return RB_FIX2ULONG(x);
297  else
298  return rb_num2ulong(x);
299 }
300 
307 static inline VALUE
309 {
310  if (RB_FIXABLE(v))
311  return RB_LONG2FIX(v);
312  else
313  return rb_int2big(v);
314 }
315 
322 static inline VALUE
323 rb_ulong2num_inline(unsigned long v)
324 {
325  if (RB_POSFIXABLE(v))
326  return RB_LONG2FIX(RBIMPL_CAST((long)v));
327  else
328  return rb_uint2big(v);
329 }
330 
339 #if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14
340 # /* C++ can write constexpr as enum values. */
341 
342 #elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
343 # undef INT2FIX
344 # define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG)
345 
346 #else
347 # undef INT2FIX
348 # define INT2FIX(i) \
349  __builtin_choose_expr( \
350  __builtin_constant_p(i), \
351  RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \
352  RB_INT2FIX(i))
353 #endif
356 #endif /* RBIMPL_ARITHMETIC_LONG_H */
Defines RBIMPL_ATTR_ARTIFICIAL.
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition: artificial.h:41
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition: assert.h:311
Defines RBIMPL_ATTR_COLD.
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition: cold.h:32
Defines RBIMPL_ATTR_CONST.
#define RBIMPL_ATTR_CONST_UNLESS_DEBUG()
Enables RBIMPL_ATTR_CONST if and only if.
Definition: const.h:41
RBIMPL_ATTR_CONSTEXPR.
#define RBIMPL_ATTR_CONSTEXPR(_)
Wraps (or simulates) C++11 constexpr.
Definition: constexpr.h:74
#define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_)
Enables RBIMPL_ATTR_CONSTEXPR if and only if.
Definition: constexpr.h:79
Tweaking visibility of C variables/functions.
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition: dllexport.h:74
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition: dllexport.h:65
Handling of integers formerly known as Fixnums.
#define RB_FIXABLE(_)
Checks if the passed value is in range of fixnum.
Definition: fixnum.h:52
#define RB_POSFIXABLE(_)
Checks if the passed value is in range of fixnum, assuming it is a positive number.
Definition: fixnum.h:43
RBIMPL_ATTR_CONST() int rb_io_oflags_fmode(int oflags)
Converts an oflags (that rb_io_modestr_oflags() returns) to a fmode (that rb_io_mode_flags() returns)...
RBIMPL_ATTR_NORETURN() void rb_eof_error(void)
Utility function to raise rb_eEOFError.
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
#define RBIMPL_ASSUME
Wraps (or simulates) __assume.
Definition: assume.h:73
Arithmetic conversion between C's intptr_t and Ruby's.
VALUE rb_uint2big(uintptr_t i)
Converts a C's intptr_t into an instance of rb_cInteger.
Definition: bignum.c:3200
VALUE rb_int2big(intptr_t i)
Converts a C's intptr_t into an instance of rb_cInteger.
Definition: bignum.c:3222
static long rb_num2long_inline(VALUE x)
Converts an instance of rb_cNumeric into C's long.
Definition: long.h:267
static VALUE RB_INT2FIX(long i)
Converts a C's long into an instance of rb_cInteger.
Definition: long.h:111
#define RB_FIX2ULONG
Just another name of rb_fix2ulong.
Definition: long.h:54
static unsigned long rb_num2ulong_inline(VALUE x)
Converts an instance of rb_cNumeric into C's unsigned long.
Definition: long.h:293
static int rb_long2int_inline(long n)
Checks if int can hold the given integer.
Definition: long.h:135
static VALUE rb_ulong2num_inline(unsigned long v)
Converts a C's unsigned long into an instance of rb_cInteger.
Definition: long.h:323
static long rb_fix2long(VALUE x)
Converts a Fixnum into C's long.
Definition: long.h:231
#define RB_FIX2LONG
Just another name of rb_fix2long.
Definition: long.h:53
void rb_out_of_int(SIGNED_VALUE num)
This is an utility function to raise an rb_eRangeError.
Definition: numeric.c:3271
long rb_num2long(VALUE num)
Converts an instance of rb_cNumeric into C's long.
Definition: numeric.c:3196
#define RB_LONG2FIX
Just another name of RB_INT2FIX.
Definition: long.h:55
unsigned long rb_num2ulong(VALUE num)
Converts an instance of rb_cNumeric into C's unsigned long.
Definition: numeric.c:3265
static VALUE rb_long2num_inline(long v)
Converts a C's long into an instance of rb_cInteger.
Definition: long.h:308
static unsigned long rb_fix2ulong(VALUE x)
Converts a Fixnum into C's unsigned long.
Definition: long.h:252
Defines RBIMPL_ATTR_NORETURN.
#define inline
Old Visual Studio versions do not support the inline keyword, so we need to define it to be __inline.
Definition: defines.h:88
Defines enum ruby_special_consts.
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.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40