Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
numeric.h
Go to the documentation of this file.
1#ifndef INTERNAL_NUMERIC_H /*-*-C-*-vi:se ft=c:*/
2#define INTERNAL_NUMERIC_H
12#include "internal/bignum.h" /* for BIGNUM_POSITIVE_P */
13#include "internal/bits.h" /* for RUBY_BIT_ROTL */
14#include "internal/fixnum.h" /* for FIXNUM_POSITIVE_P */
15#include "internal/vm.h" /* for rb_method_basic_definition_p */
16#include "ruby/intern.h" /* for rb_cmperr */
17#include "ruby/ruby.h" /* for USE_FLONUM */
18
19#define ROUND_TO(mode, even, up, down) \
20 ((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \
21 (mode) == RUBY_NUM_ROUND_HALF_UP ? up : down)
22#define ROUND_FUNC(mode, name) \
23 ROUND_TO(mode, name##_half_even, name##_half_up, name##_half_down)
24#define ROUND_CALL(mode, name, args) \
25 ROUND_TO(mode, name##_half_even args, \
26 name##_half_up args, name##_half_down args)
27
28#ifndef ROUND_DEFAULT
29# define ROUND_DEFAULT RUBY_NUM_ROUND_HALF_UP
30#endif
31
37};
38
39struct RFloat {
40 struct RBasic basic;
42};
43
44#define RFLOAT(obj) ((struct RFloat *)(obj))
45
46/* numeric.c */
47int rb_num_to_uint(VALUE val, unsigned int *ret);
48VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl);
49double ruby_float_step_size(double beg, double end, double unit, int excl);
50int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless);
63VALUE rb_int2str(VALUE num, int base);
69double rb_int_fdiv_double(VALUE x, VALUE y);
81VALUE rb_float_ceil(VALUE num, int ndigits);
82VALUE rb_float_floor(VALUE x, int ndigits);
84static inline VALUE rb_num_compare_with_zero(VALUE num, ID mid);
85static inline int rb_num_positive_int_p(VALUE num);
86static inline int rb_num_negative_int_p(VALUE num);
87static inline double rb_float_flonum_value(VALUE v);
88static inline double rb_float_noflonum_value(VALUE v);
89static inline double rb_float_value_inline(VALUE v);
90static inline VALUE rb_float_new_inline(double d);
91static inline bool INT_POSITIVE_P(VALUE num);
92static inline bool INT_NEGATIVE_P(VALUE num);
93static inline bool FLOAT_ZERO_P(VALUE num);
94#define rb_float_value rb_float_value_inline
95#define rb_float_new rb_float_new_inline
96
97RUBY_SYMBOL_EXPORT_BEGIN
98/* numeric.c (export) */
99VALUE rb_int_positive_pow(long x, unsigned long y);
100RUBY_SYMBOL_EXPORT_END
101
104double ruby_float_mod(double x, double y);
106int rb_float_cmp(VALUE x, VALUE y);
108VALUE rb_fix_aref(VALUE fix, VALUE idx);
117
118static inline bool
119INT_POSITIVE_P(VALUE num)
120{
121 if (FIXNUM_P(num)) {
122 return FIXNUM_POSITIVE_P(num);
123 }
124 else {
125 return BIGNUM_POSITIVE_P(num);
126 }
127}
128
129static inline bool
130INT_NEGATIVE_P(VALUE num)
131{
132 if (FIXNUM_P(num)) {
133 return FIXNUM_NEGATIVE_P(num);
134 }
135 else {
136 return BIGNUM_NEGATIVE_P(num);
137 }
138}
139
140static inline bool
141FLOAT_ZERO_P(VALUE num)
142{
143 return RFLOAT_VALUE(num) == 0.0;
144}
145
146static inline VALUE
147rb_num_compare_with_zero(VALUE num, ID mid)
148{
149 VALUE zero = INT2FIX(0);
150 VALUE r = rb_check_funcall(num, mid, 1, &zero);
151 if (r == Qundef) {
152 rb_cmperr(num, zero);
153 }
154 return r;
155}
156
157static inline int
158rb_num_positive_int_p(VALUE num)
159{
160 const ID mid = '>';
161
162 if (FIXNUM_P(num)) {
164 return FIXNUM_POSITIVE_P(num);
165 }
166 else if (RB_TYPE_P(num, T_BIGNUM)) {
168 return BIGNUM_POSITIVE_P(num);
169 }
170 return RTEST(rb_num_compare_with_zero(num, mid));
171}
172
173static inline int
174rb_num_negative_int_p(VALUE num)
175{
176 const ID mid = '<';
177
178 if (FIXNUM_P(num)) {
180 return FIXNUM_NEGATIVE_P(num);
181 }
182 else if (RB_TYPE_P(num, T_BIGNUM)) {
184 return BIGNUM_NEGATIVE_P(num);
185 }
186 return RTEST(rb_num_compare_with_zero(num, mid));
187}
188
189static inline double
190rb_float_flonum_value(VALUE v)
191{
192#if USE_FLONUM
193 if (v != (VALUE)0x8000000000000002) { /* LIKELY */
194 union {
195 double d;
196 VALUE v;
197 } t;
198
199 VALUE b63 = (v >> 63);
200 /* e: xx1... -> 011... */
201 /* xx0... -> 100... */
202 /* ^b63 */
203 t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~(VALUE)0x03), 3);
204 return t.d;
205 }
206#endif
207 return 0.0;
208}
209
210static inline double
211rb_float_noflonum_value(VALUE v)
212{
213 return RFLOAT(v)->float_value;
214}
215
216static inline double
217rb_float_value_inline(VALUE v)
218{
219 if (FLONUM_P(v)) {
220 return rb_float_flonum_value(v);
221 }
222 return rb_float_noflonum_value(v);
223}
224
225static inline VALUE
226rb_float_new_inline(double d)
227{
228#if USE_FLONUM
229 union {
230 double d;
231 VALUE v;
232 } t;
233 int bits;
234
235 t.d = d;
236 bits = (int)((VALUE)(t.v >> 60) & 0x7);
237 /* bits contains 3 bits of b62..b60. */
238 /* bits - 3 = */
239 /* b011 -> b000 */
240 /* b100 -> b001 */
241
242 if (t.v != 0x3000000000000000 /* 1.72723e-77 */ &&
243 !((bits-3) & ~0x01)) {
244 return (RUBY_BIT_ROTL(t.v, 3) & ~(VALUE)0x01) | 0x02;
245 }
246 else if (t.v == (VALUE)0) {
247 /* +0.0 */
248 return 0x8000000000000002;
249 }
250 /* out of range */
251#endif
252 return rb_float_new_in_heap(d);
253}
254
255#endif /* INTERNAL_NUMERIC_H */
Internal header for bitwise integer algorithms.
int bits(struct state *s, int need)
Definition: blast.c:72
void rb_cmperr(VALUE x, VALUE y)
Definition: compar.c:28
#define MJIT_SYMBOL_EXPORT_END
Definition: dllexport.h:63
#define MJIT_SYMBOL_EXPORT_BEGIN
Definition: dllexport.h:62
#define RFLOAT_VALUE
Definition: double.h:28
VALUE rb_float_new_in_heap(double)
Definition: numeric.c:922
big_t * num
Definition: enough.c:232
VALUE rb_cInteger
Definition: numeric.c:191
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:619
Internal header for Bignums.
Internal header for Fixnums.
int rb_int_negative_p(VALUE num)
Definition: numeric.c:313
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3873
VALUE rb_fix_aref(VALUE fix, VALUE idx)
Definition: numeric.c:4613
VALUE rb_num_pow(VALUE x, VALUE y)
Definition: numeric.c:4100
VALUE rb_int_comp(VALUE num)
Definition: numeric.c:4372
VALUE rb_int_abs(VALUE num)
Definition: numeric.c:4826
VALUE rb_float_floor(VALUE x, int ndigits)
Definition: numeric.c:1935
VALUE rb_int_div(VALUE x, VALUE y)
Definition: numeric.c:3803
VALUE rb_int_zero_p(VALUE num)
Definition: numeric.c:800
VALUE rb_float_pow(VALUE x, VALUE y)
Definition: numeric.c:1328
VALUE rb_int_pow(VALUE x, VALUE y)
Definition: numeric.c:4088
VALUE rb_int2str(VALUE num, int base)
Definition: numeric.c:3549
VALUE rb_float_equal(VALUE x, VALUE y)
Definition: numeric.c:1417
VALUE rb_int_uminus(VALUE num)
Definition: numeric.c:3466
VALUE rb_float_mul(VALUE x, VALUE y)
Definition: numeric.c:1102
VALUE rb_int_equal(VALUE x, VALUE y)
Definition: numeric.c:4147
VALUE rb_float_plus(VALUE x, VALUE y)
Definition: numeric.c:1054
VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:4022
VALUE rb_flo_div_flo(VALUE x, VALUE y)
Definition: numeric.c:1140
VALUE rb_int_cmp(VALUE x, VALUE y)
Definition: numeric.c:4196
double ruby_float_mod(double x, double y)
Definition: numeric.c:1237
VALUE rb_float_eql(VALUE x, VALUE y)
Definition: numeric.c:1688
VALUE rb_int_and(VALUE x, VALUE y)
Definition: numeric.c:4436
VALUE rb_float_abs(VALUE flt)
Definition: numeric.c:1732
VALUE rb_int_even_p(VALUE num)
Definition: numeric.c:3273
VALUE rb_float_uminus(VALUE num)
Definition: numeric.c:1041
VALUE rb_int_lshift(VALUE x, VALUE y)
Definition: numeric.c:4553
double ruby_float_step_size(double beg, double end, double unit, int excl)
Definition: numeric.c:2537
VALUE rb_float_gt(VALUE x, VALUE y)
Definition: numeric.c:1537
int rb_num_negative_p(VALUE)
Definition: numeric.c:319
VALUE rb_float_ceil(VALUE num, int ndigits)
Definition: numeric.c:2059
double rb_int_fdiv_double(VALUE x, VALUE y)
Definition: numeric.c:3715
int rb_int_positive_p(VALUE num)
Definition: numeric.c:307
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:2597
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless)
Definition: numeric.c:2566
enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts)
Definition: numeric.c:205
VALUE rb_int_ge(VALUE x, VALUE y)
Definition: numeric.c:4276
VALUE rb_float_div(VALUE x, VALUE y)
Definition: numeric.c:1156
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3636
VALUE rb_int_odd_p(VALUE num)
Definition: numeric.c:3243
int rb_num_to_uint(VALUE val, unsigned int *ret)
Definition: numeric.c:250
ruby_num_rounding_mode
Definition: numeric.h:32
@ RUBY_NUM_ROUND_HALF_EVEN
Definition: numeric.h:34
@ RUBY_NUM_ROUND_HALF_DOWN
Definition: numeric.h:35
@ RUBY_NUM_ROUND_HALF_UP
Definition: numeric.h:33
@ RUBY_NUM_ROUND_DEFAULT
Definition: numeric.h:36
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3591
VALUE rb_int_divmod(VALUE x, VALUE y)
Definition: numeric.c:3950
int rb_float_cmp(VALUE x, VALUE y)
Definition: numeric.c:1521
VALUE rb_int_bit_length(VALUE num)
Definition: numeric.c:4881
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3830
#define RFLOAT(obj)
Definition: numeric.h:44
VALUE rb_float_minus(VALUE x, VALUE y)
Definition: numeric.c:1078
#define ROUND_DEFAULT
Definition: numeric.h:29
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3597
VALUE rb_int_gt(VALUE x, VALUE y)
Definition: numeric.c:4236
VALUE rb_int_succ(VALUE num)
Definition: numeric.c:3337
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3686
Internal header for RubyVM.
#define rb_method_basic_definition_p(...)
Definition: internal.h:78
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define INT2FIX
Definition: long.h:48
#define Qundef
#define RTEST
#define FIXNUM_P
Definition: rbasic.h:47
Definition: numeric.h:39
double float_value
Definition: numeric.h:41
struct RBasic basic
Definition: numeric.h:40
#define t
Definition: symbol.c:253
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define T_BIGNUM
Definition: value_type.h:56