/* * $Header: /home/gene/library/website/docsrc/test-rpc/src/src/RCS/test0007.c,v 395.1 2008/04/20 17:25:55 gene Exp $ * * Copyright (c) 2006 Gene Michael Stover. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 of the * License, 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ /* * Use a memory XDR stream to decode a bunch of double-precision * floating point numbers. * We hard-code the individual octets of the XDR stream, & * we check the values that it decodes. */ #include "this.h" /* * Compare a decoded double value with an expected value. * Because we are dealing with floating point, we cannot * use a simple "=" comparison. Instead, we check that * the numbers are close enough. * They are close enough if: * * 1. They have the same sign, * * 2. They have the same magnitude (exponent), & * * 3. The different in the mantissas is at most the two * least significant bits. */ static bool_t S_EqualDouble (double a, double b) { static double mantissa = 52; /* bits in the mantissa */ static double forgiven_bits = 2; /* bits of error we can ignore */ double maximum_error; double error, relative_error; /* * The maximum error we're willing to accept is the "forgiven_bits" * most insignificant bits. Here, we convert that to a scalar. */ maximum_error = pow (2.0, forgiven_bits - mantissa); error = fabs (a - b); #if 0 printf ("\n%s:%d: error is %.3e.", __FILE__, __LINE__, error); #endif if (error > 0.0) { relative_error = error / b; } else { /* * Absolute error is 0.0. It has no representation as a * relative error. So we'll treat it as a relative error * of zero. */ relative_error = 0.0; } #if 0 printf ("\n%s:%d: relative error is %.3e.", __FILE__, __LINE__, relative_error); #endif /* * A & B are equivalent if their error is less than the maximum * acceptable error, which was computed from a number of bits. */ return relative_error < maximum_error; } int main () { int rc = 0; static char pathname[] = "./src/test0007.data"; FILE *fp; XDR xdr; static double a[] = { 0.0, -1.1e-1, M_PI, -2.2e2, 3.3e3, 4.4e-4, -5.5e5, 6.6e-6 }; static int alen = sizeof a / sizeof a[0]; int i; double d; fp = fopen (pathname, "rb"); if (fp != NULL) { xdrstdio_create (&xdr, fp, XDR_DECODE); for (i = 0; rc == 0 && i < alen; ++i) { if (xdr_double (&xdr, &d)) { if (S_EqualDouble (d, a[i])) { /* good so far */ } else { printf ("\n%s:%d: xdr_double decoded %.18e.", __FILE__, __LINE__, d); printf (" Expected a[%d] = %.18e.", i, a[i]); rc = -47; } } else { printf ("\n%s:%d: xdr_double: %s", __FILE__, __LINE__, strerror (errno)); rc = -46; } } xdr_destroy (&xdr); fclose (fp); } else { printf ("\n%s:%d: fopen: %s", __FILE__, __LINE__, strerror (errno)); printf ("%s:%d: Could not open \"%s\" for binary input.", __FILE__, __LINE__, pathname); rc = 45; } return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } /* --- end of file --- */