HP Forums

Full Version: Arc SOHCAHTOA method
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Inspired from pi day thread, I discovered a great mnemonic for arc-trig function

[Image: xsohcahtoa.png.pagespeed.ic.4syp_llbS1.png]

asinq(x) = asin(√x)
acosq(x) = acos(√x)
atanq(x) = atan(Vx)

Above definition remove the annoying square roots.
Example, from asin(x) = acos(V(1-x²)), we have:

asinq(x) = acosq(1-x) = atanq(x/(1-x))                → Triangle O, A, H = x, 1-x, 1

asinq and acosq now appeared complementary, O/H + A/H = 1, or O+A = H

Or, relative to atanq(x):

asinq(x/(1+x)) = acosq(1/(1+x)) = atanq(x)       → Triangle O, A, H = x, 1, 1+x

We can use the relation to build truly compact code. Smile
For example, to get sqrt(x^2/(1+x^2)), we only need 2 keys: ATAN SIN
To derive "half-angle" formula, we solve for relation, y from x

acos(x) = 2 * acos(y)            (*)

Let θ = acos(y), and take cos() both side:

x = cos(2θ) = 2*cos(θ)^2 - 1 = 2*y^2 - 1
y = sqrt((1+x)/2)

acos(x) = 2 * acos(sqrt((1+x)/2))
acosq(x) = 2 * acosq((1+sqrt(x))/2)

acosq(x) = 2 * asinq(1-(1+sqrt(x))/2) = 2 * asinq((1-sqrt(x))/2)
asinq(x) = acosq(1-x) = 2 * asinq((1-sqrt(1-x))/2)

Flip conjugate to the denominator for better accuracy:

asinq(x) = 2 * asinq(x/2/(1+sqrt(1-x)))

atanq(x)
= acosq(1/(1+x))
= 2 * acosq((1+1/sqrt(1+x))/2)
= 2 * acosq((sqrt(1+x)+1) / (2*sqrt(1+x)))     // CAH, A = sqrt(1+x)+1, H = 2*sqrt(1+x)
= 2 * atanq((sqrt(1+x)-1) / (sqrt(1+x)+1))      // TOA, O = H-A = sqrt(1+x)-1

Again, flip conjugate to the denominator for better accuracy:

atanq(x) = 2 * atanq(x / (sqrt(1+x)+1)^2)

This matched atan() half-angle formula
(05-31-2021 09:51 PM)Albert Chan Wrote: [ -> ]\(\displaystyle\arctan(x) = 2\arctan\left( {x \over \sqrt{1+x^2}+1} \right)\)

(*) we could get asinq() first too, with sin(2θ) = 2 sin(θ) cos(θ).
But that involve solving quadratic, and pick the right root.
(03-31-2022 09:50 PM)Albert Chan Wrote: [ -> ]Inspired from pi day thread, I discovered a great mnemonic for arc-trig function

[Image: xsohcahtoa.png.pagespeed.ic.4syp_llbS1.png]

We measure the height of trees using SOHCAHTOA. We know how far we are from the tree (adjacent) and the angle to sight the top of the tree (θ) so we calculate the height of the tree (opposite) using

tan(angle to top of tree) * distance to tree = height of tree.
(03-31-2022 11:07 PM)Albert Chan Wrote: [ -> ]acos(x) = 2 * acos(sqrt((1+x)/2))
acosq(x) = 2 * acosq((1+sqrt(x))/2)

Although relation is true, RHS argument is bigger.
Perhaps it is better to flip the sides, with reduced argument, then get acos from asin

acos(x) = 1/2 * acos(2*x^2-1) = 1/2 * (pi/2 - asin(2*x^2-1))
acosq(x) = pi/4 - asin(2*x-1)/2

asinq(x) = acosq(1-x) = pi/4 - asin(1-2*x)/2

We can reduce argument of asinq(x) to 1/4 or less, before using half-angle formula.
Code:
function asinq(x)   -- asin(sqrt(x)), x = 0 to 1
    if x > 1/2  then return pi/2 - asinq(1-x) end
    if x > 1/4  then return pi/4 - asinq((1-2*x)^2)/2 end
    if x > 4e-4 then return 2 * asinq(0.5*x/(sqrt(1-x)+1)) end
    return sqrt(x) * (1+x/6*(1+x*9/20/(1-x*25/42)))
end

The first reduction, x = (1/2,1], (x → 1-x), is cheap, and exact, see Sterbenz lemma
Second reduction, x = (1/4,1/2], (x → (1-2*x)^2), is cheap, and correctly rounded.

Note that second reduction relation is a parabola.
At some point, there is no argument reduction (for x=1/4, (1-2*x)^2 = 1/4)

We can solve for break-even point, between 2nd reduction and half-angle formula
(Below break-even point, half-angle formula reduce argument more)

CAS> normal(solve((1-2*x)^2 = x/2/(1+sqrt(1-x)), x))      → [(-√5+5)/8, 3/4]

With domain of (1/4,1/2], break-even at x = (-√5+5)/8 = 1-(ϕ/2)^2 ≈ 0.3455

asinq(1-(ϕ/2)^2) = acosq((ϕ/2)^2) = acos(ϕ/2) = pi/5, see Golden Triangle
For fun, I try the same idea to arc hyperbolics.

asinhq(x) = asinh(√x) = ln(√(x) + √(x+1))
acoshq(x) = acosh(√x) = ln(√(x) + √(x-1))
atanhq(x) = atanh(√x) = 1/2 * ln((1+√x) / (1-√x))

asinhq(x) = acoshq(x+1)      // O = x, A = 1+x, H = 1

This suggested for hyperbolics, A = O + H
TOA suggested asinhq(x) = atanhq(x/(1+x))

Lets proof this by getting tanh(y = asinh(sqrt(x)))
To simplify away the exponential, let z = e^y

tanh(y) = (z-1/z) / (z+1/z) = (z^2-1) / (z^2+1)

z = √(x) + √(x+1)      // Goal, remove all square roots.
z - √(x) = √(x+1)
z^2 - 2*√(x)*z + x = x + 1
(z^2 - 1) = 2*√(x)*z
(z^2-1)^2 = 4*x*z^2

If atanhq() expression is correct, we should have (z^2-1)/(z^2+1) = √(x/(1+x))
Or, (z^2-1)^2 * (1+x) = (z^2+1)^2 * x

(z^2-1)^2 * (1+x) - (z^2+1)^2 * x
= 1 - 2*z^2 + z^4 - 4*x*z^2
= (z^2-1)^2 - 4*x*z^2
= 0      QED

Relative to atanhq(x), we have O = x, A = 1, H = A-O = 1-x

                        SOH                        CAH

atanhq(x) = asinhq(x/(1-x)) = acoshq(1/(1-x))


Update: I was being stupid, and should prove with more familiar sinh/cosh
Or, simply work with sin/cos, then flip sign using Osborn's rule

y = asinhq(x)  → sinh(y)² = x  → cosh(y)² = 1+x  → tanh(y)² = x/(1+x)  → y = atanhq(x/(1+x))
For arc hyperbolic half-angle formulas, we can use cosh(2x) = 2 cosh(x)^2 - 1, and SOHCAHTOA rules.

acoshq(x) = 2*acoshq((sqrt(x)+1)/2) = 2*asinhq((sqrt(x)-1)/2)

asinhq(x) = acoshq(1+x) = 2*asinhq((sqrt(1+x)-1)/2) = 2*asinhq(x/2/(sqrt(1+x)+1))

atanhq(x)
= acoshq(1/(1-x))
= 2*acoshq((1/sqrt(1-x)+1)/2)
= 2*acoshq((1+sqrt(1-x)) / (2*sqrt(1-x)))      // CAH, A = 1+sqrt(1-x), H = 2*sqrt(1-x)
= 2*atanhq((1-sqrt(1-x)) / (1+sqrt(1-x)))       // TOA, O = A-H = 1-sqrt(1-x)
= 2*atanhq(x/(1+sqrt(1-x))^2)

Code:
function asinhq(x)
    if x > 4e-4 then return 2 * asinhq(0.5*x/(sqrt(1+x)+1)) end
    return sqrt(x) * (1-x/6*(1-x*9/20/(1+x*25/42)))
end

function acoshq(x) return asinhq(x-1) end
function atanhq(x) return asinhq(x/(1-x)) end
(04-02-2022 12:10 AM)Albert Chan Wrote: [ -> ]TOA suggested asinhq(x) = atanhq(x/(1+x))

Lets proof this by getting tanh(y = asinh(sqrt(x))) ...

Here is another way, by comparing slopes.

XCas> s1 := factor(diff(asinh(sqrt(x))))                  → 1/(sqrt(x)*sqrt(1+x)*2)
XCas> s2 := factor(diff(atanh(sqrt(x)/sqrt(1+x))))  → 1/(sqrt(x)*sqrt(1+x)*2)

Slope matches. Now check domain.
This is important, see blackpenredpen video, THE CONFUSING DERIVATIVES

Domain: for x = 0 to inf, we have x/(1+x) = 1 - 1/(1+x) = 0 to 1. Domain OK

asinhq(x = 0) = asinh(0) = 0
atanhq(0/(1+0)) = atanh(0) = 0

2 sides slopes have same anti-derivative, and matching constant of integration.      QED

---

Even simpler, use arc-trig identity, asinq(x) = atanq(x/(1-x))

asinhq(x) = asinq(-x) / i = atanq(-x/(1+x)) / i = atanhq(x/(1+x))      QED

Update:

Just realized OP arc-trig identity was stated without proof, but its is trivial.
With a right triangle, O² + A² = H² --> O=√x, H=1, A=√(1-x)

θ = asin(√x) = acos(√(1-x)) = atan(√(x/(1-x)))      QED

Trivia: acosq ↔ acoshq formulas, argument have same pattern.

acosq(x) = asinq(1-x) = asinhq(x-1)/i = acoshq(x)/i

--> acos(z) = acosh(z)/i = pi/2 - asin(z)
I need to simplify sum of atan()'s today.
Amazingly, simplified result is *very* compact, without even square roots !

See if you can simplify S. Good luck !

S = (
-32*atan(-1 + sqrt(6))
+32*atan(-3 + sqrt(6))
-6*atan(-1 + sqrt(6)/2)
+6*atan(sqrt(6)/2)
-6*atan( 1/2+ sqrt(5)/2)
+6*atan(-1/2+ sqrt(5)/2)
)
When I was taught the SOH CAH TOA in the early 1970's, we were taught to remember it with the mnemonic phrase, "Some Old Hippie...Caught Another Hippie...Tripping On Acid."

Seems kind of silly now, and I'm sure there are newer, better ways to remember....but it was a relevant phrase at the time and I've never forgotten it, so it works.

Smile
mike
atan(x) returns a range of ± pi/2, with sign of x
Sum or difference of 2 atan()'s might reach range of ± pi
It may be better to use atan2(y,x), then reduced down to atan()

θ = atan(x) ± atan(y)
   = arg((1+x*i) * (1±y*i))
   = arg(((1∓x*y) + (x±y)*i)
   = atan2((x±y) , (1∓x*y))

This reduced θ's 2 atan() to atan2(), which easily converted down to atan()

If (1∓x*y) part is nonnegative, θ = atan(tan(θ))
In other words, atan/tan combination "round-trip"

If not, return (θ - sign(θ)*pi) instead. (this compensated atan() limited range)

atan(3) + atan(7)
= atan2(3+7, 1-3*7)
= atan2(10, -20)         // 2nd argument negative.
= atan(-1/2) + pi        // make sure adjusted result within ± pi
≈ 2.678

We are now ready to simplify S
Code:
S = (
-32*atan(-1 + √6)       --\
+32*atan(-3 + √6)       --/ 32*atan2(-2, 10-4*√6) = -32*atan(5+2*√6) = 32*atan(5-2*√6) - 16*pi
-6*atan( -1 + √6/2)     --\
+6*atan(      √6/2)     --/ 6*atan2(1, (5-√6)/2) = 6*atan((10+2*√6)/19)
-6*atan( 1/2+ √5/2)     --\                            
+6*atan(-1/2+ √5/2)     --/ 6*atan2(-1,2) = -6*atan(1/2)
)

tan(2θ) = 2*tan(θ) / (1-tan(θ)^2)
2θ = atan2(2*tan(θ), 1-tan(θ)^2)
2θ = atan2(2, 1/tan(θ) - tan(θ))      // if tan(θ) > 0

Code:
S = (
-16*pi
+16*(2*atan(5-2*√6))    =  16*atan2(2, (5+2*√6) - (5-2*√6)) = 16*atan(1/√24)
+6*atan((10+2*√6)/19)   --\ 
-6*atan(1/2)            --/ 6*atan2((1+4*√6)/38, (24+√6)/19) = 6*atan(1/√24)
)

S = 22*atan(1/√24) - 16*pi
   = 22*atanq(1/24) - 16*pi
   = 22*asinq(1/25) - 16*pi           // SOH, O=1, A=24, H = O+A = 25

S = 22*asin(1/5) - 16*pi          // fully simplified Smile
Reference URL's