fun -double !mod -double &in -double &modulus lesser $in $modulus &store not $store &store if $store %downloop lesser $in 0 &store if $store %uploop jump %end @downloop subtract $in $modulus &in lesser $in $modulus &store not $store &store if $store %downloop jump %end @uploop add $in $modulus &in lesser $in 0 &store if $store %uploop jump %end @end return $in endfun fun -double !pi return 3.141592653589793 endfun fun -double !e return 2.718281828459045 endfun fun -double !intexp -double &base -int &power lesser $power 1 &store set &ans 1 if $store %end @loop subtract $power 1 &power multiply $ans $base &ans lesser $power 1 &store if $store %end jump %loop @end return $ans endfun fun -int !factorial -int &in set &idx $in set &ans 1 lesser $idx 0 &store if $store %error @loop equal $idx 0 &store if $store %end multiply $ans $idx &ans subtract $idx 1 &idx jump %loop @end return $ans @error error "Cannot find factorial of a negative integer" endfun fun -double !cos -double &in # Get input modulo 2π call !pi &pi multiply $pi 2 &tau pusharg $in pusharg $tau call !mod &in set &idx 0 set &ans 0 # Check if $in < π greater $in $pi &store if $store %cos2 jump %cos1 @cos1 # Taylor series at x=π/2 multiply $idx 2 &2k+1 add $2k+1 1 &2k+1 # Get (x-π/2)^(2k+1) divide $pi 2 &store subtract $in $store &store pusharg $store tostring $2k+1 &2k+1 stoi $2k+1 &2k+1 pusharg $2k+1 call !intexp &exp # Get (2k+1)! pusharg $2k+1 call !factorial &fact # Divide divide $exp $fact &tempans # Add result to $ans tostring $idx &idx stod $idx &idx pusharg $idx stod "2" &store pusharg $store call !mod &store equal $store 0 &store if $store %subtract jump %add @add add $ans $tempans &ans jump %increment @subtract subtract $ans $tempans &ans jump %increment @increment add $idx 1 &idx equal $idx 5 &store if $store %end jump %cos1 @cos2 # cos(x)=cos(2π-x) subtract $tau $in &in jump %cos1 @end return $ans endfun fun -double !sin -double &in call !pi &halfpi divide $halfpi 2 &halfpi subtract $halfpi $in &in pusharg $in call !cos &store return $store endfun fun -double !tan -double &in pusharg $in call !sin &store pusharg $in call !cos &store2 divide $store $store2 &store 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 set &c 12345 multiply $seed $a &store add $store $c &store tostring $store &store stod $store &store pusharg $store pusharg $m call !mod &store divide $store 2147483648 &store return $store endfun fun -double !itod -int &int tostring $int &int stod $int &int return $int endfun fun -int !dtoi -double &double tostring $double &double stoi $double &double return $double endfun fun -double !sqrt -double &in # Finding sqrt(a) is the same as finding the roots of # f(x) = x^2 - a # Using Newton's method: x_(k+1) = x_k - f(x_k)/f'(x_k) = x_k - ((x_k)^2-a)/2(x_k) lesser $in 0 &store if $store %error set &ans 2 @loop multiply $ans $ans &num subtract $num $in &num multiply $ans 2 &dom divide $num $dom &store equal $store 0 &store2 if $store2 %end subtract $ans $store &ans jump %loop @end return $ans @error error "Cannot find square root of a negative double" "mathError" endfun fun -double !abs -double &in lesser $in 0 &store if $store %negative return $in @negative multiply $in -1 &in return $in endfun fun -double !exp -double &in call !e &e lesser $in 0 &store if $store %negative # Find $in rounded down pusharg $in stod "1.00" &store pusharg $store call !mod &floorin subtract $in $floorin &floorin pusharg $floorin call !dtoi &floorin # e^(a+x)=e^a*e^x pusharg $e pusharg $floorin call !intexp &e^a # Find e^($in - $floorin) subtract $in $floorin &x # e^x = 1 + x + x^2/2 + x^3/6 + ... + x^k/k! set &idx 0 set &e^x 0 @loop equal $idx 10 &store if $store %return pusharg $x pusharg $idx call !intexp &store pusharg $idx call !factorial &fact divide $store $fact &store add $e^x $store &e^x add $idx 1 &idx jump %loop @return multiply $e^a $e^x &ans return $ans @negative # e^-x = 1/e^x multiply $in -1 &in pusharg $in call !exp &store divide 1 $store &store return $store endfun fun -double !ln -double &in greater $in 0 &store if $store %calculate jump %error @calculate equal $in 1 &store if $store %zero # We will use Newton's method. # ln(a) is the root of e^x-a # Therefore x_k+1 = x_k - (e^x_k - a)/(e^x_k) set &ans 0.9 @loop pusharg $ans call !exp &e^x subtract $e^x $in &store divide $store $e^x &store subtract $ans $store &ans pusharg $store call !abs &store lesser $store 0.000000000001 &store if $store %return jump %loop @return return $ans @zero stod "0" &zero return $zero @error error "Cannot find ln of a non-positive double" "mathError" endfun