home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
dev
/
umbscheme-2.12.lha
/
UMBScheme
/
src
/
complex.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-29
|
14KB
|
629 lines
/* complex.c -- UMB Scheme, complex number package.
UMB Scheme Interpreter $Revision: 2.12 $
Copyright (C) 1988, 1991 William R Campbell
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
UMB Scheme was written by Bill Campbell with help from Karl Berry,
Barbara Dixey, Ira Gerstein, Mary Glaser, Kathy Hargreaves, Bill McCabe,
Long Nguyen, Susan Quina, Jeyashree Sivasubram, Bela Sohoni and Thang Quoc Tran.
For additional information about UMB Scheme, contact the author:
Bill Campbell
Department of Mathematics and Computer Science
University of Massachusetts at Boston
Harbor Campus
Boston, MA 02125
Telephone: 617-287-6449 Internet: bill@cs.umb.edu
*/
#include "portable.h"
#include "eval.h"
#include "object.h"
#include "architecture.h"
#include "number.h"
#include "fixnum.h"
#include "bignum.h"
#include "rational.h"
#include "real.h"
#include "complex.h"
#include "steering.h"
#include "io.h"
#include <math.h>
#include <errno.h>
#define A (Get_Number_Complex_Real_Part(Top(2)))
#define B (Get_Number_Complex_Imaginary_Part(Top(2)))
#define C (Get_Number_Complex_Real_Part(Top(1)))
#define D (Get_Number_Complex_Imaginary_Part(Top(1)))
#define PI 3.14159265358979323846
#define HALF_PI 1.57079632679489661923
/* Predicates. */
Public Boolean Is_Complex_Zero()
{
return ( (C == 0.0) && (D == 0.0) );
}
Public Boolean Is_Complex_Positive()
{
Error("No Positive/Negative Concept about Complex!");
return FALSE;
}
Public Boolean Is_Complex_Negative()
{
Error("No Positive/Negative Concept about Complex!");
return FALSE;
}
Public Boolean Is_Complex_Odd()
{
Error("No Odd/Even Concept about Complex!");
return FALSE;
}
Public Boolean Is_Complex_Even()
{
Error("No Odd/Even Concept about Complex!");
return FALSE;
}
Public Boolean Is_Complex_Exact()
{
return FALSE; /* Complex numbers are always inexact */
}
Public Boolean Is_Complex_Inexact()
{
return TRUE; /* Complex numbers are always inexact */
}
/* Comparisons. */
Public Boolean Complex_Less_Than()
{
Error("No Inequality about Complex!");
return FALSE;
}
Public Boolean Complex_Greater_Than()
{
Error("No Inequality about Complex!");
return FALSE;
}
Public Boolean Complex_Equal()
{
return ( (A == C) && (B == D) );
}
Public Boolean Complex_Less_Than_Or_Equal()
{
Error("No Inequality about Complex!");
return FALSE;
}
Public Boolean Complex_Greater_Than_Or_Equal()
{
Error("No Inequality about Complex!");
return FALSE;
}
/* Arithmetic. */
Public void Complex_Add()
{
Make_Complex_Number( A + C, B + D );
}
Public void Complex_Subtract()
{
Make_Complex_Number( A - C, B - D );
}
Public void Complex_Multiply()
{
Make_Complex_Number( ( (A*C) - (B*D) ), ( (A*D) + (B*C) ) );
}
Public void Complex_Divide()
{
if (Is_Complex_Zero()) /* C+Di = 0+0i, it's on top(1) */
Error("Complex division by ZERO !!!!");
else
Make_Complex_Number( ( (A*C)+(B*D) ) / ( (C*C)+(D*D) ),
( (B*C)-(A*D) ) / ( (C*C)+(D*D) ) );
}
Public void Complex_Quotient()
{
Error("No Quotient Operation on Complex!");
}
Public void Complex_Remainder()
{
Error("No Remainder Operation on Complex!");
}
Public void Complex_Modulo()
{
Error("No Modulo Operation on Complex!");
}
Public void Complex_Negate()
{
Value_Register = Copy_Object(Top(1), Complex_Size);
Get_Number_Complex_Real_Part(Value_Register) =
- Get_Number_Complex_Real_Part(Value_Register);
Get_Number_Complex_Imaginary_Part(Value_Register) =
- Get_Number_Complex_Imaginary_Part(Value_Register);
}
Public void Complex_Abs()
{
Make_Real_Number(sqrt( (C*C) + (D*D) ));
}
Public void Complex_Numerator()
{
Error("No Numerator Operation on Complex!");
}
Public void Complex_Denominator()
{
Error("No Denominator Operation on Complex!");
}
Public void Complex_Rationalize()
{
Error("No Rationalize Operation on Complex!");
}
Public void Complex_Max()
{
Error("No Max Operation on Complex!");
}
Public void Complex_Min()
{
Error("No Min Operation on Complex!");
}
Public void Complex_GCD()
{
Error("No GCD Operation on Complex!");
}
Public void Complex_LCM()
{
Error("No LCM Operation on Complex!");
}
Public void Complex_Floor()
{
Error("No Floor Operation on Complex!");
}
Public void Complex_Ceiling()
{
Error("No Ceiling Operation on Complex!");
}
Public void Complex_Truncate()
{
Error("No Truncate Operation on Complex!");
}
Public void Complex_Round()
{
Error("No Round Operation on Complex!");
}
Public void Complex_Sqrt()
/* sqrtz = sqrt(|z|)*( cos((angle+2kPi)/2) + isin((angle+2kPi)/2) ) */
{
Double mag_sqrt = sqrt(sqrt( (C*C) + (D*D) ));
Double ang = ( C == 0.0 && D > 0.0 ) ? HALF_PI :
( ( C == 0.0 && D < 0.0 ) ? -HALF_PI : atan2(D,C) );
/* select a proper angle so that
the real part of the result is non-negative */
if (cos(ang/2.0) >= 0.0) ang /= 2.0;
else ang = (ang/2.0) + PI;
Make_Complex_Number(mag_sqrt * cos(ang), mag_sqrt * sin(ang));
}
Public void Complex_Exp()
{
Make_Complex_Number( exp(C) * cos(D) , exp(C) * sin(D) );
}
Public void Complex_Log()
/* logz = log(magnitude(z)) + angle(z)i */
{
Double ang = ( C == 0.0 && D > 0.0 ) ? HALF_PI :
( ( C == 0.0 && D < 0.0 ) ? -HALF_PI : atan2(D,C) );
if (Is_Complex_Zero()) Display_Error("Bad arg to Log : ", Top(1) );
else Make_Complex_Number( log(sqrt(C*C + D*D)), ang );
}
Public void Complex_Expt()
/* z1**z2 = e**z2log(z1) ; 0**0 is defined to be 1 */
{
#define Z1_and_Z2_are_Zeros (A == 0.0 && B == 0.0) && (C == 0.0 && D == 0.0)
#define Z1_is_Zero A == 0.0 && B == 0.0
Promote( 2 , COMPLEX_LEVEL );
if ( Z1_and_Z2_are_Zeros ) Make_Complex_Number(1.0, 0.0);
else if ( Z1_is_Zero ) Display_Error("Bad arg to Expt:", Top(2));
else
{
Push(Top(2)); /* push z1 */
Complex_Log(); /* compute logz1 */
Pop(1); /* remove z1 */
Push(Value_Register); /* push logz1 */
Complex_Multiply(); /* compute z2logz1 */
Pop(1); /* remove logz1 */
Push(Value_Register); /* push z2logz1 */
Complex_Exp(); /* compute e**z2logz1 */
Pop(1); /* remove z2logz1 */
}
#undef Z1_and_Z2_are_Zeros
#undef Z1_is_Zero
}
Public void Complex_Sin()
/* sinz = (e**iz - e**-iz) / 2i */
{
Make_Complex_Number( ((exp(-D) * sin(C)) - (exp(D) * sin(-C))) / 2.0 ,
((exp(D) * cos(-C)) - (exp(-D) * cos(C))) / 2.0 );
}
Public void Complex_Cos()
/* cosz = (e**iz + e**-iz) / 2 */
{
Make_Complex_Number(((exp(-D) * cos(C)) + (exp(D) * cos(-C))) / 2.0 ,
((exp(-D) * sin(C)) + (exp(D) * sin(-C))) / 2.0 );
}
Public void Complex_Tan()
/* tanz = sinz / cosz */
{
Complex_Sin(); /* compute sin(z) */
Push( Value_Register ); /* push sin(z) onto stack */
Push( Top(2) ); /* swap z upto top to compute cos(z) */
Complex_Cos(); /* compute cos(z) */
Pop(1); /* remove the temp z */
Push( Value_Register ); /* push cos(z) onto stack */
Complex_Divide(); /* compute tan(z) = sin(z) / cos(z) */
Pop(2); /* remove sin(z) and cos(z) off the stack */
}
Public void Complex_Asin()
/* asinz = -ilog(iz + sqrt(1-z**2)) */
{
Make_Complex_Number( 1.0 - (C*C) + (D*D), -(2.0*(C*D)) );
/* Make 1-z**2 */
Push( Value_Register ); /* push 1-z**