From b625bc6244c67caddc19ebba3274da7960397bc2 Mon Sep 17 00:00:00 2001 From: DiamondNether90 Date: Thu, 18 Sep 2025 11:00:00 +1000 Subject: [PATCH] Inverse trig functions and atan2 --- .gitignore | 1 + packages/math/math.grnd | 134 ++++++++++++++++++++++++++++++++++++++++ packages/math/readme.md | 16 +++++ programs/test.grnd | 2 +- 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9b84ca --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*test.grnd diff --git a/packages/math/math.grnd b/packages/math/math.grnd index d858bef..1842272 100644 --- a/packages/math/math.grnd +++ b/packages/math/math.grnd @@ -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" ÷ByZero + set ÷ByZero 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 diff --git a/packages/math/readme.md b/packages/math/readme.md index 226f2de..ab17b8a 100644 --- a/packages/math/readme.md +++ b/packages/math/readme.md @@ -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). diff --git a/programs/test.grnd b/programs/test.grnd index 289adc5..1e0eeec 100644 --- a/programs/test.grnd +++ b/programs/test.grnd @@ -1 +1 @@ -'\'' \ No newline at end of file +extern "file"