Skip to content

Commit fa8eb7d

Browse files
authored
Merge pull request #4343 from matugm/ruby-2.4
Add optional precision for Float#floor
2 parents e8b8bb6 + d1bfc43 commit fa8eb7d

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

core/src/main/java/org/jruby/RubyFloat.java

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -799,11 +799,56 @@ public IRubyObject rationalize(ThreadContext context, IRubyObject[] args) {
799799
/** floor
800800
*
801801
*/
802-
@JRubyMethod(name = "floor")
803-
@Override
804-
public IRubyObject floor() {
805-
return dbl2num(getRuntime(), Math.floor(value));
806-
}
802+
803+
@Override
804+
public IRubyObject floor() {
805+
return dbl2num(getRuntime(), Math.floor(value));
806+
}
807+
808+
@JRubyMethod(name = "floor", optional = 1)
809+
public IRubyObject floor(ThreadContext context, IRubyObject[] args) {
810+
if (args.length == 0) return floor();
811+
812+
double number = value;
813+
double digits = num2long(args[0]);
814+
double magnifier = Math.pow(10.0, Math.abs(digits));
815+
double reducer = Math.pow(10.0, -Math.abs(digits));
816+
817+
// Borrowed from round
818+
double binexp;
819+
if (value == 0) {
820+
binexp = 0;
821+
} else {
822+
binexp = Math.ceil(Math.log(value)/Math.log(2));
823+
}
824+
825+
if (digits >= (DIG+2) - (binexp > 0 ? binexp / 4 : binexp / 3 - 1)) {
826+
return RubyFloat.newFloat(context.runtime, value);
827+
}
828+
if (digits < -(binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
829+
return dbl2num(context.runtime, (long) 0);
830+
}
831+
832+
if (digits > 0) {
833+
number = Math.floor(value * magnifier) / magnifier;
834+
}
835+
836+
if (digits < 0) {
837+
number = Math.floor(value * reducer) * magnifier;
838+
}
839+
840+
// Deal with big numbers
841+
if (number > Long.MAX_VALUE || number < Long.MIN_VALUE) {
842+
BigDecimal roundedNumber = new BigDecimal(Double.toString(number));
843+
return RubyBignum.newBignum(context.runtime, roundedNumber.toBigInteger());
844+
}
845+
846+
if (digits > 0) {
847+
return RubyFloat.newFloat(context.runtime, number);
848+
} else {
849+
return dbl2num(context.runtime, number);
850+
}
851+
}
807852

808853
/** flo_ceil
809854
*

0 commit comments

Comments
 (0)