home *** CD-ROM | disk | FTP | other *** search
- From: timborn@ihlpg.UUCP
- Newsgroups: comp.sources.misc
- Subject: config
- Message-ID: <4081@ncoast.UUCP>
- Date: 7 Aug 87 01:07:58 GMT
- Sender: allbery@ncoast.UUCP
- Lines: 523
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/8708/6
-
- From: ihlpg!timborn
- Postmark: Pony Express
- Date: Thu Aug 6 03:19:59 1987 IH
- To: ihnp4!ptsfa!ames!ll-xn!husc6!necntc!ncoast!allbery
- Subject: config
-
- Here are some changes for UNIX System V systems.
- They are enclosed in #ifdef SYSV/#endif.
-
- tim
- ...ihnp4!hvlpb!tborn
- Hilversum, Netherlands
- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- /* Determine some properties of C types on your machine/compiler
- Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
- Bugfixes and upgrades gratefully received.
-
- The program only works if overflows are ignored by the C system or are
- catchable by signal().
-
- If your C system is not unix but does have signal/setjmp, compile with
- cc -DSIGNAL config.c
- otherwise with
- cc config.c
- Don't use any optimisation flags: the program won't work if you do.
- Some compilers need a -f flag for floating point.
-
- You may need to add some calls to signal() for other sorts of exception
- on your machine than SIGFPE, and SIGOVER. See lines beginning #ifdef
- SIGNAL later in the program.
-
- Output is produced as C style comments so that the program can be used to
- produce a .h file with minimum upheaval.
-
- I apologise unreservedly for the contorted use of the preprocessor...
-
- If your C preprocessor doesn't have the predefined __FILE__ macro, and
- you want to call this file anything other than config.c, change the
- following #define command accordingly.
- */
-
- #ifndef __FILE__
- #define __FILE__ "config.c"
- #endif
-
- #ifndef PASS
- #define PASS 1
-
- #include <stdio.h>
-
- #ifdef SYSV
- #include <sys/utsname.h>
- #include <time.h>
- #endif
-
- #ifndef SIGNAL
- #ifdef unix
- #define SIGNAL
- #endif /*unix*/
- #endif /*SIGNAL*/
-
- #ifdef SIGNAL
-
- #include <signal.h>
- #include <setjmp.h>
-
- jmp_buf lab;
- overflow(sig) int sig; { /* what to do on overflow/underflow */
- (void) signal(sig, overflow);
- longjmp(lab, 1);
- }
-
- #else /*!SIGNAL*/
- /* Dummy routines instead */
- int lab=1;
- int setjmp(lab) int lab; { return(0); }
-
- #endif /*SIGNAL*/
-
- main() {
- int bits; /* the number of bits per unit returned by sizeof() */
- int dprec, eprec, basic(), fprop(), dprop(), eprop();
- char *malloc();
- unsigned int size;
- long total;
-
- #ifdef SYSV
- struct utsname name;
- long tloc;
- #endif
-
- #ifdef SIGNAL
- #ifdef SIGFPE
- (void) signal(SIGFPE, overflow);
- #endif
- #ifdef SIGOVER
- (void) signal(SIGOVER, overflow);
- #endif
- /* Add more calls as necessary */
- #endif /* SIGNAL */
-
- if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
-
- #ifdef SYSV
- /* show the machine name and date at the top of the output for reference */
- printf("/\* Machine: ");
- uname(&name);
- printf("%s %s %s %s %s *\/\n",
- name.sysname,
- name.nodename,
- name.release,
- name.version,
- name.machine);
- tloc = time( (long *) 0);
- /* precision for date string required to avoid \n returned from asctime() */
- printf("/\* Date: %.24s *\/\n", asctime(localtime(&tloc)) );
- #endif
-
- bits= basic();
- (void) fprop(bits);
- dprec= dprop(bits);
- eprec= eprop();
- printf("\n");
- if (eprec!=dprec)
- printf("/\* Expressions are evaluated in a %s %s %d %s *\/\n",
- eprec>dprec ? "higher" : "lower (tut!)",
- "precision than double, using", eprec, "base digits");
- else printf("/\* Expressions are evaluated in double precision *\/\n");
-
- /* An extra goody: the approximate amount of data-space */
- /* Allocate store until no more available */
- size=1<<((bits*sizeof(int))-2);
- total=0;
- while (size!=0) {
- while (malloc(size)!=(char *)NULL) total+=(size/2);
- size/=2;
- }
-
- printf("\n/\* Memory mallocatable ~= %ld Kbytes *\/\n",
- (total+511)/512);
- }
-
- int basic() {
- /* The properties of the basic types.
- Returns number of bits per sizeof unit */
-
- char c; int bits;
-
- if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
-
- /* Calculate number of bits per character *************************/
- c=1; bits=0;
- do { c=c<<1; bits++; } while(c!=0);
- c= (char)(-1);
- printf("/\* Char = %d bits, %ssigned *\/\n", sizeof(c)*bits,
- ((int)c)<0?"":"un");
-
- /* Shorts, ints and longs *****************************************/
- sprop();
- iprop();
- lprop();
-
- if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
-
- /* Alignment constants ********************************************/
- printf("/\* Alignments for char=%d short=%d int=%d long=%d *\/\n",
- sizeof(struct{char i; char c;})-sizeof(char),
- sizeof(struct{short i; char c;})-sizeof(short),
- sizeof(struct{int i; char c;})-sizeof(int),
- sizeof(struct{long i; char c;})-sizeof(long));
-
- /* Pointers *******************************************************/
- printf("/\* Char pointers = %d bits%s *\/\n", sizeof(char *)*bits,
- sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"");
- printf("/\* Int pointers = %d bits%s *\/\n", sizeof(int *)*bits,
- sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"");
-
- return bits;
- }
-
- int log(base, x) int base; double x; {
- int r=0;
- while (x>=base) { r++; x/=base; }
- return r;
- }
-
- int eprop() { /* See if expressions are evaluated in extended precision */
- int imant;
- double a, b, base;
-
- if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
-
- /* Size of mantissa **************************************/
- a=1.0;
- do { a=a+a; } while ((((a+1.0)-a)-1.0) == 0.0);
- b=1.0;
- do { b=b+b; } while ((base=((a+b)-a)) == 0.0);
-
- imant=0; b=1.0;
- do { imant++; b=b*base; }
- while ((((b+1.0)-b)-1.0) == 0.0);
- return imant;
- }
-
- #define fabs(x) (((x)<0.0)?(-x):(x))
-
- #endif /* ifndef PASS */
-
- /* As I said, I apologise for the contortions below. The procedures are
- expanded twice (for float and double) or three times (for short, int and
- long) by the preprocessor. That way, I never make a change to one that
- I forget to make to the other. #undef on an already undefined thing
- is (wrongly) flagged as an error by some compilers, therefore the #ifdef
- that follows:
- */
-
- #ifdef Number
- #undef Number
- #undef THING
- #undef FPROP
- #undef Store
- #undef Sum
- #undef Diff
- #undef Mul
- #undef Div
- #endif
-
- #ifdef Integer
- #undef Integer
- #undef INT
- #undef IPROP
- #endif
-
- #if PASS == 1
-
- #define Number float
- #define THING "float"
- #define FPROP fprop
- #define Store fStore
- #define Sum fSum
- #define Diff fDiff
- #define Mul fMul
- #define Div fDiv
-
- #define Integer short
- #define INT "short"
- #define IPROP sprop
-
- #endif /* PASS == 1 */
-
- #if PASS == 2
-
- #define Number double
- #define THING "double"
- #define FPROP dprop
- #define Store dStore
- #define Sum dSum
- #define Diff dDiff
- #define Mul dMul
- #define Div dDiv
-
- #define Integer int
- #define INT "int"
- #define IPROP iprop
-
- #endif /* if PASS == 2 */
-
- #if PASS == 3
-
- #define Integer long
- #define INT "long"
- #define IPROP lprop
-
- #endif /* if PASS == 3 */
-
- IPROP() {
- Integer newi, maxi, maxeri;
- int ibits, ipower, two=2;
-
- /* Calculate max short/int/long ***********************************/
- /* Calculate 2**n-1 until overflow - then use the previous value */
-
- newi=1; maxi=0;
-
- if (setjmp(lab)==0)
- for(ipower=0; newi>maxi; ipower++) {
- maxi=newi;
- newi=newi*two+1;
- }
-
- /* Now for those daft Cybers: */
-
- maxeri=0; newi=maxi;
-
- if (setjmp(lab)==0)
- for(ibits=ipower; newi>maxeri; ibits++) {
- maxeri=newi;
- newi=newi+newi+1;
- }
-
- printf("/\* Maximum %s = %ld (= 2**%d-1) *\/\n",
- INT, (long)maxi, ipower);
-
- if (maxeri>maxi) {
- printf("/\* There is a larger %s, %ld (= 2**%d-1), %s *\/\n",
- INT, (long)maxeri, ibits,
- "but only for addition, not multiplication");
- }
- }
-
- #ifdef Number
-
- /* These routines are intended to defeat any attempt at optimisation */
- Store(a, b) Number a, *b; { *b=a; }
- Number Sum(a, b) Number a, b; { Number r; Store(a+b, &r); return (r); }
- Number Diff(a, b) Number a, b; { Number r; Store(a-b, &r); return (r); }
- Number Mul(a, b) Number a, b; { Number r; Store(a*b, &r); return (r); }
- Number Div(a, b) Number a, b; { Number r; Store(a/b, &r); return (r); }
-
- int FPROP(bits) int bits; {
- /* Properties of floating types, using algorithms by Cody and Waite
- from MA Malcolm, as modified by WM Gentleman and SB Marovich.
- Further extended by S Pemberton.
-
- Returns the number of digits in the fraction.
- */
-
- int i, ibase, iexp, irnd, imant, iz, k, machep, maxexp, minexp,
- mx, negeps, mantbits;
- Number a, b, base, basein, basem1, eps, epsneg, xmax, newxmax,
- xmin, xminner, y, y1, z, z1, z2;
-
- if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
-
- printf("\n/\* Properties of %s: *\/\n", THING);
-
- /* Base and size of mantissa **************************************/
- a=1.0;
- do { a=Sum(a, a); } while (Diff(Diff(Sum(a, 1.0), a), 1.0) == 0.0);
- b=1.0;
- do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == 0.0);
- ibase=base;
- printf("/\* Base = %d *\/\n", ibase);
-
- imant=0; b=1.0;
- do { imant++; b=Mul(b, base); }
- while (Diff(Diff(Sum(b,1.0),b),1.0) == 0.0);
- printf("/\* Significant base digits = %d %s %d %s *\/\n",
- imant, "(= at least", log(10, (double)b),
- "decimal digits)");
-
- /* Various flavours of epsilon ************************************/
- basem1=Diff(base,1.0);
- if (Diff(Sum(a, basem1), a) != 0.0) irnd=1;
- else irnd=0;
-
- negeps=imant+imant;
- basein=1.0/base;
- a=1.0;
- for(i=1; i<=negeps; i++) a*=basein;
-
- b=a;
- while (Diff(Diff(1.0, a), 1.0) == 0.0) {
- a*=base;
- negeps--;
- }
- negeps= -negeps;
- printf("/\* Smallest x such that 1.0-base**x != 1.0 = %d *\/\n", negeps);
-
- epsneg=a;
- if ((ibase!=2) && (irnd==1)) {
- /* a=(a*(1.0+a))/(1.0+1.0); => */
- a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
- /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
- if (Diff(Diff(1.0, a), 1.0) != 0.0) epsneg=a;
- }
- printf("/\* Small x such that 1.0-x != 1.0 = %g *\/\n", epsneg);
- /* it may not be the smallest */
-
- machep= -imant-imant;
- a=b;
- while (Diff(Sum(1.0, a), 1.0) == 0.0) { a*=base; machep++; }
- printf("/\* Smallest x such that 1.0+base**x != 1.0 = %d *\/\n", machep);
-
- eps=a;
- if ((ibase!=2) && (irnd==1)) {
- /* a=(a*(1.0+a))/(1.0+1.0); => */
- a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
- /* if ((1.0+a)-1.0 != 0.0) eps=a; => */
- if (Diff(Sum(1.0, a), 1.0) != 0.0) eps=a;
- }
- printf("/\* Smallest x such that 1.0+x != 1.0 = %g *\/\n", eps);
-
- /* Round or chop **************************************************/
- if (irnd == 1) { printf("/\* Arithmetic rounds *\/\n"); }
- else {
- printf("/\* Arithmetic chops");
- if (Diff(Mul(Sum(1.0,eps),1.0),1.0) != 0.0) {
- printf(" but uses guard digits");
- }
- printf(" *\/\n");
- }
-
- /* Size of and minimum normalised exponent ************************/
- y=0; i=0; k=1; z=basein; z1=(1.0+eps)/base;
-
- /* Coarse search for the largest power of two */
- if (setjmp(lab)==0) /* in case of underflow trap */
- do {
- y=z; y1=z1;
- z=Mul(y,y); z1=Mul(z1, y);
- a=Mul(z,1.0);
- z2=Div(z1,y);
- if (z2 != y1) break;
- if ((Sum(a,a) == 0.0) || (fabs(z) >= y)) break;
- i++;
- k+=k;
- } while(1);
-
- if (ibase != 10) {
- iexp=i+1; /* for the sign */
- mx=k+k;
- } else {
- iexp=2;
- iz=ibase;
- while (k >= iz) { iz*=ibase; iexp++; }
- mx=iz+iz-1;
- }
-
- /* Fine tune starting with y and y1 */
- if (setjmp(lab)==0) /* in case of underflow trap */
- do {
- xmin=y; z1=y1;
- y=Div(y,base); y1=Div(y1,base);
- a=Mul(y,1.0);
- z2=Mul(y1,base);
- if (z2 != z1) break;
- if ((Sum(a,a) == 0.0) || (fabs(y) >= xmin)) break;
- k++;
- } while (1);
-
- if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
-
- minexp=(-k)+1;
-
- if ((mx <= k+k-3) && (ibase != 10)) { mx+=mx; iexp+=1; }
- printf("/\* Number of bits used for exponent = %d *\/\n", iexp);
- printf("/\* Minimum normalised exponent = %d *\/\n", minexp);
- printf("/\* Minimum normalised positive number = %g *\/\n", xmin);
-
- /* Minimum exponent ************************************************/
- if (setjmp(lab)==0) /* in case of underflow trap */
- do {
- xminner=y;
- y=Div(y,base);
- a=Mul(y,1.0);
- if ((Sum(a,a) == 0.0) || (fabs(y) >= xminner)) break;
- } while (1);
-
- if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
-
- if (xminner != 0.0 && xminner != xmin) {
- printf("/\* The smallest numbers are not kept normalised *\/\n");
- printf("/\* Smallest unnormalised positive number = %g *\/\n",
- xminner);
- } else printf("/\* The smallest numbers are normalised *\/\n");
-
- /* Maximum exponent ************************************************/
- maxexp=2; xmax=1.0; newxmax=base+1.0;
- if (setjmp(lab) == 0) {
- while (xmax<newxmax) {
- xmax=newxmax;
- newxmax=Mul(newxmax, base);
- if (Div(newxmax, base) != xmax) break; /* ieee infinity */
- maxexp++;
- }
- }
- if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
-
- printf("/\* Maximum exponent = %d *\/\n", maxexp);
-
- /* Largest number ***************************************************/
- xmax=Diff(1.0, epsneg);
- if (Mul(xmax,1.0) != xmax) xmax=Diff(1.0, Mul(base,epsneg));
- for (i=1; i<=maxexp; i++) xmax=Mul(xmax, base);
- printf("/\* Maximum number = %g *\/\n", xmax);
-
- /* Hidden bit + sanity check ****************************************/
- if (ibase != 10) {
- mantbits=log(2, (double)ibase)*imant;
- if (mantbits+iexp+1 == sizeof(Number)*bits+1) {
- printf("/\* Arithmetic uses a hidden bit *\/\n");
- } else if (mantbits+iexp+1 == sizeof(Number)*bits) {
- printf("/\* Arithmetic doesn't use a hidden bit *\/\n");
- } else {
- printf("/\* Something fishy here! %s %s %s *\/\n",
- "Exponent size + mantissa size doesn't match",
- "with the size of a", THING);
- }
- }
- return imant;
- }
-
- #endif /* ifdef Number */
-
- #if PASS == 3
- #undef PASS
- #define PASS 4
- #endif
-
- #if PASS == 2
- #undef PASS
- #define PASS 3
- #endif
-
- #if PASS == 1
- #undef PASS
- #define PASS 2
- #endif
-
- #if PASS < 4
- #include __FILE__
- #endif
-
-
-