diff options
Diffstat (limited to 'hardinfo2')
| -rw-r--r-- | hardinfo2/Makefile.in | 5 | ||||
| -rw-r--r-- | hardinfo2/arch/common/raytrace.h | 48 | ||||
| -rw-r--r-- | hardinfo2/benchmark.c | 21 | ||||
| -rw-r--r-- | hardinfo2/callbacks.c | 7 | ||||
| -rw-r--r-- | hardinfo2/fbench.c | 744 | 
5 files changed, 818 insertions, 7 deletions
| diff --git a/hardinfo2/Makefile.in b/hardinfo2/Makefile.in index c940f939..12d48e28 100644 --- a/hardinfo2/Makefile.in +++ b/hardinfo2/Makefile.in @@ -7,7 +7,7 @@ CFLAGS = -fPIC -pipe -Wall -g $(GTK_CFLAGS) $(GLADE_CFLAGS) -I.  OBJECTS = hardinfo.o shell.o util.o iconcache.o loadgraph.o sha1.o md5.o \  		menu.o stock.o callbacks.o expr.o report.o blowfish.o binreloc.o \ -		vendor.o socket.o +		vendor.o socket.o fbench.o  MODULES = computer.so devices.so benchmark.so   all:	$(OBJECTS) $(MODULES) @@ -23,6 +23,9 @@ blowfish.o:  sha1.o:  	$(CCSLOW) $(CFLAGS) -c sha1.c -o $@ +fbench.o: +	$(CCSLOW) $(CFLAGS) -c fbench.c -o $@ +  benchmark.so:	benchmark.c  	@echo "[01;34m--- Module: $< ($@)[00m"  	$(CCSLOW) $(CFLAGS) -o $@ -shared $< $(GTK_FLAGS) $(GTK_LIBS) \ diff --git a/hardinfo2/arch/common/raytrace.h b/hardinfo2/arch/common/raytrace.h new file mode 100644 index 00000000..8cabcbbb --- /dev/null +++ b/hardinfo2/arch/common/raytrace.h @@ -0,0 +1,48 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@linuxmag.com.br> + * + *    This program is free software; you can redistribute it and/or modify + *    it under the terms of the GNU General Public License as published by + *    the Free Software Foundation, version 2. + * + *    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 General Public License for more details. + * + *    You should have received a copy of the GNU 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 + */ + +void fbench();	/* fbench.c */ + +static gchar * +benchmark_raytrace(void) +{ +    int i; +    GTimer *timer = g_timer_new(); +    gdouble elapsed = 0; +     +    shell_view_set_enabled(FALSE); +    shell_status_update("Performing John Walker's FBENCH..."); +     +    for (i = 0; i <= 1000; i++) {  +        g_timer_start(timer); +         +        fbench(); +         +        g_timer_stop(timer); +        elapsed += g_timer_elapsed(timer, NULL); +         +        shell_status_set_percentage(i/10); +    } +     +    g_timer_destroy(timer); + +    gchar *retval = g_strdup_printf("[Results <i>(in seconds; lower is better)</i>]\n" +                           "<i>This Machine</i>=%.2f\n", elapsed); +    return benchmark_include_results(retval, "FBENCH"); +} + diff --git a/hardinfo2/benchmark.c b/hardinfo2/benchmark.c index 3743f4a0..9ad586e9 100644 --- a/hardinfo2/benchmark.c +++ b/hardinfo2/benchmark.c @@ -26,7 +26,8 @@ enum {      BENCHMARK_FIB,      BENCHMARK_MD5,      BENCHMARK_SHA1, -    BENCHMARK_BLOWFISH +    BENCHMARK_BLOWFISH, +    BENCHMARK_RAYTRACE  } Entries;  static ModuleEntry hi_entries[] = { @@ -34,7 +35,8 @@ static ModuleEntry hi_entries[] = {      {"CPU Fibonacci",	"module.png"},      {"CPU MD5",		"module.png"},      {"CPU SHA1",	"module.png"}, -    {"CPU Blowfish",	"blowfish.png"} +    {"CPU Blowfish",	"blowfish.png"}, +    {"FPU Raytracing",	"module.png"}  };  static gchar * @@ -69,12 +71,14 @@ benchmark_include_results(gchar *results, const gchar *benchmark)  #include <arch/common/md5.h>  #include <arch/common/sha1.h>  #include <arch/common/blowfish.h> +#include <arch/common/raytrace.h>  static gchar *bench_zlib = NULL,               *bench_fib  = NULL,               *bench_md5  = NULL,               *bench_sha1 = NULL, -             *bench_fish = NULL; +             *bench_fish = NULL, +             *bench_ray  = NULL;  gchar *  hi_info(gint entry) @@ -87,6 +91,13 @@ hi_info(gint entry)              bench_zlib = benchmark_zlib();              return g_strdup(bench_zlib); +        case BENCHMARK_RAYTRACE: +            if (bench_ray) +                return g_strdup(bench_ray); +             +            bench_ray = benchmark_raytrace(); +            return g_strdup(bench_ray); +          case BENCHMARK_BLOWFISH:              if (bench_fish)                  return g_strdup(bench_fish); @@ -128,6 +139,10 @@ hi_reload(gint entry)              if (bench_zlib) g_free(bench_zlib);              bench_zlib = benchmark_zlib();              break; +        case BENCHMARK_RAYTRACE: +            if (bench_ray) g_free(bench_ray); +            bench_ray = benchmark_raytrace(); +            break;          case BENCHMARK_BLOWFISH:              if (bench_fish) g_free(bench_fish);              bench_fish = benchmark_fish(); diff --git a/hardinfo2/callbacks.c b/hardinfo2/callbacks.c index 27228588..d7982075 100644 --- a/hardinfo2/callbacks.c +++ b/hardinfo2/callbacks.c @@ -93,9 +93,10 @@ void cb_about()          "SCSI support by Pascal F. Martin",          "",          "Based on work by:", -        "MD5 implementation by Colin Plumb", -        "SHA1 implementation by Steve Raid", -        "Blowfish implementation by Paul Kocher", +        "MD5 implementation by Colin Plumb (see md5.c for details)", +        "SHA1 implementation by Steve Raid (see sha1.c for details)", +        "Blowfish implementation by Paul Kocher (see blowfich.c for details)", +        "Raytracing benchmark by John Walker (see fbench.c for details)",          "Some code partly based on x86cpucaps by Osamu Kayasono",          "Vendor list based on GtkSysInfo by Pissens Sebastien",          NULL diff --git a/hardinfo2/fbench.c b/hardinfo2/fbench.c new file mode 100644 index 00000000..2b4501d8 --- /dev/null +++ b/hardinfo2/fbench.c @@ -0,0 +1,744 @@ +/* + +        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 */ + +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 +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 | 
