blob: 36485167cc34e42a49c8ec35789ec2870ba9731f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
/** \noop-*-C++-*-vi:ft=cpp
* @file
* @author Ruby developers <[email protected]>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RUBY3` or `ruby3` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `int` and Ruby's.
*/
#ifndef RUBY3_ARITHMETIC_INT_H
#define RUBY3_ARITHMETIC_INT_H
#include "ruby/3/config.h"
#include "ruby/3/arithmetic/fixnum.h"
#include "ruby/3/arithmetic/intptr_t.h"
#include "ruby/3/arithmetic/long.h"
#include "ruby/3/attr/artificial.h"
#include "ruby/3/attr/const.h"
#include "ruby/3/attr/constexpr.h"
#include "ruby/3/compiler_is.h"
#include "ruby/3/dllexport.h"
#include "ruby/3/special_consts.h"
#include "ruby/3/value.h"
#include "ruby/assert.h"
#define RB_INT2NUM rb_int2num_inline
#define RB_NUM2INT rb_num2int_inline
#define RB_UINT2NUM rb_uint2num_inline
#define FIX2INT RB_FIX2INT
#define FIX2UINT RB_FIX2UINT
#define INT2NUM RB_INT2NUM
#define NUM2INT RB_NUM2INT
#define NUM2UINT RB_NUM2UINT
#define UINT2NUM RB_UINT2NUM
/** @cond INTERNAL_MACRO */
#define RB_FIX2INT RB_FIX2INT
#define RB_NUM2UINT RB_NUM2UINT
#define RB_FIX2UINT RB_FIX2UINT
/** @endcond */
RUBY3_SYMBOL_EXPORT_BEGIN()
long rb_num2int(VALUE);
long rb_fix2int(VALUE);
unsigned long rb_num2uint(VALUE);
unsigned long rb_fix2uint(VALUE);
RUBY3_SYMBOL_EXPORT_END()
RUBY3_ATTR_ARTIFICIAL()
static inline int
RB_FIX2INT(VALUE x)
{
/* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if
* that is a desired behaviour but just preserve backwards compatilibily.
*/
#if 0
RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
#endif
long ret;
if /* constexpr */ (sizeof(int) < sizeof(long)) {
ret = rb_fix2int(x);
}
else {
ret = RB_FIX2LONG(x);
}
return RUBY3_CAST((int)ret);
}
static inline int
rb_num2int_inline(VALUE x)
{
long ret;
if /* constexpr */ (sizeof(int) == sizeof(long)) {
ret = RB_NUM2LONG(x);
}
else if (RB_FIXNUM_P(x)) {
ret = rb_fix2int(x);
}
else {
ret = rb_num2int(x);
}
return RUBY3_CAST((int)ret);
}
RUBY3_ATTR_ARTIFICIAL()
static inline unsigned int
RB_NUM2UINT(VALUE x)
{
unsigned long ret;
if /* constexpr */ (sizeof(int) < sizeof(long)) {
ret = rb_num2uint(x);
}
else {
ret = RB_NUM2ULONG(x);
}
return RUBY3_CAST((unsigned int)ret);
}
RUBY3_ATTR_ARTIFICIAL()
static inline unsigned int
RB_FIX2UINT(VALUE x)
{
#if 0 /* Ditto for RB_FIX2INT. */
RUBY3_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
#endif
unsigned long ret;
if /* constexpr */ (sizeof(int) < sizeof(long)) {
ret = rb_fix2uint(x);
}
else {
ret = RB_FIX2ULONG(x);
}
return RUBY3_CAST((unsigned int)ret);
}
RUBY3_WARNING_PUSH()
#if RUBY3_COMPILER_IS(GCC)
RUBY3_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */
#elif RUBY3_HAS_WARNING("-Wtautological-constant-out-of-range-compare")
RUBY3_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare)
#endif
static inline VALUE
rb_int2num_inline(int v)
{
if (RB_FIXABLE(v))
return RB_INT2FIX(v);
else
return rb_int2big(v);
}
static inline VALUE
rb_uint2num_inline(unsigned int v)
{
if (RB_POSFIXABLE(v))
return RB_LONG2FIX(v);
else
return rb_uint2big(v);
}
RUBY3_WARNING_POP()
#endif /* RUBY3_ARITHMETIC_INT_H */
|