Post Reply 
Programming Challenge: a classic trigonometry problem
03-20-2023, 02:25 AM (This post was last modified: 03-21-2023 09:19 PM by Albert Chan.)
Post: #40
RE: Programming Challenge: a classic trigonometry problem
We could solve for s = (v/c), then v = c*s, then y = b^2 - v^2

c/u + c/v = c/c

±1/√(k+s²) + 1/s = 1       // ± to cover extend-line crossed solution
±s/√(k+s²) + 1 = s          // scaled to make it more linear     
|s-1| - s/√(k+s²) = 0       // formula V shaped, very straight for s≥1    (*)

This setup does not have secant's root overshoot problem.
It will not be hit with square root of negative number.

q ≤ -1      → s = (v/c) = (1+1/q) = 0 .. 1
q ≥ 1       → s = (v/c) = (1+1/q) = 1 .. 2

We can simply use guess [1±0.3, 1±0.7], instead of [(1-c/±a)^-1, (1+b/±a)]

Formula is concave up (2nd derivative > 0), it will not accidentally solve the "wrong" root.

CAS> factor(diff(abs(s-1) - s/sqrt(k+s*s), s, 2))      → \(\displaystyle \frac{3\,k\,s}{(k+s^2)^{5 \over 2}}\)      (**)

lua> a,b,c = 40,30,15
lua> k = (a+b)*(a-b)/(c*c)
lua> S1 = fn's: abs(s-1) - s/sqrt(k+s*s)'
lua> eps = -1e-9 -- swap worse point as first
lua> S = require'solver'
lua> S.secant(S1, 1.3, 1.7, eps, true)
1.3
1.7
1.6919260149527686
1.692328847882308
1.692329202531022
1.6923292025145777
1.6923292025145775
lua> v = c * _
lua> y = (b+v) * (b-v)
lua> y, sqrt(y) -- ladders crossed width
255.6049208211842      15.98764900856859

lua> S.secant(S1, 0.3, 0.7, eps, true)
0.3
0.7
0.6541746293109201
0.6528669490148099
0.6528724368426823
0.6528724362121412
0.6528724362121409
lua> v = c * _
lua> y = (b+v) * (b-v)
lua> y, sqrt(y) -- extended line crossed width
804.0954559577455      28.356576943590095

(*) s ≤ 1 side is not as straight, especially around s ≈ 0.
To reduce iterations, for s < 1 root with tiny k, use 3 point quadratic fit solver.

(**) there is a discontinuity at s=1. It should have another term, +abs(s-1)''
For our purpose of checking concave behavior, this subtlety can be ignored.

(03-17-2023 03:12 PM)Albert Chan Wrote:  lua> R = fn'r,s: s=r/(1+r); r*s - k/(r+s)'

I named s = (v/c) because I had used it previously, solving for r = -(1+q)

s = r/(1+r) = -(1+q)/(-q) = 1+1/q = (v/c)

We can rephrase R of r, in terms of s instead.
R guesses = cbrt(k/2) .. sqrt(k+1), can be carried over.

lua> S2 = fn's,r: r=s/(1-s); r*s - k/(r+s)'

S2 can accidentally shoot to "wrong" root, thus not recommended.
Unless with good guesses ... but S1 can use them too!
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: Programming Challenge: a classic trigonometry problem - Albert Chan - 03-20-2023 02:25 AM



User(s) browsing this thread: 1 Guest(s)