Trigonometry Libraries

Hello.

This first post consists of a trigonometry library based on the bc command line utility that ships with all Mac’s, it precision, is as good as it gets, but no better than Satimage.osax, and probably much slower.

All angles are supposed to be given in radians, and functions that returns angles as result, (the tangens functions), also returns those in radians.

To convert from a degree to a radian, multiply with pi / 180, conversely, to convert from radians to an angle, multiply with 180 / pi.

script bcTrigsLib
	
	on run
		set cos_val to my _cos(60 * pi / 180)
		set sin_val to my _sin(30 * pi / 180)
		set tan_val to my _tan(30 * pi / 180)
		set tan_deg to (my _atan(0.57733026919)) * 180 / pi
		set cos_deg to (my _acos(0.5)) * 180 / pi
		set sin_deg to (my _asin(0.5)) * 180 / pi
		set atan_angl to (my _atan2({(my _cos(60 * pi / 180)), (my _sin(60 * pi / 180))})) * 180 / pi
	end run
	to _cos(aReal)
		local tids, theRadian, tempvar
		# must adjust for Locale decimal separator before calling bc
		set theRadian to aReal as text
		tell (a reference to AppleScript's text item delimiters)
			set {tids, contents of it} to {contents of it, ","}
			set tempvar to text items of theRadian
			set contents of it to "."
			set theRadian to tempvar as text
			set contents of it to tids
		end tell
		return (do shell script "echo \"scale=20; c(" & theRadian & ")\" |bc -l | tr -s '.' ','") as number
	end _cos
	
	to _sin(aReal)
		local tids, theRadian, tempvar
		# must adjust for Locale decimal separator before calling bc
		set theRadian to aReal as text
		tell (a reference to AppleScript's text item delimiters)
			set {tids, contents of it} to {contents of it, ","}
			set tempvar to text items of theRadian
			set contents of it to "."
			set theRadian to tempvar as text
			set contents of it to tids
		end tell
		return (do shell script "echo \"scale=20; s(" & theRadian & ")\" |bc -l | tr -s '.' ','") as number
	end _sin
	
	to _tan(aReal)
		local tids, theCosine, tempvar
		# must adjust for Locale decimal separator before calling bc
		set theTangent to aReal as text
		tell (a reference to AppleScript's text item delimiters)
			set {tids, contents of it} to {contents of it, ","}
			set tempvar to text items of theTangent
			set contents of it to "."
			set theTangent to tempvar as text
			set contents of it to tids
		end tell
		
		return (do shell script "echo \"scale=20;  s(" & theTangent & ")/ c( " & theTangent & ") \" |bc -l  | tr -s '.' ','") as number
		
	end _tan
	
	to _acos(in_unity_range)
		if (in_unity_range < -1 or in_unity_range > 1) then
			error "Argument not in the range -1 ≤ arg ≤ 1" number 5001
		else
			
			local tids, theCosine, tempvar
			# must adjust for Locale decimal separator before calling bc
			set theCosine to in_unity_range as text
			tell (a reference to AppleScript's text item delimiters)
				set {tids, contents of it} to {contents of it, ","}
				set tempvar to text items of theCosine
				set contents of it to "."
				set theCosine to tempvar as text
				set contents of it to tids
			end tell
			# http://en.wikipedia.org/wiki/Inverse_trigonometric_functions, (a = atan in bc request below).
			return (do shell script "echo \"scale=20; ( a(sqrt((1 - (" & theCosine & "^2) ))/" & theCosine & ")) \" |bc -l  | tr -s '.' ','") as number
		end if
		
	end _acos
	
	
	to _asin(in_unity_range)
		if (in_unity_range < -1 or in_unity_range > 1) then
			error "Argument not in the range -1 ≤ arg ≤ 1" number 5001
		else
			return ((pi / 2) - (my _acos(in_unity_range)))
			# http://en.wikipedia.org/wiki/Inverse_trigonometric_functions
		end if
	end _asin
	
	to _atan(aReal)
		local tids, theCosine, tempvar
		# must adjust for Locale decimal separator before calling bc
		set theTangent to aReal as text
		tell (a reference to AppleScript's text item delimiters)
			set {tids, contents of it} to {contents of it, ","}
			set tempvar to text items of theTangent
			set contents of it to "."
			set theTangent to tempvar as text
			set contents of it to tids
		end tell
		
		return (do shell script "echo \"scale=20;  a(" & theTangent & ") \" |bc -l  | tr -s '.' ','") as number
	end _atan
	
	to _atan2(tupleOfReals)
		# List of two reals
		if length of tupleOfReals < 2 then
			error "bcTrigsLib: Bad argument: needs two reals" number 5002
		else if item 1 of tupleOfReals = 0 then
			error "bcTrigsLib: Bad argument: can't divide by zero." number 5001
		else if item 2 of tupleOfReals = 0 then
			return 0
		else
			return my _atan(((item 1 of tupleOfReals) / (item 2 of tupleOfReals)))
		end if
	end _atan2
	
end script
tell bcTrigsLib to run


Hello.

Here is a library of trigonometric functions, compiled from various sources, they are all implemented in AppleScript, and the better part of them are from the AppleScript source book.

I’d really recommend using bc, or Satimage.osax, since the handlers here, are both slower, and has a lower accuracy.

It may still be interesting for someone to either use them, or just have a look at them, and that was the rationale behind this post.

on sine_of(x)
	repeat until x ≥ 0 and x < 360
		if x ≥ 360 then
			set x to x - 360
		end if
		if x < 0 then
			set x to x + 360
		end if
	end repeat
	
	--convert from degrees to radians
	set x to x * (2 * pi) / 360
	
	set answer to 0
	set numerator to x
	set denominator to 1
	set factor to -(x ^ 2)
	
	repeat with i from 3 to 40 by 2
		set answer to answer + numerator / denominator
		set numerator to numerator * factor
		set denominator to denominator * i * (i - 1)
	end repeat
	
	return answer
end sine_of

on cosine_of(x)
	repeat until x ≥ 0 and x < 360
		if x ≥ 360 then
			set x to x - 360
		end if
		if x < 0 then
			set x to x + 360
		end if
	end repeat
	
	--convert from degrees to radians
	set x to x * (2 * pi) / 360
	
	set answer to 0
	set numerator to 1
	set denominator to 1
	set factor to -(x ^ 2)
	
	repeat with i from 2 to 40 by 2
		set answer to answer + numerator / denominator
		set numerator to numerator * factor
		set denominator to denominator * i * (i - 1)
	end repeat
	
	return answer
end cosine_of

--x is in degrees
on tangens_of(x)
	set answer to sine_of(x) / (cosine_of(x))
	return answer
end tangens_of

--x is ratio of opposite to adjacent sides of triangle
on inverse_tangent_of(x)
	set complimentFlag to false
	if x > 1 or x < -1 then
		set x to 1 / x
		set complimentFlag to true
	else if x = 1 then
		return 45.0
	end if
	
	set answer to 0
	set numerator to x
	set denominator to 1
	set ratio to x
	set factor to -(x ^ 2)
	
	repeat while abs (ratio) > 1.0E-4
		set answer to answer + ratio
		set numerator to numerator * factor
		set denominator to denominator + 2
		set ratio to numerator / denominator
	end repeat
	
	--convert from radians to degrees
	set answer to answer * 360 / (2 * pi)
	
	if complimentFlag is true then
		set answer to 90 - answer
	end if
	
	return answer
end inverse_tangent_of

on inverse_sine_of(x)
	if x = 1 then
		return 90
	else if x = -1 then
		return -90
	else
		return (inverse_tangent_of(x / ((1 - (x ^ 2)) ^ 0.5)))
	end if
end inverse_sine_of

on inverse_cosine_of(x)
	return (90 - inverse_sine_of(x))
end inverse_cosine_of


on inverse_tangent2_of(x, y)
	if x = 0 then
		if y = 0 then
			error "inverse_tangent2_of : y = 0 " number 9000
		else if y > 0 then
			return 90
		else
			return -90
		end if
	else if x > 0 then
		return inverse_tangent_of(y / x)
	else if y ≥ 0 then
		return inverse_tangent_of(y / x) + 180
	else
		return inverse_tangent_of(y / x) - 180
	end if
end inverse_tangent2_of