diff options
Diffstat (limited to 'tests/examplefiles/example.c')
-rw-r--r-- | tests/examplefiles/example.c | 2429 |
1 files changed, 0 insertions, 2429 deletions
diff --git a/tests/examplefiles/example.c b/tests/examplefiles/example.c index 67b8d17d..a7f546d1 100644 --- a/tests/examplefiles/example.c +++ b/tests/examplefiles/example.c @@ -2078,2432 +2078,3 @@ rb_ary_select(ary) return result; } -/* - * call-seq: - * array.delete(obj) -> obj or nil - * array.delete(obj) { block } -> obj or nil - * - * Deletes items from <i>self</i> that are equal to <i>obj</i>. If - * the item is not found, returns <code>nil</code>. If the optional - * code block is given, returns the result of <i>block</i> if the item - * is not found. - * - * a = [ "a", "b", "b", "b", "c" ] - * a.delete("b") #=> "b" - * a #=> ["a", "c"] - * a.delete("z") #=> nil - * a.delete("z") { "not found" } #=> "not found" - */ - -VALUE -rb_ary_delete(ary, item) - VALUE ary; - VALUE item; -{ - long i1, i2; - - for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { - VALUE e = RARRAY(ary)->ptr[i1]; - - if (rb_equal(e, item)) continue; - if (i1 != i2) { - rb_ary_store(ary, i2, e); - } - i2++; - } - if (RARRAY(ary)->len == i2) { - if (rb_block_given_p()) { - return rb_yield(item); - } - return Qnil; - } - - rb_ary_modify(ary); - if (RARRAY(ary)->len > i2) { - RARRAY(ary)->len = i2; - if (i2 * 2 < RARRAY(ary)->aux.capa && - RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) { - REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2); - RARRAY(ary)->aux.capa = i2 * 2; - } - } - - return item; -} - -VALUE -rb_ary_delete_at(ary, pos) - VALUE ary; - long pos; -{ - long i, len = RARRAY(ary)->len; - VALUE del; - - if (pos >= len) return Qnil; - if (pos < 0) { - pos += len; - if (pos < 0) return Qnil; - } - - rb_ary_modify(ary); - del = RARRAY(ary)->ptr[pos]; - for (i = pos + 1; i < len; i++, pos++) { - RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i]; - } - RARRAY(ary)->len = pos; - - return del; -} - -/* - * call-seq: - * array.delete_at(index) -> obj or nil - * - * Deletes the element at the specified index, returning that element, - * or <code>nil</code> if the index is out of range. See also - * <code>Array#slice!</code>. - * - * a = %w( ant bat cat dog ) - * a.delete_at(2) #=> "cat" - * a #=> ["ant", "bat", "dog"] - * a.delete_at(99) #=> nil - */ - -static VALUE -rb_ary_delete_at_m(ary, pos) - VALUE ary, pos; -{ - return rb_ary_delete_at(ary, NUM2LONG(pos)); -} - -/* - * call-seq: - * array.slice!(index) -> obj or nil - * array.slice!(start, length) -> sub_array or nil - * array.slice!(range) -> sub_array or nil - * - * Deletes the element(s) given by an index (optionally with a length) - * or by a range. Returns the deleted object, subarray, or - * <code>nil</code> if the index is out of range. Equivalent to: - * - * def slice!(*args) - * result = self[*args] - * self[*args] = nil - * result - * end - * - * a = [ "a", "b", "c" ] - * a.slice!(1) #=> "b" - * a #=> ["a", "c"] - * a.slice!(-1) #=> "c" - * a #=> ["a"] - * a.slice!(100) #=> nil - * a #=> ["a"] - */ - -static VALUE -rb_ary_slice_bang(argc, argv, ary) - int argc; - VALUE *argv; - VALUE ary; -{ - VALUE arg1, arg2; - long pos, len; - - if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { - pos = NUM2LONG(arg1); - len = NUM2LONG(arg2); - delete_pos_len: - if (pos < 0) { - pos = RARRAY(ary)->len + pos; - } - arg2 = rb_ary_subseq(ary, pos, len); - rb_ary_splice(ary, pos, len, Qundef); /* Qnil/rb_ary_new2(0) */ - return arg2; - } - - if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) { - goto delete_pos_len; - } - - return rb_ary_delete_at(ary, NUM2LONG(arg1)); -} - -/* - * call-seq: - * array.reject! {|item| block } -> array or nil - * - * Equivalent to <code>Array#delete_if</code>, deleting elements from - * _self_ for which the block evaluates to true, but returns - * <code>nil</code> if no changes were made. Also see - * <code>Enumerable#reject</code>. - */ - -static VALUE -rb_ary_reject_bang(ary) - VALUE ary; -{ - long i1, i2; - - rb_ary_modify(ary); - for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { - VALUE v = RARRAY(ary)->ptr[i1]; - if (RTEST(rb_yield(v))) continue; - if (i1 != i2) { - rb_ary_store(ary, i2, v); - } - i2++; - } - if (RARRAY(ary)->len == i2) return Qnil; - if (i2 < RARRAY(ary)->len) - RARRAY(ary)->len = i2; - - return ary; -} - -/* - * call-seq: - * array.reject {|item| block } -> an_array - * - * Returns a new array containing the items in _self_ - * for which the block is not true. - */ - -static VALUE -rb_ary_reject(ary) - VALUE ary; -{ - ary = rb_ary_dup(ary); - rb_ary_reject_bang(ary); - return ary; -} - -/* - * call-seq: - * array.delete_if {|item| block } -> array - * - * Deletes every element of <i>self</i> for which <i>block</i> evaluates - * to <code>true</code>. - * - * a = [ "a", "b", "c" ] - * a.delete_if {|x| x >= "b" } #=> ["a"] - */ - -static VALUE -rb_ary_delete_if(ary) - VALUE ary; -{ - rb_ary_reject_bang(ary); - return ary; -} - -/* - * call-seq: - * array.zip(arg, ...) -> an_array - * array.zip(arg, ...) {| arr | block } -> nil - * - * Converts any arguments to arrays, then merges elements of - * <i>self</i> with corresponding elements from each argument. This - * generates a sequence of <code>self.size</code> <em>n</em>-element - * arrays, where <em>n</em> is one more that the count of arguments. If - * the size of any argument is less than <code>enumObj.size</code>, - * <code>nil</code> values are supplied. If a block given, it is - * invoked for each output array, otherwise an array of arrays is - * returned. - * - * a = [ 4, 5, 6 ] - * b = [ 7, 8, 9 ] - * - * [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]] - * [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]] - * a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]] - */ - -static VALUE -rb_ary_zip(argc, argv, ary) - int argc; - VALUE *argv; - VALUE ary; -{ - int i, j; - long len; - VALUE result; - - for (i=0; i<argc; i++) { - argv[i] = to_a(argv[i]); - } - if (rb_block_given_p()) { - for (i=0; i<RARRAY(ary)->len; i++) { - VALUE tmp = rb_ary_new2(argc+1); - - rb_ary_push(tmp, rb_ary_elt(ary, i)); - for (j=0; j<argc; j++) { - rb_ary_push(tmp, rb_ary_elt(argv[j], i)); - } - rb_yield(tmp); - } - return Qnil; - } - len = RARRAY(ary)->len; - result = rb_ary_new2(len); - for (i=0; i<len; i++) { - VALUE tmp = rb_ary_new2(argc+1); - - rb_ary_push(tmp, rb_ary_elt(ary, i)); - for (j=0; j<argc; j++) { - rb_ary_push(tmp, rb_ary_elt(argv[j], i)); - } - rb_ary_push(result, tmp); - } - return result; -} - -/* - * call-seq: - * array.transpose -> an_array - * - * Assumes that <i>self</i> is an array of arrays and transposes the - * rows and columns. - * - * a = [[1,2], [3,4], [5,6]] - * a.transpose #=> [[1, 3, 5], [2, 4, 6]] - */ - -static VALUE -rb_ary_transpose(ary) - VALUE ary; -{ - long elen = -1, alen, i, j; - VALUE tmp, result = 0; - - alen = RARRAY(ary)->len; - if (alen == 0) return rb_ary_dup(ary); - for (i=0; i<alen; i++) { - tmp = to_ary(rb_ary_elt(ary, i)); - if (elen < 0) { /* first element */ - elen = RARRAY(tmp)->len; - result = rb_ary_new2(elen); - for (j=0; j<elen; j++) { - rb_ary_store(result, j, rb_ary_new2(alen)); - } - } - else if (elen != RARRAY(tmp)->len) { - rb_raise(rb_eIndexError, "element size differs (%d should be %d)", - RARRAY(tmp)->len, elen); - } - for (j=0; j<elen; j++) { - rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j)); - } - } - return result; -} - -/* - * call-seq: - * array.replace(other_array) -> array - * - * Replaces the contents of <i>self</i> with the contents of - * <i>other_array</i>, truncating or expanding if necessary. - * - * a = [ "a", "b", "c", "d", "e" ] - * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"] - * a #=> ["x", "y", "z"] - */ - -static VALUE -rb_ary_replace(copy, orig) - VALUE copy, orig; -{ - VALUE shared; - - rb_ary_modify(copy); - orig = to_ary(orig); - if (copy == orig) return copy; - shared = ary_make_shared(orig); - if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) - free(RARRAY(copy)->ptr); - RARRAY(copy)->ptr = RARRAY(orig)->ptr; - RARRAY(copy)->len = RARRAY(orig)->len; - RARRAY(copy)->aux.shared = shared; - FL_SET(copy, ELTS_SHARED); - - return copy; -} - -/* - * call-seq: - * array.clear -> array - * - * Removes all elements from _self_. - * - * a = [ "a", "b", "c", "d", "e" ] - * a.clear #=> [ ] - */ - -VALUE -rb_ary_clear(ary) - VALUE ary; -{ - rb_ary_modify(ary); - RARRAY(ary)->len = 0; - if (ARY_DEFAULT_SIZE * 2 < RARRAY(ary)->aux.capa) { - REALLOC_N(RARRAY(ary)->ptr, VALUE, ARY_DEFAULT_SIZE * 2); - RARRAY(ary)->aux.capa = ARY_DEFAULT_SIZE * 2; - } - return ary; -} - -/* - * call-seq: - * array.fill(obj) -> array - * array.fill(obj, start [, length]) -> array - * array.fill(obj, range ) -> array - * array.fill {|index| block } -> array - * array.fill(start [, length] ) {|index| block } -> array - * array.fill(range) {|index| block } -> array - * - * The first three forms set the selected elements of <i>self</i> (which - * may be the entire array) to <i>obj</i>. A <i>start</i> of - * <code>nil</code> is equivalent to zero. A <i>length</i> of - * <code>nil</code> is equivalent to <i>self.length</i>. The last three - * forms fill the array with the value of the block. The block is - * passed the absolute index of each element to be filled. - * - * a = [ "a", "b", "c", "d" ] - * a.fill("x") #=> ["x", "x", "x", "x"] - * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"] - * a.fill("y", 0..1) #=> ["y", "y", "z", "z"] - * a.fill {|i| i*i} #=> [0, 1, 4, 9] - * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27] - */ - -static VALUE -rb_ary_fill(argc, argv, ary) - int argc; - VALUE *argv; - VALUE ary; -{ - VALUE item, arg1, arg2; - long beg, end, len; - VALUE *p, *pend; - int block_p = Qfalse; - - if (rb_block_given_p()) { - block_p = Qtrue; - rb_scan_args(argc, argv, "02", &arg1, &arg2); - argc += 1; /* hackish */ - } - else { - rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); - } - switch (argc) { - case 1: - beg = 0; - len = RARRAY(ary)->len; - break; - case 2: - if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) { - break; - } - /* fall through */ - case 3: - beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1); - if (beg < 0) { - beg = RARRAY(ary)->len + beg; - if (beg < 0) beg = 0; - } - len = NIL_P(arg2) ? RARRAY(ary)->len - beg : NUM2LONG(arg2); - break; - } - rb_ary_modify(ary); - end = beg + len; - if (end > RARRAY(ary)->len) { - if (end >= RARRAY(ary)->aux.capa) { - REALLOC_N(RARRAY(ary)->ptr, VALUE, end); - RARRAY(ary)->aux.capa = end; - } - if (beg > RARRAY(ary)->len) { - rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len); - } - RARRAY(ary)->len = end; - } - - if (block_p) { - VALUE v; - long i; - - for (i=beg; i<end; i++) { - v = rb_yield(LONG2NUM(i)); - if (i>=RARRAY(ary)->len) break; - RARRAY(ary)->ptr[i] = v; - } - } - else { - p = RARRAY(ary)->ptr + beg; - pend = p + len; - while (p < pend) { - *p++ = item; - } - } - return ary; -} - -/* - * call-seq: - * array + other_array -> an_array - * - * Concatenation---Returns a new array built by concatenating the - * two arrays together to produce a third array. - * - * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ] - */ - -VALUE -rb_ary_plus(x, y) - VALUE x, y; -{ - VALUE z; - long len; - - y = to_ary(y); - len = RARRAY(x)->len + RARRAY(y)->len; - z = rb_ary_new2(len); - MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len); - MEMCPY(RARRAY(z)->ptr + RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len); - RARRAY(z)->len = len; - return z; -} - -/* - * call-seq: - * array.concat(other_array) -> array - * - * Appends the elements in other_array to _self_. - * - * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ] - */ - - -VALUE -rb_ary_concat(x, y) - VALUE x, y; -{ - y = to_ary(y); - if (RARRAY(y)->len > 0) { - rb_ary_splice(x, RARRAY(x)->len, 0, y); - } - return x; -} - - -/* - * call-seq: - * array * int -> an_array - * array * str -> a_string - * - * Repetition---With a String argument, equivalent to - * self.join(str). Otherwise, returns a new array - * built by concatenating the _int_ copies of _self_. - * - * - * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ] - * [ 1, 2, 3 ] * "," #=> "1,2,3" - * - */ - -static VALUE -rb_ary_times(ary, times) - VALUE ary, times; -{ - VALUE ary2, tmp; - long i, len; - - tmp = rb_check_string_type(times); - if (!NIL_P(tmp)) { - return rb_ary_join(ary, tmp); - } - - len = NUM2LONG(times); - if (len == 0) return ary_new(rb_obj_class(ary), 0); - if (len < 0) { - rb_raise(rb_eArgError, "negative argument"); - } - if (LONG_MAX/len < RARRAY(ary)->len) { - rb_raise(rb_eArgError, "argument too big"); - } - len *= RARRAY(ary)->len; - - ary2 = ary_new(rb_obj_class(ary), len); - RARRAY(ary2)->len = len; - - for (i=0; i<len; i+=RARRAY(ary)->len) { - MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); - } - OBJ_INFECT(ary2, ary); - - return ary2; -} - -/* - * call-seq: - * array.assoc(obj) -> an_array or nil - * - * Searches through an array whose elements are also arrays - * comparing _obj_ with the first element of each contained array - * using obj.==. - * Returns the first contained array that matches (that - * is, the first associated array), - * or +nil+ if no match is found. - * See also <code>Array#rassoc</code>. - * - * s1 = [ "colors", "red", "blue", "green" ] - * s2 = [ "letters", "a", "b", "c" ] - * s3 = "foo" - * a = [ s1, s2, s3 ] - * a.assoc("letters") #=> [ "letters", "a", "b", "c" ] - * a.assoc("foo") #=> nil - */ - -VALUE -rb_ary_assoc(ary, key) - VALUE ary, key; -{ - long i; - VALUE v; - - for (i = 0; i < RARRAY(ary)->len; ++i) { - v = RARRAY(ary)->ptr[i]; - if (TYPE(v) == T_ARRAY && - RARRAY(v)->len > 0 && - rb_equal(RARRAY(v)->ptr[0], key)) - return v; - } - return Qnil; -} - -/* - * call-seq: - * array.rassoc(key) -> an_array or nil - * - * Searches through the array whose elements are also arrays. Compares - * <em>key</em> with the second element of each contained array using - * <code>==</code>. Returns the first contained array that matches. See - * also <code>Array#assoc</code>. - * - * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] - * a.rassoc("two") #=> [2, "two"] - * a.rassoc("four") #=> nil - */ - -VALUE -rb_ary_rassoc(ary, value) - VALUE ary, value; -{ - long i; - VALUE v; - - for (i = 0; i < RARRAY(ary)->len; ++i) { - v = RARRAY(ary)->ptr[i]; - if (TYPE(v) == T_ARRAY && - RARRAY(v)->len > 1 && - rb_equal(RARRAY(v)->ptr[1], value)) - return v; - } - return Qnil; -} - -/* - * call-seq: - * array == other_array -> bool - * - * Equality---Two arrays are equal if they contain the same number - * of elements and if each element is equal to (according to - * Object.==) the corresponding element in the other array. - * - * [ "a", "c" ] == [ "a", "c", 7 ] #=> false - * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true - * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false - * - */ - -static VALUE -rb_ary_equal(ary1, ary2) - VALUE ary1, ary2; -{ - long i; - - if (ary1 == ary2) return Qtrue; - if (TYPE(ary2) != T_ARRAY) { - if (!rb_respond_to(ary2, rb_intern("to_ary"))) { - return Qfalse; - } - return rb_equal(ary2, ary1); - } - if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse; - for (i=0; i<RARRAY(ary1)->len; i++) { - if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i))) - return Qfalse; - } - return Qtrue; -} - -/* - * call-seq: - * array.eql?(other) -> true or false - * - * Returns <code>true</code> if _array_ and _other_ are the same object, - * or are both arrays with the same content. - */ - -static VALUE -rb_ary_eql(ary1, ary2) - VALUE ary1, ary2; -{ - long i; - - if (ary1 == ary2) return Qtrue; - if (TYPE(ary2) != T_ARRAY) return Qfalse; - if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse; - for (i=0; i<RARRAY(ary1)->len; i++) { - if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i))) - return Qfalse; - } - return Qtrue; -} - -static VALUE -recursive_hash(ary, dummy, recur) - VALUE ary, dummy; - int recur; -{ - long i, h; - VALUE n; - - if (recur) { - return LONG2FIX(0); - } - h = RARRAY(ary)->len; - for (i=0; i<RARRAY(ary)->len; i++) { - h = (h << 1) | (h<0 ? 1 : 0); - n = rb_hash(RARRAY(ary)->ptr[i]); - h ^= NUM2LONG(n); - } - return LONG2FIX(h); -} - -/* - * call-seq: - * array.hash -> fixnum - * - * Compute a hash-code for this array. Two arrays with the same content - * will have the same hash code (and will compare using <code>eql?</code>). - */ - -static VALUE -rb_ary_hash(ary) - VALUE ary; -{ - return rb_exec_recursive(recursive_hash, ary, 0); -} - -/* - * call-seq: - * array.include?(obj) -> true or false - * - * Returns <code>true</code> if the given object is present in - * <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>), - * <code>false</code> otherwise. - * - * a = [ "a", "b", "c" ] - * a.include?("b") #=> true - * a.include?("z") #=> false - */ - -VALUE -rb_ary_includes(ary, item) - VALUE ary; - VALUE item; -{ - long i; - - for (i=0; i<RARRAY(ary)->len; i++) { - if (rb_equal(RARRAY(ary)->ptr[i], item)) { - return Qtrue; - } - } - return Qfalse; -} - - -/* - * call-seq: - * array <=> other_array -> -1, 0, +1 - * - * Comparison---Returns an integer (-1, 0, - * or +1) if this array is less than, equal to, or greater than - * other_array. Each object in each array is compared - * (using <=>). If any value isn't - * equal, then that inequality is the return value. If all the - * values found are equal, then the return is based on a - * comparison of the array lengths. Thus, two arrays are - * ``equal'' according to <code>Array#<=></code> if and only if they have - * the same length and the value of each element is equal to the - * value of the corresponding element in the other array. - * - * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1 - * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1 - * - */ - -VALUE -rb_ary_cmp(ary1, ary2) - VALUE ary1, ary2; -{ - long i, len; - - ary2 = to_ary(ary2); - len = RARRAY(ary1)->len; - if (len > RARRAY(ary2)->len) { - len = RARRAY(ary2)->len; - } - for (i=0; i<len; i++) { - VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i)); - if (v != INT2FIX(0)) { - return v; - } - } - len = RARRAY(ary1)->len - RARRAY(ary2)->len; - if (len == 0) return INT2FIX(0); - if (len > 0) return INT2FIX(1); - return INT2FIX(-1); -} - -static VALUE -ary_make_hash(ary1, ary2) - VALUE ary1, ary2; -{ - VALUE hash = rb_hash_new(); - long i; - - for (i=0; i<RARRAY(ary1)->len; i++) { - rb_hash_aset(hash, RARRAY(ary1)->ptr[i], Qtrue); - } - if (ary2) { - for (i=0; i<RARRAY(ary2)->len; i++) { - rb_hash_aset(hash, RARRAY(ary2)->ptr[i], Qtrue); - } - } - return hash; -} - -/* - * call-seq: - * array - other_array -> an_array - * - * Array Difference---Returns a new array that is a copy of - * the original array, removing any items that also appear in - * other_array. (If you need set-like behavior, see the - * library class Set.) - * - * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ] - */ - -static VALUE -rb_ary_diff(ary1, ary2) - VALUE ary1, ary2; -{ - VALUE ary3, hash; - long i; - - hash = ary_make_hash(to_ary(ary2), 0); - ary3 = rb_ary_new(); - - for (i=0; i<RARRAY(ary1)->len; i++) { - if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue; - rb_ary_push(ary3, rb_ary_elt(ary1, i)); - } - return ary3; -} - -/* - * call-seq: - * array & other_array - * - * Set Intersection---Returns a new array - * containing elements common to the two arrays, with no duplicates. - * - * [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ] - */ - - -static VALUE -rb_ary_and(ary1, ary2) - VALUE ary1, ary2; -{ - VALUE hash, ary3, v, vv; - long i; - - ary2 = to_ary(ary2); - ary3 = rb_ary_new2(RARRAY(ary1)->len < RARRAY(ary2)->len ? - RARRAY(ary1)->len : RARRAY(ary2)->len); - hash = ary_make_hash(ary2, 0); - - for (i=0; i<RARRAY(ary1)->len; i++) { - v = vv = rb_ary_elt(ary1, i); - if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { - rb_ary_push(ary3, v); - } - } - - return ary3; -} - -/* - * call-seq: - * array | other_array -> an_array - * - * Set Union---Returns a new array by joining this array with - * other_array, removing duplicates. - * - * [ "a", "b", "c" ] | [ "c", "d", "a" ] - * #=> [ "a", "b", "c", "d" ] - */ - -static VALUE -rb_ary_or(ary1, ary2) - VALUE ary1, ary2; -{ - VALUE hash, ary3; - VALUE v, vv; - long i; - - ary2 = to_ary(ary2); - ary3 = rb_ary_new2(RARRAY(ary1)->len+RARRAY(ary2)->len); - hash = ary_make_hash(ary1, ary2); - - for (i=0; i<RARRAY(ary1)->len; i++) { - v = vv = rb_ary_elt(ary1, i); - if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { - rb_ary_push(ary3, v); - } - } - for (i=0; i<RARRAY(ary2)->len; i++) { - v = vv = rb_ary_elt(ary2, i); - if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { - rb_ary_push(ary3, v); - } - } - return ary3; -} - -/* - * call-seq: - * array.uniq! -> array or nil - * - * Removes duplicate elements from _self_. - * Returns <code>nil</code> if no changes are made (that is, no - * duplicates are found). - * - * a = [ "a", "a", "b", "b", "c" ] - * a.uniq! #=> ["a", "b", "c"] - * b = [ "a", "b", "c" ] - * b.uniq! #=> nil - */ - -static VALUE -rb_ary_uniq_bang(ary) - VALUE ary; -{ - VALUE hash, v, vv; - long i, j; - - hash = ary_make_hash(ary, 0); - - if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) { - return Qnil; - } - for (i=j=0; i<RARRAY(ary)->len; i++) { - v = vv = rb_ary_elt(ary, i); - if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { - rb_ary_store(ary, j++, v); - } - } - RARRAY(ary)->len = j; - - return ary; -} - -/* - * call-seq: - * array.uniq -> an_array - * - * Returns a new array by removing duplicate values in <i>self</i>. - * - * a = [ "a", "a", "b", "b", "c" ] - * a.uniq #=> ["a", "b", "c"] - */ - -static VALUE -rb_ary_uniq(ary) - VALUE ary; -{ - ary = rb_ary_dup(ary); - rb_ary_uniq_bang(ary); - return ary; -} - -/* - * call-seq: - * array.compact! -> array or nil - * - * Removes +nil+ elements from array. - * Returns +nil+ if no changes were made. - * - * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ] - * [ "a", "b", "c" ].compact! #=> nil - */ - -static VALUE -rb_ary_compact_bang(ary) - VALUE ary; -{ - VALUE *p, *t, *end; - - rb_ary_modify(ary); - p = t = RARRAY(ary)->ptr; - end = p + RARRAY(ary)->len; - - while (t < end) { - if (NIL_P(*t)) t++; - else *p++ = *t++; - } - if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) { - return Qnil; - } - RARRAY(ary)->len = RARRAY(ary)->aux.capa = (p - RARRAY(ary)->ptr); - REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); - - return ary; -} - -/* - * call-seq: - * array.compact -> an_array - * - * Returns a copy of _self_ with all +nil+ elements removed. - * - * [ "a", nil, "b", nil, "c", nil ].compact - * #=> [ "a", "b", "c" ] - */ - -static VALUE -rb_ary_compact(ary) - VALUE ary; -{ - ary = rb_ary_dup(ary); - rb_ary_compact_bang(ary); - return ary; -} - -/* - * call-seq: - * array.nitems -> int - * - * Returns the number of non-<code>nil</code> elements in _self_. - * May be zero. - * - * [ 1, nil, 3, nil, 5 ].nitems #=> 3 - */ - -static VALUE -rb_ary_nitems(ary) - VALUE ary; -{ - long n = 0; - VALUE *p, *pend; - - p = RARRAY(ary)->ptr; - pend = p + RARRAY(ary)->len; - - while (p < pend) { - if (!NIL_P(*p)) n++; - p++; - } - return LONG2NUM(n); -} - -static long -flatten(ary, idx, ary2, memo) - VALUE ary; - long idx; - VALUE ary2, memo; -{ - VALUE id; - long i = idx; - long n, lim = idx + RARRAY(ary2)->len; - - id = rb_obj_id(ary2); - if (rb_ary_includes(memo, id)) { - rb_raise(rb_eArgError, "tried to flatten recursive array"); - } - rb_ary_push(memo, id); - rb_ary_splice(ary, idx, 1, ary2); - while (i < lim) { - VALUE tmp; - - tmp = rb_check_array_type(rb_ary_elt(ary, i)); - if (!NIL_P(tmp)) { - n = flatten(ary, i, tmp, memo); - i += n; lim += n; - } - i++; - } - rb_ary_pop(memo); - - return lim - idx - 1; /* returns number of increased items */ -} - -/* - * call-seq: - * array.flatten! -> array or nil - * - * Flattens _self_ in place. - * Returns <code>nil</code> if no modifications were made (i.e., - * <i>array</i> contains no subarrays.) - * - * a = [ 1, 2, [3, [4, 5] ] ] - * a.flatten! #=> [1, 2, 3, 4, 5] - * a.flatten! #=> nil - * a #=> [1, 2, 3, 4, 5] - */ - -static VALUE -rb_ary_flatten_bang(ary) - VALUE ary; -{ - long i = 0; - int mod = 0; - VALUE memo = Qnil; - - while (i<RARRAY(ary)->len) { - VALUE ary2 = RARRAY(ary)->ptr[i]; - VALUE tmp; - - tmp = rb_check_array_type(ary2); - if (!NIL_P(tmp)) { - if (NIL_P(memo)) { - memo = rb_ary_new(); - } - i += flatten(ary, i, tmp, memo); - mod = 1; - } - i++; - } - if (mod == 0) return Qnil; - return ary; -} - -/* - * call-seq: - * array.flatten -> an_array - * - * Returns a new array that is a one-dimensional flattening of this - * array (recursively). That is, for every element that is an array, - * extract its elements into the new array. - * - * s = [ 1, 2, 3 ] #=> [1, 2, 3] - * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] - * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] - * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 - */ - -static VALUE -rb_ary_flatten(ary) - VALUE ary; -{ - ary = rb_ary_dup(ary); - rb_ary_flatten_bang(ary); - return ary; -} - - -/* Arrays are ordered, integer-indexed collections of any object. - * Array indexing starts at 0, as in C or Java. A negative index is - * assumed to be relative to the end of the array---that is, an index of -1 - * indicates the last element of the array, -2 is the next to last - * element in the array, and so on. - */ - -void -Init_Array() -{ - rb_cArray = rb_define_class("Array", rb_cObject); - rb_include_module(rb_cArray, rb_mEnumerable); - - rb_define_alloc_func(rb_cArray, ary_alloc); - rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1); - rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1); - rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1); - - rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0); - rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0); - rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0); - rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0); - rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0); - - rb_define_method(rb_cArray, "==", rb_ary_equal, 1); - rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1); - rb_define_method(rb_cArray, "hash", rb_ary_hash, 0); - - rb_define_method(rb_cArray, "[]", rb_ary_aref, -1); - rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1); - rb_define_method(rb_cArray, "at", rb_ary_at, 1); - rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1); - rb_define_method(rb_cArray, "first", rb_ary_first, -1); - rb_define_method(rb_cArray, "last", rb_ary_last, -1); - rb_define_method(rb_cArray, "concat", rb_ary_concat, 1); - rb_define_method(rb_cArray, "<<", rb_ary_push, 1); - rb_define_method(rb_cArray, "push", rb_ary_push_m, -1); - rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1); - rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1); - rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1); - rb_define_method(rb_cArray, "insert", rb_ary_insert, -1); - rb_define_method(rb_cArray, "each", rb_ary_each, 0); - rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0); - rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0); - rb_define_method(rb_cArray, "length", rb_ary_length, 0); - rb_define_alias(rb_cArray, "size", "length"); - rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0); - rb_define_method(rb_cArray, "index", rb_ary_index, -1); - rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1); - rb_define_method(rb_cArray, "join", rb_ary_join_m, -1); - rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0); - rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0); - rb_define_method(rb_cArray, "sort", rb_ary_sort, 0); - rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0); - rb_define_method(rb_cArray, "collect", rb_ary_collect, 0); - rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0); - rb_define_method(rb_cArray, "map", rb_ary_collect, 0); - rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0); - rb_define_method(rb_cArray, "select", rb_ary_select, 0); - rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1); - rb_define_method(rb_cArray, "delete", rb_ary_delete, 1); - rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1); - rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0); - rb_define_method(rb_cArray, "reject", rb_ary_reject, 0); - rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0); - rb_define_method(rb_cArray, "zip", rb_ary_zip, -1); - rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0); - rb_define_method(rb_cArray, "replace", rb_ary_replace, 1); - rb_define_method(rb_cArray, "clear", rb_ary_clear, 0); - rb_define_method(rb_cArray, "fill", rb_ary_fill, -1); - rb_define_method(rb_cArray, "include?", rb_ary_includes, 1); - rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1); - - rb_define_method(rb_cArray, "slice", rb_ary_aref, -1); - rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1); - - rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1); - rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1); - - rb_define_method(rb_cArray, "+", rb_ary_plus, 1); - rb_define_method(rb_cArray, "*", rb_ary_times, 1); - - rb_define_method(rb_cArray, "-", rb_ary_diff, 1); - rb_define_method(rb_cArray, "&", rb_ary_and, 1); - rb_define_method(rb_cArray, "|", rb_ary_or, 1); - - rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0); - rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0); - rb_define_method(rb_cArray, "compact", rb_ary_compact, 0); - rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0); - rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0); - rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0); - rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0); - - id_cmp = rb_intern("<=>"); - - rb_cValues = rb_define_class("Values", rb_cArray); -} -/********************************************************************** - ascii.c - Oniguruma (regular expression library) -**********************************************************************/ -/*- - * Copyright (c) 2002-2004 K.Kosako <sndgk393 AT ybb DOT ne DOT jp> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "regenc.h" - -static int -ascii_is_code_ctype(OnigCodePoint code, unsigned int ctype) -{ - if (code < 128) - return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); - else - return FALSE; -} - -OnigEncodingType OnigEncodingASCII = { - onigenc_single_byte_mbc_enc_len, - "US-ASCII", /* name */ - 1, /* max byte length */ - 1, /* min byte length */ - ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, - { - (OnigCodePoint )'\\' /* esc */ - , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ - , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ - , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ - , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ - , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ - }, - onigenc_is_mbc_newline_0x0a, - onigenc_single_byte_mbc_to_code, - onigenc_single_byte_code_to_mbclen, - onigenc_single_byte_code_to_mbc, - onigenc_ascii_mbc_to_normalize, - onigenc_ascii_is_mbc_ambiguous, - onigenc_ascii_get_all_pair_ambig_codes, - onigenc_nothing_get_all_comp_ambig_codes, - ascii_is_code_ctype, - onigenc_not_support_get_ctype_code_range, - onigenc_single_byte_left_adjust_char_head, - onigenc_always_true_is_allowed_reverse_match -}; -/********************************************************************** - - bignum.c - - - $Author: murphy $ - $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $ - created at: Fri Jun 10 00:48:55 JST 1994 - - Copyright (C) 1993-2003 Yukihiro Matsumoto - -**********************************************************************/ - -#include "ruby.h" - -#include <math.h> -#include <ctype.h> -#ifdef HAVE_IEEEFP_H -#include <ieeefp.h> -#endif - -VALUE rb_cBignum; - -#if defined __MINGW32__ -#define USHORT _USHORT -#endif - -#define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits) -#define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) -#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG) -#define DIGSPERLONG ((unsigned int)(SIZEOF_LONG/SIZEOF_BDIGITS)) -#if HAVE_LONG_LONG -# define DIGSPERLL ((unsigned int)(SIZEOF_LONG_LONG/SIZEOF_BDIGITS)) -#endif -#define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG) -#define BIGDN(x) RSHIFT(x,BITSPERDIG) -#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1))) -#define BDIGMAX ((BDIGIT)-1) - -#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0)) - -static VALUE -bignew_1(klass, len, sign) - VALUE klass; - long len; - char sign; -{ - NEWOBJ(big, struct RBignum); - OBJSETUP(big, klass, T_BIGNUM); - big->sign = sign; - big->len = len; - big->digits = ALLOC_N(BDIGIT, len); - - return (VALUE)big; -} - -#define bignew(len,sign) bignew_1(rb_cBignum,len,sign) - -VALUE -rb_big_clone(x) - VALUE x; -{ - VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign); - - MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len); - return z; -} - -static void -get2comp(x, carry) /* get 2's complement */ - VALUE x; - int carry; -{ - long i = RBIGNUM(x)->len; - BDIGIT *ds = BDIGITS(x); - BDIGIT_DBL num; - - while (i--) ds[i] = ~ds[i]; - i = 0; num = 1; - do { - num += ds[i]; - ds[i++] = BIGLO(num); - num = BIGDN(num); - } while (i < RBIGNUM(x)->len); - if (!carry) return; - if ((ds[RBIGNUM(x)->len-1] & (1<<(BITSPERDIG-1))) == 0) { - REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len); - ds = BDIGITS(x); - ds[RBIGNUM(x)->len-1] = ~0; - } -} - -void -rb_big_2comp(x) /* get 2's complement */ - VALUE x; -{ - get2comp(x, Qtrue); -} - -static VALUE -bignorm(x) - VALUE x; -{ - if (!FIXNUM_P(x)) { - long len = RBIGNUM(x)->len; - BDIGIT *ds = BDIGITS(x); - - while (len-- && !ds[len]) ; - RBIGNUM(x)->len = ++len; - - if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) { - long num = 0; - while (len--) { - num = BIGUP(num) + ds[len]; - } - if (num >= 0) { - if (RBIGNUM(x)->sign) { - if (POSFIXABLE(num)) return LONG2FIX(num); - } - else if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num); - } - } - } - return x; -} - -VALUE -rb_big_norm(x) - VALUE x; -{ - return bignorm(x); -} - -VALUE -rb_uint2big(n) - unsigned long n; -{ - BDIGIT_DBL num = n; - long i = 0; - BDIGIT *digits; - VALUE big; - - big = bignew(DIGSPERLONG, 1); - digits = BDIGITS(big); - while (i < DIGSPERLONG) { - digits[i++] = BIGLO(num); - num = BIGDN(num); - } - - i = DIGSPERLONG; - while (--i && !digits[i]) ; - RBIGNUM(big)->len = i+1; - return big; -} - -VALUE -rb_int2big(n) - long n; -{ - long neg = 0; - VALUE big; - - if (n < 0) { - n = -n; - neg = 1; - } - big = rb_uint2big(n); - if (neg) { - RBIGNUM(big)->sign = 0; - } - return big; -} - -VALUE -rb_uint2inum(n) - unsigned long n; -{ - if (POSFIXABLE(n)) return LONG2FIX(n); - return rb_uint2big(n); -} - -VALUE -rb_int2inum(n) - long n; -{ - if (FIXABLE(n)) return LONG2FIX(n); - return rb_int2big(n); -} - -#ifdef HAVE_LONG_LONG - -void -rb_quad_pack(buf, val) - char *buf; - VALUE val; -{ - LONG_LONG q; - - val = rb_to_int(val); - if (FIXNUM_P(val)) { - q = FIX2LONG(val); - } - else { - long len = RBIGNUM(val)->len; - BDIGIT *ds; - - if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) { - len = SIZEOF_LONG/SIZEOF_BDIGITS; - } - ds = BDIGITS(val); - q = 0; - while (len--) { - q = BIGUP(q); - q += ds[len]; - } - if (!RBIGNUM(val)->sign) q = -q; - } - memcpy(buf, (char*)&q, SIZEOF_LONG_LONG); -} - -VALUE -rb_quad_unpack(buf, sign) - const char *buf; - int sign; -{ - unsigned LONG_LONG q; - long neg = 0; - long i; - BDIGIT *digits; - VALUE big; - - memcpy(&q, buf, SIZEOF_LONG_LONG); - if (sign) { - if (FIXABLE((LONG_LONG)q)) return LONG2FIX((LONG_LONG)q); - if ((LONG_LONG)q < 0) { - q = -(LONG_LONG)q; - neg = 1; - } - } - else { - if (POSFIXABLE(q)) return LONG2FIX(q); - } - - i = 0; - big = bignew(DIGSPERLL, 1); - digits = BDIGITS(big); - while (i < DIGSPERLL) { - digits[i++] = BIGLO(q); - q = BIGDN(q); - } - - i = DIGSPERLL; - while (i-- && !digits[i]) ; - RBIGNUM(big)->len = i+1; - - if (neg) { - RBIGNUM(big)->sign = 0; - } - return bignorm(big); -} - -#else - -#define QUAD_SIZE 8 - -void -rb_quad_pack(buf, val) - char *buf; - VALUE val; -{ - long len; - - memset(buf, 0, QUAD_SIZE); - val = rb_to_int(val); - if (FIXNUM_P(val)) { - val = rb_int2big(FIX2LONG(val)); - } - len = RBIGNUM(val)->len * SIZEOF_BDIGITS; - if (len > QUAD_SIZE) { - rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'"); - } - memcpy(buf, (char*)BDIGITS(val), len); - if (!RBIGNUM(val)->sign) { - len = QUAD_SIZE; - while (len--) { - *buf = ~*buf; - buf++; - } - } -} - -#define BNEG(b) (RSHIFT(((BDIGIT*)b)[QUAD_SIZE/SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0) - -VALUE -rb_quad_unpack(buf, sign) - const char *buf; - int sign; -{ - VALUE big = bignew(QUAD_SIZE/SIZEOF_BDIGITS, 1); - - memcpy((char*)BDIGITS(big), buf, QUAD_SIZE); - if (sign && BNEG(buf)) { - long len = QUAD_SIZE; - char *tmp = (char*)BDIGITS(big); - - RBIGNUM(big)->sign = 0; - while (len--) { - *tmp = ~*tmp; - tmp++; - } - } - - return bignorm(big); -} - -#endif - -VALUE -rb_cstr_to_inum(str, base, badcheck) - const char *str; - int base; - int badcheck; -{ - const char *s = str; - char *end; - char sign = 1, nondigit = 0; - int c; - BDIGIT_DBL num; - long len, blen = 1; - long i; - VALUE z; - BDIGIT *zds; - - if (!str) { - if (badcheck) goto bad; - return INT2FIX(0); - } - if (badcheck) { - while (ISSPACE(*str)) str++; - } - else { - while (ISSPACE(*str) || *str == '_') str++; - } - - if (str[0] == '+') { - str++; - } - else if (str[0] == '-') { - str++; - sign = 0; - } - if (str[0] == '+' || str[0] == '-') { - if (badcheck) goto bad; - return INT2FIX(0); - } - if (base <= 0) { - if (str[0] == '0') { - switch (str[1]) { - case 'x': case 'X': - base = 16; - break; - case 'b': case 'B': - base = 2; - break; - case 'o': case 'O': - base = 8; - break; - case 'd': case 'D': - base = 10; - break; - default: - base = 8; - } - } - else if (base < -1) { - base = -base; - } - else { - base = 10; - } - } - switch (base) { - case 2: - len = 1; - if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) { - str += 2; - } - break; - case 3: - len = 2; - break; - case 8: - if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) { - str += 2; - } - case 4: case 5: case 6: case 7: - len = 3; - break; - case 10: - if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) { - str += 2; - } - case 9: case 11: case 12: case 13: case 14: case 15: - len = 4; - break; - case 16: - len = 4; - if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) { - str += 2; - } - break; - default: - if (base < 2 || 36 < base) { - rb_raise(rb_eArgError, "illegal radix %d", base); - } - if (base <= 32) { - len = 5; - } - else { - len = 6; - } - break; - } - if (*str == '0') { /* squeeze preceeding 0s */ - while (*++str == '0'); - --str; - } - len *= strlen(str)*sizeof(char); - - if (len <= (sizeof(VALUE)*CHAR_BIT)) { - unsigned long val = strtoul((char*)str, &end, base); - - if (*end == '_') goto bigparse; - if (badcheck) { - if (end == str) goto bad; /* no number */ - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; /* trailing garbage */ - } - - if (POSFIXABLE(val)) { - if (sign) return LONG2FIX(val); - else { - long result = -(long)val; - return LONG2FIX(result); - } - } - else { - VALUE big = rb_uint2big(val); - RBIGNUM(big)->sign = sign; - return bignorm(big); - } - } - bigparse: - len = (len/BITSPERDIG)+1; - if (badcheck && *str == '_') goto bad; - - z = bignew(len, sign); - zds = BDIGITS(z); - for (i=len;i--;) zds[i]=0; - while (c = *str++) { - if (c == '_') { - if (badcheck) { - if (nondigit) goto bad; - nondigit = c; - } - continue; - } - else if (!ISASCII(c)) { - break; - } - else if (isdigit(c)) { - c -= '0'; - } - else if (islower(c)) { - c -= 'a' - 10; - } - else if (isupper(c)) { - c -= 'A' - 10; - } - else { - break; - } - if (c >= base) break; - nondigit = 0; - i = 0; - num = c; - for (;;) { - while (i<blen) { - num += (BDIGIT_DBL)zds[i]*base; - zds[i++] = BIGLO(num); - num = BIGDN(num); - } - if (num) { - blen++; - continue; - } - break; - } - } - if (badcheck) { - str--; - if (s+1 < str && str[-1] == '_') goto bad; - while (*str && ISSPACE(*str)) str++; - if (*str) { - bad: - rb_invalid_str(s, "Integer"); - } - } - - return bignorm(z); -} - -VALUE -rb_str_to_inum(str, base, badcheck) - VALUE str; - int base; - int badcheck; -{ - char *s; - long len; - - StringValue(str); - if (badcheck) { - s = StringValueCStr(str); - } - else { - s = RSTRING(str)->ptr; - } - if (s) { - len = RSTRING(str)->len; - if (s[len]) { /* no sentinel somehow */ - char *p = ALLOCA_N(char, len+1); - - MEMCPY(p, s, char, len); - p[len] = '\0'; - s = p; - } - } - return rb_cstr_to_inum(s, base, badcheck); -} - -#if HAVE_LONG_LONG - -VALUE -rb_ull2big(n) - unsigned LONG_LONG n; -{ - BDIGIT_DBL num = n; - long i = 0; - BDIGIT *digits; - VALUE big; - - big = bignew(DIGSPERLL, 1); - digits = BDIGITS(big); - while (i < DIGSPERLL) { - digits[i++] = BIGLO(num); - num = BIGDN(num); - } - - i = DIGSPERLL; - while (i-- && !digits[i]) ; - RBIGNUM(big)->len = i+1; - return big; -} - -VALUE -rb_ll2big(n) - LONG_LONG n; -{ - long neg = 0; - VALUE big; - - if (n < 0) { - n = -n; - neg = 1; - } - big = rb_ull2big(n); - if (neg) { - RBIGNUM(big)->sign = 0; - } - return big; -} - -VALUE -rb_ull2inum(n) - unsigned LONG_LONG n; -{ - if (POSFIXABLE(n)) return LONG2FIX(n); - return rb_ull2big(n); -} - -VALUE -rb_ll2inum(n) - LONG_LONG n; -{ - if (FIXABLE(n)) return LONG2FIX(n); - return rb_ll2big(n); -} - -#endif /* HAVE_LONG_LONG */ - -VALUE -rb_cstr2inum(str, base) - const char *str; - int base; -{ - return rb_cstr_to_inum(str, base, base==0); -} - -VALUE -rb_str2inum(str, base) - VALUE str; - int base; -{ - return rb_str_to_inum(str, base, base==0); -} - -const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -VALUE -rb_big2str(x, base) - VALUE x; - int base; -{ - volatile VALUE t; - BDIGIT *ds; - long i, j, hbase; - VALUE ss; - char *s, c; - - if (FIXNUM_P(x)) { - return rb_fix2str(x, base); - } - i = RBIGNUM(x)->len; - if (BIGZEROP(x)) { - return rb_str_new2("0"); - } - j = SIZEOF_BDIGITS*CHAR_BIT*i; - switch (base) { - case 2: break; - case 3: - j = j * 647L / 1024; - break; - case 4: case 5: case 6: case 7: - j /= 2; - break; - case 8: case 9: - j /= 3; - break; - case 10: case 11: case 12: case 13: case 14: case 15: - j = j * 241L / 800; - break; - case 16: case 17: case 18: case 19: case 20: case 21: - case 22: case 23: case 24: case 25: case 26: case 27: - case 28: case 29: case 30: case 31: - j /= 4; - break; - case 32: case 33: case 34: case 35: case 36: - j /= 5; - break; - default: - rb_raise(rb_eArgError, "illegal radix %d", base); - break; - } - j += 2; - - hbase = base * base; -#if SIZEOF_BDIGITS > 2 - hbase *= hbase; -#endif - - t = rb_big_clone(x); - ds = BDIGITS(t); - ss = rb_str_new(0, j); - s = RSTRING(ss)->ptr; - - s[0] = RBIGNUM(x)->sign ? '+' : '-'; - while (i && j) { - long k = i; - BDIGIT_DBL num = 0; - - while (k--) { - num = BIGUP(num) + ds[k]; - ds[k] = (BDIGIT)(num / hbase); - num %= hbase; - } - if (ds[i-1] == 0) i--; - k = SIZEOF_BDIGITS; - while (k--) { - c = (char)(num % base); - s[--j] = ruby_digitmap[(int)c]; - num /= base; - if (i == 0 && num == 0) break; - } - } - while (s[j] == '0') j++; - RSTRING(ss)->len -= RBIGNUM(x)->sign?j:j-1; - memmove(RBIGNUM(x)->sign?s:s+1, s+j, RSTRING(ss)->len); - s[RSTRING(ss)->len] = '\0'; - - return ss; -} - -/* - * call-seq: - * big.to_s(base=10) => string - * - * Returns a string containing the representation of <i>big</i> radix - * <i>base</i> (2 through 36). - * - * 12345654321.to_s #=> "12345654321" - * 12345654321.to_s(2) #=> "1011011111110110111011110000110001" - * 12345654321.to_s(8) #=> "133766736061" - * 12345654321.to_s(16) #=> "2dfdbbc31" - * 78546939656932.to_s(36) #=> "rubyrules" - */ - -static VALUE -rb_big_to_s(argc, argv, x) - int argc; - VALUE *argv; - VALUE x; -{ - VALUE b; - int base; - - rb_scan_args(argc, argv, "01", &b); - if (argc == 0) base = 10; - else base = NUM2INT(b); - return rb_big2str(x, base); -} - -static unsigned long -big2ulong(x, type, check) - VALUE x; - char *type; - int check; -{ - long len = RBIGNUM(x)->len; - BDIGIT_DBL num; - BDIGIT *ds; - - if (len > SIZEOF_LONG/SIZEOF_BDIGITS) { - if (check) - rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); - len = SIZEOF_LONG/SIZEOF_BDIGITS; - } - ds = BDIGITS(x); - num = 0; - while (len--) { - num = BIGUP(num); - num += ds[len]; - } - return num; -} - -unsigned long -rb_big2ulong_pack(x) - VALUE x; -{ - unsigned long num = big2ulong(x, "unsigned long", Qfalse); - if (!RBIGNUM(x)->sign) { - return -num; - } - return num; -} - -unsigned long -rb_big2ulong(x) - VALUE x; -{ - unsigned long num = big2ulong(x, "unsigned long", Qtrue); - - if (!RBIGNUM(x)->sign) { - if ((long)num < 0) { - rb_raise(rb_eRangeError, "bignum out of range of unsigned long"); - } - return -num; - } - return num; -} - -long -rb_big2long(x) - VALUE x; -{ - unsigned long num = big2ulong(x, "long", Qtrue); - - if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) { - rb_raise(rb_eRangeError, "bignum too big to convert into `long'"); - } - if (!RBIGNUM(x)->sign) return -(long)num; - return num; -} - -#if HAVE_LONG_LONG - -static unsigned LONG_LONG -big2ull(x, type) - VALUE x; - char *type; -{ - long len = RBIGNUM(x)->len; - BDIGIT_DBL num; - BDIGIT *ds; - - if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) - rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); - ds = BDIGITS(x); - num = 0; - while (len--) { - num = BIGUP(num); - num += ds[len]; - } - return num; -} - -unsigned LONG_LONG -rb_big2ull(x) - VALUE x; -{ - unsigned LONG_LONG num = big2ull(x, "unsigned long long"); - - if (!RBIGNUM(x)->sign) return -num; - return num; -} - -LONG_LONG -rb_big2ll(x) - VALUE x; -{ - unsigned LONG_LONG num = big2ull(x, "long long"); - - if ((LONG_LONG)num < 0 && (RBIGNUM(x)->sign - || (LONG_LONG)num != LLONG_MIN)) { - rb_raise(rb_eRangeError, "bignum too big to convert into `long long'"); - } - if (!RBIGNUM(x)->sign) return -(LONG_LONG)num; - return num; -} - -#endif /* HAVE_LONG_LONG */ - -static VALUE -dbl2big(d) - double d; -{ - long i = 0; - BDIGIT c; - BDIGIT *digits; - VALUE z; - double u = (d < 0)?-d:d; - - if (isinf(d)) { - rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity"); - } - if (isnan(d)) { - rb_raise(rb_eFloatDomainError, "NaN"); - } - - while (!POSFIXABLE(u) || 0 != (long)u) { - u /= (double)(BIGRAD); - i++; - } - z = bignew(i, d>=0); - digits = BDIGITS(z); - while (i--) { - u *= BIGRAD; - c = (BDIGIT)u; - u -= c; - digits[i] = c; - } - - return z; -} - -VALUE -rb_dbl2big(d) - double d; -{ - return bignorm(dbl2big(d)); -} - -double -rb_big2dbl(x) - VALUE x; -{ - double d = 0.0; - long i = RBIGNUM(x)->len; - BDIGIT *ds = BDIGITS(x); - - while (i--) { - d = ds[i] + BIGRAD*d; - } - if (isinf(d)) { - rb_warn("Bignum out of Float range"); - d = HUGE_VAL; - } - if (!RBIGNUM(x)->sign) d = -d; - return d; -} - -/* - * call-seq: - * big.to_f -> float - * - * Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't - * fit in a <code>Float</code>, the result is infinity. - * - */ - -static VALUE -rb_big_to_f(x) - VALUE x; -{ - return rb_float_new(rb_big2dbl(x)); -} - -/* - * call-seq: - * big <=> numeric => -1, 0, +1 - * - * Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is - * less than, equal to, or greater than <i>numeric</i>. This is the - * basis for the tests in <code>Comparable</code>. - * - */ - -static VALUE -rb_big_cmp(x, y) - VALUE x, y; -{ - long xlen = RBIGNUM(x)->len; - - switch (TYPE(y)) { - case T_FIXNUM: - y = rb_int2big(FIX2LONG(y)); - break; - - case T_BIGNUM: - break; - - case T_FLOAT: - return rb_dbl_cmp(rb_big2dbl(x), RFLOAT(y)->value); - - default: - return rb_num_coerce_cmp(x, y); - } - - if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1); - if (RBIGNUM(x)->sign < RBIGNUM(y)->sign) return INT2FIX(-1); - if (xlen < RBIGNUM(y)->len) - return (RBIGNUM(x)->sign) ? INT2FIX(-1) : INT2FIX(1); - if (xlen > RBIGNUM(y)->len) - return (RBIGNUM(x)->sign) ? INT2FIX(1) : INT2FIX(-1); - - while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen])); - if (-1 == xlen) return INT2FIX(0); - return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ? - (RBIGNUM(x)->sign ? INT2FIX(1) : INT2FIX(-1)) : - (RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1)); -} - -/* - * call-seq: - * big == obj => true or false - * - * Returns <code>true</code> only if <i>obj</i> has the same value - * as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which - * requires <i>obj</i> to be a <code>Bignum</code>. - * - * 68719476736 == 68719476736.0 #=> true - */ - -static VALUE -rb_big_eq(x, y) - VALUE x, y; -{ - switch (TYPE(y)) { - case T_FIXNUM: - y = rb_int2big(FIX2LONG(y)); - break; - case T_BIGNUM: - break; - case T_FLOAT: - { - volatile double a, b; - - a = RFLOAT(y)->value; - b = rb_big2dbl(x); - if (isnan(a) || isnan(b)) return Qfalse; - return (a == b)?Qtrue:Qfalse; - } - default: - return rb_equal(y, x); - } - if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse; - if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse; - if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse; - return Qtrue; -} - -/* - * call-seq: - * big.eql?(obj) => true or false - * - * Returns <code>true</code> only if <i>obj</i> is a - * <code>Bignum</code> with the same value as <i>big</i>. Contrast this - * with <code>Bignum#==</code>, which performs type conversions. - * - * 68719476736.eql?(68719476736.0) #=> false - */ - -static VALUE -rb_big_eql(x, y) - VALUE x, y; -{ - if (TYPE(y) != T_BIGNUM) return Qfalse; - if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse; - if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse; - if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse; - return Qtrue; -} - -/* - * call-seq: - * -big => other_big - * - * Unary minus (returns a new Bignum whose value is 0-big) - */ - -static VALUE -rb_big_uminus(x) - VALUE x; -{ - VALUE z = rb_big_clone(x); - - RBIGNUM(z)->sign = !RBIGNUM(x)->sign; - - return bignorm(z); -} - -/* - * call-seq: - * ~big => integer - * - * Inverts the bits in big. As Bignums are conceptually infinite - * length, the result acts as if it had an infinite number of one - * bits to the left. In hex representations, this is displayed - * as two periods to the left of the digits. - * - * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA" - */ - -static VALUE -rb_big_neg(x) - VALUE x; -{ - VALUE z = rb_big_clone(x); - long i = RBIGNUM(x)->len; - BDIGIT *ds = BDIGITS(z); - - if (!RBIGNUM(x)->sign) get2comp(z, Qtrue); - while (i--) ds[i] = ~ds[i]; - if (RBIGNUM(x)->sign) get2comp(z, Qfalse); - RBIGNUM(z)->sign = !RBIGNUM(z)->sign; - - return bignorm(z); -} - -static VALUE -bigsub(x, y) - VALUE x, y; -{ - VALUE z = 0; - BDIGIT *zds; - BDIGIT_DBL_SIGNED num; - long i = RBIGNUM(x)->len; - - /* if x is larger than y, swap */ - if (RBIGNUM(x)->len < RBIGNUM(y)->len) { - z = x; x = y; y = z; /* swap x y */ - } - else if (RBIGNUM(x)->len == RBIGNUM(y)->len) { - while (i > 0) { - i--; - if (BDIGITS(x)[i] > BDIGITS(y)[i]) { - break; - } - if (BDIGITS(x)[i] < BDIGITS(y)[i]) { - z = x; x = y; y = z; /* swap x y */ - break; - } - } - } - - z = bignew(RBIGNUM(x)->len, (z == 0)?1:0); - zds = BDIGITS(z); - - for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) { - num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i]; - zds[i] = BIGLO(num); - num = BIGDN(num); - } - while (num && i < RBIGNUM(x)->len) { - num += BDIGITS(x)[i]; - zds[i++] = BIGLO(num); - num = BIGDN(num); - } - while (i < RBIGNUM(x)->len) { - zds[i] = BDIGITS(x)[i]; - i++; - } - - return z; -} - |