home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: math.icn
- #
- # Subject: Procedures to perform mathematical computations
- #
- # Author: George D. Yee
- #
- # Date: June 10, 1988
- #
- ###########################################################################
- #
- # Note:
- # Version 8 of Icon supports most of the procedures that follow as
- # built-in functions. The procedures here should not be used unless the
- # corresponding functions are disabled.
- #
- ############################################################################
- #
- # The following procedures compute standard trigonometric func-
- # tions. The arguments are in radians.
- #
- # sin(x) sine of x
- #
- # cos(x) cosine of x
- #
- # tan(x) tangent of x
- #
- # asin(x) arc sine of x in the range -pi/2 to pi/2
- #
- # acos(x) arc cosine of x in the range 0 to pi
- #
- # atan(x) arc tangent of x in the range -pi/2 to pi/2
- #
- # atan2(y,x) arc tangent of x/y in the range -pi to pi
- #
- # The following procedures convert from degrees to radians and con-
- # versely:
- #
- # dtor(d) radian equivalent of d
- #
- # rtod(r) degree equivalent of r
- #
- # The following additional procedures are available:
- #
- # sqrt(x) square root of x
- #
- # exp(x) exponential function of x
- #
- # log(x) natural logarithm of x
- #
- # log10(x) base-10 logarithm of x
- #
- # floor(x) largest integer not greater than x
- #
- # ceil(x) smallest integer nor less than x
- #
- # Failure Conditions: asin(x) and acos(x) fail if the absolute
- # value of x is greater than one. sqrt(x), log(x), and log10(x)
- # fail if x is less than zero.
- #
- ############################################################################
-
- procedure sin(x)
- return _sinus(numeric(x),0)
- end
-
- procedure cos(x)
- return _sinus(abs(numeric(x)),1)
- end
-
- procedure tan(x)
- return sin(x) / (0.0 ~= cos(x))
- end
-
- # atan returns the value of the arctangent of its
- # argument in the range [-pi/2,pi/2].
- procedure atan(x)
- if numeric(x) then
- return if x > 0.0 then _satan(x) else -_satan(-x)
- end
-
- # atan2 returns the arctangent of y/x
- # in the range [-pi,pi].
- procedure atan2(y,x)
- local r
- static pi
- initial pi := 3.141592653589793238462643
- return if numeric(y) & numeric(x) then {
- if x > 0.0 then
- atan(y/x)
- else if x < 0.0 then {
- r := pi - atan(abs(y/x))
- if y >= 0.0 then r else -r
- }
- else if x = y = 0.0 then
- 0.0 # special value if both x and y are zero
- else
- if y >= 0.0 then pi/2.0 else -pi/2.0
- }
- end
-
- procedure asin(x)
- if abs(numeric(x)) <= 1.0 then
- return atan2(x, (1.0-(x^2))^0.5)
- end
-
- procedure acos(x)
- return 1.570796326794896619231e0 - asin(x)
- end
-
- procedure dtor(deg)
- return numeric(deg)/57.29577951308232
- end
-
- procedure rtod(rad)
- return numeric(rad)*57.29577951308232
- end
-
- procedure sqrt(x)
- return (0.0 <= numeric(x)) ^ 0.5
- end
-
- procedure floor(x)
- return if numeric(x) then
- if x>=0.0 | real(x)=integer(x) then integer(x) else -integer(-x+1)
- end
-
- procedure ceil(x)
- return -floor(-numeric(x))
- end
-
- procedure log(x)
- local z, zsq, ex
- static log2, sqrto2, p0, p1, p2, p3, q0, q1, q2
- initial {
- # The coefficients are #2705 from Hart & Cheney. (19.38D)
- log2 := 0.693147180559945309e0
- sqrto2 := 0.707106781186547524e0
- p0 := -0.240139179559210510e2
- p1 := 0.309572928215376501e2
- p2 := -0.963769093368686593e1
- p3 := 0.421087371217979714e0
- q0 := -0.120069589779605255e2
- q1 := 0.194809660700889731e2
- q2 := -0.891110902798312337e1
- }
- if numeric(x) > 0.0 then {
- ex := 0
- while x >= 1.0 do {
- x /:= 2.0
- ex +:= 1
- }
- while x < 0.5 do {
- x *:= 2.0
- ex -:= 1
- }
- if x < sqrto2 then {
- x *:= 2.0
- ex -:= 1
- }
- return ((((p3*(zsq:=(z:=(x-1.0)/(x+1.0))^2)+p2)*zsq+p1)*zsq+p0)/
- (((1.0*zsq+q2)*zsq+q1)*zsq+q0))*z+ex*log2
- }
- end
-
- procedure exp(x)
- return 2.718281828459045235360287 ^ numeric(x)
- end
-
- procedure log10(x)
- return log(x)/2.30258509299404568402
- end
-
- procedure _sinus(x,quad)
- local ysq, y, k
- static twoopi, p0, p1, p2, p3, p4, q0, q1, q2, q3
- initial {
- # Coefficients are #3370 from Hart & Cheney (18.80D).
- twoopi := 0.63661977236758134308
- p0 := 0.1357884097877375669092680e8
- p1 := -0.4942908100902844161158627e7
- p2 := 0.4401030535375266501944918e6
- p3 := -0.1384727249982452873054457e5
- p4 := 0.1459688406665768722226959e3
- q0 := 0.8644558652922534429915149e7
- q1 := 0.4081792252343299749395779e6
- q2 := 0.9463096101538208180571257e4
- q3 := 0.1326534908786136358911494e3
- }
- if x < 0.0 then {
- x := -x
- quad +:= 2
- }
- y := (x *:= twoopi) - (k := integer(x))
- if (quad := (quad + k) % 4) = (1|3) then
- y := 1.0 - y
- if quad > 1 then
- y := -y
- return (((((p4*(ysq:=y^2)+p3)*ysq+p2)*ysq+p1)*ysq+p0)*y) /
- ((((ysq+q3)*ysq+q2)*ysq+q1)*ysq+q0)
- end
-
- procedure _satan(x)
- static sq2p1,sq2m1,pio2,pio4
- initial {
- sq2p1 := 2.414213562373095048802e0
- sq2m1 := 0.414213562373095048802e0
- pio2 := 1.570796326794896619231e0
- pio4 := 0.785398163397448309615e0
- }
- return if x < sq2m1 then
- _xatan(x)
- else if x > sq2p1 then
- pio2 - _xatan(1.0/x)
- else
- pio4 + _xatan((x-1.0)/(x+1.0))
- end
-
- procedure _xatan(x)
- local xsq
- static p4,p3,p2,p1,p0,q4,q3,q2,q1,q0
- initial {
- # coefficients are #5077 from Hart & Cheney. (19.56D)
- p4 := 0.161536412982230228262e2
- p3 := 0.26842548195503973794141e3
- p2 := 0.11530293515404850115428136e4
- p1 := 0.178040631643319697105464587e4
- p0 := 0.89678597403663861959987488e3
- q4 := 0.5895697050844462222791e2
- q3 := 0.536265374031215315104235e3
- q2 := 0.16667838148816337184521798e4
- q1 := 0.207933497444540981287275926e4
- q0 := 0.89678597403663861962481162e3
- }
- return x * ((((p4*(xsq:=x^2)+p3)*xsq+p2)*xsq+p1)*xsq+p0) /
- (((((xsq+q4)*xsq+q3)*xsq+q2)*xsq+q1)*xsq+q0)
- end
-