Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accurate (as possible) fdiv for Fixnum and Bignum #1508

Closed
wants to merge 3 commits into from

Conversation

metanest
Copy link

This is an accurate (as possible) fdiv implementation for Fixnum and Bignum.

@nobu
Copy link
Member

nobu commented Jan 2, 2017

Do you have an example that the result changes, or a test case in other words?

@metanest
Copy link
Author

metanest commented Jan 2, 2017

A Fixnum example is,

  $ ruby24 --disable=gems -e 'print "%a\n" % [2319276427521816828.fdiv(3325853508004318597)]'
  0x1.650ac352d9ccp-1
  $ ./miniruby -v --disable=gems -e 'print "%a\n" % [2319276427521816828.fdiv(3325853508004318597)]'
  ruby 2.5.0dev (2016-12-30) [x86_64-freebsd10.3]  <== (my patched version)
  0x1.650ac352d9cc1p-1

(due to 2319276427521816828/3325853508004318597r is irreducible, this pattern didn't affect by reducing )

@nobu
Copy link
Member

nobu commented Jan 3, 2017

Current trunk is:

$ ruby -v -e 'x=2319276427521816828; y=3325853508004318597; z=x.fdiv(y)*y; p z, z-x'
ruby 2.5.0dev (2017-01-01 trunk 57245) [universal.x86_64-darwin15]
2.3192764275218166e+18
0.0

but yours is:

$ ./ruby -e 'x=2319276427521816828; y=3325853508004318597; z=x.fdiv(y)*y; p z, z-x'
2.319276427521817e+18
512.0

@metanest
Copy link
Author

metanest commented Jan 3, 2017

HMM, but it is correctly rounded value as below. I'm thinking more better demonstration...

$ cat sample.rb
x=2319276427521816828
y=3325853508004318597
print "%a\n" % [2319276427521816828.fdiv(y)]
print "%x\n" % [(x<<57)/y]
$ ./miniruby sample.rb (this miniruby is my version)
0x1.650ac352d9cc1p-1
1650ac352d9cc0a

@metanest
Copy link
Author

I've found more demonstrable edge case.

$ cat fdiv_edgecase.rb
#
require 'bigdecimal'

strx = '66767141308812624791109361755796'
stry = '17022200380664065'

bdx = BigDecimal(strx)
bdy = BigDecimal(stry)
print "#{(bdx/bdy).to_s('f')}\n"

x = strx.to_i
y = stry.to_i
print "%f\n" % [x.fdiv(y)]

$ ../ruby-trunk -v fdiv_edgecase.rb
ruby 2.5.0dev (2017-01-11 trunk 57302) [x86_64-freebsd10.3]
3922356676323412.249999999999999985313297082086923792468241814443649323
3922356676323412.500000

$ ../ruby fdiv_edgecase.rb # (mine)
3922356676323412.249999999999999985313297082086923792468241814443649323
3922356676323412.000000

How is this ?

@nobu
Copy link
Member

nobu commented Jan 29, 2017

Also in that case, x.fdiv(y)*y will not equal to x while currently does.
Maybe related to denormalization?

@k0kubun k0kubun changed the base branch from trunk to master August 15, 2019 17:37
@k0kubun
Copy link
Member

k0kubun commented Aug 17, 2019

It seems to have a conflict now. Could you rebase this from master?

@k0kubun
Copy link
Member

k0kubun commented Aug 19, 2019

Let me close this as it has not been updated for a while. Please reopen this after resolving conflicts. Thanks.

@k0kubun k0kubun closed this Aug 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants