home *** CD-ROM | disk | FTP | other *** search
- /*
- * Complex number library translated from Pascal source listing
- * in Dr. Dobbs October, 1984 "Simple Calculations with Complex Numbers"
- * by David Clark.
- *
- * To insure that the same structure could be used as both an 'argument'
- * and 'result' immediate tranfer of structure members is done to a
- * local variable - in many of the functions this may not be necessary,
- * but it was done in all of the following functions for consistency
- *
- * Author: R. Hellman
- * Date: 02/21/86
- *
- * Released to the Public Domain
- */
-
- #include <malloc.h>
- #include <math.h>
-
- #define TINY 2.2e-308 /* tiny value */
- #define LOGHUGE 709.778 /* natural log of huge value */
-
- typedef struct {
- double re;
- double im;
- } complex;
-
- /*
- * Initializes storage for each address of an array of complex pointers
- * *f[] with 'arraysz' number of elements
- */
-
- initcmplx(f, arraysz)
- complex *f[];
- int arraysz;
- {
- int i;
-
- for (i = 0; i < arraysz; i++)
- if ((f[i] = (complex *)malloc(sizeof(complex))) == NULL) {
- puts("Error: complex number allocation\n");
- exit(1);
- }
- }
-
- /* adds arg1 and arg2 and returns sum in result */
-
- cadd(result, arg1, arg2)
- complex *result, *arg1, *arg2;
- {
- complex targ1, targ2;
-
- targ1.re = arg1->re;
- targ1.im = arg1->im;
- targ2.re = arg2->re;
- targ2.im = arg2->im;
-
- result->re = targ1.re + targ2.re;
- result->im = targ1.im + targ2.im;
- }
-
- /* subtracts arg1 and arg2 and returns sum in result */
-
- csub(result, arg1, arg2)
- complex *result, *arg1, *arg2;
- {
- complex targ1, targ2;
-
- targ1.re = arg1->re;
- targ1.im = arg1->im;
- targ2.re = arg2->re;
- targ2.im = arg2->im;
-
- result->re = targ1.re - targ2.re;
- result->im = targ1.im - targ2.im;
- }
-
- /* multiplies arg1 and arg2 and returns product in result */
-
- cmult(result, arg1, arg2)
- complex *result, *arg1, *arg2;
- {
- complex targ1, targ2;
-
- targ1.re = arg1->re;
- targ1.im = arg1->im;
- targ2.re = arg2->re;
- targ2.im = arg2->im;
-
- result->re = (targ1.re * targ2.re) - (targ1.im * targ2.im);
- result->im = (targ1.im * targ2.re) + (targ1.re * targ2.im);
- }
-
- /* divides arg1 and arg2 and returns quotient in result */
-
- cdiv(result, arg1, arg2)
- complex *result, *arg1, *arg2;
- {
- double denom;
- complex targ1,targ2;
-
- targ1.re = arg1->re;
- targ1.im = arg1->im;
- targ2.re = arg2->re;
- targ2.im = arg2->im;
- denom = (targ2.re * targ2.re) + (targ2.im * targ2.im);
-
- result->re = (targ1.re * targ2.re + targ1.im * targ2.im) / denom;
- result->im = (targ1.im * targ2.re - targ1.re * targ2.im) / denom;
- }
-
- /* converts a complex number arg in rectangular form to polar form */
-
- polar(arg, modulus, amplitude)
- complex *arg;
- double *modulus, *amplitude;
- {
- complex targ;
-
- targ.re = arg->re;
- targ.im = arg->im;
-
- if (fabs(targ.re) < TINY)
- targ.re = 0.0;
-
- if (fabs(targ.im) < TINY)
- targ.im = 0.0;
-
- *modulus = sqrt((targ.re * targ.re) + (targ.im * targ.im));
-
- if (targ.im == 0.0)
- *amplitude = 0.0;
- else if (targ.re == 0.0) {
- if (targ.im > 0.0)
- *amplitude = M_PI_2;
- else
- *amplitude = -M_PI_2;
- }
- else if ((log(fabs(targ.im)) - log(fabs(targ.re))) > LOGHUGE) {
- if (targ.re > 0.0) {
- if (targ.im > 0.0)
- *amplitude = M_PI_2;
- else
- *amplitude = -M_PI_2;
- }
- else if (targ.im > 0.0)
- *amplitude = -M_PI_2;
- else
- *amplitude = M_PI_2;
- }
- }
- else
- *amplitude = atan(targ.im / targ.re);
- }
-
- /* raises arg to the positive integral power and returns answer in result */
-
- ctopower(result, arg, power)
- complex *result, *arg;
- int power;
- {
- int i;
- double modulus, amplitude, newmod, powamp;
- complex targ;
-
- targ.re = arg->re;
- targ.im = arg->im;
-
- if (power == 0) {
- result->re = 1.0;
- result->im = 0.0;
- }
- else {
- polar(&targ, &modulus, &litude);
- newmod = 1.0;
-
- if (power > 0)
- for (i = 0; i < power; i++)
- newmod = newmod * modulus;
- else
- for (i = 0; i < abs(power); i++)
- newmod = newmod / modulus;
-
- powamp = power * amplitude;
-
- result->re = newmod * cos(powamp);
- result->im = newmod * sin(powamp);
- }
- }
-
- /* raises e to the arg and returns the answer in result */
-
- cexp(result, arg)
- complex *result, *arg;
- {
- double expo;
- complex targ;
-
- targ.re = arg->re;
- targ.im = arg->im;
- expo = exp(targ.re);
-
- result->re = expo * cos(targ.im);
- result->im = expo * sin(targ.im);
- }
-
- /* takes the natural logarithm of arg and returns the answer in result */
-
- cln(result, arg)
- complex *result, *arg;
- {
- double modulus, amplitude;
- complex targ;
-
- targ.re = arg->re;
- targ.im = arg->im;
-
- polar(&targ, &modulus, &litude);
-
- result->re = log(modulus);
- result->im = amplitude;
- }
-
- /* raise complex number arg1 to complex power arg2 and return answer in result */
-
- ctoc(result, arg1, arg2)
- complex *result, *arg1, *arg2;
- {
- complex logpart, expo, targ1, targ2;
-
- targ1.re = arg1->re;
- targ1.im = arg1->im;
- targ2.re = arg2->re;
- targ2.im = arg2->im;
-
- cln(&logpart, &targ1);
- cmult(&expo, &targ2, &logpart);
- cexp(result, &expo);
- }
-
- /* takes the sine of arg and returns it in result */
-
- csin(result, arg)
- complex *result, *arg;
- {
- complex targ, exp1, exp2, part1,
- part2, sum, divisor;
-
- targ.re = arg->re;
- targ.im = arg->im;
- exp1.re = -targ.im;
- exp1.im = targ.re;
-
- cexp(&part1, &exp1);
-
- exp2.re = targ.im;
- exp2.im = -targ.re;
-
- cexp(&part2, &exp2);
- csub(&sum, &part1, &part2);
-
- divisor.re = 0.0;
- divisor.im = 2.0;
-
- cdiv(result, &sum, &divisor);
- }
-
- /* takes the cosine of arg and returns it in result */
-
- ccos(result, arg)
- complex *result, *arg;
- {
- complex targ, exp1, exp2, part1,
- part2, sum, divisor;
-
- targ.re = arg->re;
- targ.im = arg->im;
- exp1.re = -targ.im;
- exp1.im = targ.re;
-
- cexp(&part1, &exp1);
-
- exp2.re = targ.im;
- exp2.im = -targ.re;
-
- cexp(&part2, &exp2);
- cadd(&sum, &part1, &part2);
-
- divisor.re = 2.0;
- divisor.im = 0.0;
-
- cdiv(result, &sum, &divisor);
-