     COMPLEX(3V)                                                     COMPLEX(3V)
                                        LOCAL

     NAME
          complex - complex arithmetic operations

     SYNOPSIS
          #include <complex.h>     /* assuming appropriate cc -I option */
          /* All the following functions are declared in this header file. */

          complex *CxAdd(ap,bp);
          complex *ap, *bp;

          complex *CxSub(ap,bp);
          complex *ap, *bp;

          complex *CxMul(ap,bp);
          complex *ap, *bp;

          complex *CxDiv(ap,bp);
          complex *ap, *bp;

          complex *CxSqrt(cp);
          complex *cp;

          complex *CxScal(cp,s);
          complex *cp;
          double s;

          complex *CxNeg(cp);
          complex *cp;

          complex *CxConj(cp);
          complex *cp;

          complex *CxCopy(ap,bp);
          complex *ap, *bp;

          complex *CxCons(cp,r,i);
          complex *cp;
          double r, i;

          complex *CxPhsr(cp,m,p);
          complex *cp;
          double m, p;

          double CxReal(cp);
          complex *cp;

          double CxImag(cp);
          complex *cp;

          double CxAmpl(cp);
          complex *cp;

                                        - 1 -            Formatted:  May 25, 2000

     COMPLEX(3V)                                                      COMPLEX(3V)
                                        LOCAL

          double CxPhas(cp);
          complex *cp;

          complex *CxAllo( );

          void CxFree(cp);
          complex *cp;

     DESCRIPTION
          These routines perform arithmetic and other useful operations on
          complex numbers.  An appropriate data structure complex is defined in
          the header file; all access to complex data should be via these
          predefined functions.  (See HINTS for further information.)

          In the following descriptions, the names a, b, and c represent the
          complex data addressed by the corresponding pointers ap, bp, and cp.

          CxAdd adds b to a and returns a pointer to the result.

          CxSub subtracts b from a and returns a pointer to the result.

          CxMul multiplies a by b and returns a pointer to the result.

          CxDiv divides a by b and returns a pointer to the result.  The divisor
          must not be precisely zero.

          CxSqrt replaces c by the ``principal value'' of its square root (one
          having a non-negative imaginary part) and returns a pointer to the
          result.

          CxScal multiplies c by the scalar s and returns a pointer to the
          result.

          CxNeg negates c and returns a pointer to the result.

          CxConj conjugates c and returns a pointer to the result.

          CxCopy assigns the value of b to a and returns a pointer to the
          result.

          CxCons constructs the complex number c from its real and imaginary
          parts r and i, respectively, and returns a pointer to the result.

          CxPhsr constructs the complex number c from its ``phasor'' amplitude
          and phase (given in radians) m and p, respectively, and returns a
          pointer to the result.

          CxReal returns the real part of the complex number c.

          CxImag returns the imaginary part of the complex number c.

                                        - 2 -           Formatted:  May 25, 2000

     COMPLEX(3V)                                                     COMPLEX(3V)
                                        LOCAL

          CxAmpl returns the amplitude of the complex number c.

          CxPhas returns the phase of the complex number c, as radians in the
          range (-PI,PI].

          CxAllo allocates storage for a complex datum; it returns NULL (defined
          as 0 in <stdio.h>) if not enough storage is available.

          CxFree releases storage previously allocated by CxAllo.  The contents
          of such storage must not be used afterward.

     HINTS
          The complex data type consists of real and imaginary components;
          CxReal and CxImag are actually macros that access these components
          directly.  This allows addresses of the components to be taken, as in
          the following EXAMPLE.

          The complex functions are designed to be nested; see the following
          EXAMPLE.  For this reason, many of them modify the contents of their
          first parameter.  CxCopy can be used to create a ``working copy'' of
          complex data that would otherwise be modified.

          The square-root function is inherently double-valued; in most
          applications, both roots should receive equal consideration.  The
          second root is the negative of the ``principal value''.

                                        - 3 -           Formatted:  May 25, 2000

     COMPLEX(3V)                                                     COMPLEX(3V)
                                        LOCAL

     EXAMPLE
          The following program is compiled by the command
               $ cc -I/usr/local/include example.c /usr/local/lib/libcomplex.a
          -lm
          It reads in two complex vectors, then computes and prints their inner
          product.

               #include  <stdio.h>
               #include  <complex.h>

               main( argc, argv )
                    int       argc;
                    char      *argv[];
                    {
                    int       n;        /* # elements in each array */
                    int       i;        /* indexes arrays */
                    complex        a[10], b[10];  /* input vectors */
                    complex        s;        /* accumulates scalar product */
                    complex        *c = CxAllo(); /* holds cross-term */

                    if ( c == NULL )
                         {
                         (void)fprintf( stderr, ``not enough memory\n'' );
                         return 1;
                         }
                    (void)printf( ``\nenter number of elements: '' );
                    (void)scanf( `` %d'', &n );
                    /* (There really should be some input validation here.) */
                    (void) printf( ``\nenter real, imaginary pairs for first
          array:\n'' );
                    for ( i = 0; i < n; ++i )
                         (void)scanf( `` %lg %lg'', &CxReal( &a[i] ), &CxImag(
          &a[i] ) );
                    (void)printf( ``\nenter real, imaginary pairs for second
          array:\n'' );
                    for ( i = 0; i < n; ++i )
                         (void)scanf( `` %lg %lg'', &CxReal( &b[i] ), &CxImag(
          &b[i] ) );
                    (void)CxCons( &s, 0.0, 0.0 ); /* initialize accumulator */
                    for ( i = 0; i < n; ++i )
                         (void)CxAdd( &s, CxMul( &a[i], CxConj( CxCopy( c, &b[i]
          ) ) ) );
                    (void)printf( ``\nproduct is (%g,%g)\n'', CxReal( &s ),
          CxImag( &s ) );
                    CxFree( c );
                    return 0;
                    }

     FILES
          /usr/local/include/complex.h       header file containing definitions

                                        - 4 -           Formatted:  May 25, 2000

     COMPLEX(3V)                                                     COMPLEX(3V)
                                        LOCAL

          /usr/local/lib/libcomplex.a        complex run-time support library

     AUTHORS
          Douglas A. Gwyn, BRL/VLD-VMB
          Jeff Hanes, BRL/VLD-VMB (original version of CxSqrt)

                                        - 5 -           Formatted:  May 25, 2000