home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
pc
/
source
/
byteunix.lzh
/
byte.2
/
precision.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-11
|
6KB
|
195 lines
/*******************************************************************************
* The BYTE UNIX Benchmarks - Release 2
* Module: precision.c SID: 2.4 4/17/90 16:45:35
*
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Ben Smith or Rick Grehan at BYTE Magazine
* bensmith@bixpb.UUCP rick_g@bixpb.UUCP
*
*******************************************************************************
* Modification Log:
* $Header: precision.c,v 3.5 87/08/06 08:10:59 kenj Exp $
*
******************************************************************************/
char SCCSid[] = "@(#) @(#)precision.c:2.4 -- 4/17/90 16:45:35";
/* Program to determine properties of the arithmetic available. */
/* Makes certain assumptions about the likely format of numbers */
/* */
/* Author: Steven Pemberton, CWI, Amsterdam. steven@mcvax */
/* */
/* If your C system is not unix but does have signal/setjmp, */
/* add a #define unix */
/* You may also need to change the #include <sys/signal.h> line */
/* and add some calls to signal(). */
/*
*/
#ifdef unix
#define SIGNAL
#include <sys/signal.h>
#include <setjmp.h>
jmp_buf lab;
overflow(sig) int sig; { /*what to do on overflow*/
signal(sig, overflow);
longjmp(lab, 1);
}
#endif
int tenlog(v) double v; {
/*The largest power of ten less than v*/
int p=0;
while (v>10) { p++; v/=10; }
return p;
}
int two(v) int v; {
/* (the closest power of two to v)-1 */
int t=1, s;
while (t<v) t=t*2+1;
s=(t-1)/2;
if ((v-s)>(t-v)) return(t);
return(s);
}
double twopower(n, e) int n, *e; {
/* Calculate 2**n without overflow worries */
/* Result is r*10**e */
double r=1.0; *e=0;
while (n-- > 0) {
r*=2.0;
if (r>10.0) { r/=10.0; (*e)++; }
}
return(r);
}
main() {
short maxshort, newshort;
int maxint, newint, i, maxfexp, maxdexp, bits,
fmantis, dmantis, ddmantis,
shortpower, intpower, longpower,
fpower, dpower, fipower, dipower, ddipower, lpower, base;
long maxlong, newlong;
float maxfloat, newfloat, sum, f, maxifloat;
double maxdouble, newdouble, maxidouble, maxiexpr,
d, incr, dsum;
#ifdef SIGNAL
signal(SIGFPE, overflow); /*signal(SIGOVER, overflow);*/
#endif
/****** Calculate max short *********************************************/
/* Calculate 2**n-1 until overflow - then use the previous value */
newshort=1; maxshort=0;
#ifdef SIGNAL
if (setjmp(lab)==0)
#endif
for(shortpower=0; newshort>maxshort; shortpower++) {
maxshort=newshort;
newshort=newshort*2+1;
}
bits= (shortpower+1)/sizeof(short);
printf("maxshort=%d (=2**%d-1)\n", maxshort, shortpower);
/****** Calculate max int by the same method ***************************/
newint=1; maxint=0;
#ifdef SIGNAL
if (setjmp(lab)==0)
#endif
for(intpower=0; newint>maxint; intpower++) {
maxint=newint;
newint=newint*2+1;
}
printf("maxint=%d (=2**%d-1)\n", maxint, intpower);
/****** Calculate max long by the same method ***************************/
newlong=1; maxlong=0;
#ifdef SIGNAL
if (setjmp(lab)==0)
#endif
for(longpower=0; newlong>maxlong; longpower++) {
maxlong=newlong;
newlong=newlong*2+1;
}
printf("maxlong=%ld (=2**%d-1)\n", maxlong, longpower);
/****** Calculate max float, assuming it's a power of two ***************/
/* Calculate 2**i until it overflows, and then use the nearest */
/* power of two (some machines overflow early, some late) */
newfloat=1; maxfloat=0;
#ifdef SIGNAL
if (setjmp(lab)==0)
#endif
for(i=0;newfloat>maxfloat;i++) {
maxfloat=newfloat;
newfloat=newfloat*2;
}
maxfexp=two(i); maxfloat=twopower(maxfexp, &fpower);
printf("maxfloat=~%fE%d (=~2**%d) (%d bits)\n",
maxfloat, fpower, maxfexp, sizeof(float)*bits);
/****** Calculate max double, assuming it's a power of two **************/
newdouble=1; maxdouble=0;
#ifdef SIGNAL
if (setjmp(lab)==0)
#endif
for(i=0;newdouble>maxdouble;i++) {
maxdouble=newdouble;
newdouble*=2;
}
#ifdef SIGNAL
if (setjmp(lab)!=0) { printf("\nUnexpected overflow\n"); exit(1); }
#endif
maxdexp=two(i); maxdouble=twopower(maxdexp, &dpower);
printf("maxdouble=~%fE%d (=~2**%d) (%d bits)\n",
maxdouble, dpower, maxdexp, sizeof(double)*bits);
/****** Calculate the accuracy for float, double, and expressions *******/
/* maxintfloat and maxintdouble are the largest values that can */
/* still be integer values; ie such that (x+1)-x=1. */
/* Some systems really do use extra precision in expressions */
f=2.0; incr=1.0; sum=f+incr;
for (fmantis=0; sum>2.0; fmantis++) { incr/=2; sum=f+incr; }
printf("max float exp=%d mantissa bits=%d\n", maxfexp, fmantis);
d=2.0; incr=1.0; dsum=d+incr;
for (dmantis=0; dsum>2.0; dmantis++) { incr/=2; dsum=d+incr; }
printf("max double exp=%d mantissa bits=%d\n", maxdexp, dmantis);
d=2.0; incr=1.0;
for (ddmantis=0; d+incr>2.0; ddmantis++) incr/=2;
maxifloat=twopower(fmantis, &fipower);
printf("maxintfloat=~%fE%d (=2**%d-1) (%d digit precision)\n",
maxifloat, fipower, fmantis, fipower);
maxidouble=twopower(dmantis, &dipower);
printf("maxintdouble=~%fE%d (=2**%d-1) (%d digit precision)\n",
maxidouble, dipower, dmantis, dipower);
maxiexpr=twopower(ddmantis, &ddipower);
printf("maxint for expressions=~%fE%d (=2**%d-1) (%d digit precision)\n",
maxiexpr, ddipower, ddmantis, ddipower);
/****** BASE is the largest power of ten such that BASE*BASE can be */
/* computed exactly as a double, and BASE+BASE as a long, useful */
/* for multi-length arithmetic */
lpower= tenlog((double)(maxlong/2));
base= (dipower/2)>lpower?lpower:(dipower/2);
printf("BASE=1E%d\n", base);
exit(0);
}