Feature #14401 » inverse_of_digits.patch
numeric.c | ||
---|---|---|
}
|
||
}
|
||
static VALUE
|
||
rb_int_s_from_digits(int argc, VALUE *argv, VALUE klass) {
|
||
VALUE digits, base, array;
|
||
long size, levels, level;
|
||
rb_check_arity(argc, 1, 2);
|
||
digits = rb_to_array_type(argv[0]);
|
||
base = argc == 2 ? rb_to_int(argv[1]) : INT2FIX(10);
|
||
if (FIXNUM_P(base) && FIX2LONG(base) < 2)
|
||
rb_raise(rb_eArgError, "invalid radix %ld", FIX2LONG(base));
|
||
else if (RB_TYPE_P(base, T_BIGNUM) && BIGNUM_NEGATIVE_P(base))
|
||
rb_raise(rb_eArgError, "negative radix");
|
||
array = rb_ary_dup(digits);
|
||
size = RARRAY_LEN(array);
|
||
levels = bit_length(size);
|
||
for (level = 0; level < levels; level++) {
|
||
long stride = 2 << level;
|
||
long i, n = (size + stride - 1) / stride;
|
||
if (level) base = rb_int_mul(base, base);
|
||
for (i = 0; i < n; i++) {
|
||
VALUE div = INT2FIX(0);
|
||
VALUE mod = rb_to_int(RARRAY_AREF(array, 2 * i));
|
||
RARRAY_ASET(array, 2 * i, INT2FIX(0));
|
||
if (2 * i + 1 < size) {
|
||
div = rb_to_int(RARRAY_AREF(array, 2 * i + 1));
|
||
RARRAY_ASET(array, 2 * i + 1, INT2FIX(0));
|
||
}
|
||
if (div == INT2FIX(0)) {
|
||
RARRAY_ASET(array, i, mod);
|
||
} else {
|
||
div = rb_to_int(div);
|
||
RARRAY_ASET(array, i, rb_int_plus(rb_int_mul(div, base), mod));
|
||
}
|
||
}
|
||
}
|
||
return RARRAY_AREF(array, 0);
|
||
}
|
||
/*
|
||
* Document-class: ZeroDivisionError
|
||
*
|
||
... | ... | |
rb_undef_alloc_func(rb_cInteger);
|
||
rb_undef_method(CLASS_OF(rb_cInteger), "new");
|
||
rb_define_singleton_method(rb_cInteger, "sqrt", rb_int_s_isqrt, 1);
|
||
rb_define_singleton_method(rb_cInteger, "from_digits", rb_int_s_from_digits, -1);
|
||
rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
|
||
rb_define_alias(rb_cInteger, "inspect", "to_s");
|
test/ruby/test_integer.rb | ||
---|---|---|
assert_equal([0, 1], 10.digits(o))
|
||
end
|
||
def test_from_digits
|
||
assert_equal(Integer.from_digits([0]), 0)
|
||
assert_equal(Integer.from_digits([1]), 1)
|
||
assert_equal(Integer.from_digits([4, 3, 2, 1]), 1234)
|
||
assert_equal(Integer.from_digits([1, 0, 1, 1, 1], 2), 29)
|
||
assert_equal(Integer.from_digits((9**999).digits), 9**999)
|
||
assert_equal(Integer.from_digits([1, 1, 1], 1 << 128), (1 << 256) | (1 << 128) | 1)
|
||
assert_raise(TypeError) { Integer.from_digits("4321") }
|
||
assert_raise(TypeError) { Integer.from_digits([4, 3, 2, 1], "10") }
|
||
assert_raise(TypeError) { Integer.from_digits([4, "3", 2, 1]) }
|
||
assert_raise(ArgumentError) { Integer.from_digits([4, 3, 2, 1], 1) }
|
||
assert_raise(ArgumentError) { Integer.from_digits([4, 3, 2, 1], 0) }
|
||
assert_raise(ArgumentError) { Integer.from_digits([4, 3, 2, 1], -9**999) }
|
||
end
|
||
def test_square_root
|
||
assert_raise(TypeError) {Integer.sqrt("x")}
|
||
assert_raise(Math::DomainError) {Integer.sqrt(-1)}
|