Project

General

Profile

Feature #14401 » inverse_of_digits.patch

tompng (tomoya ishida), 01/25/2018 12:43 PM

View differences:

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)}
    (1-1/1)