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