Skip to content

Commit

Permalink
[ruby 2.4] Fixes for Integer#digits in PR #4375 (#4490)
Browse files Browse the repository at this point in the history
* [ruby 2.4] Implemented Integer#digits

It passes all the following tests of TestInteger of MRI:

* test_digits
* test_digits_for_negative_numbers
* test_digits_for_invalid_base_numbers
* test_digits_for_non_integral_base_numbers
* test_digits_for_non_numeric_base_argument

* Moved Integer#digits to Fixnum & Bignum

* Fixed some styling issues
whwilder authored and kares committed Feb 24, 2017
1 parent edbd1d5 commit d84615c
Showing 3 changed files with 105 additions and 0 deletions.
49 changes: 49 additions & 0 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -236,6 +236,55 @@ public static BigInteger long2big(long arg) {
* ================
*/

/** rb_big_digits
*
*/
@Override
public RubyArray digits(ThreadContext context, IRubyObject base) {
BigInteger self = value;
Ruby runtime = context.runtime;
if (self.compareTo(BigInteger.ZERO) == -1) {
throw runtime.newMathDomainError("out of domain");
}
if (!(base instanceof RubyInteger)) {
try {
base = base.convertToInteger();
} catch (ClassCastException e) {
String cname = base.getMetaClass().getRealClass().getName();
throw runtime.newTypeError("wrong argument type " + cname + " (expected Integer)");
}
}

BigInteger bigBase;
if (base instanceof RubyBignum) {
bigBase = ((RubyBignum) base).getValue();
} else {
bigBase = long2big( ((RubyFixnum) base).getLongValue() );
}

if (bigBase.compareTo(BigInteger.ZERO) == -1) {
throw runtime.newArgumentError("negative radix");
}
if (bigBase.compareTo(new BigInteger("2")) == -1) {
throw runtime.newArgumentError("invalid radix: " + bigBase);
}

RubyArray res = RubyArray.newArray(context.runtime, 0);

if (self.compareTo(BigInteger.ZERO) == 0) {
res.append(RubyFixnum.newFixnum(context.getRuntime(), 0));
return res;
}

while (self.compareTo(BigInteger.ZERO) > 0) {
BigInteger q = self.mod(bigBase);
res.append(RubyBignum.newBignum(context.getRuntime(), q));
self = self.divide(bigBase);
}

return res;
}

/** rb_big_to_s
*
*/
48 changes: 48 additions & 0 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -302,6 +302,54 @@ public IRubyObject times(ThreadContext context, Block block) {
return RubyEnumerator.enumeratorizeWithSize(context, this, "times", timesSizeFn(context.runtime));
}

/** rb_fix_digits
*
*/
@Override
public RubyArray digits(ThreadContext context, IRubyObject base) {

long self = getLongValue();
Ruby runtime = context.getRuntime();
if (self < 0) {
throw runtime.newMathDomainError("out of domain");
}
if (!(base instanceof RubyInteger)) {
try {
base = base.convertToInteger();
} catch (ClassCastException e) {
String cname = base.getMetaClass().getRealClass().getName();
throw runtime.newTypeError("wrong argument type " + cname + " (expected Integer)");
}
}
if (base instanceof RubyBignum){
return RubyArray
.newArray(context.runtime, 1)
.append(newFixnum(runtime, self));
}
long longBase = ((RubyFixnum)base).getLongValue();
if (longBase < 0) {
throw runtime.newArgumentError("negative radix");
}
if (longBase < 2) {
throw runtime.newArgumentError("invalid radix: " + longBase);
}

RubyArray res = RubyArray.newArray(context.runtime, 0);

if (self == 0) {
res.append(newFixnum(runtime, 0));
return res;
}

while (self > 0) {
long q = self % longBase;
res.append(newFixnum(runtime, q));
self /= longBase;
}

return res;
}

/** fix_to_s
*
*/
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/RubyInteger.java
Original file line number Diff line number Diff line change
@@ -515,6 +515,14 @@ public IRubyObject gcdlcm(ThreadContext context, IRubyObject other) {
return context.runtime.newArray(f_gcd(context, this, other), f_lcm(context, this, other));
}

@JRubyMethod(name = "digits")
public RubyArray digits(ThreadContext context) {
return digits(context, RubyFixnum.newFixnum(context.getRuntime(), 10));
}

@JRubyMethod(name = "digits")
public abstract RubyArray digits(ThreadContext context, IRubyObject base);

@Override
@JRubyMethod(name = "numerator")
public IRubyObject numerator(ThreadContext context) {

0 comments on commit d84615c

Please sign in to comment.