Ruby  2.0.0p481(2014-05-08revision45883)
range.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   range.c -
00004 
00005   $Author: nagachika $
00006   created at: Thu Aug 19 17:46:47 JST 1993
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009 
00010 **********************************************************************/
00011 
00012 #include "ruby/ruby.h"
00013 #include "ruby/encoding.h"
00014 #include "internal.h"
00015 #include "id.h"
00016 
00017 #ifdef HAVE_FLOAT_H
00018 #include <float.h>
00019 #endif
00020 #include <math.h>
00021 
00022 VALUE rb_cRange;
00023 static ID id_cmp, id_succ, id_beg, id_end, id_excl, id_integer_p, id_div;
00024 
00025 #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
00026 #define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
00027 #define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
00028 
00029 #define EXCL(r) RTEST(RANGE_EXCL(r))
00030 #define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
00031 
00032 static VALUE
00033 range_failed(void)
00034 {
00035     rb_raise(rb_eArgError, "bad value for range");
00036     return Qnil;                /* dummy */
00037 }
00038 
00039 static VALUE
00040 range_check(VALUE *args)
00041 {
00042     return rb_funcall(args[0], id_cmp, 1, args[1]);
00043 }
00044 
00045 static void
00046 range_init(VALUE range, VALUE beg, VALUE end, int exclude_end)
00047 {
00048     VALUE args[2];
00049 
00050     args[0] = beg;
00051     args[1] = end;
00052 
00053     if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
00054         VALUE v;
00055 
00056         v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
00057         if (NIL_P(v))
00058             range_failed();
00059     }
00060 
00061     SET_EXCL(range, exclude_end);
00062     RSTRUCT(range)->as.ary[0] = beg;
00063     RSTRUCT(range)->as.ary[1] = end;
00064 }
00065 
00066 VALUE
00067 rb_range_new(VALUE beg, VALUE end, int exclude_end)
00068 {
00069     VALUE range = rb_obj_alloc(rb_cRange);
00070 
00071     range_init(range, beg, end, exclude_end);
00072     return range;
00073 }
00074 
00075 /*
00076  *  call-seq:
00077  *     Range.new(begin, end, exclude_end=false)    -> rng
00078  *
00079  *  Constructs a range using the given +begin+ and +end+. If the +exclude_end+
00080  *  parameter is omitted or is <code>false</code>, the +rng+ will include
00081  *  the end object; otherwise, it will be excluded.
00082  */
00083 
00084 static VALUE
00085 range_initialize(int argc, VALUE *argv, VALUE range)
00086 {
00087     VALUE beg, end, flags;
00088 
00089     rb_scan_args(argc, argv, "21", &beg, &end, &flags);
00090     /* Ranges are immutable, so that they should be initialized only once. */
00091     if (RANGE_EXCL(range) != Qnil) {
00092         rb_name_error(idInitialize, "`initialize' called twice");
00093     }
00094     range_init(range, beg, end, RTEST(flags));
00095     return Qnil;
00096 }
00097 
00098 #define range_initialize_copy rb_struct_init_copy /* :nodoc: */
00099 
00100 /*
00101  *  call-seq:
00102  *     rng.exclude_end?    -> true or false
00103  *
00104  *  Returns <code>true</code> if the range excludes its end value.
00105  *
00106  *     (1..5).exclude_end?     #=> false
00107  *     (1...5).exclude_end?    #=> true
00108  */
00109 
00110 static VALUE
00111 range_exclude_end_p(VALUE range)
00112 {
00113     return EXCL(range) ? Qtrue : Qfalse;
00114 }
00115 
00116 static VALUE
00117 recursive_equal(VALUE range, VALUE obj, int recur)
00118 {
00119     if (recur) return Qtrue; /* Subtle! */
00120     if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
00121         return Qfalse;
00122     if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
00123         return Qfalse;
00124 
00125     if (EXCL(range) != EXCL(obj))
00126         return Qfalse;
00127     return Qtrue;
00128 }
00129 
00130 
00131 /*
00132  *  call-seq:
00133  *     rng == obj    -> true or false
00134  *
00135  *  Returns <code>true</code> only if +obj+ is a Range, has equivalent
00136  *  begin and end items (by comparing them with <code>==</code>), and has
00137  *  the same #exclude_end? setting as the range.
00138  *
00139  *    (0..2) == (0..2)            #=> true
00140  *    (0..2) == Range.new(0,2)    #=> true
00141  *    (0..2) == (0...2)           #=> false
00142  *
00143  */
00144 
00145 static VALUE
00146 range_eq(VALUE range, VALUE obj)
00147 {
00148     if (range == obj)
00149         return Qtrue;
00150     if (!rb_obj_is_kind_of(obj, rb_cRange))
00151         return Qfalse;
00152 
00153     return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
00154 }
00155 
00156 static int
00157 r_lt(VALUE a, VALUE b)
00158 {
00159     VALUE r = rb_funcall(a, id_cmp, 1, b);
00160 
00161     if (NIL_P(r))
00162         return (int)Qfalse;
00163     if (rb_cmpint(r, a, b) < 0)
00164         return (int)Qtrue;
00165     return (int)Qfalse;
00166 }
00167 
00168 static int
00169 r_le(VALUE a, VALUE b)
00170 {
00171     int c;
00172     VALUE r = rb_funcall(a, id_cmp, 1, b);
00173 
00174     if (NIL_P(r))
00175         return (int)Qfalse;
00176     c = rb_cmpint(r, a, b);
00177     if (c == 0)
00178         return (int)INT2FIX(0);
00179     if (c < 0)
00180         return (int)Qtrue;
00181     return (int)Qfalse;
00182 }
00183 
00184 
00185 static VALUE
00186 recursive_eql(VALUE range, VALUE obj, int recur)
00187 {
00188     if (recur) return Qtrue; /* Subtle! */
00189     if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
00190         return Qfalse;
00191     if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
00192         return Qfalse;
00193 
00194     if (EXCL(range) != EXCL(obj))
00195         return Qfalse;
00196     return Qtrue;
00197 }
00198 
00199 /*
00200  *  call-seq:
00201  *     rng.eql?(obj)    -> true or false
00202  *
00203  *  Returns <code>true</code> only if +obj+ is a Range, has equivalent
00204  *  begin and end items (by comparing them with <code>eql?</code>),
00205  *  and has the same #exclude_end? setting as the range.
00206  *
00207  *    (0..2).eql?(0..2)            #=> true
00208  *    (0..2).eql?(Range.new(0,2))  #=> true
00209  *    (0..2).eql?(0...2)           #=> false
00210  *
00211  */
00212 
00213 static VALUE
00214 range_eql(VALUE range, VALUE obj)
00215 {
00216     if (range == obj)
00217         return Qtrue;
00218     if (!rb_obj_is_kind_of(obj, rb_cRange))
00219         return Qfalse;
00220     return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
00221 }
00222 
00223 static VALUE
00224 recursive_hash(VALUE range, VALUE dummy, int recur)
00225 {
00226     st_index_t hash = EXCL(range);
00227     VALUE v;
00228 
00229     hash = rb_hash_start(hash);
00230     if (!recur) {
00231         v = rb_hash(RANGE_BEG(range));
00232         hash = rb_hash_uint(hash, NUM2LONG(v));
00233         v = rb_hash(RANGE_END(range));
00234         hash = rb_hash_uint(hash, NUM2LONG(v));
00235     }
00236     hash = rb_hash_uint(hash, EXCL(range) << 24);
00237     hash = rb_hash_end(hash);
00238 
00239     return LONG2FIX(hash);
00240 }
00241 
00242 /*
00243  * call-seq:
00244  *   rng.hash    -> fixnum
00245  *
00246  * Compute a hash-code for this range. Two ranges with equal
00247  * begin and end points (using <code>eql?</code>), and the same
00248  * #exclude_end? value will generate the same hash-code.
00249  */
00250 
00251 static VALUE
00252 range_hash(VALUE range)
00253 {
00254     return rb_exec_recursive_outer(recursive_hash, range, 0);
00255 }
00256 
00257 static void
00258 range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
00259 {
00260     int c;
00261     VALUE b = RANGE_BEG(range);
00262     VALUE e = RANGE_END(range);
00263     VALUE v = b;
00264 
00265     if (EXCL(range)) {
00266         while (r_lt(v, e)) {
00267             (*func) (v, arg);
00268             v = rb_funcall(v, id_succ, 0, 0);
00269         }
00270     }
00271     else {
00272         while ((c = r_le(v, e)) != Qfalse) {
00273             (*func) (v, arg);
00274             if (c == (int)INT2FIX(0))
00275                 break;
00276             v = rb_funcall(v, id_succ, 0, 0);
00277         }
00278     }
00279 }
00280 
00281 static VALUE
00282 sym_step_i(VALUE i, void *arg)
00283 {
00284     VALUE *iter = arg;
00285 
00286     if (FIXNUM_P(iter[0])) {
00287         iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
00288     }
00289     else {
00290         iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
00291     }
00292     if (iter[0] == INT2FIX(0)) {
00293         rb_yield(rb_str_intern(i));
00294         iter[0] = iter[1];
00295     }
00296     return Qnil;
00297 }
00298 
00299 static VALUE
00300 step_i(VALUE i, void *arg)
00301 {
00302     VALUE *iter = arg;
00303 
00304     if (FIXNUM_P(iter[0])) {
00305         iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
00306     }
00307     else {
00308         iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
00309     }
00310     if (iter[0] == INT2FIX(0)) {
00311         rb_yield(i);
00312         iter[0] = iter[1];
00313     }
00314     return Qnil;
00315 }
00316 
00317 static int
00318 discrete_object_p(VALUE obj)
00319 {
00320     if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
00321     return rb_respond_to(obj, id_succ);
00322 }
00323 
00324 static VALUE
00325 range_step_size(VALUE range, VALUE args)
00326 {
00327     VALUE b = RANGE_BEG(range), e = RANGE_END(range);
00328     VALUE step = INT2FIX(1);
00329     if (args) {
00330         step = RARRAY_PTR(args)[0];
00331         if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
00332             step = rb_to_int(step);
00333         }
00334     }
00335     if (rb_funcall(step, '<', 1, INT2FIX(0))) {
00336         rb_raise(rb_eArgError, "step can't be negative");
00337     }
00338     else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
00339         rb_raise(rb_eArgError, "step can't be 0");
00340     }
00341 
00342     if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
00343         return num_interval_step_size(b, e, step, EXCL(range));
00344     }
00345     return Qnil;
00346 }
00347 
00348 /*
00349  *  call-seq:
00350  *     rng.step(n=1) {| obj | block }    -> rng
00351  *     rng.step(n=1)                     -> an_enumerator
00352  *
00353  *  Iterates over the range, passing each <code>n</code>th element to the block.
00354  *  If begin and end are numeric, +n+ is added for each iteration.
00355  *  Otherwise <code>step</code> invokes <code>succ</code> to iterate through
00356  *  range elements.
00357  *
00358  *  If no block is given, an enumerator is returned instead.
00359  *
00360  *    range = Xs.new(1)..Xs.new(10)
00361  *    range.step(2) {|x| puts x}
00362  *    puts
00363  *    range.step(3) {|x| puts x}
00364  *
00365  *  <em>produces:</em>
00366  *
00367  *     1 x
00368  *     3 xxx
00369  *     5 xxxxx
00370  *     7 xxxxxxx
00371  *     9 xxxxxxxxx
00372  *
00373  *     1 x
00374  *     4 xxxx
00375  *     7 xxxxxxx
00376  *    10 xxxxxxxxxx
00377  *
00378  *  See Range for the definition of class Xs.
00379  */
00380 
00381 
00382 static VALUE
00383 range_step(int argc, VALUE *argv, VALUE range)
00384 {
00385     VALUE b, e, step, tmp;
00386 
00387     RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);
00388 
00389     b = RANGE_BEG(range);
00390     e = RANGE_END(range);
00391     if (argc == 0) {
00392         step = INT2FIX(1);
00393     }
00394     else {
00395         rb_scan_args(argc, argv, "01", &step);
00396         if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
00397             step = rb_to_int(step);
00398         }
00399         if (rb_funcall(step, '<', 1, INT2FIX(0))) {
00400             rb_raise(rb_eArgError, "step can't be negative");
00401         }
00402         else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
00403             rb_raise(rb_eArgError, "step can't be 0");
00404         }
00405     }
00406 
00407     if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
00408         long end = FIX2LONG(e);
00409         long i, unit = FIX2LONG(step);
00410 
00411         if (!EXCL(range))
00412             end += 1;
00413         i = FIX2LONG(b);
00414         while (i < end) {
00415             rb_yield(LONG2NUM(i));
00416             if (i + unit < i) break;
00417             i += unit;
00418         }
00419 
00420     }
00421     else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */
00422         VALUE args[2], iter[2];
00423 
00424         args[0] = rb_sym_to_s(e);
00425         args[1] = EXCL(range) ? Qtrue : Qfalse;
00426         iter[0] = INT2FIX(1);
00427         iter[1] = step;
00428         rb_block_call(rb_sym_to_s(b), rb_intern("upto"), 2, args, sym_step_i, (VALUE)iter);
00429     }
00430     else if (ruby_float_step(b, e, step, EXCL(range))) {
00431         /* done */
00432     }
00433     else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
00434              !NIL_P(rb_check_to_integer(b, "to_int")) ||
00435              !NIL_P(rb_check_to_integer(e, "to_int"))) {
00436         ID op = EXCL(range) ? '<' : idLE;
00437         VALUE v = b;
00438         int i = 0;
00439 
00440         while (RTEST(rb_funcall(v, op, 1, e))) {
00441             rb_yield(v);
00442             i++;
00443             v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
00444         }
00445     }
00446     else {
00447         tmp = rb_check_string_type(b);
00448 
00449         if (!NIL_P(tmp)) {
00450             VALUE args[2], iter[2];
00451 
00452             b = tmp;
00453             args[0] = e;
00454             args[1] = EXCL(range) ? Qtrue : Qfalse;
00455             iter[0] = INT2FIX(1);
00456             iter[1] = step;
00457             rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
00458         }
00459         else {
00460             VALUE args[2];
00461 
00462             if (!discrete_object_p(b)) {
00463                 rb_raise(rb_eTypeError, "can't iterate from %s",
00464                          rb_obj_classname(b));
00465             }
00466             args[0] = INT2FIX(1);
00467             args[1] = step;
00468             range_each_func(range, step_i, args);
00469         }
00470     }
00471     return range;
00472 }
00473 
00474 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
00475 union int64_double {
00476     int64_t i;
00477     double d;
00478 };
00479 
00480 static VALUE
00481 int64_as_double_to_num(int64_t i)
00482 {
00483     union int64_double convert;
00484     if (i < 0) {
00485         convert.i = -i;
00486         return DBL2NUM(-convert.d);
00487     }
00488     else {
00489         convert.i = i;
00490         return DBL2NUM(convert.d);
00491     }
00492 }
00493 
00494 static int64_t
00495 double_as_int64(double d)
00496 {
00497     union int64_double convert;
00498     convert.d = fabs(d);
00499     return d < 0 ? -convert.i : convert.i;
00500 }
00501 #endif
00502 
00503 static int
00504 is_integer_p(VALUE v)
00505 {
00506     VALUE is_int = rb_check_funcall(v, id_integer_p, 0, 0);
00507     return RTEST(is_int) && is_int != Qundef;
00508 }
00509 
00510 /*
00511  *  call-seq:
00512  *     rng.bsearch {|obj| block }  -> value
00513  *
00514  *  By using binary search, finds a value in range which meets the given
00515  *  condition in O(log n) where n is the size of the range.
00516  *
00517  *  You can use this method in two use cases: a find-minimum mode and
00518  *  a find-any mode.  In either case, the elements of the range must be
00519  *  monotone (or sorted) with respect to the block.
00520  *
00521  *  In find-minimum mode (this is a good choice for typical use case),
00522  *  the block must return true or false, and there must be a value x
00523  *  so that:
00524  *
00525  *  - the block returns false for any value which is less than x, and
00526  *  - the block returns true for any value which is greater than or
00527  *    equal to i.
00528  *
00529  *  If x is within the range, this method returns the value x.
00530  *  Otherwise, it returns nil.
00531  *
00532  *     ary = [0, 4, 7, 10, 12]
00533  *     (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
00534  *     (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
00535  *     (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
00536  *     (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
00537  *
00538  *     (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
00539  *
00540  *  In find-any mode (this behaves like libc's bsearch(3)), the block
00541  *  must return a number, and there must be two values x and y (x <= y)
00542  *  so that:
00543  *
00544  *  - the block returns a positive number for v if v < x,
00545  *  - the block returns zero for v if x <= v < y, and
00546  *  - the block returns a negative number for v if y <= v.
00547  *
00548  *  This method returns any value which is within the intersection of
00549  *  the given range and x...y (if any).  If there is no value that
00550  *  satisfies the condition, it returns nil.
00551  *
00552  *     ary = [0, 100, 100, 100, 200]
00553  *     (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
00554  *     (0..4).bsearch {|i| 300 - ary[i] } #=> nil
00555  *     (0..4).bsearch {|i|  50 - ary[i] } #=> nil
00556  *
00557  *  You must not mix the two modes at a time; the block must always
00558  *  return either true/false, or always return a number.  It is
00559  *  undefined which value is actually picked up at each iteration.
00560  */
00561 
00562 static VALUE
00563 range_bsearch(VALUE range)
00564 {
00565     VALUE beg, end;
00566     int smaller, satisfied = 0;
00567 
00568     /* Implementation notes:
00569      * Floats are handled by mapping them to 64 bits integers.
00570      * Apart from sign issues, floats and their 64 bits integer have the
00571      * same order, assuming they are represented as exponent followed
00572      * by the mantissa. This is true with or without implicit bit.
00573      *
00574      * Finding the average of two ints needs to be careful about
00575      * potential overflow (since float to long can use 64 bits)
00576      * as well as the fact that -1/2 can be 0 or -1 in C89.
00577      *
00578      * Note that -0.0 is mapped to the same int as 0.0 as we don't want
00579      * (-1...0.0).bsearch to yield -0.0.
00580      */
00581 
00582 #define BSEARCH_CHECK(val) \
00583     do { \
00584         VALUE v = rb_yield(val); \
00585         if (FIXNUM_P(v)) { \
00586             if (FIX2INT(v) == 0) return val; \
00587             smaller = FIX2INT(v) < 0; \
00588         } \
00589         else if (v == Qtrue) { \
00590             satisfied = 1; \
00591             smaller = 1; \
00592         } \
00593         else if (v == Qfalse || v == Qnil) { \
00594             smaller = 0; \
00595         } \
00596         else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
00597             int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
00598             if (!cmp) return val; \
00599             smaller = cmp < 0; \
00600         } \
00601         else { \
00602             rb_raise(rb_eTypeError, "wrong argument type %s" \
00603                 " (must be numeric, true, false or nil)", \
00604                 rb_obj_classname(v)); \
00605         } \
00606     } while (0)
00607 
00608 #define BSEARCH(conv) \
00609     do { \
00610         RETURN_ENUMERATOR(range, 0, 0); \
00611         if (EXCL(range)) high--; \
00612         org_high = high; \
00613         while (low < high) { \
00614             mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
00615                 : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
00616             BSEARCH_CHECK(conv(mid)); \
00617             if (smaller) { \
00618                 high = mid; \
00619             } \
00620             else { \
00621                 low = mid + 1; \
00622             } \
00623         } \
00624         if (low == org_high) { \
00625             BSEARCH_CHECK(conv(low)); \
00626             if (!smaller) return Qnil; \
00627         } \
00628         if (!satisfied) return Qnil; \
00629         return conv(low); \
00630     } while (0)
00631 
00632 
00633     beg = RANGE_BEG(range);
00634     end = RANGE_END(range);
00635 
00636     if (FIXNUM_P(beg) && FIXNUM_P(end)) {
00637         long low = FIX2LONG(beg);
00638         long high = FIX2LONG(end);
00639         long mid, org_high;
00640         BSEARCH(INT2FIX);
00641     }
00642 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
00643     else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
00644         int64_t low  = double_as_int64(RFLOAT_VALUE(rb_Float(beg)));
00645         int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end)));
00646         int64_t mid, org_high;
00647         BSEARCH(int64_as_double_to_num);
00648     }
00649 #endif
00650     else if (is_integer_p(beg) && is_integer_p(end)) {
00651         VALUE low = rb_to_int(beg);
00652         VALUE high = rb_to_int(end);
00653         VALUE mid, org_high;
00654         RETURN_ENUMERATOR(range, 0, 0);
00655         if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1));
00656         org_high = high;
00657 
00658         while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
00659             mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
00660             BSEARCH_CHECK(mid);
00661             if (smaller) {
00662                 high = mid;
00663             }
00664             else {
00665                 low = rb_funcall(mid, '+', 1, INT2FIX(1));
00666             }
00667         }
00668         if (rb_equal(low, org_high)) {
00669             BSEARCH_CHECK(low);
00670             if (!smaller) return Qnil;
00671         }
00672         if (!satisfied) return Qnil;
00673         return low;
00674     }
00675     else {
00676         rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
00677     }
00678     return range;
00679 }
00680 
00681 static VALUE
00682 each_i(VALUE v, void *arg)
00683 {
00684     rb_yield(v);
00685     return Qnil;
00686 }
00687 
00688 static VALUE
00689 sym_each_i(VALUE v, void *arg)
00690 {
00691     rb_yield(rb_str_intern(v));
00692     return Qnil;
00693 }
00694 
00695 /*
00696  *  call-seq:
00697  *     rng.size                   -> num
00698  *
00699  *  Returns the number of elements in the range. Both the begin and the end of
00700  *  the Range must be Numeric, otherwise nil is returned.
00701  *
00702  *    (10..20).size    #=> 11
00703  *    ('a'..'z').size  #=> nil
00704  *    (-Float::INFINITY..Float::INFINITY).size #=> Infinity
00705  */
00706 
00707 static VALUE
00708 range_size(VALUE range)
00709 {
00710     VALUE b = RANGE_BEG(range), e = RANGE_END(range);
00711     if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
00712         return num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
00713     }
00714     return Qnil;
00715 }
00716 
00717 /*
00718  *  call-seq:
00719  *     rng.each {| i | block } -> rng
00720  *     rng.each                -> an_enumerator
00721  *
00722  *  Iterates over the elements of range, passing each in turn to the
00723  *  block.
00724  *
00725  *  The +each+ method can only be used if the begin object of the range
00726  *  supports the +succ+ method.  A TypeError is raised if the object
00727  *  does not have +succ+ method defined (like Float).
00728  *
00729  *  If no block is given, an enumerator is returned instead.
00730  *
00731  *     (10..15).each {|n| print n, ' ' }
00732  *     # prints: 10 11 12 13 14 15
00733  *
00734  *     (2.5..5).each {|n| print n, ' ' }
00735  *     # raises: TypeError: can't iterate from Float
00736  */
00737 
00738 static VALUE
00739 range_each(VALUE range)
00740 {
00741     VALUE beg, end;
00742 
00743     RETURN_SIZED_ENUMERATOR(range, 0, 0, range_size);
00744 
00745     beg = RANGE_BEG(range);
00746     end = RANGE_END(range);
00747 
00748     if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
00749         long lim = FIX2LONG(end);
00750         long i;
00751 
00752         if (!EXCL(range))
00753             lim += 1;
00754         for (i = FIX2LONG(beg); i < lim; i++) {
00755             rb_yield(LONG2FIX(i));
00756         }
00757     }
00758     else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */
00759         VALUE args[2];
00760 
00761         args[0] = rb_sym_to_s(end);
00762         args[1] = EXCL(range) ? Qtrue : Qfalse;
00763         rb_block_call(rb_sym_to_s(beg), rb_intern("upto"), 2, args, sym_each_i, 0);
00764     }
00765     else {
00766         VALUE tmp = rb_check_string_type(beg);
00767 
00768         if (!NIL_P(tmp)) {
00769             VALUE args[2];
00770 
00771             args[0] = end;
00772             args[1] = EXCL(range) ? Qtrue : Qfalse;
00773             rb_block_call(tmp, rb_intern("upto"), 2, args, rb_yield, 0);
00774         }
00775         else {
00776             if (!discrete_object_p(beg)) {
00777                 rb_raise(rb_eTypeError, "can't iterate from %s",
00778                          rb_obj_classname(beg));
00779             }
00780             range_each_func(range, each_i, NULL);
00781         }
00782     }
00783     return range;
00784 }
00785 
00786 /*
00787  *  call-seq:
00788  *     rng.begin    -> obj
00789  *
00790  *  Returns the object that defines the beginning of the range.
00791  *
00792  *      (1..10).begin   #=> 1
00793  */
00794 
00795 static VALUE
00796 range_begin(VALUE range)
00797 {
00798     return RANGE_BEG(range);
00799 }
00800 
00801 
00802 /*
00803  *  call-seq:
00804  *     rng.end    -> obj
00805  *
00806  *  Returns the object that defines the end of the range.
00807  *
00808  *     (1..10).end    #=> 10
00809  *     (1...10).end   #=> 10
00810  */
00811 
00812 
00813 static VALUE
00814 range_end(VALUE range)
00815 {
00816     return RANGE_END(range);
00817 }
00818 
00819 
00820 static VALUE
00821 first_i(VALUE i, VALUE *ary)
00822 {
00823     long n = NUM2LONG(ary[0]);
00824 
00825     if (n <= 0) {
00826         rb_iter_break();
00827     }
00828     rb_ary_push(ary[1], i);
00829     n--;
00830     ary[0] = INT2NUM(n);
00831     return Qnil;
00832 }
00833 
00834 /*
00835  *  call-seq:
00836  *     rng.first    -> obj
00837  *     rng.first(n) -> an_array
00838  *
00839  *  Returns the first object in the range, or an array of the first +n+
00840  *  elements.
00841  *
00842  *    (10..20).first     #=> 10
00843  *    (10..20).first(3)  #=> [10, 11, 12]
00844  */
00845 
00846 static VALUE
00847 range_first(int argc, VALUE *argv, VALUE range)
00848 {
00849     VALUE n, ary[2];
00850 
00851     if (argc == 0) return RANGE_BEG(range);
00852 
00853     rb_scan_args(argc, argv, "1", &n);
00854     ary[0] = n;
00855     ary[1] = rb_ary_new2(NUM2LONG(n));
00856     rb_block_call(range, idEach, 0, 0, first_i, (VALUE)ary);
00857 
00858     return ary[1];
00859 }
00860 
00861 
00862 /*
00863  *  call-seq:
00864  *     rng.last    -> obj
00865  *     rng.last(n) -> an_array
00866  *
00867  *  Returns the last object in the range,
00868  *  or an array of the last +n+ elements.
00869  *
00870  *  Note that with no arguments +last+ will return the object that defines
00871  *  the end of the range even if #exclude_end? is +true+.
00872  *
00873  *    (10..20).last      #=> 20
00874  *    (10...20).last     #=> 20
00875  *    (10..20).last(3)   #=> [18, 19, 20]
00876  *    (10...20).last(3)  #=> [17, 18, 19]
00877  */
00878 
00879 static VALUE
00880 range_last(int argc, VALUE *argv, VALUE range)
00881 {
00882     if (argc == 0) return RANGE_END(range);
00883     return rb_ary_last(argc, argv, rb_Array(range));
00884 }
00885 
00886 
00887 /*
00888  *  call-seq:
00889  *     rng.min                    -> obj
00890  *     rng.min {| a,b | block }   -> obj
00891  *
00892  *  Returns the minimum value in the range. Returns +nil+ if the begin
00893  *  value of the range is larger than the end value.
00894  *
00895  *  Can be given an optional block to override the default comparison
00896  *  method <code>a <=> b</code>.
00897  *
00898  *    (10..20).min    #=> 10
00899  */
00900 
00901 
00902 static VALUE
00903 range_min(VALUE range)
00904 {
00905     if (rb_block_given_p()) {
00906         return rb_call_super(0, 0);
00907     }
00908     else {
00909         VALUE b = RANGE_BEG(range);
00910         VALUE e = RANGE_END(range);
00911         int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
00912 
00913         if (c > 0 || (c == 0 && EXCL(range)))
00914             return Qnil;
00915         return b;
00916     }
00917 }
00918 
00919 /*
00920  *  call-seq:
00921  *     rng.max                    -> obj
00922  *     rng.max {| a,b | block }   -> obj
00923  *
00924  *  Returns the maximum value in the range. Returns +nil+ if the begin
00925  *  value of the range larger than the end value.
00926  *
00927  *  Can be given an optional block to override the default comparison
00928  *  method <code>a <=> b</code>.
00929  *
00930  *    (10..20).max    #=> 20
00931  */
00932 
00933 static VALUE
00934 range_max(VALUE range)
00935 {
00936     VALUE e = RANGE_END(range);
00937     int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
00938 
00939     if (rb_block_given_p() || (EXCL(range) && !nm)) {
00940         return rb_call_super(0, 0);
00941     }
00942     else {
00943         VALUE b = RANGE_BEG(range);
00944         int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
00945 
00946         if (c > 0)
00947             return Qnil;
00948         if (EXCL(range)) {
00949             if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) {
00950                 rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
00951             }
00952             if (c == 0) return Qnil;
00953             if (!FIXNUM_P(b) && !rb_obj_is_kind_of(b,rb_cInteger)) {
00954                 rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
00955             }
00956             if (FIXNUM_P(e)) {
00957                 return LONG2NUM(FIX2LONG(e) - 1);
00958             }
00959             return rb_funcall(e, '-', 1, INT2FIX(1));
00960         }
00961         return e;
00962     }
00963 }
00964 
00965 int
00966 rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
00967 {
00968     VALUE b, e;
00969     int excl;
00970 
00971     if (rb_obj_is_kind_of(range, rb_cRange)) {
00972         b = RANGE_BEG(range);
00973         e = RANGE_END(range);
00974         excl = EXCL(range);
00975     }
00976     else {
00977         if (!rb_respond_to(range, id_beg)) return (int)Qfalse;
00978         if (!rb_respond_to(range, id_end)) return (int)Qfalse;
00979         b = rb_funcall(range, id_beg, 0);
00980         e = rb_funcall(range, id_end, 0);
00981         excl = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
00982     }
00983     *begp = b;
00984     *endp = e;
00985     *exclp = excl;
00986     return (int)Qtrue;
00987 }
00988 
00989 VALUE
00990 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
00991 {
00992     long beg, end, origbeg, origend;
00993     VALUE b, e;
00994     int excl;
00995 
00996     if (!rb_range_values(range, &b, &e, &excl))
00997         return Qfalse;
00998     beg = NUM2LONG(b);
00999     end = NUM2LONG(e);
01000     origbeg = beg;
01001     origend = end;
01002     if (beg < 0) {
01003         beg += len;
01004         if (beg < 0)
01005             goto out_of_range;
01006     }
01007     if (end < 0)
01008         end += len;
01009     if (!excl)
01010         end++;                  /* include end point */
01011     if (err == 0 || err == 2) {
01012         if (beg > len)
01013             goto out_of_range;
01014         if (end > len)
01015             end = len;
01016     }
01017     len = end - beg;
01018     if (len < 0)
01019         len = 0;
01020 
01021     *begp = beg;
01022     *lenp = len;
01023     return Qtrue;
01024 
01025   out_of_range:
01026     if (err) {
01027         rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
01028                  origbeg, excl ? "." : "", origend);
01029     }
01030     return Qnil;
01031 }
01032 
01033 /*
01034  * call-seq:
01035  *   rng.to_s   -> string
01036  *
01037  * Convert this range object to a printable form (using #to_s to convert the
01038  * begin and end objects).
01039  */
01040 
01041 static VALUE
01042 range_to_s(VALUE range)
01043 {
01044     VALUE str, str2;
01045 
01046     str = rb_obj_as_string(RANGE_BEG(range));
01047     str2 = rb_obj_as_string(RANGE_END(range));
01048     str = rb_str_dup(str);
01049     rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
01050     rb_str_append(str, str2);
01051     OBJ_INFECT(str, str2);
01052 
01053     return str;
01054 }
01055 
01056 static VALUE
01057 inspect_range(VALUE range, VALUE dummy, int recur)
01058 {
01059     VALUE str, str2;
01060 
01061     if (recur) {
01062         return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
01063     }
01064     str = rb_inspect(RANGE_BEG(range));
01065     str2 = rb_inspect(RANGE_END(range));
01066     str = rb_str_dup(str);
01067     rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
01068     rb_str_append(str, str2);
01069     OBJ_INFECT(str, str2);
01070 
01071     return str;
01072 }
01073 
01074 /*
01075  * call-seq:
01076  *   rng.inspect  -> string
01077  *
01078  * Convert this range object to a printable form (using
01079  * <code>inspect</code> to convert the begin and end
01080  * objects).
01081  */
01082 
01083 
01084 static VALUE
01085 range_inspect(VALUE range)
01086 {
01087     return rb_exec_recursive(inspect_range, range, 0);
01088 }
01089 
01090 /*
01091  *  call-seq:
01092  *     rng === obj       ->  true or false
01093  *
01094  *  Returns <code>true</code> if +obj+ is an element of the range,
01095  *  <code>false</code> otherwise.  Conveniently, <code>===</code> is the
01096  *  comparison operator used by <code>case</code> statements.
01097  *
01098  *     case 79
01099  *     when 1..50   then   print "low\n"
01100  *     when 51..75  then   print "medium\n"
01101  *     when 76..100 then   print "high\n"
01102  *     end
01103  *
01104  *  <em>produces:</em>
01105  *
01106  *     high
01107  */
01108 
01109 static VALUE
01110 range_eqq(VALUE range, VALUE val)
01111 {
01112     return rb_funcall(range, rb_intern("include?"), 1, val);
01113 }
01114 
01115 
01116 /*
01117  *  call-seq:
01118  *     rng.member?(obj)  ->  true or false
01119  *     rng.include?(obj) ->  true or false
01120  *
01121  *  Returns <code>true</code> if +obj+ is an element of
01122  *  the range, <code>false</code> otherwise.  If begin and end are
01123  *  numeric, comparison is done according to the magnitude of the values.
01124  *
01125  *     ("a".."z").include?("g")   #=> true
01126  *     ("a".."z").include?("A")   #=> false
01127  *     ("a".."z").include?("cc")  #=> false
01128  */
01129 
01130 static VALUE
01131 range_include(VALUE range, VALUE val)
01132 {
01133     VALUE beg = RANGE_BEG(range);
01134     VALUE end = RANGE_END(range);
01135     int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
01136              rb_obj_is_kind_of(beg, rb_cNumeric) ||
01137              rb_obj_is_kind_of(end, rb_cNumeric);
01138 
01139     if (nv ||
01140         !NIL_P(rb_check_to_integer(beg, "to_int")) ||
01141         !NIL_P(rb_check_to_integer(end, "to_int"))) {
01142         if (r_le(beg, val)) {
01143             if (EXCL(range)) {
01144                 if (r_lt(val, end))
01145                     return Qtrue;
01146             }
01147             else {
01148                 if (r_le(val, end))
01149                     return Qtrue;
01150             }
01151         }
01152         return Qfalse;
01153     }
01154     else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING) &&
01155              RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
01156         if (NIL_P(val)) return Qfalse;
01157         if (RB_TYPE_P(val, T_STRING)) {
01158             if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
01159                 return Qfalse;
01160             else {
01161                 char b = RSTRING_PTR(beg)[0];
01162                 char e = RSTRING_PTR(end)[0];
01163                 char v = RSTRING_PTR(val)[0];
01164 
01165                 if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
01166                     if (b <= v && v < e) return Qtrue;
01167                     if (!EXCL(range) && v == e) return Qtrue;
01168                     return Qfalse;
01169                 }
01170             }
01171         }
01172     }
01173     /* TODO: ruby_frame->this_func = rb_intern("include?"); */
01174     return rb_call_super(1, &val);
01175 }
01176 
01177 
01178 /*
01179  *  call-seq:
01180  *     rng.cover?(obj)  ->  true or false
01181  *
01182  *  Returns <code>true</code> if +obj+ is between the begin and end of
01183  *  the range.
01184  *
01185  *  This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
01186  *  and <code>begin <= obj < end</code> when #exclude_end? is +true+.
01187  *
01188  *     ("a".."z").cover?("c")    #=> true
01189  *     ("a".."z").cover?("5")    #=> false
01190  *     ("a".."z").cover?("cc")   #=> true
01191  */
01192 
01193 static VALUE
01194 range_cover(VALUE range, VALUE val)
01195 {
01196     VALUE beg, end;
01197 
01198     beg = RANGE_BEG(range);
01199     end = RANGE_END(range);
01200     if (r_le(beg, val)) {
01201         if (EXCL(range)) {
01202             if (r_lt(val, end))
01203                 return Qtrue;
01204         }
01205         else {
01206             if (r_le(val, end))
01207                 return Qtrue;
01208         }
01209     }
01210     return Qfalse;
01211 }
01212 
01213 static VALUE
01214 range_dumper(VALUE range)
01215 {
01216     VALUE v;
01217     NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT);
01218 
01219     v = (VALUE)m;
01220 
01221     rb_ivar_set(v, id_excl, RANGE_EXCL(range));
01222     rb_ivar_set(v, id_beg, RANGE_BEG(range));
01223     rb_ivar_set(v, id_end, RANGE_END(range));
01224     return v;
01225 }
01226 
01227 static VALUE
01228 range_loader(VALUE range, VALUE obj)
01229 {
01230     if (!RB_TYPE_P(obj, T_OBJECT) || RBASIC(obj)->klass != rb_cObject) {
01231         rb_raise(rb_eTypeError, "not a dumped range object");
01232     }
01233 
01234     RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
01235     RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
01236     RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
01237     return range;
01238 }
01239 
01240 static VALUE
01241 range_alloc(VALUE klass)
01242 {
01243   /* rb_struct_alloc_noinit itself should not be used because
01244    * rb_marshal_define_compat uses equality of allocaiton function */
01245     return rb_struct_alloc_noinit(klass);
01246 }
01247 
01248 /*  A <code>Range</code> represents an interval---a set of values with a
01249  *  beginning and an end. Ranges may be constructed using the
01250  *  <em>s</em><code>..</code><em>e</em> and
01251  *  <em>s</em><code>...</code><em>e</em> literals, or with
01252  *  Range::new. Ranges constructed using <code>..</code>
01253  *  run from the beginning to the end inclusively. Those created using
01254  *  <code>...</code> exclude the end value. When used as an iterator,
01255  *  ranges return each value in the sequence.
01256  *
01257  *     (-1..-5).to_a      #=> []
01258  *     (-5..-1).to_a      #=> [-5, -4, -3, -2, -1]
01259  *     ('a'..'e').to_a    #=> ["a", "b", "c", "d", "e"]
01260  *     ('a'...'e').to_a   #=> ["a", "b", "c", "d"]
01261  *
01262  *  == Custom Objects in Ranges
01263  *
01264  *  Ranges can be constructed using any objects that can be compared
01265  *  using the <code><=></code> operator.
01266  *  Methods that treat the range as a sequence (#each and methods inherited
01267  *  from Enumerable) expect the begin object to implement a
01268  *  <code>succ</code> method to return the next object in sequence.
01269  *  The #step and #include? methods require the begin
01270  *  object to implement <code>succ</code> or to be numeric.
01271  *
01272  *  In the <code>Xs</code> class below both <code><=></code> and
01273  *  <code>succ</code> are implemented so <code>Xs</code> can be used
01274  *  to construct ranges. Note that the Comparable module is included
01275  *  so the <code>==</code> method is defined in terms of <code><=></code>.
01276  *
01277  *     class Xs                # represent a string of 'x's
01278  *       include Comparable
01279  *       attr :length
01280  *       def initialize(n)
01281  *         @length = n
01282  *       end
01283  *       def succ
01284  *         Xs.new(@length + 1)
01285  *       end
01286  *       def <=>(other)
01287  *         @length <=> other.length
01288  *       end
01289  *       def to_s
01290  *         sprintf "%2d #{inspect}", @length
01291  *       end
01292  *       def inspect
01293  *         'x' * @length
01294  *       end
01295  *     end
01296  *
01297  *  An example of using <code>Xs</code> to construct a range:
01298  *
01299  *     r = Xs.new(3)..Xs.new(6)   #=> xxx..xxxxxx
01300  *     r.to_a                     #=> [xxx, xxxx, xxxxx, xxxxxx]
01301  *     r.member?(Xs.new(5))       #=> true
01302  *
01303  */
01304 
01305 void
01306 Init_Range(void)
01307 {
01308 #undef rb_intern
01309 #define rb_intern(str) rb_intern_const(str)
01310 
01311     id_cmp = rb_intern("<=>");
01312     id_succ = rb_intern("succ");
01313     id_beg = rb_intern("begin");
01314     id_end = rb_intern("end");
01315     id_excl = rb_intern("excl");
01316     id_integer_p = rb_intern("integer?");
01317     id_div = rb_intern("div");
01318 
01319     rb_cRange = rb_struct_define_without_accessor(
01320         "Range", rb_cObject, range_alloc,
01321         "begin", "end", "excl", NULL);
01322 
01323     rb_include_module(rb_cRange, rb_mEnumerable);
01324     rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
01325     rb_define_method(rb_cRange, "initialize", range_initialize, -1);
01326     rb_define_method(rb_cRange, "initialize_copy", range_initialize_copy, 1);
01327     rb_define_method(rb_cRange, "==", range_eq, 1);
01328     rb_define_method(rb_cRange, "===", range_eqq, 1);
01329     rb_define_method(rb_cRange, "eql?", range_eql, 1);
01330     rb_define_method(rb_cRange, "hash", range_hash, 0);
01331     rb_define_method(rb_cRange, "each", range_each, 0);
01332     rb_define_method(rb_cRange, "step", range_step, -1);
01333     rb_define_method(rb_cRange, "bsearch", range_bsearch, 0);
01334     rb_define_method(rb_cRange, "begin", range_begin, 0);
01335     rb_define_method(rb_cRange, "end", range_end, 0);
01336     rb_define_method(rb_cRange, "first", range_first, -1);
01337     rb_define_method(rb_cRange, "last", range_last, -1);
01338     rb_define_method(rb_cRange, "min", range_min, 0);
01339     rb_define_method(rb_cRange, "max", range_max, 0);
01340     rb_define_method(rb_cRange, "size", range_size, 0);
01341     rb_define_method(rb_cRange, "to_s", range_to_s, 0);
01342     rb_define_method(rb_cRange, "inspect", range_inspect, 0);
01343 
01344     rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
01345 
01346     rb_define_method(rb_cRange, "member?", range_include, 1);
01347     rb_define_method(rb_cRange, "include?", range_include, 1);
01348     rb_define_method(rb_cRange, "cover?", range_cover, 1);
01349 }
01350