Inverse trig functions and atan2

This commit is contained in:
2025-09-18 11:00:00 +10:00
parent 6ad56ccc5f
commit b625bc6244
4 changed files with 152 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*test.grnd

View File

@@ -158,6 +158,140 @@ fun -double !tan -double &in
return $store
endfun
fun -double !asin -double &in
pusharg $in
call !abs &store
greater $store 1 &store
if $store %error
# asin(a) is the root of sin(x)-a=0, -pi/2 <= x <= pi/2
# Using Newton's Method: x_k+1 = x_k - (sin(x_k)-a)/cos(x_k)
stod "0" &ans
@loop
pusharg $ans
call !sin &sin
subtract $sin $in &sin
pusharg $ans
call !cos &cos
divide $sin $cos &store
subtract $ans $store &ans
equal $store 0 &store
if $store %return
jump %loop
@return
return $ans
@error
error "Cannot find sin of a double with magnetude greater than 1" "mathError"
endfun
fun -double !acos -double &in
# asin(x) + acos(x) = pi/2
pusharg $in
call !asin &store
call !pi &pi
divide $pi 2 &pi
subtract $pi $store &store
return $store
endfun
fun -double !atan -double &in
# atan(a) is the root of tan(x)-a=0, -pi/2 <= x <= pi/2
# Using Newton's Method: x_k+1 = x_k - (tan(x_k)-a)/sec^2(x_k) = x_k - (tan(x_k)-a)cos^2(x_k)
stod "0" &ans
@loop
pusharg $ans
call !tan &num
subtract $num $in &num
pusharg $ans
call !cos &dom
multiply $dom $dom &dom
multiply $num $dom &store
subtract $ans $store &ans
pusharg $store
call !abs &store
lesser $store 0.000000000001 &store
if $store %return
jump %loop
@return
# Make answer in range [-pi/2, pi/2]
call !pi &pi
pusharg $ans
pusharg $pi
call !mod &ans
divide $pi 2 &pi
greater $ans $pi &store
if $store %negans
return $ans
@negans
call !pi &pi
subtract $ans $pi &ans
return $ans
endfun
fun -double !atan2 -double &y -double &x
call !pi &pi
divide $pi 2 &pi/2
# catch "mathError" &divideByZero
set &divideByZero true
divide $y $x &ratio
if $divideByZero %continue
jump %error
@continue
# When x > 0, return atan(y/x). When x < 0, return pi+atan(y/x) mod 2pi
greater $x 0 &store
if $store %atan
# When x < 0, check sign of y
lesser $y 0 &store
if $store %quadrant3
pusharg $ratio
call !atan &store
add $store $pi &store
return $store
@quadrant3
pusharg $ratio
call !atan &store
subtract $store $pi &store
return $store
@atan
pusharg $ratio
call !atan &store
return $store
@error
greater $y 0 &store
if $store %90deg
lesser $y 0 &store
if $store %neg90deg
error "Cannot find atan of (0,0)" "mathError"
divide $pi 2 &pi/2
@90deg
return $pi/2
@neg90deg
multiply $pi/2 -1 &store
return $store
endfun
fun -double !random -int &seed
set &m 2147483648
set &a 1103515245

View File

@@ -18,6 +18,22 @@ Gets the cos of input.
Gets the tan of input.
### fun -double !asin -double &input
Finds the angle *x* in the range [-pi/2, pi/2] such that sin(x) equals the input.
### fun -double !acos -double &input
Finds the angle *x* in the range [0, pi] such that cos(x) equals the input.
### fun -double !atan -double &input
Finds the angle *x* in the range [-pi/2, pi/2] such that tan(x) equals the input.
### fun -double !atan2 -double &y -double &x
Finds the angle in the range (-pi, pi] between the positive x axis and the point (x,y). This is equivalent to atan(y/x) for positive values of x.
### fun -double !intexp -double &base -int &power
Returns base^power, for positive integer values of power. Returns 1 if power is non-positive (and thus is inaccurate for negative values of power).

View File

@@ -1 +1 @@
'\''
extern "file"