[#79440] [Ruby trunk Bug#13188] Reinitialize Ruby VM. — shyouhei@...
Issue #13188 has been updated by Shyouhei Urabe.
6 messages
2017/02/06
[#79441] Re: [Ruby trunk Bug#13188] Reinitialize Ruby VM.
— SASADA Koichi <ko1@...>
2017/02/06
On 2017/02/06 10:10, shyouhei@ruby-lang.org wrote:
[#79532] Immutable Strings vs Symbols — Daniel Ferreira <subtileos@...>
Hi,
15 messages
2017/02/15
[#79541] Re: Immutable Strings vs Symbols
— Rodrigo Rosenfeld Rosas <rr.rosas@...>
2017/02/15
Em 15-02-2017 05:05, Daniel Ferreira escreveu:
[#79543] Re: Immutable Strings vs Symbols
— Daniel Ferreira <subtileos@...>
2017/02/16
Hi Rodrigo,
[#79560] Re: Immutable Strings vs Symbols
— Rodrigo Rosenfeld Rosas <rr.rosas@...>
2017/02/16
Em 15-02-2017 22:39, Daniel Ferreira escreveu:
[ruby-core:79718] [Ruby trunk Feature#13219] bug in Math.sqrt(n).to_i, to compute integer squareroot, new word to accurately fix it
From:
jzakiya@...
Date:
2017-02-23 06:31:49 UTC
List:
ruby-core #79718
Issue #13219 has been updated by Jabari Zakiya.
So the clear winner, and new champeen is...**newtons_fast**, at least for squareroots.
Just goes to show, don't f**k with Newton!
```
class Integer
def irootn(n)
return nil if self < 0 && n.even?
raise "root n is < 2 or not an Integer" unless n.is_a?(Integer) && n > 1
num = self.abs
bits_shift = (num.bit_length)/n + 2
root, bitn_mask = 0, (1 << bits_shift)
until (bitn_mask >>= 1) == 0
root |= bitn_mask
root ^= bitn_mask if root**n > num
end
root *= (self < 0 ? -1 : 1)
end
def iroot2; irootn(2) end
end
def isqrt1(n)
r = 0
x = 1 << ((n.bit_length >> 1 ) << 1)
until x == 0
t = r | x
r >>= 1
(n -= t; r |= x) if n >= t
x >>= 2
end
r
end
def newtons_fast(n) # Newton's method with √n < initial_x <= 2*√n
raise if n<0
return n if n<=1
x = 1<<((n.bit_length+1)/2)
y = (x + n/x)/2
while y < x
x = y
y = (x + n/x)/2
end
x
end
Benchmark.ips do |x|
exp = 400; n = 10**exp
puts "integer squareroot tests for n = 10**#{exp}"
x.report("iroot2" ) { n.iroot2 }
x.report("isqrt1(n)" ) { isqrt1(n) }
x.report("newtons_fast(n)") { newtons_fast(n)
x.compare!
end
```
```
2.4.0 :138 > load 'irootstest.rb'
integer squareroot tests for n = 10**5
Warming up --------------------------------------
iroot2 85.000k i/100ms
isqrt1(n) 87.646k i/100ms
newtons_fast(n) 191.796k i/100ms
Calculating -------------------------------------
iroot2 1.014M (± 2.9%) i/s - 5.100M in 5.031392s
isqrt1(n) 1.049M (± 3.0%) i/s - 5.259M in 5.018645s
newtons_fast(n) 2.846M (± 4.6%) i/s - 14.385M in 5.066760s
Comparison:
newtons_fast(n): 2845709.1 i/s
isqrt1(n): 1048817.1 i/s - 2.71x slower
iroot2: 1014498.5 i/s - 2.81x slower
=> true
2.4.0 :139 > load 'irootstest.rb'
integer squareroot tests for n = 10**50
Warming up --------------------------------------
iroot2 4.077k i/100ms
isqrt1(n) 3.992k i/100ms
newtons_fast(n) 24.377k i/100ms
Calculating -------------------------------------
iroot2 41.189k (± 6.1%) i/s - 207.927k in 5.071463s
isqrt1(n) 40.293k (± 3.4%) i/s - 203.592k in 5.058807s
newtons_fast(n) 260.960k (± 3.4%) i/s - 1.316M in 5.050191s
Comparison:
newtons_fast(n): 260959.7 i/s
iroot2: 41188.8 i/s - 6.34x slower
isqrt1(n): 40292.7 i/s - 6.48x slower
=> true
2.4.0 :140 > load 'irootstest.rb'
integer squareroot tests for n = 10**500
Warming up --------------------------------------
iroot2 74.000 i/100ms
isqrt1(n) 127.000 i/100ms
newtons_fast(n) 3.775k i/100ms
Calculating -------------------------------------
iroot2 741.359 (± 4.6%) i/s - 3.700k in 5.001895s
isqrt1(n) 1.258k (± 7.0%) i/s - 6.350k in 5.077988s
newtons_fast(n) 37.762k (± 4.5%) i/s - 188.750k in 5.008756s
Comparison:
newtons_fast(n): 37761.5 i/s
isqrt1(n): 1257.6 i/s - 30.03x slower
iroot2: 741.4 i/s - 50.94x slower
=> true
2.4.0 :141 > load 'irootstest.rb'
integer squareroot tests for n = 10**5000
Warming up --------------------------------------
iroot2 1.000 i/100ms
isqrt1(n) 5.000 i/100ms
newtons_fast(n) 340.000 i/100ms
Calculating -------------------------------------
iroot2 11.196 (± 8.9%) i/s - 56.000 in 5.013699s
isqrt1(n) 53.056 (± 3.8%) i/s - 265.000 in 5.002572s
newtons_fast(n) 3.402k (± 3.1%) i/s - 17.000k in 5.002400s
Comparison:
newtons_fast(n): 3401.9 i/s
isqrt1(n): 53.1 i/s - 64.12x slower
iroot2: 11.2 i/s - 303.85x slower
```
----------------------------------------
Feature #13219: bug in Math.sqrt(n).to_i, to compute integer squareroot, new word to accurately fix it
https://bugs.ruby-lang.org/issues/13219#change-63139
* Author: Jabari Zakiya
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
In doing a math application using **Math.sqrt(n).to_i** to compute integer squareroots
of integers I started noticing errors for numbers > 10**28.
I coded an algorithm that accurately computes the integer squareroot for arbirary sized numbers
but its significantly slower than the math library written in C.
Thus, I request a new method **Math.intsqrt(n)** be created, that is coded in C and part of the
core library, that will compute the integer squareroots of integers accurately and fast.
Here is working highlevel code to accurately compute the integer squareroot.
```
def intsqrt(n)
bits_shift = (n.to_s(2).size)/2 + 1
bitn_mask = root = 1 << bits_shift
while true
root ^= bitn_mask if (root * root) > n
bitn_mask >>= 1
return root if bitn_mask == 0
root |= bitn_mask
end
end
def intsqrt1(n)
return n if n | 1 == 1 # if n is 0 or 1
bits_shift = (Math.log2(n).ceil)/2 + 1
bitn_mask = root = 1 << bits_shift
while true
root ^= bitn_mask if (root * root) > n
bitn_mask >>= 1
return root if bitn_mask == 0
root |= bitn_mask
end
end
require "benchmark/ips"
Benchmark.ips do |x|
n = 10**40
puts "integer squareroot tests for n = #{n}"
x.report("intsqrt(n)" ) { intsqrt(n) }
x.report("intsqrt1(n)" ) { intsqrt1(n) }
x.report("Math.sqrt(n).to_i") { Math.sqrt(n).to_i }
x.compare!
end
```
Here's why it needs to be done in C.
```
2.4.0 :178 > load 'intsqrttest.rb'
integer squareroot tests for n = 10000000000000000000000000000000000000000
Warming up --------------------------------------
intsqrt(n) 5.318k i/100ms
intsqrt1(n) 5.445k i/100ms
Math.sqrt(n).to_i 268.281k i/100ms
Calculating -------------------------------------
intsqrt(n) 54.219k (± 5.5%) i/s - 271.218k in 5.017552s
intsqrt1(n) 55.872k (± 5.4%) i/s - 283.140k in 5.082953s
Math.sqrt(n).to_i 5.278M (± 6.1%) i/s - 26.560M in 5.050707s
Comparison:
Math.sqrt(n).to_i: 5278477.8 i/s
intsqrt1(n): 55871.7 i/s - 94.47x slower
intsqrt(n): 54219.4 i/s - 97.35x slower
=> true
2.4.0 :179 >
```
Here are examples of math errors using **Math.sqrt(n).to_i** run on Ruby-2.4.0.
```
2.4.0 :101 > n = 10**27; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
1000000000000000000000000000
31622776601683
999999999999949826038432489
31622776601683
999999999999949826038432489
31622776601683
999999999999949826038432489
=> nil
2.4.0 :102 > n = 10**28; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
10000000000000000000000000000
100000000000000
10000000000000000000000000000
100000000000000
10000000000000000000000000000
100000000000000
10000000000000000000000000000
=> nil
2.4.0 :103 > n = 10**29; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
100000000000000000000000000000
316227766016837
99999999999999409792567484569
316227766016837
99999999999999409792567484569
316227766016837
99999999999999409792567484569
=> nil
2.4.0 :104 > n = 10**30; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
1000000000000000000000000000000
1000000000000000
1000000000000000000000000000000
1000000000000000
1000000000000000000000000000000
1000000000000000
1000000000000000000000000000000
=> nil
2.4.0 :105 > n = 10**31; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
10000000000000000000000000000000
3162277660168379
9999999999999997900254631487641
3162277660168379
9999999999999997900254631487641
3162277660168379
9999999999999997900254631487641
=> nil
2.4.0 :106 > n = 10**32; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
100000000000000000000000000000000
10000000000000000
100000000000000000000000000000000
10000000000000000
100000000000000000000000000000000
10000000000000000
100000000000000000000000000000000
=> nil
2.4.0 :107 > n = 10**33; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
1000000000000000000000000000000000
31622776601683793
999999999999999979762122758866849
31622776601683793
999999999999999979762122758866849
31622776601683792
999999999999999916516569555499264
=> nil
2.4.0 :108 > n = 10**34; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
10000000000000000000000000000000000
100000000000000000
10000000000000000000000000000000000
100000000000000000
10000000000000000000000000000000000
100000000000000000
10000000000000000000000000000000000
=> nil
2.4.0 :109 > n = 10**35; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
100000000000000000000000000000000000
316227766016837933
99999999999999999873578871987712489
316227766016837933
99999999999999999873578871987712489
316227766016837952
100000000000000011890233980627554304
=> nil
2.4.0 :110 > n = 10**36; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
1000000000000000000000000000000000000
1000000000000000000
1000000000000000000000000000000000000
1000000000000000000
1000000000000000000000000000000000000
1000000000000000000
1000000000000000000000000000000000000
=> nil
2.4.0 :111 > n = 10**37; puts n, (a = intsqrt(n)), a*a, (b = intsqrt1(n)), b*b, (c = Math.sqrt(n).to_i), c*c
10000000000000000000000000000000000000
3162277660168379331
9999999999999999993682442519108007561
3162277660168379331
9999999999999999993682442519108007561
3162277660168379392
10000000000000000379480317059650289664
=> nil
2.4.0 :112 >
```
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>