Inverse trig functions and atan2
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| *test.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 | ||||
|   | ||||
| @@ -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). | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| '\'' | ||||
| extern "file" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user