diff options
Diffstat (limited to 'hardinfo2/modules/benchmark/fbench.c')
-rw-r--r-- | hardinfo2/modules/benchmark/fbench.c | 745 |
1 files changed, 0 insertions, 745 deletions
diff --git a/hardinfo2/modules/benchmark/fbench.c b/hardinfo2/modules/benchmark/fbench.c deleted file mode 100644 index df1b8e19..00000000 --- a/hardinfo2/modules/benchmark/fbench.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - - 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 point. - - 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², 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. - - 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 */ - -static 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 -#endif -static int niter = ITERATIONS; /* Iteration counter */ - -#if 0 -static char *refarr[] = { /* Reference results. These happen to - be derived from a run on Microsoft - 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" -}; -#endif - -/* 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] = { - {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 = pic, - twopi = pic * 2.0, - piover4 = pic / 4.0, fouroverpi = 4.0 / pic, piover2 = pic / 2.0; - -/* Coefficients for ATAN evaluation */ - -static double atanc[] = { - 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 = x; - if ((int) (-0.5) != 0 && l < 0) - l++; - x = l; - return x; -} - -/* sin(x) Return sine, x in radians */ - -static double sin(x) -double x; -{ - int sign; - double y, r, z; - - x = (((sign = (x < 0.0)) != 0) ? -x : x); - - if (x > twopi) - x -= (aint(x / twopi) * twopi); - - if (x > pi) { - x -= pi; - sign = !sign; - } - - if (x > piover2) - x = pi - x; - - if (x < piover4) { - y = x * fouroverpi; - z = y * y; - r = 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 = (piover2 - x) * fouroverpi; - z = y * y; - r = ((((((-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 = (x < 0.0) ? -x : x; - if (x > twopi) /* Do range reduction here to limit */ - x = 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 == 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 = (0.154116 + 1.893872 * x) / (1.0 + 1.047988 * x); - - c = (y - x / y) / 2.0; - cl = 0.0; - for (n = 50; c != cl && n--;) { - y = y - c; - cl = c; - c = (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 = (((sign = (x < 0.0)) != 0) ? -x : x); - l = 0; - - if (x >= 4.0) { - l = -1; - x = 1.0 / x; - y = 0; - goto atl; - } else { - if (x < 0.25) { - y = 0; - goto atl; - } - } - - y = aint(x / 0.5); - z = y * 0.5; - x = (x - z) / (x * z + 1); - - atl: - z = x * x; - b = ((((893025.0 * z + 49116375.0) * z + 425675250.0) * z + - 1277025750.0) * z + 1550674125.0) * z + 654729075.0; - a = (((13852575.0 * z + 216602100.0) * z + 891080190.0) * z + - 1332431100.0) * z + 654729075.0; - a = (a / b) * x + atanc[y]; - if (l) - a = piover2 - 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 == 0.0) { - if (y == 0.0) /* Special case: atan2(0,0) = 0 */ - return 0.0; - else if (y > 0) - return piover2; - else - return -piover2; - } - temp = atan(y / x); - if (x < 0.0) { - if (y >= 0.0) - temp += pic; - else - temp -= 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 == 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 != 0.0) { - if (object_distance == 0.0) { - axis_slope_angle = 0.0; - iang_sin = ray_height / radius_of_curvature; - } else - iang_sin = ((object_distance - - radius_of_curvature) / radius_of_curvature) * - axis_slope_angle; - - rang_sin = (from_index / to_index) * iang_sin; - old_axis_slope_angle = axis_slope_angle; - axis_slope_angle = axis_slope_angle + iang_sin - rang_sin; - if (object_distance != 0.0) - ray_height = object_distance * old_axis_slope_angle; - object_distance = ray_height / axis_slope_angle; - return; - } - object_distance = object_distance * (to_index / from_index); - axis_slope_angle = axis_slope_angle * (from_index / to_index); - return; - } - - if (radius_of_curvature != 0.0) { - if (object_distance == 0.0) { - axis_slope_angle = 0.0; - iang_sin = ray_height / radius_of_curvature; - } else { - iang_sin = ((object_distance - - radius_of_curvature) / radius_of_curvature) * - sin(axis_slope_angle); - } - iang = asin(iang_sin); - rang_sin = (from_index / to_index) * iang_sin; - old_axis_slope_angle = axis_slope_angle; - axis_slope_angle = axis_slope_angle + iang - asin(rang_sin); - sagitta = sin((old_axis_slope_angle + iang) / 2.0); - sagitta = 2.0 * radius_of_curvature * sagitta * sagitta; - object_distance = - ((radius_of_curvature * sin(old_axis_slope_angle + iang)) * - cot(axis_slope_angle)) + sagitta; - return; - } - - rang = -asin((from_index / to_index) * sin(axis_slope_angle)); - object_distance = object_distance * ((to_index * - cos(-rang)) / (from_index * - cos - (axis_slope_angle))); - axis_slope_angle = -rang; -} - -/* Perform ray trace in specific spectral line */ - -static void trace_line(line, ray_h) -int line; -double ray_h; -{ - int i; - - object_distance = 0.0; - ray_height = ray_h; - from_index = 1.0; - - for (i = 1; i <= current_surfaces; i++) { - radius_of_curvature = s[i][1]; - to_index = s[i][2]; - if (to_index > 1.0) - to_index = 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 = to_index; - if (i < current_surfaces) - object_distance = object_distance - s[i][4]; - } -} - -/* Initialise when called the first time */ - -void fbench() -{ - int i, j; - double od_fline, od_cline; - - spectral_line[1] = 7621.0; /* A */ - spectral_line[2] = 6869.955; /* B */ - spectral_line[3] = 6562.816; /* C */ - spectral_line[4] = 5895.944; /* D */ - spectral_line[5] = 5269.557; /* E */ - spectral_line[6] = 4861.344; /* F */ - spectral_line[7] = 4340.477; /* G' */ - spectral_line[8] = 3968.494; /* H */ - - niter = 3000; - - /* Load test case into working array */ - - clear_aperture = 4.0; - current_surfaces = 4; - for (i = 0; i < current_surfaces; i++) - for (j = 0; j < 4; j++) - s[i + 1][j + 1] = testcase[i][j]; - - for (itercount = 0; itercount < niter; itercount++) { - for (paraxial = 0; paraxial <= 1; paraxial++) { - - /* Do main trace in D light */ - - trace_line(4, clear_aperture / 2.0); - od_sa[paraxial][0] = object_distance; - od_sa[paraxial][1] = axis_slope_angle; - } - paraxial = FALSE; - - /* Trace marginal ray in C */ - - trace_line(3, clear_aperture / 2.0); - od_cline = object_distance; - - /* Trace marginal ray in F */ - - trace_line(6, clear_aperture / 2.0); - od_fline = object_distance; - - aberr_lspher = od_sa[1][0] - od_sa[0][0]; - aberr_osc = 1.0 - (od_sa[1][0] * od_sa[1][1]) / - (sin(od_sa[0][1]) * od_sa[0][0]); - aberr_lchrom = od_fline - od_cline; - max_lspher = sin(od_sa[0][1]); - - /* D light */ - - max_lspher = 0.0000926 / (max_lspher * max_lspher); - max_osc = 0.0025; - max_lchrom = max_lspher; - } -} - -#ifdef __FBENCH_TEST__ -int main(void) -{ - fbench(); - - return 0; -} -#endif |