|
From: <sv...@va...> - 2006-01-23 03:36:51
|
Author: sewardj Date: 2006-01-23 03:36:40 +0000 (Mon, 23 Jan 2006) New Revision: 5588 Log: Use perf/fbench as a simple FP test too. This is a modified copy, not a = symlink. Added: trunk/memcheck/tests/vcpu_fbench.c trunk/memcheck/tests/vcpu_fbench.stderr.exp trunk/memcheck/tests/vcpu_fbench.stdout.exp trunk/memcheck/tests/vcpu_fbench.vgtest Modified: trunk/memcheck/tests/Makefile.am Modified: trunk/memcheck/tests/Makefile.am =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/memcheck/tests/Makefile.am 2006-01-23 00:09:07 UTC (rev 5587) +++ trunk/memcheck/tests/Makefile.am 2006-01-23 03:36:40 UTC (rev 5588) @@ -108,6 +108,7 @@ trivialleak.stderr.exp trivialleak.vgtest \ metadata.stderr.exp metadata.stdout.exp metadata.vgtest-HIDING \ vcpu_bz2.stdout.exp vcpu_bz2.stderr.exp vcpu_bz2.vgtest \ + vcpu_fbench.stdout.exp vcpu_fbench.stderr.exp vcpu_fbench.vgtest \ vgtest_ume.stderr.exp vgtest_ume.disabled \ wrap1.vgtest wrap1.stdout.exp wrap1.stderr.exp \ wrap2.vgtest wrap2.stdout.exp wrap2.stderr.exp \ @@ -150,7 +151,7 @@ supp_unknown supp1 supp2 suppfree \ trivialleak \ mismatches new_override metadata \ - vcpu_bz2 \ + vcpu_bz2 vcpu_fbench \ xml1 \ wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \ writev zeropage Added: trunk/memcheck/tests/vcpu_fbench.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/memcheck/tests/vcpu_fbench.c (rev 0) +++ trunk/memcheck/tests/vcpu_fbench.c 2006-01-23 03:36:40 UTC (rev 5588) @@ -0,0 +1,872 @@ + +// This is slightly hacked version of perf/fbench.c. It does some +// some basic FP arithmetic (+/-/*/divide) and not a lot else. + +// This small program does some raytracing. It tests Valgrind's handlin= g of +// FP operations. It apparently does a lot of trigonometry operations. + +// Licensing: This program is closely based on the one of the same name = from +// http://www.fourmilab.ch/. The front page of that site says: +// +// "Except for a few clearly-marked exceptions, all the material on th= is +// site is in the public domain and may be used in any manner without +// permission, restriction, attribution, or compensation." + +/* This program can be used in two ways. If INTRIG is undefined, sin, + cos, tan, etc, will be used as supplied by <math.h>. If it is + defined, then the program calculates all this stuff from first + principles (so to speak) and does not use the libc facilities. For + benchmarking purposes it seems better to avoid the libc stuff, so + that the inner loops (sin, sqrt) present a workload independent of + libc implementations on different platforms. Hence: */ + +#define INTRIG 1 + + +/* + + John Walker's Floating Point Benchmark, derived from... + + Marinchip Interactive Lens Design System + + John Walker December 1980 + + By John Walker + http://www.fourmilab.ch/ + + This program may be used, distributed, and modified freely as + long as the origin information is preserved. + + This is a complete optical design raytracing algorithm, + stripped of its user interface and recast into portable C. It + not only determines execution speed on an extremely floating + point (including trig function) intensive real-world + application, it checks accuracy on an algorithm that is + exquisitely sensitive to errors. The performance of this + program is typically far more sensitive to changes in the + efficiency of the trigonometric library routines than the + average floating point program. + + The benchmark may be compiled in two modes. If the symbol + INTRIG is defined, built-in trigonometric and square root + routines will be used for all calculations. Timings made with + INTRIG defined reflect the machine's basic floating point + performance for the arithmetic operators. If INTRIG is not + defined, the system library <math.h> functions are used. + Results with INTRIG not defined reflect the system's library + performance and/or floating point hardware support for trig + functions and square root. Results with INTRIG defined are a + good guide to general floating point performance, while + results with INTRIG undefined indicate the performance of an + application which is math function intensive. + + Special note regarding errors in accuracy: this program has + generated numbers identical to the last digit it formats and + checks on the following machines, floating point + architectures, and languages: + + Marinchip 9900 QBASIC IBM 370 double-precision (REAL * 8) format + + IBM PC / XT / AT Lattice C IEEE 64 bit, 80 bit temporaries + High C same, in line 80x87 code + BASICA "Double precision" + Quick BASIC IEEE double precision, software routines + + Sun 3 C IEEE 64 bit, 80 bit temporaries, + in-line 68881 code, in-line FPA code. + + MicroVAX II C Vax "G" format floating point + + Macintosh Plus MPW C SANE floating point, IEEE 64 bit format + implemented in ROM. + + Inaccuracies reported by this program should be taken VERY + SERIOUSLY INDEED, as the program has been demonstrated to be + invariant under changes in floating point format, as long as + the format is a recognised double precision format. If you + encounter errors, please remember that they are just as likely + to be in the floating point editing library or the + trigonometric libraries as in the low level operator code. + + The benchmark assumes that results are basically reliable, and + only tests the last result computed against the reference. If + you're running on a suspect system you can compile this + program with ACCURACY defined. This will generate a version + which executes as an infinite loop, performing the ray trace + and checking the results on every pass. All incorrect results + will be reported. + + Representative timings are given below. All have been + normalised as if run for 1000 iterations. + + Time in seconds Computer, Compiler, and notes + Normal INTRIG + + 3466.00 4031.00 Commodore 128, 2 Mhz 8510 with software floating + point. Abacus Software/Data-Becker Super-C 128, + version 3.00, run in fast (2 Mhz) mode. Note: + the results generated by this system differed + from the reference results in the 8th to 10th + decimal place. + + 3290.00 IBM PC/AT 6 Mhz, Microsoft/IBM BASICA version A3.00. + Run with the "/d" switch, software floating poin= t. + + 2131.50 IBM PC/AT 6 Mhz, Lattice C version 2.14, small model. + This version of Lattice compiles subroutine + calls which either do software floating point + or use the 80x87. The machine on which I ran + this had an 80287, but the results were so bad + I wonder if it was being used. + + 1598.00 Macintosh Plus, MPW C, SANE Software floating point. + + 1582.13 Marinchip 9900 2 Mhz, QBASIC compiler with software + floating point. This was a QBASIC version of the + program which contained the identical algorithm. + + 404.00 IBM PC/AT 6 Mhz, Microsoft QuickBASIC version 2.0. + Software floating point. + + 165.15 IBM PC/AT 6 Mhz, Metaware High C version 1.3, small + model. This was compiled to call subroutines for + floating point, and the machine contained an 80287 + which was used by the subroutines. + + 143.20 Macintosh II, MPW C, SANE calls. I was unable to + determine whether SANE was using the 68881 chip or + not. + + 121.80 Sun 3/160 16 Mhz, Sun C. Compiled with -fsoft switch + which executes floating point in software. + + 78.78 110.11 IBM RT PC (Model 6150). IBM AIX 1.0 C compiler + with -O switch. + + 75.2 254.0 Microsoft Quick C 1.0, in-line 8087 instructions, + compiled with 80286 optimisation on. (Switches + were -Ol -FPi87-G2 -AS). Small memory model. + + 69.50 IBM PC/AT 6Mhz, Borland Turbo BASIC 1.0. Compiled + in "8087 required" mode to generate in-line + code for the math coprocessor. + + 66.96 IBM PC/AT 6Mhz, Microsoft QuickBASIC 4.0. This + release of QuickBASIC compiles code for the + 80287 math coprocessor. + + 66.36 206.35 IBM PC/AT 6Mhz, Metaware High C version 1.3, small + model. This was compiled with in-line code for the + 80287 math coprocessor. Trig functions still call + library routines. + + 63.07 220.43 IBM PC/AT, 6Mhz, Borland Turbo C, in-line 8087 code, + small model, word alignment, no stack checking, + 8086 code mode. + + 17.18 Apollo DN-3000, 12 Mhz 68020 with 68881, compiled + with in-line code for the 68881 coprocessor. + According to Apollo, the library routines are chosen + at runtime based on coprocessor presence. Since the + coprocessor was present, the library is supposed to + use in-line floating point code. + + 15.55 27.56 VAXstation II GPX. Compiled and executed under + VAX/VMS C. + + 15.14 37.93 Macintosh II, Unix system V. Green Hills 68020 + Unix compiler with in-line code for the 68881 + coprocessor (-O -ZI switches). + + 12.69 Sun 3/160 16 Mhz, Sun C. Compiled with -fswitch, + which calls a subroutine to select the fastest + floating point processor. This was using the 68881. + + 11.74 26.73 Compaq Deskpro 386, 16 Mhz 80386 with 16 Mhz 80387. + Metaware High C version 1.3, compiled with in-line + for the math coprocessor (but not optimised for the + 80386/80387). Trig functions still call library + routines. + + 8.43 30.49 Sun 3/160 16 Mhz, Sun C. Compiled with -f68881, + generating in-line MC68881 instructions. Trig + functions still call library routines. + + 6.29 25.17 Sun 3/260 25 Mhz, Sun C. Compiled with -f68881, + generating in-line MC68881 instructions. Trig + functions still call library routines. + + 4.57 Sun 3/260 25 Mhz, Sun FORTRAN 77. Compiled with + -O -f68881, generating in-line MC68881 instructions. + Trig functions are compiled in-line. This used + the FORTRAN 77 version of the program, FBFORT77.F. + + 4.00 14.20 Sun386i/25 Mhz model 250, Sun C compiler. + + 4.00 14.00 Sun386i/25 Mhz model 250, Metaware C. + + 3.10 12.00 Compaq 386/387 25 Mhz running SCO Xenix 2. + Compiled with Metaware HighC 386, optimized + for 386. + + 3.00 12.00 Compaq 386/387 25MHZ optimized for 386/387. + + 2.96 5.17 Sun 4/260, Sparc RISC processor. Sun C, + compiled with the -O2 switch for global + optimisation. + + 2.47 COMPAQ 486/25, secondary cache disabled, High C, + 486/387, inline f.p., small memory model. + + 2.20 3.40 Data General Motorola 88000, 16 Mhz, Gnu C. + + 1.56 COMPAQ 486/25, 128K secondary cache, High C, 486/387, + inline f.p., small memory model. + + 0.66 1.50 DEC Pmax, Mips processor. + + 0.63 0.91 Sun SparcStation 2, Sun C (SunOS 4.1.1) with + -O4 optimisation and "/usr/lib/libm.il" inline + floating point. + + 0.60 1.07 Intel 860 RISC processor, 33 Mhz, Greenhills + C compiler. + + 0.40 0.90 Dec 3MAX, MIPS 3000 processor, -O4. + + 0.31 0.90 IBM RS/6000, -O. + + 0.1129 0.2119 Dell Dimension XPS P133c, Pentium 133 MHz, + Windows 95, Microsoft Visual C 5.0. + + 0.0883 0.2166 Silicon Graphics Indigo=B2, MIPS R4400, + 175 Mhz, "-O3". + + 0.0351 0.0561 Dell Dimension XPS R100, Pentium II 400 MHz, + Windows 98, Microsoft Visual C 5.0. + + 0.0312 0.0542 Sun Ultra 2, UltraSPARC V9, 300 MHz, Solaris + 2.5.1. + =09 + 0.00862 0.01074 Dell Inspiron 9100, Pentium 4, 3.4 GHz, gcc -O3. + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef INTRIG +#include <math.h> +#endif + +#define cot(x) (1.0 / tan(x)) + +#define TRUE 1 +#define FALSE 0 + +#define max_surfaces 10 + +/* Local variables */ + +/* static char tbfr[132]; */ + +static short current_surfaces; +static short paraxial; + +static double clear_aperture; + +static double aberr_lspher; +static double aberr_osc; +static double aberr_lchrom; + +static double max_lspher; +static double max_osc; +static double max_lchrom; + +static double radius_of_curvature; +static double object_distance; +static double ray_height; +static double axis_slope_angle; +static double from_index; +static double to_index; + +static double spectral_line[9]; +static double s[max_surfaces][5]; +static double od_sa[2][2]; + +static char outarr[8][80]; /* Computed output of program goes here */ + +int itercount; /* The iteration counter for the main loop + in the program is made global so that + the compiler should not be allowed to + optimise out the loop over the ray + tracing code. */ + +#ifndef ITERATIONS +#define ITERATIONS /*1000*/ /*500000*/ 100 +#endif +int niter =3D ITERATIONS; /* Iteration counter */ + +static char *refarr[] =3D { /* Reference results. These happen to + be derived from a run on Microsoft=20 + Quick BASIC on the IBM PC/AT. */ + + " Marginal ray 47.09479120920 0.04178472683", + " Paraxial ray 47.08372160249 0.04177864821", + "Longitudinal spherical aberration: -0.01106960671", + " (Maximum permissible): 0.05306749907", + "Offense against sine condition (coma): 0.00008954761", + " (Maximum permissible): 0.00250000000", + "Axial chromatic aberration: 0.00448229032", + " (Maximum permissible): 0.05306749907" +}; + +/* The test case used in this program is the design for a 4 inch + achromatic telescope objective used as the example in Wyld's + classic work on ray tracing by hand, given in Amateur Telescope + Making, Volume 3. */ + +static double testcase[4][4] =3D { + {27.05, 1.5137, 63.6, 0.52}, + {-16.68, 1, 0, 0.138}, + {-16.68, 1.6164, 36.7, 0.38}, + {-78.1, 1, 0, 0} +}; + +/* Internal trig functions (used only if INTRIG is defined). These + standard functions may be enabled to obtain timings that reflect + the machine's floating point performance rather than the speed of + its trig function evaluation. */ + +#ifdef INTRIG + +/* The following definitions should keep you from getting intro trouble + with compilers which don't let you redefine intrinsic functions. */ + +#define sin I_sin +#define cos I_cos +#define tan I_tan +#define sqrt I_sqrt +#define atan I_atan +#define atan2 I_atan2 +#define asin I_asin + +#define fabs(x) ((x < 0.0) ? -x : x) + +#define pic 3.1415926535897932 + +/* Commonly used constants */ + +static double pi =3D pic, + twopi =3Dpic * 2.0, + piover4 =3D pic / 4.0, + fouroverpi =3D 4.0 / pic, + piover2 =3D pic / 2.0; + +/* Coefficients for ATAN evaluation */ + +static double atanc[] =3D { + 0.0, + 0.4636476090008061165, + 0.7853981633974483094, + 0.98279372324732906714, + 1.1071487177940905022, + 1.1902899496825317322, + 1.2490457723982544262, + 1.2924966677897852673, + 1.3258176636680324644 +}; + +/* aint(x) Return integer part of number. Truncates towards 0 */ + +double aint(x) +double x; +{ + long l; + + /* Note that this routine cannot handle the full floating point + number range. This function should be in the machine-dependent + floating point library! */ + + l =3D x; + if ((int)(-0.5) !=3D 0 && l < 0 ) + l++; + x =3D l; + return x; +} + +/* sin(x) Return sine, x in radians */ + +static double sin(x) +double x; +{ + int sign; + double y, r, z; + + x =3D (((sign=3D (x < 0.0)) !=3D 0) ? -x: x); + + if (x > twopi) + x -=3D (aint(x / twopi) * twopi); + + if (x > pi) { + x -=3D pi; + sign =3D !sign; + } + + if (x > piover2) + x =3D pi - x; + + if (x < piover4) { + y =3D x * fouroverpi; + z =3D y * y; + r =3D y * (((((((-0.202253129293E-13 * z + 0.69481520350522E-11) * z= - + 0.17572474176170806E-8) * z + 0.313361688917325348E-6) * z - + 0.365762041821464001E-4) * z + 0.249039457019271628E-2) * z - + 0.0807455121882807815) * z + 0.785398163397448310); + } else { + y =3D (piover2 - x) * fouroverpi; + z =3D y * y; + r =3D ((((((-0.38577620372E-12 * z + 0.11500497024263E-9) * z - + 0.2461136382637005E-7) * z + 0.359086044588581953E-5) * z - + 0.325991886926687550E-3) * z + 0.0158543442438154109) * z - + 0.308425137534042452) * z + 1.0; + } + return sign ? -r : r; +} + +/* cos(x) Return cosine, x in radians, by identity */ + +static double cos(x) +double x; +{ + x =3D (x < 0.0) ? -x : x; + if (x > twopi) /* Do range reduction here to limit */ + x =3D x - (aint(x / twopi) * twopi); /* roundoff on add of PI/2 *= / + return sin(x + piover2); +} + +/* tan(x) Return tangent, x in radians, by identity */ + +static double tan(x) +double x; +{ + return sin(x) / cos(x); +} + +/* sqrt(x) Return square root. Initial guess, then Newton- + Raphson refinement */ + +double sqrt(x) +double x; +{ + double c, cl, y; + int n; + + if (x =3D=3D 0.0) + return 0.0; + + if (x < 0.0) { + fprintf(stderr, + "\nGood work! You tried to take the square root of %g", + x); + fprintf(stderr, + "\nunfortunately, that is too complex for me to handle.\n"= ); + exit(1); + } + + y =3D (0.154116 + 1.893872 * x) / (1.0 + 1.047988 * x); + + c =3D (y - x / y) / 2.0; + cl =3D 0.0; + for (n =3D 50; c !=3D cl && n--;) { + y =3D y - c; + cl =3D c; + c =3D (y - x / y) / 2.0; + } + return y; +} + +/* atan(x) Return arctangent in radians, + range -pi/2 to pi/2 */ + +static double atan(x) +double x; +{ + int sign, l, y; + double a, b, z; + + x =3D (((sign =3D (x < 0.0)) !=3D 0) ? -x : x); + l =3D 0; + + if (x >=3D 4.0) { + l =3D -1; + x =3D 1.0 / x; + y =3D 0; + goto atl; + } else { + if (x < 0.25) { + y =3D 0; + goto atl; + } + } + + y =3D aint(x / 0.5); + z =3D y * 0.5; + x =3D (x - z) / (x * z + 1); + +atl: + z =3D x * x; + b =3D ((((893025.0 * z + 49116375.0) * z + 425675250.0) * z + + 1277025750.0) * z + 1550674125.0) * z + 654729075.0; + a =3D (((13852575.0 * z + 216602100.0) * z + 891080190.0) * z + + 1332431100.0) * z + 654729075.0; + a =3D (a / b) * x + atanc[y]; + if (l) + a=3Dpiover2 - a; + return sign ? -a : a; +} + +/* atan2(y,x) Return arctangent in radians of y/x, + range -pi to pi */ + +static double atan2(y, x) +double y, x; +{ + double temp; + + if (x =3D=3D 0.0) { + if (y =3D=3D 0.0) /* Special case: atan2(0,0) =3D 0 */ + return 0.0; + else if (y > 0) + return piover2; + else + return -piover2; + } + temp =3D atan(y / x); + if (x < 0.0) { + if (y >=3D 0.0) + temp +=3D pic; + else + temp -=3D pic; + } + return temp; +} + +/* asin(x) Return arcsine in radians of x */ + +static double asin(x) +double x; +{ + if (fabs(x)>1.0) { + fprintf(stderr, + "\nInverse trig functions lose much of their gloss when"); + fprintf(stderr, + "\ntheir arguments are greater than 1, such as the"); + fprintf(stderr, + "\nvalue %g you passed.\n", x); + exit(1); + } + return atan2(x, sqrt(1 - x * x)); +} +#endif + +/* Calculate passage through surface + + If the variable PARAXIAL is true, the trace through the + surface will be done using the paraxial approximations. + Otherwise, the normal trigonometric trace will be done. + + This routine takes the following inputs: + + RADIUS_OF_CURVATURE Radius of curvature of surface + being crossed. If 0, surface is + plane. + + OBJECT_DISTANCE Distance of object focus from + lens vertex. If 0, incoming + rays are parallel and + the following must be specified: + + RAY_HEIGHT Height of ray from axis. Only + relevant if OBJECT.DISTANCE =3D=3D 0 + + AXIS_SLOPE_ANGLE Angle incoming ray makes with axis + at intercept + + FROM_INDEX Refractive index of medium being left + + TO_INDEX Refractive index of medium being + entered. + + The outputs are the following variables: + + OBJECT_DISTANCE Distance from vertex to object focus + after refraction. + + AXIS_SLOPE_ANGLE Angle incoming ray makes with axis + at intercept after refraction. + +*/ + +static void transit_surface() { + double iang, /* Incidence angle */ + rang, /* Refraction angle */ + iang_sin, /* Incidence angle sin */ + rang_sin, /* Refraction angle sin */ + old_axis_slope_angle, sagitta; + + if (paraxial) { + if (radius_of_curvature !=3D 0.0) { + if (object_distance =3D=3D 0.0) { + axis_slope_angle =3D 0.0; + iang_sin =3D ray_height / radius_of_curvature; + } else + iang_sin =3D ((object_distance - + radius_of_curvature) / radius_of_curvature) * + axis_slope_angle; + + rang_sin =3D (from_index / to_index) * + iang_sin; + old_axis_slope_angle =3D axis_slope_angle; + axis_slope_angle =3D axis_slope_angle + + iang_sin - rang_sin; + if (object_distance !=3D 0.0) + ray_height =3D object_distance * old_axis_slope_angle; + object_distance =3D ray_height / axis_slope_angle; + return; + } + object_distance =3D object_distance * (to_index / from_index); + axis_slope_angle =3D axis_slope_angle * (from_index / to_index); + return; + } + + if (radius_of_curvature !=3D 0.0) { + if (object_distance =3D=3D 0.0) { + axis_slope_angle =3D 0.0; + iang_sin =3D ray_height / radius_of_curvature; + } else { + iang_sin =3D ((object_distance - + radius_of_curvature) / radius_of_curvature) * + sin(axis_slope_angle); + } + iang =3D asin(iang_sin); + rang_sin =3D (from_index / to_index) * + iang_sin; + old_axis_slope_angle =3D axis_slope_angle; + axis_slope_angle =3D axis_slope_angle + + iang - asin(rang_sin); + sagitta =3D sin((old_axis_slope_angle + iang) / 2.0); + sagitta =3D 2.0 * radius_of_curvature*sagitta*sagitta; + object_distance =3D ((radius_of_curvature * sin( + old_axis_slope_angle + iang)) * + cot(axis_slope_angle)) + sagitta; + return; + } + + rang =3D -asin((from_index / to_index) * + sin(axis_slope_angle)); + object_distance =3D object_distance * ((to_index * + cos(-rang)) / (from_index * + cos(axis_slope_angle))); + axis_slope_angle =3D -rang; +} + +/* Perform ray trace in specific spectral line */ + +static void trace_line(line, ray_h) +int line; +double ray_h; +{ + int i; + + object_distance =3D 0.0; + ray_height =3D ray_h; + from_index =3D 1.0; + + for (i =3D 1; i <=3D current_surfaces; i++) { + radius_of_curvature =3D s[i][1]; + to_index =3D s[i][2]; + if (to_index > 1.0) + to_index =3D to_index + ((spectral_line[4] - + spectral_line[line]) / + (spectral_line[3] - spectral_line[6])) * ((s[i][2] - 1.0) / + s[i][3]); + transit_surface(); + from_index =3D to_index; + if (i < current_surfaces) + object_distance =3D object_distance - s[i][4]; + } +} + +/* Initialise when called the first time */ + +int main(argc, argv) +int argc; +char *argv[]; +{ + int i, j, k, errors; + double od_fline, od_cline; +#ifdef ACCURACY + long passes; +#endif + + spectral_line[1] =3D 7621.0; /* A */ + spectral_line[2] =3D 6869.955; /* B */ + spectral_line[3] =3D 6562.816; /* C */ + spectral_line[4] =3D 5895.944; /* D */ + spectral_line[5] =3D 5269.557; /* E */ + spectral_line[6] =3D 4861.344; /* F */ + spectral_line[7] =3D 4340.477; /* G'*/ + spectral_line[8] =3D 3968.494; /* H */ + + /* Process the number of iterations argument, if one is supplied. */ + + if (argc > 1) { + niter =3D atoi(argv[1]); + if (*argv[1] =3D=3D '-' || niter < 1) { + printf("This is John Walker's floating point accuracy and\= n"); + printf("performance benchmark program. You call it with\n= "); + printf("\nfbench <itercount>\n\n"); + printf("where <itercount> is the number of iterations\n"); + printf("to be executed. Archival timings should be made\n= "); + printf("with the iteration count set so that roughly five\= n"); + printf("minutes of execution is timed.\n"); + exit(0); + } + } + + /* Load test case into working array */ + + clear_aperture =3D 4.0; + current_surfaces =3D 4; + for (i =3D 0; i < current_surfaces; i++) + for (j =3D 0; j < 4; j++) + s[i + 1][j + 1] =3D testcase[i][j]; + +#ifdef ACCURACY + printf("Beginning execution of floating point accuracy test...\n= "); + passes =3D 0; +#else + printf("Ready to begin John Walker's floating point accuracy\n")= ; + printf("and performance benchmark. %d iterations will be made.\= n\n", + niter); + + printf("\nMeasured run time in seconds should be divided by %.f\= n", niter / 1000.0); + printf("to normalise for reporting results. For archival result= s,\n"); + printf("adjust iteration count so the benchmark runs about five = minutes.\n\n"); + + //printf("Press return to begin benchmark:"); + //gets(tbfr); +#endif + + /* Perform ray trace the specified number of times. */ + +#ifdef ACCURACY + while (TRUE) { + passes++; + if ((passes % 100L) =3D=3D 0) { + printf("Pass %ld.\n", passes); + } +#else + for (itercount =3D 0; itercount < niter; itercount++) { +#endif + + for (paraxial =3D 0; paraxial <=3D 1; paraxial++) { + + /* Do main trace in D light */ + + trace_line(4, clear_aperture / 2.0); + od_sa[paraxial][0] =3D object_distance; + od_sa[paraxial][1] =3D axis_slope_angle; + } + paraxial =3D FALSE; + + /* Trace marginal ray in C */ + + trace_line(3, clear_aperture / 2.0); + od_cline =3D object_distance; + + /* Trace marginal ray in F */ + + trace_line(6, clear_aperture / 2.0); + od_fline =3D object_distance; + + aberr_lspher =3D od_sa[1][0] - od_sa[0][0]; + aberr_osc =3D 1.0 - (od_sa[1][0] * od_sa[1][1]) / + (sin(od_sa[0][1]) * od_sa[0][0]); + aberr_lchrom =3D od_fline - od_cline; + max_lspher =3D sin(od_sa[0][1]); + + /* D light */ + + max_lspher =3D 0.0000926 / (max_lspher * max_lspher); + max_osc =3D 0.0025; + max_lchrom =3D max_lspher; +#ifndef ACCURACY + } + + //printf("Stop the timer:\007"); + //gets(tbfr); +#endif + + /* Now evaluate the accuracy of the results from the last ray trace */ + + sprintf(outarr[0], "%15s %21.11f %14.11f", + "Marginal ray", od_sa[0][0], od_sa[0][1]); + sprintf(outarr[1], "%15s %21.11f %14.11f", + "Paraxial ray", od_sa[1][0], od_sa[1][1]); + sprintf(outarr[2], + "Longitudinal spherical aberration: %16.11f", + aberr_lspher); + sprintf(outarr[3], + " (Maximum permissible): %16.11f", + max_lspher); + sprintf(outarr[4], + "Offense against sine condition (coma): %16.11f", + aberr_osc); + sprintf(outarr[5], + " (Maximum permissible): %16.11f", + max_osc); + sprintf(outarr[6], + "Axial chromatic aberration: %16.11f", + aberr_lchrom); + sprintf(outarr[7], + " (Maximum permissible): %16.11f", + max_lchrom); + + /* Now compare the edited results with the master values from + reference executions of this program. */ + + errors =3D 0; + for (i =3D 0; i < 8; i++) { + if (strcmp(outarr[i], refarr[i]) !=3D 0) { +#ifdef ACCURACY + printf("\nError in pass %ld for results on line %d...\n", + passes, i + 1); +#else + printf("\nError in results on line %d...\n", i + 1); +#endif + printf("Expected: \"%s\"\n", refarr[i]); + printf("Received: \"%s\"\n", outarr[i]); + printf("(Errors) "); + k =3D strlen(refarr[i]); + for (j =3D 0; j < k; j++) { + printf("%c", refarr[i][j] =3D=3D outarr[i][j] ? ' ' : '= ^'); + if (refarr[i][j] !=3D outarr[i][j]) + errors++; + } + printf("\n"); + } + } +#ifdef ACCURACY + } +#else + if (errors > 0) { + printf("\n%d error%s in results. This is VERY SERIOUS.\n", + errors, errors > 1 ? "s" : ""); + } else + printf("\nNo errors in results.\n"); +#endif + return 0; +} Added: trunk/memcheck/tests/vcpu_fbench.stderr.exp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Added: trunk/memcheck/tests/vcpu_fbench.stdout.exp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/memcheck/tests/vcpu_fbench.stdout.exp (= rev 0) +++ trunk/memcheck/tests/vcpu_fbench.stdout.exp 2006-01-23 03:36:40 UTC (= rev 5588) @@ -0,0 +1,10 @@ +Ready to begin John Walker's floating point accuracy +and performance benchmark. 100 iterations will be made. + + +Measured run time in seconds should be divided by 0 +to normalise for reporting results. For archival results, +adjust iteration count so the benchmark runs about five minutes. + + +No errors in results. Added: trunk/memcheck/tests/vcpu_fbench.vgtest =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/memcheck/tests/vcpu_fbench.vgtest (rev = 0) +++ trunk/memcheck/tests/vcpu_fbench.vgtest 2006-01-23 03:36:40 UTC (rev = 5588) @@ -0,0 +1,2 @@ +prog: vcpu_fbench +vgopts: -q |