⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 paranoia.c

📁 lcc,一个可变目标c语言编译器的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
#undef V9#define NOPAUSE/*	A C version of Kahan's Floating Point Test "Paranoia"			Thos Sumner, UCSF, Feb. 1985			David Gay, BTL, Jan. 1986	This is a rewrite from the Pascal version by			B. A. Wichmann, 18 Jan. 1985	(and does NOT exhibit good C programming style).(C) Apr 19 1983 in BASIC version by:	Professor W. M. Kahan,	567 Evans Hall	Electrical Engineering & Computer Science Dept.	University of California	Berkeley, California 94720	USAconverted to Pascal by:	B. A. Wichmann	National Physical Laboratory	Teddington Middx	TW11 OLW	UKconverted to C by:	David M. Gay		and	Thos Sumner	AT&T Bell Labs			Computer Center, Rm. U-76	600 Mountain Avenue		University of California	Murray Hill, NJ 07974		San Francisco, CA 94143	USA				USAwith simultaneous corrections to the Pascal source (reflectedin the Pascal source available over netlib).[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]Reports of results on various systems from all the versionsof Paranoia are being collected by Richard Karpinski at thesame address as Thos Sumner.  This includes sample outputs,bug reports, and criticisms.You may copy this program freely if you acknowledge its source.Comments on the Pascal version to NPL, please.The C version catches signals from floating-point exceptions.If signal(SIGFPE,...) is unavailable in your environment, you may#define NOSIGNAL to comment out the invocations of signal.This source file is too big for some C compilers, but may be splitinto pieces.  Comments containing "SPLIT" suggest convenient placesfor this splitting.  At the end of these comments is an "ed script"(for the UNIX(tm) editor ed) that will do this splitting.By #defining Single when you compile this source, you may obtaina single-precision C version of Paranoia.The following is from the introductory commentary from Wichmann's work:The BASIC program of Kahan is written in Microsoft BASIC using manyfacilities which have no exact analogy in Pascal.  The Pascalversion below cannot therefore be exactly the same.  Rather than bea minimal transcription of the BASIC program, the Pascal codingfollows the conventional style of block-structured languages.  Hencethe Pascal version could be useful in producing versions in otherstructured languages.Rather than use identifiers of minimal length (which therefore havelittle mnemonic significance), the Pascal version uses meaningfulidentifiers as follows [Note: A few changes have been made for C]:BASIC   C               BASIC   C               BASIC   C                  A                       J                       S    StickyBit   A1   AInverse           J0   NoErrors           T   B    Radix                    [Failure]         T0   Underflow   B1   BInverse           J1   NoErrors           T2   ThirtyTwo   B2   RadixD2                  [SeriousDefect]   T5   OneAndHalf   B9   BMinusU2           J2   NoErrors           T7   TwentySeven   C                             [Defect]          T8   TwoForty   C1   CInverse           J3   NoErrors           U    OneUlp   D                             [Flaw]            U0   UnderflowThreshold   D4   FourD              K    PageNo             U1   E0                      L    Milestone          U2   E1                      M                       V   E2   Exp2               N                       V0   E3                      N1                      V8   E5   MinSqEr            O    Zero               V9   E6   SqEr               O1   One                W   E7   MaxSqEr            O2   Two                X   E8                      O3   Three              X1   E9                      O4   Four               X8   F1   MinusOne           O5   Five               X9   Random1   F2   Half               O8   Eight              Y   F3   Third              O9   Nine               Y1   F6                      P    Precision          Y2   F9                      Q                       Y9   Random2   G1   GMult              Q8                      Z   G2   GDiv               Q9                      Z0   PseudoZero   G3   GAddSub            R                       Z1   H                       R1   RMult              Z2   H1   HInverse           R2   RDiv               Z9   I                       R3   RAddSub   IO   NoTrials           R4   RSqrt   I3   IEEE               R9   Random9   SqRWrngAll the variables in BASIC are true variables and in consequence,the program is more difficult to follow since the "constants" mustbe determined (the glossary is very helpful).  The Pascal versionuses Real constants, but checks are added to ensure that the valuesare correctly converted by the compiler.The major textual change to the Pascal version apart from theidentifiersis that named procedures are used, inserting parameterswherehelpful.  New procedures are also introduced.  Thecorrespondence is as follows:BASIC       Pascallines   90- 140   Pause 170- 250   Instructions 380- 460   Heading 480- 670   Characteristics 690- 870   History2940-2950   Random3710-3740   NewD4040-4080   DoesYequalX4090-4110   PrintIfNPositive4640-4850   TestPartialUnderflow=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=Below is an "ed script" that splits para.c into 10 filesof the form part[1-8].c, subs.c, and msgs.c, plus a headerfile, paranoia.h, that these files require.r paranoia.c$?SPLIT+,$w msgs.c .,$d?SPLIT .d+d-,$w subs.c-,$d?part8+d?include .,$w part8.c .,$d-d?part7+d?include .,$w part7.c .,$d-d?part6+d?include .,$w part6.c .,$d-d?part5+d?include .,$w part5.c .,$d-d?part4+d?include .,$w part4.c .,$d-d?part3+d?include .,$w part3.c .,$d-d?part2+d?include .,$w part2.c .,$d?SPLIT .d1,/^#include/-1d1,$w part1.c/Computed constants/,$d1,$s/^int/extern &/1,$s/^FLOAT/extern &/1,$s/^char/extern &/1,$s! = .*!;!/^Guard/,/^Round/s/^/extern //^jmp_buf/s/^/extern //^Sig_type/s/^/extern /s/$/\extern void sigfpe();/w paranoia.hq*/#include <stdio.h>#ifndef NOSIGNAL#include <signal.h>#endif#include <setjmp.h>extern double fabs(), floor(), log(), pow(), sqrt();#ifdef Single#define FLOAT float#define FABS(x) (float)fabs((double)(x))#define FLOOR(x) (float)floor((double)(x))#define LOG(x) (float)log((double)(x))#define POW(x,y) (float)pow((double)(x),(double)(y))#define SQRT(x) (float)sqrt((double)(x))#else#define FLOAT double#define FABS(x) fabs(x)#define FLOOR(x) floor(x)#define LOG(x) log(x)#define POW(x,y) pow(x,y)#define SQRT(x) sqrt(x)#endifjmp_buf ovfl_buf;typedef void (*Sig_type)();Sig_type sigsave;#define KEYBOARD 0FLOAT Radix, BInvrse, RadixD2, BMinusU2;FLOAT Sign(), Random();/*Small floating point constants.*/FLOAT Zero = 0.0;FLOAT Half = 0.5;FLOAT One = 1.0;FLOAT Two = 2.0;FLOAT Three = 3.0;FLOAT Four = 4.0;FLOAT Five = 5.0;FLOAT Eight = 8.0;FLOAT Nine = 9.0;FLOAT TwentySeven = 27.0;FLOAT ThirtyTwo = 32.0;FLOAT TwoForty = 240.0;FLOAT MinusOne = -1.0;FLOAT OneAndHalf = 1.5;/*Integer constants*/int NoTrials = 20; /*Number of tests for commutativity. */#define False 0#define True 1/* Definitions for declared types 	Guard == (Yes, No);	Rounding == (Chopped, Rounded, Other);	Message == packed array [1..40] of char;	Class == (Flaw, Defect, Serious, Failure);	  */#define Yes 1#define No  0#define Chopped 2#define Rounded 1#define Other   0#define Flaw    3#define Defect  2#define Serious 1#define Failure 0typedef int Guard, Rounding, Class;typedef char Message;/* Declarations of Variables */int Indx;char ch[8];FLOAT AInvrse, A1;FLOAT C, CInvrse;FLOAT D, FourD;FLOAT E0, E1, Exp2, E3, MinSqEr;FLOAT SqEr, MaxSqEr, E9;FLOAT Third;FLOAT F6, F9;FLOAT H, HInvrse;int I;FLOAT StickyBit, J;FLOAT MyZero;FLOAT Precision;FLOAT Q, Q9;FLOAT R, Random9;FLOAT T, Underflow, S;FLOAT OneUlp, UfThold, U1, U2;FLOAT V, V0, V9;FLOAT W;FLOAT X, X1, X2, X8, Random1;FLOAT Y, Y1, Y2, Random2;FLOAT Z, PseudoZero, Z1, Z2, Z9;int ErrCnt[4];int fpecount;int Milestone;int PageNo;int M, N, N1;Guard GMult, GDiv, GAddSub;Rounding RMult, RDiv, RAddSub, RSqrt;int Break, Done, NotMonot, Monot, Anomaly, IEEE,		SqRWrng, UfNGrad;/* Computed constants. *//*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 *//*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 *//* floating point exception receiver */ voidsigfpe(i){	fpecount++;	printf("\n* * * FLOATING-POINT ERROR * * *\n");	fflush(stdout);	if (sigsave) {#ifndef NOSIGNAL		signal(SIGFPE, sigsave);#endif		sigsave = 0;		longjmp(ovfl_buf, 1);		}	abort();}main(){#ifdef mc	char *out;	ieee_flags("set", "precision", "double", &out);#endif	/* First two assignments use integer right-hand sides. */	Zero = 0;	One = 1;	Two = One + One;	Three = Two + One;	Four = Three + One;	Five = Four + One;	Eight = Four + Four;	Nine = Three * Three;	TwentySeven = Nine * Three;	ThirtyTwo = Four * Eight;	TwoForty = Four * Five * Three * Four;	MinusOne = -One;	Half = One / Two;	OneAndHalf = One + Half;	ErrCnt[Failure] = 0;	ErrCnt[Serious] = 0;	ErrCnt[Defect] = 0;	ErrCnt[Flaw] = 0;	PageNo = 1;	/*=============================================*/	Milestone = 0;	/*=============================================*/#ifndef NOSIGNAL	signal(SIGFPE, sigfpe);#endif	Instructions();	Pause();	Heading();	Pause();	Characteristics();	Pause();	History();	Pause();	/*=============================================*/	Milestone = 7;	/*=============================================*/	printf("Program is now RUNNING tests on small integers:\n");		TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero)		   && (One > Zero) && (One + One == Two),			"0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2");	Z = - Zero;	if (Z != 0.0) {		ErrCnt[Failure] = ErrCnt[Failure] + 1;		printf("Comparison alleges that -0.0 is Non-zero!\n");		U1 = 0.001;		Radix = 1;		TstPtUf();		}	TstCond (Failure, (Three == Two + One) && (Four == Three + One)		   && (Four + Two * (- Two) == Zero)		   && (Four - Three - One == Zero),		   "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0");	TstCond (Failure, (MinusOne == (0 - One))		   && (MinusOne + One == Zero ) && (One + MinusOne == Zero)		   && (MinusOne + FABS(One) == Zero)		   && (MinusOne + MinusOne * MinusOne == Zero),		   "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0");	TstCond (Failure, Half + MinusOne + Half == Zero,		  "1/2 + (-1) + 1/2 != 0");	/*=============================================*/	/*SPLIT	part2();	part3();	part4();	part5();	part6();	part7();	part8();	}#include "paranoia.h"part2(){*/	Milestone = 10;	/*=============================================*/	TstCond (Failure, (Nine == Three * Three)		   && (TwentySeven == Nine * Three) && (Eight == Four + Four)		   && (ThirtyTwo == Eight * Four)		   && (ThirtyTwo - TwentySeven - Four - One == Zero),		   "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0");	TstCond (Failure, (Five == Four + One) &&			(TwoForty == Four * Five * Three * Four)		   && (TwoForty / Three - Four * Four * Five == Zero)		   && ( TwoForty / Four - Five * Three * Four == Zero)		   && ( TwoForty / Five - Four * Three * Four == Zero),		  "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48");	if (ErrCnt[Failure] == 0) {		printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");		printf("\n");		}	printf("Searching for Radix and Precision.\n");	W = One;	do  {		W = W + W;		Y = W + One;		Z = Y - W;		Y = Z - One;		} while (MinusOne + FABS(Y) < Zero);	/*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/	Precision = Zero;	Y = One;	do  {		Radix = W + Y;		Y = Y + Y;		Radix = Radix - W;		} while ( Radix == Zero);	if (Radix < Two) Radix = One;	printf("Radix = %f .\n", Radix);	if (Radix != 1) {		W = One;		do  {			Precision = Precision + One;			W = W * Radix;			Y = W + One;			} while ((Y - W) == One);		}	/*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1			                              ...*/	U1 = One / W;	U2 = Radix * U1;	printf("Closest relative separation found is U1 = %.7e .\n\n", U1);	printf("Recalculating radix and precision\n ");		/*save old values*/	E0 = Radix;	E1 = U1;	E9 = U2;	E3 = Precision;		X = Four / Three;	Third = X - One;	F6 = Half - Third;	X = F6 + F6;	X = FABS(X - Third);	if (X < U2) X = U2;		/*... now X = (unknown no.) ulps of 1+...*/	do  {		U2 = X;		Y = Half * U2 + ThirtyTwo * U2 * U2;		Y = One + Y;		X = Y - One;		} while ( ! ((U2 <= X) || (X <= Zero)));		/*... now U2 == 1 ulp of 1 + ... */	X = Two / Three;	F6 = X - Half;	Third = F6 + F6;	X = Third - Half;	X = FABS(X + F6);	if (X < U1) X = U1;		/*... now  X == (unknown no.) ulps of 1 -... */	do  {		U1 = X;		Y = Half * U1 + ThirtyTwo * U1 * U1;		Y = Half - Y;		X = Half + Y;		Y = Half - X;		X = Half + Y;		} while ( ! ((U1 <= X) || (X <= Zero)));	/*... now U1 == 1 ulp of 1 - ... */	if (U1 == E1) printf("confirms closest relative separation U1 .\n");	else printf("gets better closest relative separation U1 = %.7e .\n", U1);	W = One / U1;	F9 = (Half - U1) + Half;	Radix = FLOOR(0.01 + U2 / U1);	if (Radix == E0) printf("Radix confirmed.\n");	else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix);	TstCond (Defect, Radix <= Eight + Eight,		   "Radix is too big: roundoff problems");	TstCond (Flaw, (Radix == Two) || (Radix == 10)		   || (Radix == One), "Radix is not as good as 2 or 10");	/*=============================================*/	Milestone = 20;	/*=============================================*/	TstCond (Failure, F9 - Half < Half,		   "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");	X = F9;	I = 1;	Y = X - Half;	Z = Y - Half;	TstCond (Failure, (X != One)		   || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");	X = One + U2;	I = 0;	/*=============================================*/	Milestone = 25;	/*=============================================*/	/*... BMinusU2 = nextafter(Radix, 0) */	BMinusU2 = Radix - One;	BMinusU2 = (BMinusU2 - U2) + One;	/* Purify Integers */	if (Radix != One)  {		X = - TwoForty * LOG(U1) / LOG(Radix);		Y = FLOOR(Half + X);		if (FABS(X - Y) * Four < One) X = Y;		Precision = X / TwoForty;		Y = FLOOR(Half + Precision);		if (FABS(Precision - Y) * TwoForty < Half) Precision = Y;		}	if ((Precision != FLOOR(Precision)) || (Radix == One)) {		printf("Precision cannot be characterized by an Integer number\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -