home *** CD-ROM | disk | FTP | other *** search
- /* 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(). */
- /*
- * $Header: precision.c,v 3.5 87/08/06 08:10:59 kenj Exp $
- */
-
- #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);
- }
-