Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
range.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  range.c -
4 
5  $Author$
6  created at: Thu Aug 19 17:46:47 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "internal.h"
13 #include "id.h"
14 #include <assert.h>
15 
16 #ifdef HAVE_FLOAT_H
17 #include <float.h>
18 #endif
19 #include <math.h>
20 
22 static ID id_beg, id_end, id_excl;
23 #define id_cmp idCmp
24 #define id_succ idSucc
25 
26 static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
27 
28 #define RANGE_SET_BEG(r, v) (RSTRUCT_SET(r, 0, v))
29 #define RANGE_SET_END(r, v) (RSTRUCT_SET(r, 1, v))
30 #define RANGE_SET_EXCL(r, v) (RSTRUCT_SET(r, 2, v))
31 #define RBOOL(v) ((v) ? Qtrue : Qfalse)
32 
33 #define EXCL(r) RTEST(RANGE_EXCL(r))
34 
35 static void
36 range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
37 {
38  if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) {
39  VALUE v;
40 
41  v = rb_funcall(beg, id_cmp, 1, end);
42  if (NIL_P(v))
43  rb_raise(rb_eArgError, "bad value for range");
44  }
45 
46  RANGE_SET_EXCL(range, exclude_end);
47  RANGE_SET_BEG(range, beg);
48  RANGE_SET_END(range, end);
49 }
50 
51 VALUE
52 rb_range_new(VALUE beg, VALUE end, int exclude_end)
53 {
55 
56  range_init(range, beg, end, RBOOL(exclude_end));
57  return range;
58 }
59 
60 static void
61 range_modify(VALUE range)
62 {
64  /* Ranges are immutable, so that they should be initialized only once. */
65  if (RANGE_EXCL(range) != Qnil) {
66  rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
67  }
68 }
69 
70 /*
71  * call-seq:
72  * Range.new(begin, end, exclude_end=false) -> rng
73  *
74  * Constructs a range using the given +begin+ and +end+. If the +exclude_end+
75  * parameter is omitted or is <code>false</code>, the range will include
76  * the end object; otherwise, it will be excluded.
77  */
78 
79 static VALUE
80 range_initialize(int argc, VALUE *argv, VALUE range)
81 {
82  VALUE beg, end, flags;
83 
84  rb_scan_args(argc, argv, "21", &beg, &end, &flags);
85  range_modify(range);
86  range_init(range, beg, end, RBOOL(RTEST(flags)));
87  return Qnil;
88 }
89 
90 /* :nodoc: */
91 static VALUE
92 range_initialize_copy(VALUE range, VALUE orig)
93 {
94  range_modify(range);
96  return range;
97 }
98 
99 /*
100  * call-seq:
101  * rng.exclude_end? -> true or false
102  *
103  * Returns <code>true</code> if the range excludes its end value.
104  *
105  * (1..5).exclude_end? #=> false
106  * (1...5).exclude_end? #=> true
107  */
108 
109 static VALUE
110 range_exclude_end_p(VALUE range)
111 {
112  return EXCL(range) ? Qtrue : Qfalse;
113 }
114 
115 static VALUE
116 recursive_equal(VALUE range, VALUE obj, int recur)
117 {
118  if (recur) return Qtrue; /* Subtle! */
120  return Qfalse;
122  return Qfalse;
123 
124  if (EXCL(range) != EXCL(obj))
125  return Qfalse;
126  return Qtrue;
127 }
128 
129 
130 /*
131  * call-seq:
132  * rng == obj -> true or false
133  *
134  * Returns <code>true</code> only if +obj+ is a Range, has equivalent
135  * begin and end items (by comparing them with <code>==</code>), and has
136  * the same #exclude_end? setting as the range.
137  *
138  * (0..2) == (0..2) #=> true
139  * (0..2) == Range.new(0,2) #=> true
140  * (0..2) == (0...2) #=> false
141  *
142  */
143 
144 static VALUE
145 range_eq(VALUE range, VALUE obj)
146 {
147  if (range == obj)
148  return Qtrue;
150  return Qfalse;
151 
152  return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
153 }
154 
155 /* compares _a_ and _b_ and returns:
156  * < 0: a < b
157  * = 0: a = b
158  * > 0: a > b or non-comparable
159  */
160 static int
161 r_less(VALUE a, VALUE b)
162 {
163  VALUE r = rb_funcall(a, id_cmp, 1, b);
164 
165  if (NIL_P(r))
166  return INT_MAX;
167  return rb_cmpint(r, a, b);
168 }
169 
170 static VALUE
171 recursive_eql(VALUE range, VALUE obj, int recur)
172 {
173  if (recur) return Qtrue; /* Subtle! */
175  return Qfalse;
177  return Qfalse;
178 
179  if (EXCL(range) != EXCL(obj))
180  return Qfalse;
181  return Qtrue;
182 }
183 
184 /*
185  * call-seq:
186  * rng.eql?(obj) -> true or false
187  *
188  * Returns <code>true</code> only if +obj+ is a Range, has equivalent
189  * begin and end items (by comparing them with <code>eql?</code>),
190  * and has the same #exclude_end? setting as the range.
191  *
192  * (0..2).eql?(0..2) #=> true
193  * (0..2).eql?(Range.new(0,2)) #=> true
194  * (0..2).eql?(0...2) #=> false
195  *
196  */
197 
198 static VALUE
199 range_eql(VALUE range, VALUE obj)
200 {
201  if (range == obj)
202  return Qtrue;
204  return Qfalse;
205  return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
206 }
207 
208 /*
209  * call-seq:
210  * rng.hash -> integer
211  *
212  * Compute a hash-code for this range. Two ranges with equal
213  * begin and end points (using <code>eql?</code>), and the same
214  * #exclude_end? value will generate the same hash-code.
215  *
216  * See also Object#hash.
217  */
218 
219 static VALUE
220 range_hash(VALUE range)
221 {
222  st_index_t hash = EXCL(range);
223  VALUE v;
224 
225  hash = rb_hash_start(hash);
226  v = rb_hash(RANGE_BEG(range));
227  hash = rb_hash_uint(hash, NUM2LONG(v));
228  v = rb_hash(RANGE_END(range));
229  hash = rb_hash_uint(hash, NUM2LONG(v));
230  hash = rb_hash_uint(hash, EXCL(range) << 24);
231  hash = rb_hash_end(hash);
232 
233  return ST2FIX(hash);
234 }
235 
236 static void
237 range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg)
238 {
239  int c;
240  VALUE b = RANGE_BEG(range);
241  VALUE e = RANGE_END(range);
242  VALUE v = b;
243 
244  if (EXCL(range)) {
245  while (r_less(v, e) < 0) {
246  if ((*func)(v, arg)) break;
247  v = rb_funcallv(v, id_succ, 0, 0);
248  }
249  }
250  else {
251  while ((c = r_less(v, e)) <= 0) {
252  if ((*func)(v, arg)) break;
253  if (!c) break;
254  v = rb_funcallv(v, id_succ, 0, 0);
255  }
256  }
257 }
258 
259 static int
260 sym_step_i(VALUE i, VALUE arg)
261 {
262  VALUE *iter = (VALUE *)arg;
263 
264  if (FIXNUM_P(iter[0])) {
265  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
266  }
267  else {
268  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
269  }
270  if (iter[0] == INT2FIX(0)) {
272  iter[0] = iter[1];
273  }
274  return 0;
275 }
276 
277 static int
278 step_i(VALUE i, VALUE arg)
279 {
280  VALUE *iter = (VALUE *)arg;
281 
282  if (FIXNUM_P(iter[0])) {
283  iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
284  }
285  else {
286  iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
287  }
288  if (iter[0] == INT2FIX(0)) {
289  rb_yield(i);
290  iter[0] = iter[1];
291  }
292  return 0;
293 }
294 
295 static int
296 discrete_object_p(VALUE obj)
297 {
298  if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
299  return rb_respond_to(obj, id_succ);
300 }
301 
302 static int
303 linear_object_p(VALUE obj)
304 {
305  if (FIXNUM_P(obj) || FLONUM_P(obj)) return TRUE;
306  if (SPECIAL_CONST_P(obj)) return FALSE;
307  switch (BUILTIN_TYPE(obj)) {
308  case T_FLOAT:
309  case T_BIGNUM:
310  return TRUE;
311  }
312  if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE;
313  if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE;
314  return FALSE;
315 }
316 
317 static VALUE
318 check_step_domain(VALUE step)
319 {
320  VALUE zero = INT2FIX(0);
321  int cmp;
322  if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
323  step = rb_to_int(step);
324  }
325  cmp = rb_cmpint(rb_funcallv(step, idCmp, 1, &zero), step, zero);
326  if (cmp < 0) {
327  rb_raise(rb_eArgError, "step can't be negative");
328  }
329  else if (cmp == 0) {
330  rb_raise(rb_eArgError, "step can't be 0");
331  }
332  return step;
333 }
334 
335 static VALUE
336 range_step_size(VALUE range, VALUE args, VALUE eobj)
337 {
338  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
339  VALUE step = INT2FIX(1);
340  if (args) {
341  step = check_step_domain(RARRAY_AREF(args, 0));
342  }
343 
345  return ruby_num_interval_step_size(b, e, step, EXCL(range));
346  }
347  return Qnil;
348 }
349 
350 /*
351  * Document-method: Range#step
352  * Document-method: Range#%
353  * call-seq:
354  * rng.step(n=1) {| obj | block } -> rng
355  * rng.step(n=1) -> an_enumerator
356  * rng.step(n=1) -> an_arithmetic_sequence
357  * rng % n -> an_enumerator
358  * rng % n -> an_arithmetic_sequence
359  *
360  * Iterates over the range, passing each <code>n</code>th element to the block.
361  * If begin and end are numeric, +n+ is added for each iteration.
362  * Otherwise #step invokes #succ to iterate through range elements.
363  *
364  * If no block is given, an enumerator is returned instead.
365  * Especially, the enumerator is an Enumerator::ArithmeticSequence
366  * if begin and end of the range are numeric.
367  *
368  * range = Xs.new(1)..Xs.new(10)
369  * range.step(2) {|x| puts x}
370  * puts
371  * range.step(3) {|x| puts x}
372  *
373  * <em>produces:</em>
374  *
375  * 1 x
376  * 3 xxx
377  * 5 xxxxx
378  * 7 xxxxxxx
379  * 9 xxxxxxxxx
380  *
381  * 1 x
382  * 4 xxxx
383  * 7 xxxxxxx
384  * 10 xxxxxxxxxx
385  *
386  * See Range for the definition of class Xs.
387  */
388 
389 
390 static VALUE
391 range_step(int argc, VALUE *argv, VALUE range)
392 {
393  VALUE b, e, step, tmp;
394 
395  b = RANGE_BEG(range);
396  e = RANGE_END(range);
397  step = (!rb_check_arity(argc, 0, 1) ? INT2FIX(1) : argv[0]);
398 
399  if (!rb_block_given_p()) {
400  const VALUE b_num_p = rb_obj_is_kind_of(b, rb_cNumeric);
401  const VALUE e_num_p = rb_obj_is_kind_of(e, rb_cNumeric);
402  if ((b_num_p && (NIL_P(e) || e_num_p)) || (NIL_P(b) && e_num_p)) {
404  range_step_size, b, e, step, EXCL(range));
405  }
406 
407  RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);
408  }
409 
410  step = check_step_domain(step);
411 
412  if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) {
413  long i = FIX2LONG(b), unit = FIX2LONG(step);
414  do {
415  rb_yield(LONG2FIX(i));
416  i += unit; /* FIXABLE+FIXABLE never overflow */
417  } while (FIXABLE(i));
418  b = LONG2NUM(i);
419 
420  for (;; b = rb_big_plus(b, step))
421  rb_yield(b);
422  }
423  else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
424  long end = FIX2LONG(e);
425  long i, unit = FIX2LONG(step);
426 
427  if (!EXCL(range))
428  end += 1;
429  i = FIX2LONG(b);
430  while (i < end) {
431  rb_yield(LONG2NUM(i));
432  if (i + unit < i) break;
433  i += unit;
434  }
435 
436  }
437  else if (SYMBOL_P(b) && (NIL_P(e) || SYMBOL_P(e))) { /* symbols are special */
438  VALUE iter[2];
439  iter[0] = INT2FIX(1);
440  iter[1] = step;
441 
442  b = rb_sym2str(b);
443  if (NIL_P(e)) {
444  rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter);
445  }
446  else {
447  rb_str_upto_each(b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
448  }
449  }
450  else if (ruby_float_step(b, e, step, EXCL(range), TRUE)) {
451  /* done */
452  }
453  else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
454  !NIL_P(rb_check_to_integer(b, "to_int")) ||
455  !NIL_P(rb_check_to_integer(e, "to_int"))) {
456  ID op = EXCL(range) ? '<' : idLE;
457  VALUE v = b;
458  int i = 0;
459 
460  while (NIL_P(e) || RTEST(rb_funcall(v, op, 1, e))) {
461  rb_yield(v);
462  i++;
463  v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
464  }
465  }
466  else {
467  tmp = rb_check_string_type(b);
468 
469  if (!NIL_P(tmp)) {
470  VALUE iter[2];
471 
472  b = tmp;
473  iter[0] = INT2FIX(1);
474  iter[1] = step;
475 
476  if (NIL_P(e)) {
477  rb_str_upto_endless_each(b, step_i, (VALUE)iter);
478  }
479  else {
480  rb_str_upto_each(b, e, EXCL(range), step_i, (VALUE)iter);
481  }
482  }
483  else {
484  VALUE args[2];
485 
486  if (!discrete_object_p(b)) {
487  rb_raise(rb_eTypeError, "can't iterate from %s",
488  rb_obj_classname(b));
489  }
490  args[0] = INT2FIX(1);
491  args[1] = step;
492  range_each_func(range, step_i, (VALUE)args);
493  }
494  }
495  return range;
496 }
497 
498 static VALUE
499 range_percent_step(VALUE range, VALUE step)
500 {
501  return range_step(1, &step, range);
502 }
503 
504 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
505 union int64_double {
506  int64_t i;
507  double d;
508 };
509 
510 static VALUE
511 int64_as_double_to_num(int64_t i)
512 {
513  union int64_double convert;
514  if (i < 0) {
515  convert.i = -i;
516  return DBL2NUM(-convert.d);
517  }
518  else {
519  convert.i = i;
520  return DBL2NUM(convert.d);
521  }
522 }
523 
524 static int64_t
525 double_as_int64(double d)
526 {
527  union int64_double convert;
528  convert.d = fabs(d);
529  return d < 0 ? -convert.i : convert.i;
530 }
531 #endif
532 
533 static int
534 is_integer_p(VALUE v)
535 {
536  ID id_integer_p;
537  VALUE is_int;
538  CONST_ID(id_integer_p, "integer?");
539  is_int = rb_check_funcall(v, id_integer_p, 0, 0);
540  return RTEST(is_int) && is_int != Qundef;
541 }
542 
543 static VALUE
544 bsearch_integer_range(VALUE beg, VALUE end, int excl)
545 {
546  VALUE satisfied = Qnil;
547  int smaller;
548 
549 #define BSEARCH_CHECK(expr) \
550  do { \
551  VALUE val = (expr); \
552  VALUE v = rb_yield(val); \
553  if (FIXNUM_P(v)) { \
554  if (v == INT2FIX(0)) return val; \
555  smaller = (SIGNED_VALUE)v < 0; \
556  } \
557  else if (v == Qtrue) { \
558  satisfied = val; \
559  smaller = 1; \
560  } \
561  else if (v == Qfalse || v == Qnil) { \
562  smaller = 0; \
563  } \
564  else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
565  int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
566  if (!cmp) return val; \
567  smaller = cmp < 0; \
568  } \
569  else { \
570  rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE \
571  " (must be numeric, true, false or nil)", \
572  rb_obj_class(v)); \
573  } \
574  } while (0)
575 
576  VALUE low = rb_to_int(beg);
577  VALUE high = rb_to_int(end);
578  VALUE mid, org_high;
579  ID id_div;
580  CONST_ID(id_div, "div");
581 
582  if (excl) high = rb_funcall(high, '-', 1, INT2FIX(1));
583  org_high = high;
584 
585  while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
586  mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
587  BSEARCH_CHECK(mid);
588  if (smaller) {
589  high = mid;
590  }
591  else {
592  low = rb_funcall(mid, '+', 1, INT2FIX(1));
593  }
594  }
595  if (rb_equal(low, org_high)) {
596  BSEARCH_CHECK(low);
597  if (!smaller) return Qnil;
598  }
599  return satisfied;
600 }
601 
602 /*
603  * call-seq:
604  * rng.bsearch {|obj| block } -> value
605  *
606  * By using binary search, finds a value in range which meets the given
607  * condition in O(log n) where n is the size of the range.
608  *
609  * You can use this method in two use cases: a find-minimum mode and
610  * a find-any mode. In either case, the elements of the range must be
611  * monotone (or sorted) with respect to the block.
612  *
613  * In find-minimum mode (this is a good choice for typical use case),
614  * the block must return true or false, and there must be a value x
615  * so that:
616  *
617  * - the block returns false for any value which is less than x, and
618  * - the block returns true for any value which is greater than or
619  * equal to x.
620  *
621  * If x is within the range, this method returns the value x.
622  * Otherwise, it returns nil.
623  *
624  * ary = [0, 4, 7, 10, 12]
625  * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
626  * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
627  * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
628  * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
629  *
630  * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
631  *
632  * In find-any mode (this behaves like libc's bsearch(3)), the block
633  * must return a number, and there must be two values x and y (x <= y)
634  * so that:
635  *
636  * - the block returns a positive number for v if v < x,
637  * - the block returns zero for v if x <= v < y, and
638  * - the block returns a negative number for v if y <= v.
639  *
640  * This method returns any value which is within the intersection of
641  * the given range and x...y (if any). If there is no value that
642  * satisfies the condition, it returns nil.
643  *
644  * ary = [0, 100, 100, 100, 200]
645  * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
646  * (0..4).bsearch {|i| 300 - ary[i] } #=> nil
647  * (0..4).bsearch {|i| 50 - ary[i] } #=> nil
648  *
649  * You must not mix the two modes at a time; the block must always
650  * return either true/false, or always return a number. It is
651  * undefined which value is actually picked up at each iteration.
652  */
653 
654 static VALUE
655 range_bsearch(VALUE range)
656 {
657  VALUE beg, end, satisfied = Qnil;
658  int smaller;
659 
660  /* Implementation notes:
661  * Floats are handled by mapping them to 64 bits integers.
662  * Apart from sign issues, floats and their 64 bits integer have the
663  * same order, assuming they are represented as exponent followed
664  * by the mantissa. This is true with or without implicit bit.
665  *
666  * Finding the average of two ints needs to be careful about
667  * potential overflow (since float to long can use 64 bits)
668  * as well as the fact that -1/2 can be 0 or -1 in C89.
669  *
670  * Note that -0.0 is mapped to the same int as 0.0 as we don't want
671  * (-1...0.0).bsearch to yield -0.0.
672  */
673 
674 #define BSEARCH(conv) \
675  do { \
676  RETURN_ENUMERATOR(range, 0, 0); \
677  if (EXCL(range)) high--; \
678  org_high = high; \
679  while (low < high) { \
680  mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
681  : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
682  BSEARCH_CHECK(conv(mid)); \
683  if (smaller) { \
684  high = mid; \
685  } \
686  else { \
687  low = mid + 1; \
688  } \
689  } \
690  if (low == org_high) { \
691  BSEARCH_CHECK(conv(low)); \
692  if (!smaller) return Qnil; \
693  } \
694  return satisfied; \
695  } while (0)
696 
697 
698  beg = RANGE_BEG(range);
699  end = RANGE_END(range);
700 
701  if (FIXNUM_P(beg) && FIXNUM_P(end)) {
702  long low = FIX2LONG(beg);
703  long high = FIX2LONG(end);
704  long mid, org_high;
705  BSEARCH(INT2FIX);
706  }
707 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
708  else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
709  int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg)));
710  int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end)));
711  int64_t mid, org_high;
712  BSEARCH(int64_as_double_to_num);
713  }
714 #endif
715  else if (is_integer_p(beg) && is_integer_p(end)) {
716  RETURN_ENUMERATOR(range, 0, 0);
717  return bsearch_integer_range(beg, end, EXCL(range));
718  }
719  else if (is_integer_p(beg) && NIL_P(end)) {
720  VALUE diff = LONG2FIX(1);
721  RETURN_ENUMERATOR(range, 0, 0);
722  while (1) {
723  VALUE mid = rb_funcall(beg, '+', 1, diff);
724  BSEARCH_CHECK(mid);
725  if (smaller) {
726  return bsearch_integer_range(beg, mid, 0);
727  }
728  diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
729  }
730  }
731  else if (NIL_P(beg) && is_integer_p(end)) {
732  VALUE diff = LONG2FIX(-1);
733  RETURN_ENUMERATOR(range, 0, 0);
734  while (1) {
735  VALUE mid = rb_funcall(end, '+', 1, diff);
736  BSEARCH_CHECK(mid);
737  if (!smaller) {
738  return bsearch_integer_range(mid, end, 0);
739  }
740  diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
741  }
742  }
743  else {
744  rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
745  }
746  return range;
747 }
748 
749 static int
750 each_i(VALUE v, VALUE arg)
751 {
752  rb_yield(v);
753  return 0;
754 }
755 
756 static int
757 sym_each_i(VALUE v, VALUE arg)
758 {
760  return 0;
761 }
762 
763 /*
764  * call-seq:
765  * rng.size -> num
766  *
767  * Returns the number of elements in the range. Both the begin and the end of
768  * the Range must be Numeric, otherwise nil is returned.
769  *
770  * (10..20).size #=> 11
771  * ('a'..'z').size #=> nil
772  * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
773  */
774 
775 static VALUE
776 range_size(VALUE range)
777 {
778  VALUE b = RANGE_BEG(range), e = RANGE_END(range);
779  if (rb_obj_is_kind_of(b, rb_cNumeric)) {
780  if (rb_obj_is_kind_of(e, rb_cNumeric)) {
781  return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
782  }
783  if (NIL_P(e)) {
784  return DBL2NUM(HUGE_VAL);
785  }
786  }
787  else if (NIL_P(b)) {
788  return DBL2NUM(HUGE_VAL);
789  }
790 
791  return Qnil;
792 }
793 
794 /*
795  * call-seq:
796  * rng.to_a -> array
797  * rng.entries -> array
798  *
799  * Returns an array containing the items in the range.
800  *
801  * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
802  * (1..).to_a #=> RangeError: cannot convert endless range to an array
803  */
804 
805 static VALUE
806 range_to_a(VALUE range)
807 {
808  if (NIL_P(RANGE_END(range))) {
809  rb_raise(rb_eRangeError, "cannot convert endless range to an array");
810  }
811  return rb_call_super(0, 0);
812 }
813 
814 static VALUE
815 range_enum_size(VALUE range, VALUE args, VALUE eobj)
816 {
817  return range_size(range);
818 }
819 
820 /*
821  * call-seq:
822  * rng.each {| i | block } -> rng
823  * rng.each -> an_enumerator
824  *
825  * Iterates over the elements of range, passing each in turn to the
826  * block.
827  *
828  * The +each+ method can only be used if the begin object of the range
829  * supports the +succ+ method. A TypeError is raised if the object
830  * does not have +succ+ method defined (like Float).
831  *
832  * If no block is given, an enumerator is returned instead.
833  *
834  * (10..15).each {|n| print n, ' ' }
835  * # prints: 10 11 12 13 14 15
836  *
837  * (2.5..5).each {|n| print n, ' ' }
838  * # raises: TypeError: can't iterate from Float
839  */
840 
841 static VALUE
842 range_each(VALUE range)
843 {
844  VALUE beg, end;
845  long i, lim;
846 
847  RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
848 
849  beg = RANGE_BEG(range);
850  end = RANGE_END(range);
851 
852  if (FIXNUM_P(beg) && NIL_P(end)) {
853  fixnum_endless:
854  i = FIX2LONG(beg);
855  while (FIXABLE(i)) {
856  rb_yield(LONG2FIX(i++));
857  }
858  beg = LONG2NUM(i);
859  bignum_endless:
860  for (;; beg = rb_big_plus(beg, INT2FIX(1)))
861  rb_yield(beg);
862  }
863  else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
864  fixnum_loop:
865  lim = FIX2LONG(end);
866  if (!EXCL(range))
867  lim += 1;
868  for (i = FIX2LONG(beg); i < lim; i++) {
869  rb_yield(LONG2FIX(i));
870  }
871  }
872  else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
873  if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
874  if (!FIXNUM_P(beg)) {
875  if (RBIGNUM_NEGATIVE_P(beg)) {
876  do {
877  rb_yield(beg);
878  } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
879  if (NIL_P(end)) goto fixnum_endless;
880  if (FIXNUM_P(end)) goto fixnum_loop;
881  }
882  else {
883  if (NIL_P(end)) goto bignum_endless;
884  if (FIXNUM_P(end)) return range;
885  }
886  }
887  if (FIXNUM_P(beg)) {
888  i = FIX2LONG(beg);
889  do {
890  rb_yield(LONG2FIX(i));
891  } while (POSFIXABLE(++i));
892  beg = LONG2NUM(i);
893  }
894  ASSUME(!FIXNUM_P(beg));
895  ASSUME(!SPECIAL_CONST_P(end));
896  }
897  if (!FIXNUM_P(beg) && RBIGNUM_SIGN(beg) == RBIGNUM_SIGN(end)) {
898  if (EXCL(range)) {
899  while (rb_big_cmp(beg, end) == INT2FIX(-1)) {
900  rb_yield(beg);
901  beg = rb_big_plus(beg, INT2FIX(1));
902  }
903  }
904  else {
905  VALUE c;
906  while ((c = rb_big_cmp(beg, end)) != INT2FIX(1)) {
907  rb_yield(beg);
908  if (c == INT2FIX(0)) break;
909  beg = rb_big_plus(beg, INT2FIX(1));
910  }
911  }
912  }
913  }
914  else if (SYMBOL_P(beg) && (NIL_P(end) || SYMBOL_P(end))) { /* symbols are special */
915  beg = rb_sym2str(beg);
916  if (NIL_P(end)) {
917  rb_str_upto_endless_each(beg, sym_each_i, 0);
918  }
919  else {
920  rb_str_upto_each(beg, rb_sym2str(end), EXCL(range), sym_each_i, 0);
921  }
922  }
923  else {
924  VALUE tmp = rb_check_string_type(beg);
925 
926  if (!NIL_P(tmp)) {
927  if (!NIL_P(end)) {
928  rb_str_upto_each(tmp, end, EXCL(range), each_i, 0);
929  }
930  else {
931  rb_str_upto_endless_each(tmp, each_i, 0);
932  }
933  }
934  else {
935  if (!discrete_object_p(beg)) {
936  rb_raise(rb_eTypeError, "can't iterate from %s",
937  rb_obj_classname(beg));
938  }
939  if (!NIL_P(end))
940  range_each_func(range, each_i, 0);
941  else
942  for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
943  rb_yield(beg);
944  }
945  }
946  return range;
947 }
948 
949 /*
950  * call-seq:
951  * rng.begin -> obj
952  *
953  * Returns the object that defines the beginning of the range.
954  *
955  * (1..10).begin #=> 1
956  */
957 
958 static VALUE
959 range_begin(VALUE range)
960 {
961  return RANGE_BEG(range);
962 }
963 
964 
965 /*
966  * call-seq:
967  * rng.end -> obj
968  *
969  * Returns the object that defines the end of the range.
970  *
971  * (1..10).end #=> 10
972  * (1...10).end #=> 10
973  */
974 
975 
976 static VALUE
977 range_end(VALUE range)
978 {
979  return RANGE_END(range);
980 }
981 
982 
983 static VALUE
984 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
985 {
986  VALUE *ary = (VALUE *)cbarg;
987  long n = NUM2LONG(ary[0]);
988 
989  if (n <= 0) {
990  rb_iter_break();
991  }
992  rb_ary_push(ary[1], i);
993  n--;
994  ary[0] = INT2NUM(n);
995  return Qnil;
996 }
997 
998 /*
999  * call-seq:
1000  * rng.first -> obj
1001  * rng.first(n) -> an_array
1002  *
1003  * Returns the first object in the range, or an array of the first +n+
1004  * elements.
1005  *
1006  * (10..20).first #=> 10
1007  * (10..20).first(3) #=> [10, 11, 12]
1008  */
1009 
1010 static VALUE
1011 range_first(int argc, VALUE *argv, VALUE range)
1012 {
1013  VALUE n, ary[2];
1014 
1015  if (NIL_P(RANGE_BEG(range))) {
1016  rb_raise(rb_eRangeError, "cannot get the first element of beginless range");
1017  }
1018  if (argc == 0) return RANGE_BEG(range);
1019 
1020  rb_scan_args(argc, argv, "1", &n);
1021  ary[0] = n;
1022  ary[1] = rb_ary_new2(NUM2LONG(n));
1023  rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
1024 
1025  return ary[1];
1026 }
1027 
1028 static VALUE
1029 rb_int_range_last(int argc, VALUE *argv, VALUE range)
1030 {
1031  static const VALUE ONE = INT2FIX(1);
1032 
1033  VALUE b, e, len_1, len, nv, ary;
1034  int x;
1035  long n;
1036 
1037  assert(argc > 0);
1038 
1039  b = RANGE_BEG(range);
1040  e = RANGE_END(range);
1042 
1043  x = EXCL(range);
1044 
1045  len_1 = rb_int_minus(e, b);
1046  if (FIXNUM_ZERO_P(len_1) || rb_num_negative_p(len_1)) {
1047  return rb_ary_new_capa(0);
1048  }
1049 
1050  if (x) {
1051  e = rb_int_minus(e, ONE);
1052  len = len_1;
1053  }
1054  else {
1055  len = rb_int_plus(len_1, ONE);
1056  }
1057 
1058  rb_scan_args(argc, argv, "1", &nv);
1059  n = NUM2LONG(nv);
1060  if (n < 0) {
1061  rb_raise(rb_eArgError, "negative array size");
1062  }
1063 
1064  nv = LONG2NUM(n);
1065  if (RTEST(rb_int_gt(nv, len))) {
1066  nv = len;
1067  n = NUM2LONG(nv);
1068  }
1069 
1070  ary = rb_ary_new_capa(n);
1071  b = rb_int_minus(e, nv);
1072  while (n) {
1073  b = rb_int_plus(b, ONE);
1074  rb_ary_push(ary, b);
1075  --n;
1076  }
1077 
1078  return ary;
1079 }
1080 
1081 /*
1082  * call-seq:
1083  * rng.last -> obj
1084  * rng.last(n) -> an_array
1085  *
1086  * Returns the last object in the range,
1087  * or an array of the last +n+ elements.
1088  *
1089  * Note that with no arguments +last+ will return the object that defines
1090  * the end of the range even if #exclude_end? is +true+.
1091  *
1092  * (10..20).last #=> 20
1093  * (10...20).last #=> 20
1094  * (10..20).last(3) #=> [18, 19, 20]
1095  * (10...20).last(3) #=> [17, 18, 19]
1096  */
1097 
1098 static VALUE
1099 range_last(int argc, VALUE *argv, VALUE range)
1100 {
1101  VALUE b, e;
1102 
1103  if (NIL_P(RANGE_END(range))) {
1104  rb_raise(rb_eRangeError, "cannot get the last element of endless range");
1105  }
1106  if (argc == 0) return RANGE_END(range);
1107 
1108  b = RANGE_BEG(range);
1109  e = RANGE_END(range);
1110  if (RB_INTEGER_TYPE_P(b) && RB_INTEGER_TYPE_P(e) &&
1112  return rb_int_range_last(argc, argv, range);
1113  }
1114  return rb_ary_last(argc, argv, rb_Array(range));
1115 }
1116 
1117 
1118 /*
1119  * call-seq:
1120  * rng.min -> obj
1121  * rng.min {| a,b | block } -> obj
1122  * rng.min(n) -> array
1123  * rng.min(n) {| a,b | block } -> array
1124  *
1125  * Returns the minimum value in the range. Returns +nil+ if the begin
1126  * value of the range is larger than the end value. Returns +nil+ if
1127  * the begin value of an exclusive range is equal to the end value.
1128  *
1129  * Can be given an optional block to override the default comparison
1130  * method <code>a <=> b</code>.
1131  *
1132  * (10..20).min #=> 10
1133  */
1134 
1135 
1136 static VALUE
1137 range_min(int argc, VALUE *argv, VALUE range)
1138 {
1139  if (NIL_P(RANGE_BEG(range))) {
1140  rb_raise(rb_eRangeError, "cannot get the minimum of beginless range");
1141  }
1142 
1143  if (rb_block_given_p()) {
1144  if (NIL_P(RANGE_END(range))) {
1145  rb_raise(rb_eRangeError, "cannot get the minimum of endless range with custom comparison method");
1146  }
1147  return rb_call_super(argc, argv);
1148  }
1149  else if (argc != 0) {
1150  return range_first(argc, argv, range);
1151  }
1152  else {
1153  struct cmp_opt_data cmp_opt = { 0, 0 };
1154  VALUE b = RANGE_BEG(range);
1155  VALUE e = RANGE_END(range);
1156  int c = NIL_P(e) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt);
1157 
1158  if (c > 0 || (c == 0 && EXCL(range)))
1159  return Qnil;
1160  return b;
1161  }
1162 }
1163 
1164 /*
1165  * call-seq:
1166  * rng.max -> obj
1167  * rng.max {| a,b | block } -> obj
1168  * rng.max(n) -> obj
1169  * rng.max(n) {| a,b | block } -> obj
1170  *
1171  * Returns the maximum value in the range. Returns +nil+ if the begin
1172  * value of the range larger than the end value. Returns +nil+ if
1173  * the begin value of an exclusive range is equal to the end value.
1174  *
1175  * Can be given an optional block to override the default comparison
1176  * method <code>a <=> b</code>.
1177  *
1178  * (10..20).max #=> 20
1179  */
1180 
1181 static VALUE
1182 range_max(int argc, VALUE *argv, VALUE range)
1183 {
1184  VALUE e = RANGE_END(range);
1185  int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
1186 
1187  if (NIL_P(RANGE_END(range))) {
1188  rb_raise(rb_eRangeError, "cannot get the maximum of endless range");
1189  }
1190 
1191  if (rb_block_given_p() || (EXCL(range) && !nm) || argc) {
1192  if (NIL_P(RANGE_BEG(range))) {
1193  rb_raise(rb_eRangeError, "cannot get the maximum of beginless range with custom comparison method");
1194  }
1195  return rb_call_super(argc, argv);
1196  }
1197  else {
1198  struct cmp_opt_data cmp_opt = { 0, 0 };
1199  VALUE b = RANGE_BEG(range);
1200  int c = OPTIMIZED_CMP(b, e, cmp_opt);
1201 
1202  if (c > 0)
1203  return Qnil;
1204  if (EXCL(range)) {
1205  if (!RB_INTEGER_TYPE_P(e)) {
1206  rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
1207  }
1208  if (c == 0) return Qnil;
1209  if (!RB_INTEGER_TYPE_P(b)) {
1210  rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
1211  }
1212  if (FIXNUM_P(e)) {
1213  return LONG2NUM(FIX2LONG(e) - 1);
1214  }
1215  return rb_funcall(e, '-', 1, INT2FIX(1));
1216  }
1217  return e;
1218  }
1219 }
1220 
1221 /*
1222  * call-seq:
1223  * rng.minmax -> [obj, obj]
1224  * rng.minmax {| a,b | block } -> [obj, obj]
1225  *
1226  * Returns a two element array which contains the minimum and the
1227  * maximum value in the range.
1228  *
1229  * Can be given an optional block to override the default comparison
1230  * method <code>a <=> b</code>.
1231  */
1232 
1233 static VALUE
1234 range_minmax(VALUE range)
1235 {
1236  if (rb_block_given_p()) {
1237  return rb_call_super(0, NULL);
1238  }
1239  return rb_assoc_new(range_min(0, NULL, range), range_max(0, NULL, range));
1240 }
1241 
1242 int
1243 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
1244 {
1245  VALUE b, e;
1246  int excl;
1247 
1249  b = RANGE_BEG(range);
1250  e = RANGE_END(range);
1251  excl = EXCL(range);
1252  }
1253  else if (RTEST(rb_obj_is_kind_of(range, rb_cArithSeq))) {
1254  return (int)Qfalse;
1255  }
1256  else {
1257  VALUE x;
1258  b = rb_check_funcall(range, id_beg, 0, 0);
1259  if (b == Qundef) return (int)Qfalse;
1260  e = rb_check_funcall(range, id_end, 0, 0);
1261  if (e == Qundef) return (int)Qfalse;
1262  x = rb_check_funcall(range, rb_intern("exclude_end?"), 0, 0);
1263  if (x == Qundef) return (int)Qfalse;
1264  excl = RTEST(x);
1265  }
1266  *begp = b;
1267  *endp = e;
1268  *exclp = excl;
1269  return (int)Qtrue;
1270 }
1271 
1272 VALUE
1273 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
1274 {
1275  long beg, end, origbeg, origend;
1276  VALUE b, e;
1277  int excl;
1278 
1279  if (!rb_range_values(range, &b, &e, &excl))
1280  return Qfalse;
1281  beg = NIL_P(b) ? 0 : NUM2LONG(b);
1282  end = NIL_P(e) ? -1 : NUM2LONG(e);
1283  if (NIL_P(e)) excl = 0;
1284  origbeg = beg;
1285  origend = end;
1286  if (beg < 0) {
1287  beg += len;
1288  if (beg < 0)
1289  goto out_of_range;
1290  }
1291  if (end < 0)
1292  end += len;
1293  if (!excl)
1294  end++; /* include end point */
1295  if (err == 0 || err == 2) {
1296  if (beg > len)
1297  goto out_of_range;
1298  if (end > len)
1299  end = len;
1300  }
1301  len = end - beg;
1302  if (len < 0)
1303  len = 0;
1304 
1305  *begp = beg;
1306  *lenp = len;
1307  return Qtrue;
1308 
1309  out_of_range:
1310  if (err) {
1311  rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
1312  origbeg, excl ? "." : "", origend);
1313  }
1314  return Qnil;
1315 }
1316 
1317 /*
1318  * call-seq:
1319  * rng.to_s -> string
1320  *
1321  * Convert this range object to a printable form (using #to_s to convert the
1322  * begin and end objects).
1323  */
1324 
1325 static VALUE
1326 range_to_s(VALUE range)
1327 {
1328  VALUE str, str2;
1329 
1331  str2 = rb_obj_as_string(RANGE_END(range));
1332  str = rb_str_dup(str);
1333  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1334  rb_str_append(str, str2);
1335 
1336  return str;
1337 }
1338 
1339 static VALUE
1340 inspect_range(VALUE range, VALUE dummy, int recur)
1341 {
1342  VALUE str, str2 = Qundef;
1343 
1344  if (recur) {
1345  return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
1346  }
1347  if (!NIL_P(RANGE_BEG(range)) || NIL_P(RANGE_END(range))) {
1349  }
1350  else {
1351  str = rb_str_new(0, 0);
1352  }
1353  rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
1354  if (NIL_P(RANGE_BEG(range)) || !NIL_P(RANGE_END(range))) {
1355  str2 = rb_inspect(RANGE_END(range));
1356  }
1357  if (str2 != Qundef) rb_str_append(str, str2);
1358 
1359  return str;
1360 }
1361 
1362 /*
1363  * call-seq:
1364  * rng.inspect -> string
1365  *
1366  * Convert this range object to a printable form (using #inspect to
1367  * convert the begin and end objects).
1368  */
1369 
1370 
1371 static VALUE
1372 range_inspect(VALUE range)
1373 {
1374  return rb_exec_recursive(inspect_range, range, 0);
1375 }
1376 
1377 static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover);
1378 
1379 /*
1380  * call-seq:
1381  * rng === obj -> true or false
1382  *
1383  * Returns <code>true</code> if +obj+ is between begin and end of range,
1384  * <code>false</code> otherwise (same as #cover?). Conveniently,
1385  * <code>===</code> is the comparison operator used by <code>case</code>
1386  * statements.
1387  *
1388  * case 79
1389  * when 1..50 then puts "low"
1390  * when 51..75 then puts "medium"
1391  * when 76..100 then puts "high"
1392  * end
1393  * # Prints "high"
1394  *
1395  * case "2.6.5"
1396  * when ..."2.4" then puts "EOL"
1397  * when "2.4"..."2.5" then puts "maintenance"
1398  * when "2.5"..."2.7" then puts "stable"
1399  * when "2.7".. then puts "upcoming"
1400  * end
1401  * # Prints "stable"
1402  *
1403  */
1404 
1405 static VALUE
1406 range_eqq(VALUE range, VALUE val)
1407 {
1408  VALUE ret = range_include_internal(range, val, 1);
1409  if (ret != Qundef) return ret;
1410  return r_cover_p(range, RANGE_BEG(range), RANGE_END(range), val);
1411 }
1412 
1413 
1414 /*
1415  * call-seq:
1416  * rng.member?(obj) -> true or false
1417  * rng.include?(obj) -> true or false
1418  *
1419  * Returns <code>true</code> if +obj+ is an element of
1420  * the range, <code>false</code> otherwise.
1421  *
1422  * ("a".."z").include?("g") #=> true
1423  * ("a".."z").include?("A") #=> false
1424  * ("a".."z").include?("cc") #=> false
1425  *
1426  * If you need to ensure +obj+ is between +begin+ and +end+, use #cover?
1427  *
1428  * ("a".."z").cover?("cc") #=> true
1429  *
1430  * If begin and end are numeric, #include? behaves like #cover?
1431  *
1432  * (1..3).include?(1.5) # => true
1433  */
1434 
1435 static VALUE
1436 range_include(VALUE range, VALUE val)
1437 {
1438  VALUE ret = range_include_internal(range, val, 0);
1439  if (ret != Qundef) return ret;
1440  return rb_call_super(1, &val);
1441 }
1442 
1443 static VALUE
1444 range_include_internal(VALUE range, VALUE val, int string_use_cover)
1445 {
1446  VALUE beg = RANGE_BEG(range);
1447  VALUE end = RANGE_END(range);
1448  int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
1449  linear_object_p(beg) || linear_object_p(end);
1450 
1451  if (nv ||
1452  !NIL_P(rb_check_to_integer(beg, "to_int")) ||
1453  !NIL_P(rb_check_to_integer(end, "to_int"))) {
1454  return r_cover_p(range, beg, end, val);
1455  }
1456  else if (RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING)) {
1457  if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) {
1458  if (string_use_cover) {
1459  return r_cover_p(range, beg, end, val);
1460  }
1461  else {
1462  VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
1463  return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range));
1464  }
1465  }
1466  else if (NIL_P(beg)) {
1467  VALUE r = rb_funcall(val, id_cmp, 1, end);
1468  if (NIL_P(r)) return Qfalse;
1469  if (rb_cmpint(r, val, end) <= 0) return Qtrue;
1470  return Qfalse;
1471  }
1472  else if (NIL_P(end)) {
1473  VALUE r = rb_funcall(beg, id_cmp, 1, val);
1474  if (NIL_P(r)) return Qfalse;
1475  if (rb_cmpint(r, beg, val) <= 0) return Qtrue;
1476  return Qfalse;
1477  }
1478  }
1479  return Qundef;
1480 }
1481 
1482 static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val);
1483 
1484 /*
1485  * call-seq:
1486  * rng.cover?(obj) -> true or false
1487  * rng.cover?(range) -> true or false
1488  *
1489  * Returns <code>true</code> if +obj+ is between the begin and end of
1490  * the range.
1491  *
1492  * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1493  * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1494  *
1495  * If called with a Range argument, returns <code>true</code> when the
1496  * given range is covered by the receiver,
1497  * by comparing the begin and end values. If the argument can be treated as
1498  * a sequence, this method treats it that way. In the specific case of
1499  * <code>(a..b).cover?(c...d)</code> with <code>a <= c && b < d</code>,
1500  * the end of the sequence must be calculated, which may exhibit poor
1501  * performance if <code>c</code> is non-numeric.
1502  * Returns <code>false</code> if the begin value of the
1503  * range is larger than the end value. Also returns +false+ if one of the
1504  * internal calls to <code><=></code> returns +nil+ (indicating the objects
1505  * are not comparable).
1506  *
1507  * ("a".."z").cover?("c") #=> true
1508  * ("a".."z").cover?("5") #=> false
1509  * ("a".."z").cover?("cc") #=> true
1510  * ("a".."z").cover?(1) #=> false
1511  * (1..5).cover?(2..3) #=> true
1512  * (1..5).cover?(0..6) #=> false
1513  * (1..5).cover?(1...6) #=> true
1514  */
1515 
1516 static VALUE
1517 range_cover(VALUE range, VALUE val)
1518 {
1519  VALUE beg, end;
1520 
1521  beg = RANGE_BEG(range);
1522  end = RANGE_END(range);
1523 
1524  if (rb_obj_is_kind_of(val, rb_cRange)) {
1525  return RBOOL(r_cover_range_p(range, beg, end, val));
1526  }
1527  return r_cover_p(range, beg, end, val);
1528 }
1529 
1530 static VALUE
1531 r_call_max(VALUE r)
1532 {
1533  return rb_funcallv(r, rb_intern("max"), 0, 0);
1534 }
1535 
1536 static int
1537 r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1538 {
1539  VALUE val_beg, val_end, val_max;
1540  int cmp_end;
1541 
1542  val_beg = RANGE_BEG(val);
1543  val_end = RANGE_END(val);
1544 
1545  if (!NIL_P(end) && NIL_P(val_end)) return FALSE;
1546  if (!NIL_P(beg) && NIL_P(val_beg)) return FALSE;
1547  if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > -EXCL(val)) return FALSE;
1548  if (!NIL_P(val_beg) && !r_cover_p(range, beg, end, val_beg)) return FALSE;
1549 
1550  cmp_end = r_less(end, val_end);
1551 
1552  if (EXCL(range) == EXCL(val)) {
1553  return cmp_end >= 0;
1554  }
1555  else if (EXCL(range)) {
1556  return cmp_end > 0;
1557  }
1558  else if (cmp_end >= 0) {
1559  return TRUE;
1560  }
1561 
1562  val_max = rb_rescue2(r_call_max, val, NULL, Qnil, rb_eTypeError, (VALUE)0);
1563  if (val_max == Qnil) return FALSE;
1564 
1565  return r_less(end, val_max) >= 0;
1566 }
1567 
1568 static VALUE
1569 r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1570 {
1571  if (NIL_P(beg) || r_less(beg, val) <= 0) {
1572  int excl = EXCL(range);
1573  if (NIL_P(end) || r_less(val, end) <= -excl)
1574  return Qtrue;
1575  }
1576  return Qfalse;
1577 }
1578 
1579 static VALUE
1580 range_dumper(VALUE range)
1581 {
1582  VALUE v;
1584 
1585  v = (VALUE)m;
1586 
1587  rb_ivar_set(v, id_excl, RANGE_EXCL(range));
1588  rb_ivar_set(v, id_beg, RANGE_BEG(range));
1589  rb_ivar_set(v, id_end, RANGE_END(range));
1590  return v;
1591 }
1592 
1593 static VALUE
1594 range_loader(VALUE range, VALUE obj)
1595 {
1596  VALUE beg, end, excl;
1597 
1598  if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
1599  rb_raise(rb_eTypeError, "not a dumped range object");
1600  }
1601 
1602  range_modify(range);
1603  beg = rb_ivar_get(obj, id_beg);
1604  end = rb_ivar_get(obj, id_end);
1605  excl = rb_ivar_get(obj, id_excl);
1606  if (!NIL_P(excl)) {
1607  range_init(range, beg, end, RBOOL(RTEST(excl)));
1608  }
1609  return range;
1610 }
1611 
1612 static VALUE
1613 range_alloc(VALUE klass)
1614 {
1615  /* rb_struct_alloc_noinit itself should not be used because
1616  * rb_marshal_define_compat uses equality of allocation function */
1617  return rb_struct_alloc_noinit(klass);
1618 }
1619 
1620 /*
1621  * call-seq:
1622  * range.count -> int
1623  * range.count(item) -> int
1624  * range.count { |obj| block } -> int
1625  *
1626  * Identical to Enumerable#count, except it returns Infinity for endless
1627  * ranges.
1628  *
1629  */
1630 static VALUE
1631 range_count(int argc, VALUE *argv, VALUE range)
1632 {
1633  if (argc != 0) {
1634  /* It is odd for instance (1...).count(0) to return Infinity. Just let
1635  * it loop. */
1636  return rb_call_super(argc, argv);
1637  }
1638  else if (rb_block_given_p()) {
1639  /* Likewise it is odd for instance (1...).count {|x| x == 0 } to return
1640  * Infinity. Just let it loop. */
1641  return rb_call_super(argc, argv);
1642  }
1643  else if (NIL_P(RANGE_END(range))) {
1644  /* We are confident that the answer is Infinity. */
1645  return DBL2NUM(HUGE_VAL);
1646  }
1647  else if (NIL_P(RANGE_BEG(range))) {
1648  /* We are confident that the answer is Infinity. */
1649  return DBL2NUM(HUGE_VAL);
1650  }
1651  else {
1652  return rb_call_super(argc, argv);
1653  }
1654 }
1655 
1656 /* A Range represents an interval---a set of values with a
1657  * beginning and an end. Ranges may be constructed using the
1658  * <em>s</em><code>..</code><em>e</em> and
1659  * <em>s</em><code>...</code><em>e</em> literals, or with
1660  * Range::new. Ranges constructed using <code>..</code>
1661  * run from the beginning to the end inclusively. Those created using
1662  * <code>...</code> exclude the end value. When used as an iterator,
1663  * ranges return each value in the sequence.
1664  *
1665  * (-1..-5).to_a #=> []
1666  * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
1667  * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
1668  * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
1669  *
1670  * == Beginless/Endless Ranges
1671  *
1672  * A "beginless range" and "endless range" represents a semi-infinite
1673  * range. Literal notation for a beginless range is:
1674  *
1675  * (..1)
1676  * # or
1677  * (...1)
1678  *
1679  * Literal notation for an endless range is:
1680  *
1681  * (1..)
1682  * # or similarly
1683  * (1...)
1684  *
1685  * Which is equivalent to
1686  *
1687  * (1..nil) # or similarly (1...nil)
1688  * Range.new(1, nil) # or Range.new(1, nil, true)
1689  *
1690  * Beginless/endless ranges are useful, for example, for idiomatic
1691  * slicing of arrays:
1692  *
1693  * [1, 2, 3, 4, 5][...2] # => [1, 2]
1694  * [1, 2, 3, 4, 5][2...] # => [3, 4, 5]
1695  *
1696  * Some implementation details:
1697  *
1698  * * +begin+ of beginless range and +end+ of endless range are +nil+;
1699  * * +each+ of beginless range raises an exception;
1700  * * +each+ of endless range enumerates infinite sequence (may be
1701  * useful in combination with Enumerable#take_while or similar
1702  * methods);
1703  * * <code>(1..)</code> and <code>(1...)</code> are not equal,
1704  * although technically representing the same sequence.
1705  *
1706  * == Custom Objects in Ranges
1707  *
1708  * Ranges can be constructed using any objects that can be compared
1709  * using the <code><=></code> operator.
1710  * Methods that treat the range as a sequence (#each and methods inherited
1711  * from Enumerable) expect the begin object to implement a
1712  * <code>succ</code> method to return the next object in sequence.
1713  * The #step and #include? methods require the begin
1714  * object to implement <code>succ</code> or to be numeric.
1715  *
1716  * In the <code>Xs</code> class below both <code><=></code> and
1717  * <code>succ</code> are implemented so <code>Xs</code> can be used
1718  * to construct ranges. Note that the Comparable module is included
1719  * so the <code>==</code> method is defined in terms of <code><=></code>.
1720  *
1721  * class Xs # represent a string of 'x's
1722  * include Comparable
1723  * attr :length
1724  * def initialize(n)
1725  * @length = n
1726  * end
1727  * def succ
1728  * Xs.new(@length + 1)
1729  * end
1730  * def <=>(other)
1731  * @length <=> other.length
1732  * end
1733  * def to_s
1734  * sprintf "%2d #{inspect}", @length
1735  * end
1736  * def inspect
1737  * 'x' * @length
1738  * end
1739  * end
1740  *
1741  * An example of using <code>Xs</code> to construct a range:
1742  *
1743  * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
1744  * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
1745  * r.member?(Xs.new(5)) #=> true
1746  *
1747  */
1748 
1749 void
1751 {
1752 #undef rb_intern
1753 #define rb_intern(str) rb_intern_const(str)
1754 
1755  id_beg = rb_intern("begin");
1756  id_end = rb_intern("end");
1757  id_excl = rb_intern("excl");
1758 
1760  "Range", rb_cObject, range_alloc,
1761  "begin", "end", "excl", NULL);
1762 
1764  rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
1765  rb_define_method(rb_cRange, "initialize", range_initialize, -1);
1766  rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
1767  rb_define_method(rb_cRange, "==", range_eq, 1);
1768  rb_define_method(rb_cRange, "===", range_eqq, 1);
1769  rb_define_method(rb_cRange, "eql?", range_eql, 1);
1770  rb_define_method(rb_cRange, "hash", range_hash, 0);
1771  rb_define_method(rb_cRange, "each", range_each, 0);
1772  rb_define_method(rb_cRange, "step", range_step, -1);
1773  rb_define_method(rb_cRange, "%", range_percent_step, 1);
1774  rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
1775  rb_define_method(rb_cRange, "begin", range_begin, 0);
1776  rb_define_method(rb_cRange, "end", range_end, 0);
1777  rb_define_method(rb_cRange, "first", range_first, -1);
1778  rb_define_method(rb_cRange, "last", range_last, -1);
1779  rb_define_method(rb_cRange, "min", range_min, -1);
1780  rb_define_method(rb_cRange, "max", range_max, -1);
1781  rb_define_method(rb_cRange, "minmax", range_minmax, 0);
1782  rb_define_method(rb_cRange, "size", range_size, 0);
1783  rb_define_method(rb_cRange, "to_a", range_to_a, 0);
1784  rb_define_method(rb_cRange, "entries", range_to_a, 0);
1785  rb_define_method(rb_cRange, "to_s", range_to_s, 0);
1786  rb_define_method(rb_cRange, "inspect", range_inspect, 0);
1787 
1788  rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
1789 
1790  rb_define_method(rb_cRange, "member?", range_include, 1);
1791  rb_define_method(rb_cRange, "include?", range_include, 1);
1792  rb_define_method(rb_cRange, "cover?", range_cover, 1);
1793  rb_define_method(rb_cRange, "count", range_count, -1);
1794 }
FLONUM_P
#define FLONUM_P(x)
Definition: ruby.h:430
rb_ary_new_capa
VALUE rb_ary_new_capa(long capa)
Definition: array.c:717
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5464
ID
unsigned long ID
Definition: ruby.h:103
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
RANGE_SET_EXCL
#define RANGE_SET_EXCL(r, v)
Definition: range.c:30
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5742
TRUE
#define TRUE
Definition: nkf.h:175
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_range_beg_len
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Definition: range.c:1273
assert
#define assert(x)
Definition: dlmalloc.c:1176
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13259
range
#define range(low, item, hi)
Definition: date_strftime.c:21
rb_arith_seq_new
VALUE rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, rb_enumerator_size_func *size_fn, VALUE beg, VALUE end, VALUE step, int excl)
Definition: enumerator.c:3308
id_div
#define id_div
Definition: enum.c:24
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
id_cmp
#define id_cmp
Definition: range.c:23
RBIGNUM_POSITIVE_P
#define RBIGNUM_POSITIVE_P(b)
Definition: ruby.h:1262
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:2037
idEach
@ idEach
Definition: rb_mjit_min_header-2.7.1.h:8708
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.1.h:6585
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5456
RObject
Definition: ruby.h:922
idInitialize
@ idInitialize
Definition: rb_mjit_min_header-2.7.1.h:8714
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:133
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:2048
FIXNUM_ZERO_P
#define FIXNUM_ZERO_P(num)
Definition: internal.h:1778
RB_LIKELY
#define RB_LIKELY(x)
Definition: defines.h:91
rb_num_negative_p
int rb_num_negative_p(VALUE)
Definition: numeric.c:313
id.h
RBOOL
#define RBOOL(v)
Definition: range.c:31
Init_Range
void Init_Range(void)
Definition: range.c:1750
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:306
assert.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
RANGE_END
#define RANGE_END(r)
Definition: internal.h:2091
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_Float
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3493
rb_str_include_range_p
VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive)
Definition: string.c:4398
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
idLE
@ idLE
Definition: id.h:93
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.1.h:6116
Qfalse
#define Qfalse
Definition: ruby.h:467
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:271
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:967
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
NULL
#define NULL
Definition: _sdbm.c:101
rb_cmpint
#define rb_cmpint(cmp, a, b)
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
RBIGNUM_SIGN
#define RBIGNUM_SIGN(b)
Definition: ruby.h:1261
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_struct_alloc_noinit
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:352
T_OBJECT
#define T_OBJECT
Definition: ruby.h:523
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
ASSUME
#define ASSUME(x)
Definition: ruby.h:52
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_eql
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
EXCL
#define EXCL(r)
Definition: range.c:33
rb_cRange
VALUE rb_cRange
Definition: range.c:21
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
id_succ
#define id_succ
Definition: range.c:24
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:926
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
BSEARCH_CHECK
#define BSEARCH_CHECK(expr)
FIXNUM_FLAG
#define FIXNUM_FLAG
Definition: ruby.h:472
HUGE_VAL
#define HUGE_VAL
Definition: missing.h:161
rb_str_upto_endless_each
VALUE rb_str_upto_endless_each(VALUE, int(*each)(VALUE, VALUE), VALUE)
Definition: string.c:4345
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
POSFIXABLE
#define POSFIXABLE(f)
Definition: ruby.h:397
rb_Array
VALUE rb_Array(VALUE)
Equivalent to Kernel#Array in Ruby.
Definition: object.c:3684
rb_big_cmp
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5419
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1183
RANGE_BEG
#define RANGE_BEG(r)
Definition: internal.h:2090
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.1.h:7905
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
rb_ary_last
VALUE rb_ary_last(int argc, const VALUE *argv, VALUE ary)
Definition: array.c:1677
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
rb_struct_define_without_accessor
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:421
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
FALSE
#define FALSE
Definition: nkf.h:174
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
rb_struct_init_copy
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:977
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
cmp_opt_data
Definition: internal.h:1322
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1546
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
fabs
double fabs(double)
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6372
rb_cArithSeq
VALUE rb_cArithSeq
Definition: enumerator.c:180
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
ruby_num_interval_step_size
VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
Definition: numeric.c:2555
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
internal.h
OPTIMIZED_CMP
#define OPTIMIZED_CMP(a, b, data)
Definition: internal.h:1337
argv
char ** argv
Definition: ruby.c:223
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
ruby_float_step
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless)
Definition: numeric.c:2524
rb_hash_end
#define rb_hash_end(h)
Definition: intern.h:816
BSEARCH
#define BSEARCH(conv)
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition: cxxanyargs.hpp:178
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argc
int argc
Definition: ruby.c:222
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
rb_big_plus
VALUE rb_big_plus(VALUE x, VALUE y)
Definition: bignum.c:5824
recur
#define recur(fmt)
Definition: date_strptime.c:152
err
int err
Definition: win32.c:135
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:966
rb_int_gt
VALUE rb_int_gt(VALUE x, VALUE y)
Definition: numeric.c:4252
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12337
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
RANGE_SET_BEG
#define RANGE_SET_BEG(r, v)
Definition: range.c:28
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:962
len
uint8_t len
Definition: escape.c:17
idCmp
@ idCmp
Definition: id.h:84
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
ONE
#define ONE
Definition: complex.c:21
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5086
int64_t
__int64_t int64_t
Definition: rb_mjit_min_header-2.7.1.h:1180
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
RGENGC_WB_PROTECTED_OBJECT
#define RGENGC_WB_PROTECTED_OBJECT
Definition: ruby.h:814
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
rb_range_new
VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end)
Definition: range.c:52
FIXABLE
#define FIXABLE(f)
Definition: ruby.h:399
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
rb_range_values
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:1243
Qnil
#define Qnil
Definition: ruby.h:469
RANGE_EXCL
#define RANGE_EXCL(r)
Definition: internal.h:2092
rb_intern
#define rb_intern(str)
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1576
rb_int_plus
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3610
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.1.h:4052
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
RTEST
#define RTEST(v)
Definition: ruby.h:481
RBIGNUM_NEGATIVE_P
#define RBIGNUM_NEGATIVE_P(b)
Definition: ruby.h:1263
RANGE_SET_END
#define RANGE_SET_END(r, v)
Definition: range.c:29
rb_int_minus
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3649
rb_str_upto_each
VALUE rb_str_upto_each(VALUE, VALUE, int, int(*each)(VALUE, VALUE), VALUE)
Definition: string.c:4263
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.1.h:7904