home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sa104os2.zip
/
SATHR104.ZIP
/
SATHER
/
LIBRARY
/
CPX.SA
< prev
next >
Wrap
Text File
|
1995-02-05
|
8KB
|
239 lines
-- Copyright (C) International Computer Science Institute, 1994. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
-- cpx.sa: Complex numbers.
-------------------------------------------------------------------
value class CPX{T} is
-- Complex numbers.
--
-- Some of the algorithms are taken from:
-- Press, Flannery, Teukolsky, and Vettering, "Numerical Recipes in
-- C", second edition, Cambridge University Press, 1993.
--
-- Some of the choices of branch cut were chosen to be consistent
-- with:
-- Guy L. Steele, "Common Lisp, The Language", second edition,
-- 1990, Digital Press.
attr re,im:T; -- Real and imaginary parts.
str:STR is
-- A string representation of self of the form "1.02+3.23i".
buf:FSTR;
if im>=#T(0.0) then
buf:=buf + re.str + ("+") + im.str + "i";
else buf:=buf + re.str + ("-") + (-im).str + "i" end;
return buf.str end;
create(x:FLT):SAME is return #(#T(x),#T(0.0)) end;
create(re,im:T):SAME is
-- A complex number with real part `re' and imaginary part `im'.
r:SAME; return r.re(re).im(im) end;
plus(c:SAME):SAME is
-- The sum of self and `c'.
return #(re+c.re,im+c.im) end;
minus(c:SAME):SAME is
-- The difference of self and `c'.
return #(re-c.re,im-c.im) end;
negate:SAME is
-- The additive inverse of self.
return #(-re,-im) end;
conjugate:SAME is
-- The complex conjugate of self.
return #(re,-im) end;
times(c:SAME):SAME is
-- The product of self and `c'.
return #(re*c.re-im*c.im, re*c.im+im*c.re) end;
div(c:SAME):SAME is
-- The ratio of self and `c'.
-- From Numerical Recipes in C, 2nd ed. p. 949.
if c.re.abs>=c.im.abs then
r::=c.im/c.re; den::=c.re+r*c.im;
return #((re+r*im)/den,(im-r*re)/den)
-- else r::=c.re/c.im; den::=c.im+r*c.re; -- NLP
end; r::=c.re/c.im; den::=c.im+r*c.re; -- NLP
-- return #((re*r+im)/den,(im*r-re)/den) end end; -- NLP
return #((re*r+im)/den,(im*r-re)/den); end; -- NLP
reciprocal:SAME is
-- The multiplicative inverse of self.
if re.abs>=im.abs then
r::=im/re; den::=re+r*im;
return #(#T(1.0)/den,-r/den)
-- else r::=re/im; den::=im+r*re; -- NLP
end; r::=re/im; den::=im+r*re; -- NLP
-- return #(r/den,#T(-1.0)/den) end end; -- NLP
return #(r/den,#T(-1.0)/den); end; -- NLP
exp:SAME is
-- The complex exponential `e^self'.
rp::=re.exp; return #(rp*im.cos,rp*im.sin) end;
times(f:T):SAME is
-- Self times the floating point c.
return #(re*f,im*f) end;
div(f:T):SAME is
-- Self div the floating point f.
return #(re/f,im/f) end;
sqrt:SAME is
-- The square root of self.
-- From Numerical Recipes in C, 2nd ed. p. 949.
-- Steele, p. 302 chooses the branch cut by `e^((log z)/2)'
if re=#T(0.0) and im=#T(0.0) then return #(#T(0.0),#T(0.0)) end;
x::=re.abs; y::=im.abs;
w:T;
if x>=y then r::=y/x; w:=x.sqrt*(#T(0.5)*(#T(1.0)+(#T(1.0)+r*r).sqrt)).sqrt;
else r::=x/y; w:=y.sqrt*(#T(0.5)*(r+(#T(1.0)+r*r).sqrt)).sqrt end;
if re>=#T(0.0) then return #(w,im/(#T(2.0)*w));
elsif im>=#T(0.0) then return #(im/(#T(2.0)*w),w)
-- else return #(-im/(#T(2.0)*w),-w) end end; -- NLP
end; return #(-im/(#T(2.0)*w),-w); end; -- NLP
abs:T is
-- The absolute magnitude of self.
-- From Numerical Recipes in C, 2nd ed. p. 949.
x::=re.abs; y::=im.abs; temp:T;
if x=#T(0.0) then return y
elsif y=#T(0.0) then return x
elsif x>y then temp:=y/x; return x*(#T(1.0)+temp*temp).sqrt;
-- else temp:=x/y; return y*(#T(1.0)+temp*temp).sqrt end end; -- NLP
end; temp:=x/y; return y*(#T(1.0)+temp*temp).sqrt; end; -- NLP
abs_squared:T is
-- The square of the absolute magnitude of self.
return re*re+im*im end;
magnitude:T is
-- The absolute magnitude of self.
return abs end;
magnitude_squared:T is
-- The square of the absolute magnitude of self.
return abs_squared end;
phase:T is
-- The angle part of the polar represenation of self.
-- `-pi < res <= pi'. Also get "-pi" from a negative real
-- part and a "-0.0" imaginary part.
-- They say 0+0i should be +0, 0-0i should be -0, -0+0i
-- should be +pi, and -0-0i should be -pi.
-- Same convention as Steele, p. 303.
return im.atan2(re) end;
log:SAME is
-- The complex logarithm. The chosen branch is
-- `log |z| + i phase(z)'.
-- Same convention as Steele, p. 302.
return #((re*re+im*im).sqrt.log,phase) end;
sign:SAME is
-- If not zero, a number with same sign as self but unit
-- magnitude. If it is, then returns self.
-- Steele, p. 304
--***
raise "CPX::sign:SAME not defined."
end;
create_from_polar(mag,phase:T):SAME is
-- A complex number with magnitude `mag' and phase `phase'.
r:SAME; return r.re(mag * phase.cos).im(mag * phase.sin) end;
cis(f:T):SAME is
-- Ignores self, e^i*f=cos f + i sin f .
-- Steele p. 304.
r:SAME; return r.re(f.cos).im(f.sin) end;
asin:SAME is
-- -i log(iz + sqrt(1-z^2))
-- Steele p. 305.
--***
raise "CPX::asin:SAME missing."
end;
acos:SAME is
-- -i log(z + sqrt(1-z^2))
-- better to use: (pi/2)-asin(z)
-- Steele p. 305.
--***
raise "CPX::acos:SAME missing."
end;
atan:SAME is
-- (log(1+i*y)-log(1-i*y))/(2*i)
-- Steele p. 307.
--***
raise "CPX::atan:SAME missing."
end;
sinh:SAME is
-- (e^z-e^(-z))/2
-- Steele p. 308
--***
raise "CPX::sinh:SAME missing."
end;
cosh:SAME is
-- (e^z+e^(-z))/2
-- Steele p. 308
--***
raise "CPX::cosh:SAME missing."
end;
tanh:SAME is
-- (e^z-e^(-z))/(e^z+e^(-z))
-- Steele p. 308
--***
raise "CPX::tanh:SAME missing."
end;
asinh:SAME is
-- log(z+sqrt(1+z^2))
-- Steele p. 308
--***
raise "CPX::asinh:SAME missing."
end;
acosh:SAME is
-- log(z+(z+1)sqrt((z-1)/(z+1)))
-- Steele p. 308
--***
raise "CPX::acosh:SAME missing."
end;
atanh:SAME is
-- log((1+z)sqrt(1/(1-z^2)))
-- Steele p. 308
--***
raise "CPX::atanh:SAME missing."
end;
end; -- class CPX{T}
-------------------------------------------------------------------
value class CPX is
include CPX{FLT}
end; -- class CPX
-------------------------------------------------------------------
value class CPXD is
include CPX{FLTD}
end; -- class CPXD
-------------------------------------------------------------------