Bug: Numeric#divmod calculates wrongly

Hi all!

I submitted the following bug report to
http://rubyforge.org/tracker/index.php?func=detail&aid=14540&
group_id=426&atid=1698

===================================================
There is a calculating bug in Numeric#divmod.
The divisor is reproducibly calculated wrongly for certain numbers.

See the following example to illustrate the problem:

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

z1=x.map {|a| a/y}
z2=x.map {|a| a.divmod(y).inspect}

a=[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PATCHLEVEL, RUBY_PLATFORM]
puts “ruby #{a[0]} (#{a[1]} patchlevel #{a[2].to_s}) [#{a[3]}]”
puts
print ‘x=’
p x
puts ‘y=1/12.0’
puts
puts “x/y\n—”
puts z1
puts
puts “x.divmod(y)\n-----------”
puts z2

Output:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]

As you can see the divisor 7 is wrongly displayed as 6, while the
modulos are correct.

Dirk T.

Am 8 Oct 2007 um 19:49 hat Dirk T. geschrieben:

Output:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

modulos are correct.

I tested Numeric#divmod on two more systems: SUSE 10.1 and Kubuntu
6.10.
They both run Ruby 1.8.4 and under both systems Numeric#divmod works
correctly!
So this bug was either introduced between Ruby 1.8.4 and 1.8.6 or it is
a problem depending on the OS.

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly…

Dirk T.

The testcode:

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

z1=x.map {|a| a/y}
z2=x.map {|a| a.divmod(y).inspect}

a=[RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM]
puts “ruby #{a[0]} (#{a[1]}) [#{a[2]}]”
puts
print ‘x=’
p x
puts ‘y=1/12.0’
puts
puts “x/y\n—”
puts z1
puts
puts “x.divmod(y)\n-----------”
puts z2

gives under
SUSE 10.1:

ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]

and Kubuntu 6.10:

ruby 1.8.4 (2005-12-24) [i586-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

Quoth Dirk T.:

[6, 0.0466666666666667]
They both run Ruby 1.8.4 and under both systems Numeric#divmod works

puts “ruby #{a[0]} (#{a[1]}) [#{a[2]}]”


[7.0, 0.0466666666666667]
y=1/12.0

[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]

I can’t confirm this (incorrect) behaviour.

0.58.divmod(1/12.0) # => [6.0, 0.08]
0.59.divmod(1/12.0) # => [7.0, 0.00666666666666667]

Ruby 1.8.6, Fedora 7.

Regards,

On Oct 14, 2007, at 24:18 , Dirk T. wrote:

nail down this massive bug. A computer should really calculate
correctly…

You may want to bring this up on ruby-core (maybe you have? There
was also a documentation patch for divmod, so I may be confused).

I get the same results for 1.8.6 and 1.9.0:

ruby 1.8.6 (2007-09-23) [powerpc-darwin8.10.0]
ruby 1.9.0 (2007-10-13) [powerpc-darwin8.10.0]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

On Oct 14, 10:18 am, “Dirk T.” [email protected] wrote:

Could somebody please confirm these findings? Especially with other
System and Ruby version combinations this would be really helpful to
nail down this massive bug. A computer should really calculate
correctly…

It’s correct on my system:

Debian lenny (testing)
Linux 2.6.21-2-686 #1 SMP Wed Jul 11 03:53:02 UTC 2007 i686 GNU/Linux

===================================================
ruby 1.8.6 (2007-06-07) [i486-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

Hi Eric!

Am 14 Oct 2007 um 17:03 hat Eric H. geschrieben:

You may want to bring this up on ruby-core (maybe you have? There
was also a documentation patch for divmod, so I may be confused).

I took your advice and send a mail to ruby-core.

The documentation patch, which is also from me, is for the
same method, but unrelated.

Thanks for testing.

Dirk

Dirk T. wrote:

[6, 0.0466666666666667]
They both run Ruby 1.8.4 and under both systems Numeric#divmod works

puts “ruby #{a[0]} (#{a[1]}) [#{a[2]}]”


[7.0, 0.0466666666666667]
y=1/12.0

[6.0, 0.08]
[7.0, 0.00666666666666667]
[7.0, 0.0466666666666667]
[7.0, 0.0766666666666667]
[8.0, 0.00333333333333341]

And on Gentoo Linux with ruby-1.8.6-p110-r1

$ ruby divmod-test.rb
ruby 1.8.6 (2007-09-24) [i686-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

[6, 0.08]
[7, 0.00666666666666667]
[7, 0.0466666666666667]
[7, 0.0766666666666667]
[8, 0.00333333333333341]

If it matters, the hardware is an Athlon Thunderbird and Ruby was
compiled from source, as most of Gentoo is, using gcc 4.2.1 and CFLAGS
“-march athlon-tbird -O2”. So … where is it broken again?

Dirk says “ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32] is
broken”
Dirk says “Kubuntu 6.10 and SuSE 10.1 using Ruby 1.8.4 works.”
Konrad says “two test cases worked on Fedora 7 with 1.8.6”
And I have it working on Ruby 1.8.6-p110 on Gentoo, compiled from source
with GCC 4.2.1
And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby
1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

And everybody – recompile ruby-1.8.6-p111 and see whether it works or
not. I say it’s a compiler problem at this point – maybe
over-aggressive floating-point optimization?? I doubt if the Ruby source
is broken.

Ubuntu 7.04
Linux imagine 2.6.20-16-generic #2 SMP Sun Sep 23 19:50:39 UTC 2007
i686 GNU/Linux

ruby 1.8.5 (2006-08-25) [i486-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

On Oct 14, 2007, at 03:44 , M. Edward (Ed) Borasky wrote:

And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby
1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

And everybody – recompile ruby-1.8.6-p111 and see whether it works
or not. I say it’s a compiler problem at this point – maybe over-
aggressive floating-point optimization?? I doubt if the Ruby source
is broken.

$ gcc -v
[…]
gcc version 4.0.1 (Apple Computer, Inc. build 5367)
$ ruby19 -v -rrbconfig -e ‘p Config::CONFIG[“CFLAGS”]’
ruby 1.9.0 (2007-10-13 patchlevel 0) [powerpc-darwin8.10.0]
“-g -O2 -pipe -fno-common”
$ ruby18 -v -rrbconfig -e ‘p Config::CONFIG[“CFLAGS”]’
ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0]
“-g -O2 -fno-schedule-insns2 -pipe -fno-common”

-fno-schedule-insns2 is to work around a GCC bug.

“Dirk T.” [email protected] writes:

[6, 0.0466666666666667]
The testcode:
print ‘x=’
p x
puts ‘y=1/12.0’
puts
puts “x/y\n—”
puts z1
puts
puts “x.divmod(y)\n-----------”
puts z2

Mine has the same problem running on an Athlon64 running on Debian’s
AMD64 version of Etch:

ruby 1.8.5 (2006-08-25) [x86_64-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

Eric H. wrote:

-fno-schedule-insns2 is to work around a GCC bug.


Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. – Syndicate Wars

As an aside, I downloaded “paranoia”
(http://netlib2.cs.utk.edu/paranoia/paranoia.c) and ELEFUNT
(http://www.math.utah.edu/pub/elefunt/elefunt.tar.gz) and ran them with
gcc 4.2.2 on my Athlon64. “paranoia” tests the basic floating point
hardware, and ELEFUNT tests the math libraries. I’m satisfied from those
tests that gcc is “doing the right thing”.

An exercise to the student would be to port these two test suites to
Ruby and see how well they do. But relative to the bug in question, I
ran the divmod.rb with all optimization turned off on the Athlon64 using
gcc 4.2.2 and it’s broken.

I took a look at “numeric.c” in Ruby 1.8.6-p111 to see what “divmod” is
actually doing. I was somewhat disturbed by the complicated path that it
takes to get its answer, and in thinking about the function itself, I
wonder what its usefulness is, given the willy-nilly way it flits
between integer and floating point arithmetic. And it’s essentially
doing “divmod” by doing a “div” and a “mod”, so there’s no efficiency
gain, unlike what you’d have in the integer case where you do a divide
and get the remainder for free, at least at the hardware level.

Does the original poster have an actual use case for “divmod” in its
present definition? I couldn’t think of any use for it in its present
definition. What I would find useful would be something that took a
Bignum dividend and divisor and returned the Bignum quotient and
remainder.

On 10/14/07, M. Edward (Ed) Borasky [email protected] wrote:

Eric H. wrote:

On Oct 14, 2007, at 03:44 , M. Edward (Ed) Borasky wrote:

And Eric has it broken on PowerPC Macs for both Ruby 1.8.6 and Ruby 1.9.0

Eric, what compiler made the Ruby interpreters on your PowerPC?

I don’t believe that anyone has brought up the intel Macs as yet, but
I get the same results as the OP on my MacBook:
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.2]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)

[6, 0.08]
[6, 0.00666666666666667]
[6, 0.0466666666666667]
[6, 0.0766666666666667]
[8, 0.00333333333333341]

I’ve already added this as a comment to the trac report.

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Just for the records: (Suse 10.2 , Ruby compiled with
with gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)

ruby 1.8.6 (2007-03-13) [x86_64-linux]

x=[0.58, 0.59, 0.63, 0.66, 0.67]
y=1/12.0

x/y

6.96
7.08
7.56
7.92
8.04

x.divmod(y)