@@ -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