[comp.sources.unix] v10i056: Complex arithmetic library

rs@uunet.UU.NET (Rich Salz) (07/16/87)

Submitted-by: gwyn@brl.arpa (Doug Gwyn)
Posting-Number: Volume 10, Issue 56
Archive-name: complex-lib

[  Here is a package to do complex arithmetic; blame me for the Makefile.
	--r$  ]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile complex.3 complex.h cx_test.c cxadd.c cxampl.c
#   cxconj.c cxcons.c cxcopy.c cxdiv.c cxmul.c cxphas.c cxphsr.c
#   cxscal.c cxsqrt.c cxsub.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(395 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
XALL=complex.3 complex.h libcomplex.a
XOBJS=\
X    cxadd.o cxampl.o cxconj.o cxcons.o cxcopy.o cxdiv.o cxmul.o \
X    cxphas.o cxphsr.o cxscal.o cxsqrt.o cxsub.o
X
Xall:	$(ALL)
X
Xinstall:	$(ALL)
X	@echo install $(ALL) according to local convention.
X
Xcx_test:	cx_test.c libcomplex.a
X	$(CC) $(CFLAGS) -o cx_test cx_test.c libcomplex.a
X
Xlibcomplex.a:	$(OBJS)
X	ar r libcomplex.a $(OBJS)
X
X$(OBJS):	complex.h
END_OF_Makefile
if test 395 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f complex.3 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"complex.3\"
else
echo shar: Extracting \"complex.3\" \(5830 characters\)
sed "s/^X//" >complex.3 <<'END_OF_complex.3'
X'\" e
X.TH COMPLEX 3V LOCAL
X'\"	last edit:	86/02/03	D A Gwyn
X'\"	SCCS ID:	@(#)complex.3	1.2 (modified for public version)
X.EQ
Xdelim @@
X.EN
X.SH NAME
Xcomplex \- complex arithmetic operations
X.SH SYNOPSIS
X.B
X#include <complex.h>	/* assuming appropriate cc \-I option */
X.br
X/* All the following functions are declared in this header file. */
X.P
X.B complex *CxAdd(ap,bp);
X.br
X.B complex *ap, *bp;
X.P
X.B complex *CxSub(ap,bp);
X.br
X.B complex *ap, *bp;
X.P
X.B complex *CxMul(ap,bp);
X.br
X.B complex *ap, *bp;
X.P
X.B complex *CxDiv(ap,bp);
X.br
X.B complex *ap, *bp;
X.P
X.B complex *CxSqrt(cp);
X.br
X.B complex *cp;
X.P
X.B complex *CxScal(cp,\^s);
X.br
X.B complex *cp;
X.br
X.B double s;
X.P
X.B complex *CxNeg(cp);
X.br
X.B complex *cp;
X.P
X.B complex *CxConj(cp);
X.br
X.B complex *cp;
X.P
X.B complex *CxCopy(ap,bp);
X.br
X.B complex *ap, *bp;
X.P
X.B complex *CxCons(cp,\^r,\^i);
X.br
X.B complex *cp;
X.br
X.B double r, i;
X.P
X.B complex *CxPhsr(cp,m,p);
X.br
X.B complex *cp;
X.br
X.B double m, p;
X.P
X.B double CxReal(cp);
X.br
X.B complex *cp;
X.P
X.B double CxImag(cp);
X.br
X.B complex *cp;
X.P
X.B double CxAmpl(cp);
X.br
X.B complex *cp;
X.P
X.B double CxPhas(cp);
X.br
X.B complex *cp;
X.P
X.B complex *CxAllo(\ );
X.P
X.B void CxFree(cp);
X.br
X.B complex *cp;
X.SH DESCRIPTION
XThese routines perform arithmetic
Xand other useful operations on complex numbers.
XAn appropriate data structure
X.B complex
Xis defined in the header file;
Xall access to
X.B complex
Xdata should be
X.I via
Xthese predefined functions.
X(See
X.SM HINTS
Xfor further information.)
X.P
XIn the following descriptions,
Xthe names
X.IR a ,
X.IR b ,
Xand
X.I c
Xrepresent the
X.B complex
Xdata addressed by the corresponding pointers
X.IR ap ,
X.IR bp ,
Xand
X.IR cp .
X.P
X.I CxAdd\^
Xadds
X.I b
Xto
X.I a
Xand returns a pointer to the result.
X.P
X.I CxSub
Xsubtracts
X.I b
Xfrom
X.I a
Xand returns a pointer to the result.
X.P
X.I CxMul\^
Xmultiplies
X.I a
Xby
X.I b
Xand returns a pointer to the result.
X.P
X.I CxDiv
Xdivides
X.I a
Xby
X.I b
Xand returns a pointer to the result.
XThe divisor must not be precisely zero.
X.P
X.I CxSqrt
Xreplaces
X.I c
Xby the ``principal value'' of its square root
X(one having a non-negative imaginary part)
Xand returns a pointer to the result.
X.P
X.I CxScal\^
Xmultiplies
X.I c
Xby the scalar
X.I s
Xand returns a pointer to the result.
X.P
X.I CxNeg
Xnegates
X.I c
Xand returns a pointer to the result.
X.P
X.I CxConj
Xconjugates
X.I c
Xand returns a pointer to the result.
X.P
X.I CxCopy
Xassigns the value of
X.I b
Xto
X.I a
Xand returns a pointer to the result.
X.P
X.I CxCons
Xconstructs the complex number
X.I c
Xfrom its real and imaginary parts
X.I r
Xand
X.IR i ,
Xrespectively,
Xand returns a pointer to the result.
X.P
X.I CxPhsr
Xconstructs the complex number
X.I c
Xfrom its ``phasor'' amplitude and phase (given in radians)
X.I m
Xand
X.IR p ,
Xrespectively,
Xand returns a pointer to the result.
X.P
X.I CxReal\^
Xreturns the real part of the complex number
X.IR c .
X.P
X.I CxImag
Xreturns the imaginary part of the complex number
X.IR c .
X.P
X.I CxAmpl\^
Xreturns the amplitude of the complex number
X.IR c .
X.P
X.I CxPhas
Xreturns the phase of the complex number
X.IR c ,
Xas radians in the range @(- pi , pi ]@.
X.P
X.I CxAllo
Xallocates storage for a
X.B complex
Xdatum; it returns
X.SM
X.B NULL
X(defined as 0 in
X.BR <stdio.h> )
Xif not enough storage is available.
X.P
X.I CxFree
Xreleases storage previously allocated by
X.IR CxAllo .
XThe contents of such storage must not be used afterward.
X.SH HINTS
XThe
X.B complex
Xdata type consists of real and imaginary components;
X.I CxReal\^
Xand
X.I CxImag
Xare actually macros that access these components directly.
XThis allows addresses of the components to be taken,
Xas in the following \s-1EXAMPLE\s0.
X.P
XThe complex functions are designed to be nested;
Xsee the following \s-1EXAMPLE\s0.
XFor this reason,
Xmany of them modify the contents of their first parameter.
X.I CxCopy
Xcan be used to create a ``working copy'' of
X.B complex
Xdata that would otherwise be modified.
X.P
XThe square-root function is inherently double-valued;
Xin most applications, both roots should receive equal consideration.
XThe second root is the negative of the ``principal value''.
X.bp
X.SH EXAMPLE
XThe following program is compiled by the command
X.br
X	$ \fIcc \|\-I/usr/local/include \|example.c \|/usr/local/lib/libcomplex.a \|\-lm\fP
X.br
XIt reads in two complex vectors,
Xthen computes and prints their inner product.
X.sp
X.P
X	#include	<stdio.h>
X.br
X	#include	<complex.h>
X.sp
X	main( argc, argv )
X.br
X		int		argc;
X.br
X		char		*argv[\|];
X.br
X		{
X.br
X		int		n;		/* # elements in each array */
X.br
X		int		i;		/* indexes arrays */
X.br
X		complex		a[10], b[10];	/* input vectors */
X.br
X		complex		s;		/* accumulates scalar product */
X.br
X		complex		*c = CxAllo(\|);	/* holds cross-term */
X.sp
X		if ( c == NULL )
X.br
X			{
X.br
X			(void)fprintf( stderr, ``not enough memory\en'' );
X.br
X			return 1;
X.br
X			}
X.br
X		(void)printf( ``\enenter number of elements: '' );
X.br
X		(void)scanf( `` %d'', &n );
X.br
X		/* (There really should be some input validation here.) */
X.br
X		(void) printf( ``\enenter real, imaginary pairs for first array:\en'' );
X.br
X		for ( i = 0; i < n; ++i )
X.br
X			(void)scanf( `` %lg %lg'', &CxReal( &a[i] ), &CxImag( &a[i] ) );
X.br
X		(void)printf( ``\enenter real, imaginary pairs for second array:\en'' );
X.br
X		for ( i = 0; i < n; ++i )
X.br
X			(void)scanf( `` %lg %lg'', &CxReal( &b[i] ), &CxImag( &b[i] ) );
X.br
X		(void)CxCons( &s, 0.0, 0.0 );	/* initialize accumulator */
X.br
X		for ( i = 0; i < n; ++i )
X.br
X			(void)CxAdd( &s, CxMul( &a[i], CxConj( CxCopy( c, &b[i] ) ) ) );
X.br
X		(void)printf( ``\enproduct is (%g,%g)\en'', CxReal( &s ), CxImag( &s ) );
X.br
X		CxFree( c );
X.br
X		return 0;
X.br
X		}
X.SH FILES
X/usr/local/include/complex.h		header file containing definitions
X.br
X/usr/local/lib/libcomplex.a		complex run-time support library
X.SH AUTHORS
XDouglas A. Gwyn, BRL/VLD-VMB
X.br
XJeff Hanes, BRL/VLD-VMB (original version of
X.IR CxSqrt\^ )
END_OF_complex.3
if test 5830 -ne `wc -c <complex.3`; then
    echo shar: \"complex.3\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f complex.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"complex.h\"
else
echo shar: Extracting \"complex.h\" \(966 characters\)
sed "s/^X//" >complex.h <<'END_OF_complex.h'
X/*
X	<complex.h> -- definitions for complex arithmetic routines
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)complex.h	1.1 (modified for public version)
X*/
X
X/* "complex number" data type: */
X
Xtypedef struct
X	{
X	double		re;		/* real part */
X	double		im;		/* imaginary part */
X	}	complex;
X
X/* "The future is now": */
X
X#ifdef __STDC__	/* X3J11 */
X#define	_CxGenPtr	void *		/* generic pointer type */
X#else		/* K&R */
X#define	_CxGenPtr	char *		/* generic pointer type */
X#endif
X
X/* functions that are correctly done as macros: */
X
X#define	CxAllo()		((complex *)malloc( sizeof (complex) ))
X#define	CxFree( cp )		free( (_CxGenPtr)(cp) )
X#define	CxNeg( cp )		CxScal( cp, -1.0 )
X#define	CxReal( cp )		(cp)->re
X#define	CxImag( cp )		(cp)->im
X
Xextern void		free();
Xextern _CxGenPtr	malloc();
X
X/* library functions: */
X
Xextern double	CxAmpl(), CxPhas();
Xextern complex	*CxAdd(), *CxConj(), *CxCons(), *CxCopy(), *CxDiv(),
X		*CxMul(), *CxPhsr(), *CxScal(), *CxSqrt(), *CxSub();
END_OF_complex.h
if test 966 -ne `wc -c <complex.h`; then
    echo shar: \"complex.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cx_test.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cx_test.c\"
else
echo shar: Extracting \"cx_test.c\" \(4250 characters\)
sed "s/^X//" >cx_test.c <<'END_OF_cx_test.c'
X/*
X	ctest -- complex arithmetic test
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cx_test.c	1.1 (modified for public version)
X*/
X
X#include	<stdio.h>
X#include	<math.h>
X
X#include	<complex.h>
X
X#define DEGRAD	57.2957795130823208767981548141051703324054724665642
X					/* degrees per radian */
X#define Abs( x )	((x) < 0 ? -(x) : (x))
X#define Max( a, b )	((a) > (b) ? (a) : (b))
X
Xextern void	exit();
X
X#define	Printf	(void)printf
X
X#define	TOL	1.0e-10			/* tolerance for checks */
X
Xstatic int	errs = 0;		/* tally errors */
X
Xstatic void	CCheck(), RCheck();
Xstatic double	RelDif();
X
X
X/*ARGSUSED*/
Xmain( argc, argv )
X	int	argc;
X	char	*argv[];
X	{
X	complex a, *bp, *cp;
X
X	/* CxAllo test */
X	bp = CxAllo();
X	if ( bp == NULL )
X		{
X		Printf( "CxAllo failed\n" );
X		exit( 1 );
X		}
X
X	/* CxReal, CxImag test */
X	CxReal( bp ) = 1.0;
X	CxImag( bp ) = 2.0;
X	RCheck( "CxReal", CxReal( bp ), 1.0 );
X	RCheck( "CxImag", CxImag( bp ), 2.0 );
X
X	/* CxCons test */
X	cp = CxCons( &a, -3.0, -4.0);
X	CCheck( "CxCons 1", a, -3.0, -4.0 );
X	CCheck( "CxCons 2", *cp, -3.0, -4.0 );
X
X	/* CxNeg test */
X	cp = CxNeg( &a );
X	CCheck( "CxNeg 1", a, 3.0, 4.0 );
X	CCheck( "CxNeg 2", *cp, 3.0, 4.0 );
X
X	/* CxCopy test */
X	cp = CxCopy( bp, &a );
X	(void)CxCons( &a, 1.0, sqrt( 3.0 ) );
X	CCheck( "CxCopy 1", *bp, 3.0, 4.0 );
X	CCheck( "CxCopy 2", *cp, 3.0, 4.0 );
X
X	/* CxAmpl, CxPhas test */
X	RCheck( "CxAmpl 1", CxAmpl( &a ), 2.0 );
X	RCheck( "CxPhas 1", CxPhas( &a ) * DEGRAD, 60.0 );
X	/* try other quadrants */
X	a.re = -a.re;
X	RCheck( "CxAmpl 2", CxAmpl( &a ), 2.0 );
X	RCheck( "CxPhas 2", CxPhas( &a ) * DEGRAD, 120.0 );
X	a.im = -a.im;
X	RCheck( "CxAmpl 3", CxAmpl( &a ), 2.0 );
X	RCheck( "CxPhas 3", CxPhas( &a ) * DEGRAD, -120.0 );
X	a.re = -a.re;
X	RCheck( "CxAmpl 4", CxAmpl( &a ), 2.0 );
X	RCheck( "CxPhas 4", CxPhas( &a ) * DEGRAD, -60.0 );
X	/* one more for good measure */
X	RCheck( "CxAmpl 5", CxAmpl( bp ), 5.0 );
X
X	/* CxPhsr test */
X	cp = CxPhsr( &a, 100.0, -20.0 / DEGRAD );
X	RCheck( "CxPhsr 1", CxAmpl( &a ), 100.0 );
X	RCheck( "CxPhsr 2", CxPhas( &a ) * DEGRAD, -20.0 );
X	RCheck( "CxPhsr 3", CxAmpl( cp ), 100.0 );
X	RCheck( "CxPhsr 4", CxPhas( cp ) * DEGRAD, -20.0 );
X
X	/* CxConj test */
X	cp = CxConj( bp );
X	CCheck( "CxConj 1", *bp, 3.0, -4.0 );
X	CCheck( "CxConj 2", *cp, 3.0, -4.0 );
X
X	/* CxScal test */
X	cp = CxScal( bp, 2.0 );
X	CCheck( "CxScal 1", *bp, 6.0, -8.0 );
X	CCheck( "CxScal 2", *cp, 6.0, -8.0 );
X
X	/* CxAdd test */
X	cp = CxAdd( CxCons( &a, -4.0, 11.0 ), bp );
X	CCheck( "CxAdd 1", a, 2.0, 3.0 );
X	CCheck( "CxAdd 2", *cp, 2.0, 3.0 );
X
X	/* CxSub test */
X	cp = CxSub( CxCons( &a, 4.0, 7.0 ), bp );
X	CCheck( "CxSub 1", a, -2.0, 15.0 );
X	CCheck( "CxSub 2", *cp, -2.0, 15.0 );
X
X	/* CxMul test */
X	cp = CxMul( CxCons( bp, -1.0, 3.0 ), CxCons( &a, 1.0, 2.0 ) );
X	CCheck( "CxMul 1", *bp, -7.0, 1.0 );
X	CCheck( "CxMul 2", *cp, -7.0, 1.0 );
X
X	/* CxDiv test */
X	cp = CxDiv( bp, &a );
X	CCheck( "CxDiv 1", *bp, -1.0, 3.0 );
X	CCheck( "CxDiv 2", *cp, -1.0, 3.0 );
X
X	/* CxSqrt and overlapping CxMul tests */
X	(void)CxCons( &a, -1.0, 2.0 );
X	cp = CxSqrt( CxMul( &a, &a ) );
X	CCheck( "CxSqrt 1", a, -1.0, 2.0 );
X	CCheck( "CxSqrt 2", *cp, -1.0, 2.0 );
X	(void)CxCons( &a, 3.0, 2.0 );
X	cp = CxSqrt( CxMul( &a, &a ) );
X	CCheck( "CxSqrt 3", a, 3.0, 2.0 );
X	CCheck( "CxSqrt 4", *cp, 3.0, 2.0 );
X
X	/* CxFree "test" */
X	CxFree( bp );
X
X	return errs;
X	}
X
X
Xstatic void
XCCheck( s, c, r, i )			/* check complex number */
X	char	*s;			/* message string for failure */
X	complex	c;			/* complex to be checked */
X	double	r, i;			/* expected real, imaginary parts */
X	{
X	if ( RelDif( CxReal( &c ), r ) > TOL
X	  || RelDif( CxImag( &c ), i ) > TOL
X	   )	{
X		++errs;
X		Printf( "%s; s.b. (%f,%f), was (%g,%g)\n",
X			s, r, i, c.re, c.im
X		      );
X		}
X	}
X
X
Xstatic void
XRCheck( s, d, r )			/* check real number */
X	char	*s;			/* message string for failure */
X	double	d;			/* real to be checked */
X	double	r;			/* expected value */
X	{
X	if ( RelDif( d, r ) > TOL )
X		{
X		++errs;
X		Printf( "%s; s.b. %f, was %g\n", s, r, d );
X		}
X	}
X
X
Xstatic double
XRelDif( a, b )			/* returns relative difference:	*/
X	double	a, b;		/* 0.0 if exactly the same,
X				   otherwise ratio of difference
X				   to the larger of the two	*/
X	{
X	double	c = Abs( a );
X	double	d = Abs( b );
X
X	d = Max( c, d );
X
X	return d == 0.0 ? 0.0 : Abs( a - b ) / d;
X	}
END_OF_cx_test.c
if test 4250 -ne `wc -c <cx_test.c`; then
    echo shar: \"cx_test.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxadd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxadd.c\"
else
echo shar: Extracting \"cxadd.c\" \(304 characters\)
sed "s/^X//" >cxadd.c <<'END_OF_cxadd.c'
X/*
X	CxAdd -- add one complex to another
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxadd.c	1.1
X
X	CxAdd( &a, &b )	adds  b  to  a  and returns  &a
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxAdd( ap, bp )
X	register complex	*ap, *bp;	/* may coincide */
X	{
X	ap->re += bp->re;
X	ap->im += bp->im;
X
X	return ap;
X	}
END_OF_cxadd.c
if test 304 -ne `wc -c <cxadd.c`; then
    echo shar: \"cxadd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxampl.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxampl.c\"
else
echo shar: Extracting \"cxampl.c\" \(278 characters\)
sed "s/^X//" >cxampl.c <<'END_OF_cxampl.c'
X/*
X	CxAmpl -- amplitude (magnitude, modulus, norm) of a complex
X
X	CxAmpl( &c )	returns  |c|
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxampl.c	1.1
X*/
X
X#include	<math.h>
X
X#include	<complex.h>
X
Xdouble
XCxAmpl( cp )
X	register complex	*cp;
X	{
X	return hypot( cp->re, cp->im );
X	}
END_OF_cxampl.c
if test 278 -ne `wc -c <cxampl.c`; then
    echo shar: \"cxampl.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxconj.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxconj.c\"
else
echo shar: Extracting \"cxconj.c\" \(278 characters\)
sed "s/^X//" >cxconj.c <<'END_OF_cxconj.c'
X/*
X	CxConj -- conjugate a complex
X
X	CxConj( &c )	conjugates  c  and returns  &c
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxconj.c	1.1
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxConj( cp )
X	register complex	*cp;
X	{
X	/* (real part unchanged) */
X	cp->im = -cp->im;
X
X	return cp;
X	}
END_OF_cxconj.c
if test 278 -ne `wc -c <cxconj.c`; then
    echo shar: \"cxconj.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxcons.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxcons.c\"
else
echo shar: Extracting \"cxcons.c\" \(329 characters\)
sed "s/^X//" >cxcons.c <<'END_OF_cxcons.c'
X/*
X	CxCons -- construct a complex from real and imaginary parts
X
X	CxCons( &c, re, im )	makes  c = re + i im  and returns  &c
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxcons.c	1.1
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxCons( cp, re, im )
X	register complex	*cp;
X	double			re, im;
X	{
X	cp->re = re;
X	cp->im = im;
X
X	return cp;
X	}
END_OF_cxcons.c
if test 329 -ne `wc -c <cxcons.c`; then
    echo shar: \"cxcons.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxcopy.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxcopy.c\"
else
echo shar: Extracting \"cxcopy.c\" \(264 characters\)
sed "s/^X//" >cxcopy.c <<'END_OF_cxcopy.c'
X/*
X	CxCopy -- copy a complex
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxcopy.c	1.1
X
X	CxCopy( &a, &b )	copies  b  to  a  and returns  &a
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxCopy( ap, bp )
X	complex	*ap, *bp;		/* may coincide */
X	{
X	*ap = *bp;
X
X	return ap;
X	}
END_OF_cxcopy.c
if test 264 -ne `wc -c <cxcopy.c`; then
    echo shar: \"cxcopy.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxdiv.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxdiv.c\"
else
echo shar: Extracting \"cxdiv.c\" \(820 characters\)
sed "s/^X//" >cxdiv.c <<'END_OF_cxdiv.c'
X/*
X	CxDiv -- divide one complex by another
X
X	CxDiv( &a, &b )	divides  a  by  b  and returns  &a;
X			zero divisor fails
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxdiv.c	1.1 (modified for public version)
X*/
X
X#include	<complex.h>
X
X#define Abs( x )	((x) < 0 ? -(x) : (x))
X
Xcomplex *
XCxDiv( ap, bp )
X	register complex	*ap, *bp;	/* may coincide (?) */
X	{
X	double	r, s;
X	double	ap__re = ap->re;
X
X	/* Note: classical formula may cause unnecessary overflow */
X	r = bp->re;
X	s = bp->im;
X	if ( Abs( r ) >= Abs( s ) )
X		{
X		r = s / r;		/* <= 1 */
X		s = bp->re + r * s;
X		ap->re = (ap->re + ap->im * r) / s;
X		ap->im = (ap->im - ap__re * r) / s;
X		}
X	else /* Abs( s ) > Abs( r ) */
X		{
X		r = r / s;		/* < 1 */
X		s = s + r * bp->re;
X		ap->re = (ap->re * r + ap->im) / s;
X		ap->im = (ap->im * r - ap__re) / s;
X		}
X
X	return ap;
X	}
END_OF_cxdiv.c
if test 820 -ne `wc -c <cxdiv.c`; then
    echo shar: \"cxdiv.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxmul.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxmul.c\"
else
echo shar: Extracting \"cxmul.c\" \(424 characters\)
sed "s/^X//" >cxmul.c <<'END_OF_cxmul.c'
X/*
X	CxMul -- multiply one complex by another
X
X	CxMul( &a, &b )	multiplies  a  by  b  and returns  &a
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxmul.c	1.1
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxMul( ap, bp )
X	register complex	*ap, *bp;	/* (may coincide) */
X	{
X	double			ap__re = ap->re;
X	double			bp__re = bp->re;
X
X	ap->re = ap__re * bp__re - ap->im * bp->im;
X	ap->im = ap__re * bp->im + ap->im * bp__re;
X
X	return ap;
X	}
END_OF_cxmul.c
if test 424 -ne `wc -c <cxmul.c`; then
    echo shar: \"cxmul.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxphas.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxphas.c\"
else
echo shar: Extracting \"cxphas.c\" \(406 characters\)
sed "s/^X//" >cxphas.c <<'END_OF_cxphas.c'
X/*
X	CxPhas -- phase (angle, argument) of a complex
X
X	CxPhas( &c )	returns  arg(c)  in radians (-Pi,Pi]
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxphas.c	1.1 (modified for public version)
X*/
X
X#include	<math.h>
X
X#include	<complex.h>
X
Xdouble
XCxPhas( cp )
X	register complex	*cp;
X	{
X	if ( cp->re == 0.0 && cp->im == 0.0 )
X		return 0.0;		/* can't trust atan2() */
X	else
X		return atan2( cp->im, cp->re );
X	}
END_OF_cxphas.c
if test 406 -ne `wc -c <cxphas.c`; then
    echo shar: \"cxphas.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxphsr.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxphsr.c\"
else
echo shar: Extracting \"cxphsr.c\" \(395 characters\)
sed "s/^X//" >cxphsr.c <<'END_OF_cxphsr.c'
X/*
X	CxPhsr -- construct a complex "phasor" from amplitude and phase
X
X	CxPhsr( &c, amp, phs )	makes  c = amp exp(i phs)
X					and returns  &c
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxphsr.c	1.1
X*/
X
X#include	<math.h>
X
X#include	<complex.h>
X
Xcomplex *
XCxPhsr( cp, amp, phs )
X	register complex	*cp;
X	double			amp, phs;
X	{
X	cp->re = amp * cos( phs );
X	cp->im = amp * sin( phs );
X
X	return cp;
X	}
END_OF_cxphsr.c
if test 395 -ne `wc -c <cxphsr.c`; then
    echo shar: \"cxphsr.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxscal.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxscal.c\"
else
echo shar: Extracting \"cxscal.c\" \(291 characters\)
sed "s/^X//" >cxscal.c <<'END_OF_cxscal.c'
X/*
X	CxScal -- multiply a complex by a scalar
X
X	CxScal( &c, s )	scales  c  by  s  and returns  &c
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxscal.c	1.1
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxScal( cp, s )
X	register complex	*cp;
X	double			s;
X	{
X	cp->re *= s;
X	cp->im *= s;
X
X	return cp;
X	}
END_OF_cxscal.c
if test 291 -ne `wc -c <cxscal.c`; then
    echo shar: \"cxscal.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxsqrt.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxsqrt.c\"
else
echo shar: Extracting \"cxsqrt.c\" \(1339 characters\)
sed "s/^X//" >cxsqrt.c <<'END_OF_cxsqrt.c'
X/*
X	CxSqrt -- compute square root of complex number
X
X	CxSqrt( &c )	replaces  c  by  sqrt(c)  and returns  &c
X
X	Note:	This is a double-valued function; the result of
X		CxSqrt() always has nonnegative imaginary part.
X
X	inspired by Jeff Hanes' version
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxsqrt.c	1.1 (modified for public version)
X*/
X
X#include	<math.h>
X
X#include	<complex.h>
X
X#define	Sgn( x )	((x) == 0 ? 0 : (x) > 0 ? 1 : -1)
X
Xcomplex *
XCxSqrt( cp )
X	register complex	*cp;
X	{
X	/* record signs of original real & imaginary parts */
X	int			re_sign = Sgn( cp->re );
X	int			im_sign = Sgn( cp->im );
X
X	/* special cases are not necessary; they are here for speed */
X
X	if ( re_sign == 0 )
X		if ( im_sign == 0 )
X			;		/* (0,0) already there */
X		else if ( im_sign > 0 )
X			cp->re = cp->im = sqrt( cp->im / 2.0 );
X		else			/* im_sign < 0 */
X			cp->re = -(cp->im = sqrt( -cp->im / 2.0 ));
X	else if ( im_sign == 0 )
X		if ( re_sign > 0 )
X			cp->re = sqrt( cp->re );
X/*			cp->im = 0.0;	/* 0 already there */
X		else	{		/* re_sign < 0 */
X			cp->im = sqrt( -cp->re );
X			cp->re = 0.0;
X			}
X	else	{			/* no shortcuts */
X		double	ampl = CxAmpl( cp );
X
X		cp->im = sqrt( (ampl - cp->re) /2.0 );
X
X		if ( im_sign > 0 )
X			cp->re = sqrt( (ampl + cp->re) / 2.0 );
X		else			/* im_sign < 0 */
X			cp->re = -sqrt( (ampl + cp->re) / 2.0 );
X		}
X
X	return cp;
X	}
END_OF_cxsqrt.c
if test 1339 -ne `wc -c <cxsqrt.c`; then
    echo shar: \"cxsqrt.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cxsub.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cxsub.c\"
else
echo shar: Extracting \"cxsub.c\" \(320 characters\)
sed "s/^X//" >cxsub.c <<'END_OF_cxsub.c'
X/*
X	CxSub -- subtract one complex from another
X
X	CxSub( &a, &b )	subtracts  b  from  a  and returns  &a
X
X	last edit:	86/01/04	D A Gwyn
X
X	SCCS ID:	@(#)cxsub.c	1.1
X*/
X
X#include	<complex.h>
X
Xcomplex *
XCxSub( ap, bp )
X	register complex	*ap, *bp;	/* (may coincide) */
X	{
X	ap->re -= bp->re;
X	ap->im -= bp->im;
X
X	return ap;
X	}
END_OF_cxsub.c
if test 320 -ne `wc -c <cxsub.c`; then
    echo shar: \"cxsub.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net
-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net