Skip to content

Improve sqrt calculation #343

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

Closed
wants to merge 1 commit into from
Closed

Improve sqrt calculation #343

wants to merge 1 commit into from

Conversation

tompng
Copy link
Member

@tompng tompng commented Jun 5, 2025

There are two pull request with different approach to improve sqrt performance.
This one improves existing C-implemented newton's method.
Another one #319 is to use implement it in Ruby using Integer.sqrt.

Reduce iteration count of Newton's method

Speeds up in every scenario

# SQRT2
two = BigDecimal(2);

10000.times { two.sqrt(10) }
# processing time: 0.119187s → 0.015462s

10000.times { two.sqrt(32) }
# processing time: 0.026030s → 0.022965s

10000.times { two.sqrt(100) }
# processing time: 0.046182s → 0.029414s

10000.times { two.sqrt(1000) }
# processing time: 2.851953s → 0.623147s

two.sqrt(10000)
# processing time: 0.379927s → 0.018168s

# Fast path
BigDecimal(121).sqrt(10000)
# processing time: 0.020247s → 0.000196s

# Many digits
BigDecimal(2).div(7, 10000).sqrt(10000)
# processing time: 1.004524s → 0.017824s
# note: using Integer.sqrt is faster(0.002656s) in this case

// ε = 10**(-(digits+1)/2) is enough
// Required digits for y0 should be at least (digits+1)/2+1
// Adding some safe margin because it does not affect performance
VpSqrtNewton(f, r, x, y, 3 + digits / 2);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this to (digits+1) / 2 + 1 still passes this test.

10000.times do
  x=BigDecimal("#{1+rand}e#{rand(-100..100)}")
  prec=rand(10..1000)
  raise unless (x.sqrt(prec)/x.sqrt(prec+100)-1).exponent <= -prec-10
end

(Initially, it failed in some case because there was a bug in VpVtoD)

Reduce iteration count of Newton's method
@tompng
Copy link
Member Author

tompng commented Jul 18, 2025

Ruby implementation with the same approach is in #381

@tompng tompng closed this Jul 18, 2025
@tompng tompng deleted the faster_sqrt branch July 18, 2025 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant