home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / g / gnu_c / pmlsrc23.zoo / pmltests / cc2c.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-19  |  11.1 KB  |  455 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *                N O T I C E                *
  4.  *                                    *
  5.  *            Copyright Abandoned, 1987, Fred Fish        *
  6.  *                                    *
  7.  *    This previously copyrighted work has been placed into the    *
  8.  *    public domain by the author (Fred Fish) and may be freely used    *
  9.  *    for any purpose, private or commercial.  I would appreciate    *
  10.  *    it, as a courtesy, if this notice is left in all copies and    *
  11.  *    derivative works.  Thank you, and enjoy...            *
  12.  *                                    *
  13.  *    The author makes no warranty of any kind with respect to this    *
  14.  *    product and explicitly disclaims any implied warranties of    *
  15.  *    merchantability or fitness for any particular purpose.        *
  16.  *                                    *
  17.  ************************************************************************
  18.  */
  19.  
  20. /*
  21.  *  FILE
  22.  *
  23.  *    cc2c.c   test complex to complex math functions
  24.  *
  25.  *  KEY WORDS
  26.  *
  27.  *    portable math library
  28.  *    test functions
  29.  *
  30.  *  DESCRIPTION
  31.  *
  32.  *    Tests double precision functions for the Portable Math
  33.  *    Library.  Tests those functions which expect two
  34.  *    double precision complex arguments and return a double
  35.  *    precision complex result.
  36.  *
  37.  *    Most of the test data in the current data file (cc2c.dat)
  38.  *    was generated using double precision FORTRAN arithmetic
  39.  *    on a Decsystem-20.
  40.  *
  41.  *    Note that the ordering of functions is important for
  42.  *    optimum error information.  Since some functions call
  43.  *    others in the library, the functions being called should
  44.  *    be tested first.  Naturally, an error in a lower level
  45.  *    function will cause propagation of errors up to higher
  46.  *    level functions.
  47.  *
  48.  *  USAGE
  49.  *
  50.  *    cc2c [-esv] [-l limit]
  51.  *
  52.  *        -e    =>    force error for each test
  53.  *                to verify error handling
  54.  *
  55.  *        -l    =>    report errors greater than
  56.  *                specified limit (default 10**-6)
  57.  *
  58.  *        -s    =>    print summary after tests
  59.  *
  60.  *        -v    =>    print each function, argument,
  61.  *                and result
  62.  *
  63.  *    Test directives are read from the standard input, which
  64.  *    may be redirected to the provided test file (cc2c.dat),
  65.  *    and any relative errors are automatically written to standard
  66.  *    output if they exceed a maximum allowable limit.
  67.  *    Each test directive has the form:
  68.  *
  69.  *        <name> <arg1> <arg2> <expected result>
  70.  *
  71.  *    Each field is separated by a one or more space character(s).
  72.  *    Both the argument and the expected result are given
  73.  *    in the form:
  74.  *
  75.  *        <real> <imag>
  76.  *
  77.  *    where <real> is the real part and <imag> is the
  78.  *    imaginary part, separated by one or more spaces.
  79.  *        
  80.  *        
  81.  *  NOTE
  82.  *
  83.  *    This program uses both the csubt and the cdiv routines,
  84.  *    which are pml functions!.  Thus if either of these screw
  85.  *    up, the results will be unpredictable.  BEWARE!
  86.  *
  87.  *  PROGRAMMER
  88.  *
  89.  *    Fred Fish
  90.  *    Tempe, Az 85281
  91.  *
  92.  */
  93.  
  94.  
  95. #include <stdio.h>
  96. #include <math.h>
  97. #include "pml.h"
  98.  
  99. #ifdef atarist
  100. #define STDERR    stdout
  101. #else
  102. #define STDERR stderr
  103. #endif
  104.  
  105. #define MAX_ABS_ERR 1.0e-6    /* Set to catch only gross errors */
  106.  
  107. static int vflag;        /* Flag for verbose option */
  108. static int eflag;        /* Simulate an error to error printout */
  109. static int sflag;        /* Flag to show final statistics */
  110.  
  111. static double max_abs_err = MAX_ABS_ERR;
  112.  
  113. /*
  114.  *    External functions which are used internally.
  115.  */
  116.  
  117. extern char *strtok ();
  118. extern double atof ();
  119. extern double cabs ();
  120. extern COMPLEX csubt ();
  121. extern COMPLEX cdiv ();
  122.  
  123. /*
  124.  *    External functions to be tested.
  125.  */
  126.  
  127. extern COMPLEX cadd();
  128. extern COMPLEX csubt();
  129. extern COMPLEX cdiv();
  130. extern COMPLEX cmult();
  131.  
  132.  
  133. /*
  134.  *    Define all recognized test functions.  Each function
  135.  *    must have an entry in this table, where each
  136.  *    entry contains the information specified in the 
  137.  *    structure "test".
  138.  *
  139.  */
  140.  
  141. struct test {            /* Structure of each function to be tested */
  142.     char *name;            /* Name of the function to test */
  143.     COMPLEX (*func)();        /* Pointer to the function's entry point */
  144.     double max_err;        /* Error accumulator for this function */
  145. };
  146.  
  147. static struct test tests[] = {    /* Table of all recognized functions */
  148.     "cadd", cadd, 0.0,         /* Complex addition */
  149.     "csubt", csubt, 0.0,     /* Complex subtraction */
  150.     "cdiv", cdiv, 0.0,         /* Complex division */
  151.     "cmult", cmult, 0.0,    /* Complex multiplication */
  152.     NULL, NULL, 0.0        /* Function list end marker */
  153. };
  154.  
  155.  
  156. /*
  157.  *  FUNCTION
  158.  *
  159.  *    main   entry point for cc2c test utility
  160.  *
  161.  *  PSEUDO CODE
  162.  *
  163.  *    Begin main
  164.  *        Process any options in command line.
  165.  *        Do all tests requested by stdin directives.
  166.  *        Report final statistics (if enabled).
  167.  *    End main
  168.  *
  169.  */
  170.  
  171. main (argc, argv)
  172. int argc;
  173. char *argv[];
  174. {
  175.     ENTER ("main");
  176.     DEBUGWHO (argv[0]);
  177.     options (argc, argv);
  178.     dotests (argv);
  179.     statistics ();
  180.     LEAVE ();
  181. }
  182.  
  183.  
  184. /*
  185.  *  FUNCTION
  186.  *
  187.  *    dotests   process each test from stdin directives
  188.  *
  189.  *  ERROR REPORTING
  190.  *
  191.  *    Note that in most cases, the error criterion is based
  192.  *    on relative error, defined as:
  193.  *
  194.  *        error = (result - expected) / expected
  195.  *
  196.  *    Naturally, if the expected result is zero, some
  197.  *    other criterion must be used.  In this case, the
  198.  *    absolute error is used.  That is:
  199.  *
  200.  *        error = result
  201.  *
  202.  *  PSEUDO CODE
  203.  *
  204.  *    Begin dotests
  205.  *        While a test directive is successfully read from stdin
  206.  *        Default function name to "{null}"
  207.  *        Default real part of argument to 0.0
  208.  *        Default imaginary part of argument to 0.0
  209.  *        Default expected result to 0.0
  210.  *        Extract function name, argument and expected result
  211.  *        Lookup test in available test list
  212.  *        If no test was found then
  213.  *            Tell user that unknown function was specified
  214.  *        Else
  215.  *            Call function with argument and save result
  216.  *            If the verify flag is set then
  217.  *            Print function name, argument, and result
  218.  *            End if
  219.  *            If the expected result is not zero then
  220.  *            Compute the relative error
  221.  *            Else
  222.  *            Use the absolute error
  223.  *            End if
  224.  *            Get absolute value of error
  225.  *            If error exceeds limit or error force flag set
  226.  *            Print error notification on stderr
  227.  *            End if
  228.  *            If this error is max for given function then
  229.  *            Remember this error for summary
  230.  *            End if
  231.  *        End if
  232.  *        End while
  233.  *    End dotests
  234.  *
  235.  */
  236.  
  237.  
  238. dotests (argv)
  239. char *argv[];
  240. {
  241.     char buffer[256];        /* Directive buffer */
  242.     char function[64];        /* Specified function name */
  243.     COMPLEX arg1;        /* Specified function argument 1 */
  244.     COMPLEX arg2;        /* Specified function argument 2 */
  245.     COMPLEX expected;        /* Specified expected result */
  246.     COMPLEX result;        /* Actual result */
  247.     COMPLEX error;        /* Relative or absolute error */
  248.     double abs_err;        /* Absolute value of error */
  249.     struct test *testp;        /* Pointer to function test */
  250.     struct test *lookup ();    /* Returns function test pointer */
  251.     register char *strp;    /* Pointer to next token in string */
  252.  
  253. #ifdef MJR
  254.     FILE * save_stdin, * re_stdin;
  255.     save_stdin = stdin;
  256.     re_stdin = freopen("cc2c.dat","r",stdin);
  257.     if( re_stdin == (FILE *)NULL ) {
  258.     exit(-33);
  259.     }
  260. #endif
  261.     ENTER ("dotests");
  262.     while (fgets (buffer, sizeof(buffer), stdin) != NULL) {
  263.     strcpy (function, "{null}");
  264.     arg1.real = arg1.imag = 0.0;
  265.     arg2.real = arg2.imag = 0.0;
  266.     expected.real = expected.imag = 0.0;
  267.     sscanf (buffer, "%s %le %le %le %le %le %le", function,
  268.         &arg1.real, &arg1.imag, &arg2.real, &arg2.imag,
  269.         &expected.real, &expected.imag);
  270.         testp = lookup (function);
  271.         if (testp == NULL) {
  272.             fprintf (STDERR, "%s: unknown function \"%s\".\n",
  273.             argv[0], function);
  274.         } else {
  275.         result = (*testp -> func)(arg1, arg2);
  276.         if (vflag) {
  277.             printf ("%s(%le + j %le, %le + j %le)\n",
  278.             function, arg1.real, arg1.imag, arg2.real, arg2.imag);
  279.         printf ("  = %30.23le + j %30.23le.\n", result.real,
  280.             result.imag);
  281.         }
  282.         if (expected.real != 0.0 || expected.imag != 0.0) {
  283.         error = csubt (result, expected);
  284.         error = cdiv (error, expected);
  285.         } else {
  286.         error = result;
  287.         }
  288.         abs_err = cabs (error);
  289.             if ((abs_err > max_abs_err) || eflag) {
  290.         fprintf (STDERR, "%s: error in \"%s\"\n", argv[0], function);
  291.         fprintf (STDERR, "\treal (arg1)\t\t%25.20le\n", arg1.real);
  292.         fprintf (STDERR, "\timag (arg1)\t\t%25.20le\n", arg1.imag);
  293.         fprintf (STDERR, "\treal (arg2)\t\t%25.20le\n", arg2.real);
  294.         fprintf (STDERR, "\timag (arg2)\t\t%25.20le\n", arg2.imag);
  295.         fprintf (STDERR, "\treal (result)\t\t%25.20le\n",result.real);
  296.         fprintf (STDERR, "\timag (result)\t\t%25.20le\n",result.imag);
  297.         fprintf (STDERR, "\treal (expected)\t\t%25.20le\n",expected.real);
  298.         fprintf (STDERR, "\timag (expected)\t\t%25.20le\n",expected.imag);
  299.             }
  300.         if (abs_err > testp -> max_err) {
  301.             testp -> max_err = abs_err;
  302.         }
  303.         }
  304.     }
  305. #ifdef MJR
  306.     fclose( re_stdin );
  307. #endif
  308.     LEAVE ();
  309. }
  310.  
  311.  
  312. /*
  313.  *  FUNCTION
  314.  *
  315.  *    options   process command line options
  316.  *
  317.  *  PSEUDO CODE
  318.  *
  319.  *    Begin options
  320.  *        Reset all flags to FALSE by default
  321.  *        Initialize flag argument scan pointer
  322.  *        If there is a second command line argument then
  323.  *        If the argument specifies flags then
  324.  *            While there is an unprocessed flag
  325.  *            Switch on flag
  326.  *            Case "force error flag":
  327.  *                Set the "force error" flag
  328.  *                Break switch
  329.  *            Case "print summary":
  330.  *                Set "print summary" flag
  331.  *                Break switch
  332.  *            Case "verbose":
  333.  *                Set "verbose" flag
  334.  *                Break switch
  335.  *            Default:
  336.  *                Tell user unknown flag
  337.  *                Break switch
  338.  *            End switch
  339.  *            End while
  340.  *        End if
  341.  *        End if
  342.  *    End options
  343.  *
  344.  */
  345.  
  346.  
  347. options (argc, argv)
  348. int argc;
  349. char *argv[];
  350. {
  351.     register int flag;
  352.     extern int getopt ();
  353.     extern char *optarg;
  354.  
  355.     ENTER ("options");
  356.     eflag = sflag = vflag = FALSE;
  357.     while ((flag = getopt (argc, argv, "#:el:sv")) != EOF) {
  358.     switch (flag) {
  359.         case '#':
  360.             DEBUGPUSH (optarg);
  361.         break;
  362.         case 'e':
  363.         eflag = TRUE;
  364.         break;
  365.         case 'l':
  366.             sscanf (optarg, "%le", &max_abs_err);
  367.         DEBUG3 ("args", "max_abs_err = %le", max_abs_err);
  368.         break;
  369.         case 's':
  370.         sflag = TRUE;
  371.         break;
  372.         case 'v':
  373.         vflag = TRUE;
  374.         break;
  375.     }
  376.     }
  377.     LEAVE ();
  378. }
  379.  
  380.  
  381. /*
  382.  *  FUNCTION
  383.  *
  384.  *    loopup   lookup test in known test list
  385.  *
  386.  *  DESCRIPTION
  387.  *
  388.  *    Given the name of a desired test, looks up the test
  389.  *    in the known test list and returns a pointer to the
  390.  *    test structure.
  391.  *
  392.  *    Since the table is so small we simply use a linear
  393.  *    search.
  394.  *
  395.  *  PSEUDO CODE
  396.  *
  397.  *    Begin lookup
  398.  *        For each known test
  399.  *        If the test's name matches the desired test name
  400.  *            Return pointer to the test structure
  401.  *        End if
  402.  *        End for
  403.  *    End lookup
  404.  *
  405.  */
  406.  
  407. struct test *lookup (funcname)
  408. char *funcname;
  409. {
  410.     struct test *testp;
  411.     struct test *rtnval;
  412.  
  413.     ENTER ("lookup");
  414.     rtnval = (struct test *) NULL;
  415.     for (testp = tests; testp -> name != NULL && rtnval == NULL; testp++) {
  416.     if (!strcmp (testp -> name, funcname)) {
  417.         rtnval = testp;
  418.      }
  419.     }
  420.     LEAVE ();
  421.     return (rtnval);
  422. }
  423.  
  424.  
  425. /*
  426.  *  FUNCTION
  427.  *
  428.  *    statistics   print final statistics if desired
  429.  *
  430.  *  PSEUDO CODE
  431.  *
  432.  *    Begin statistics
  433.  *        If a final statistics (summary) is desired then
  434.  *        For each test in the known test list
  435.  *            Print the maximum error encountered
  436.  *        End for
  437.  *        End if
  438.  *    End statistics
  439.  *
  440.  */
  441.  
  442. statistics ()
  443. {
  444.     struct test *tp;
  445.  
  446.     ENTER ("statistics");
  447.     if (sflag) {
  448.         for (tp = tests; tp -> name != NULL; tp++) {
  449.         printf ("%s:\tmaximum relative error %le\n", 
  450.             tp -> name, tp -> max_err);
  451.     }
  452.     }
  453.     LEAVE ();
  454. }
  455.