Permalink
Browse files

Fix JRUBY-5941: ZeroDivisionError with DateTime strftime("%S")

* RubyRational did not override getDoubleValue from RubyNumeric, and always returned 0.
  • Loading branch information...
1 parent e293abf commit 422b6c7e39a4611485bfbbfd65a6a0f08aeee54f @headius headius committed Aug 17, 2011
@@ -333,6 +333,10 @@ public static IRubyObject newRationalConvert(ThreadContext context, IRubyObject
return convert(context, context.getRuntime().getRational(), x, y);
}
+ public static RubyRational newRational(Ruby runtime, long x, long y) {
+ return new RubyRational(runtime, runtime.getRational(), runtime.newFixnum(x), runtime.newFixnum(y));
+ }
+
@Deprecated
public static IRubyObject convert(ThreadContext context, IRubyObject clazz, IRubyObject[]args) {
switch (args.length) {
@@ -856,8 +860,17 @@ public IRubyObject op_round(ThreadContext context, IRubyObject n) {
private static long ML = (long)(Math.log(Double.MAX_VALUE) / Math.log(2.0) - 1);
@JRubyMethod(name = "to_f")
public IRubyObject to_f(ThreadContext context) {
- Ruby runtime = context.getRuntime();
- if (f_zero_p(context, num)) return runtime.newFloat(0);
+ return context.runtime.newFloat(getDoubleValue(context));
+ }
+
+ @Override
+ public double getDoubleValue() {
+ return getDoubleValue(getRuntime().getCurrentContext());
+ }
+
+ public double getDoubleValue(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ if (f_zero_p(context, num)) return 0;
IRubyObject myNum = this.num;
IRubyObject myDen = this.den;
@@ -887,7 +900,7 @@ public IRubyObject to_f(ThreadContext context) {
if (e > 1023 || e < -1022) {
runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
- return runtime.newFloat(e > 0 ? Double.MAX_VALUE : 0);
+ return e > 0 ? Double.MAX_VALUE : 0;
}
double f = RubyNumeric.num2dbl(myNum) / RubyNumeric.num2dbl(myDen);
@@ -900,7 +913,7 @@ public IRubyObject to_f(ThreadContext context) {
runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
}
- return runtime.newFloat(f);
+ return f;
}
/** nurat_to_r
@@ -88,6 +88,7 @@ public static Test suite() throws Throwable {
suite.addTestSuite(org.jruby.runtime.load.LoadServiceResourceInputStreamTest.class);
suite.addTestSuite(TestRubyString.class);
suite.addTestSuite(TestRubyNKF.class);
+ suite.addTestSuite(TestRubyRational.class);
return suite;
}
}
@@ -0,0 +1,61 @@
+/***** BEGIN LICENSE BLOCK *****
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Common Public
+ * License Version 1.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the CPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the CPL, the GPL or the LGPL.
+ ***** END LICENSE BLOCK *****/
+package org.jruby.test;
+
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+import org.jruby.CompatVersion;
+
+import org.jruby.Ruby;
+import org.jruby.RubyFloat;
+import org.jruby.RubyInstanceConfig;
+import org.jruby.RubyRational;
+import org.jruby.RubySymbol;
+
+public class TestRubyRational extends TestCase {
+ private Ruby runtime;
+
+ public TestRubyRational(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ runtime = Ruby.newInstance(new RubyInstanceConfig() {
+ {
+ setCompatVersion(CompatVersion.RUBY1_9);
+ }
+ });
+ }
+
+ // JRUBY-5941
+ public void testRationalToDouble() throws Exception {
+ RubyRational rational = RubyRational.newRational(runtime, 1, 1000);
+ double toDouble = rational.getDoubleValue();
+ double expected = ((RubyFloat)rational.to_f(runtime.getCurrentContext())).getDoubleValue();
+ assertEquals(expected, toDouble);
+ }
+}

0 comments on commit 422b6c7

Please sign in to comment.