home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8708 / 6 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  13.5 KB

  1. From: timborn@ihlpg.UUCP
  2. Newsgroups: comp.sources.misc
  3. Subject: config
  4. Message-ID: <4081@ncoast.UUCP>
  5. Date: 7 Aug 87 01:07:58 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Lines: 523
  8. Approved: allbery@ncoast.UUCP
  9. X-Archive: comp.sources.misc/8708/6
  10.  
  11. From: ihlpg!timborn
  12. Postmark: Pony Express
  13. Date: Thu Aug 6 03:19:59 1987 IH
  14. To: ihnp4!ptsfa!ames!ll-xn!husc6!necntc!ncoast!allbery
  15. Subject: config
  16.  
  17. Here are some changes for UNIX System V systems.
  18. They are enclosed in #ifdef SYSV/#endif.
  19.  
  20. tim
  21. ...ihnp4!hvlpb!tborn
  22. Hilversum, Netherlands
  23. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  24. /* Determine some properties of C types on your machine/compiler
  25.    Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
  26.    Bugfixes and upgrades gratefully received.
  27.  
  28.    The program only works if overflows are ignored by the C system or are
  29.    catchable by signal().
  30.  
  31.    If your C system is not unix but does have signal/setjmp, compile with
  32.     cc -DSIGNAL config.c
  33.    otherwise with
  34.     cc config.c
  35.    Don't use any optimisation flags: the program won't work if you do.
  36.    Some compilers need a -f flag for floating point.
  37.  
  38.    You may need to add some calls to signal() for other sorts of exception
  39.    on your machine than SIGFPE, and SIGOVER. See lines beginning #ifdef
  40.    SIGNAL later in the program.
  41.  
  42.    Output is produced as C style comments so that the program can be used to
  43.    produce a .h file with minimum upheaval.
  44.  
  45.    I apologise unreservedly for the contorted use of the preprocessor...
  46.  
  47.    If your C preprocessor doesn't have the predefined __FILE__ macro, and
  48.    you want to call this file anything other than config.c, change the
  49.    following #define command accordingly.
  50. */
  51.  
  52. #ifndef __FILE__
  53. #define __FILE__ "config.c"
  54. #endif
  55.  
  56. #ifndef PASS
  57. #define PASS 1
  58.  
  59. #include <stdio.h>
  60.  
  61. #ifdef SYSV
  62. #include    <sys/utsname.h>
  63. #include    <time.h>
  64. #endif
  65.  
  66. #ifndef SIGNAL
  67. #ifdef unix
  68. #define SIGNAL
  69. #endif /*unix*/
  70. #endif /*SIGNAL*/
  71.  
  72. #ifdef SIGNAL
  73.  
  74. #include <signal.h>
  75. #include <setjmp.h>
  76.  
  77.     jmp_buf lab;
  78.     overflow(sig) int sig; { /* what to do on overflow/underflow */
  79.         (void) signal(sig, overflow);
  80.         longjmp(lab, 1);
  81.     }
  82.  
  83. #else /*!SIGNAL*/
  84.     /* Dummy routines instead */
  85.     int lab=1;
  86.     int setjmp(lab) int lab; { return(0); }
  87.  
  88. #endif /*SIGNAL*/
  89.  
  90. main() {
  91.     int bits; /* the number of bits per unit returned by sizeof() */
  92.     int dprec, eprec, basic(), fprop(), dprop(), eprop();
  93.     char *malloc();
  94.     unsigned int size;
  95.     long total;
  96.  
  97. #ifdef SYSV
  98.     struct utsname name;
  99.     long    tloc;
  100. #endif
  101.  
  102. #ifdef SIGNAL
  103. #ifdef SIGFPE
  104.     (void) signal(SIGFPE, overflow);
  105. #endif
  106. #ifdef SIGOVER
  107.     (void) signal(SIGOVER, overflow);
  108. #endif
  109. /* Add more calls as necessary */
  110. #endif /* SIGNAL */
  111.  
  112.     if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  113.  
  114. #ifdef SYSV
  115.     /* show the machine name and date at the top of the output for reference */
  116.     printf("/\* Machine: ");
  117.     uname(&name);
  118.     printf("%s %s %s %s %s *\/\n",
  119.         name.sysname, 
  120.         name.nodename, 
  121.         name.release, 
  122.         name.version, 
  123.         name.machine);
  124.     tloc = time( (long *) 0);
  125.     /* precision for date string required to avoid \n returned from asctime() */
  126.     printf("/\* Date: %.24s *\/\n", asctime(localtime(&tloc)) );
  127. #endif
  128.  
  129.     bits=  basic();
  130.     (void) fprop(bits);
  131.     dprec= dprop(bits);
  132.     eprec= eprop();
  133.     printf("\n");
  134.     if (eprec!=dprec)
  135.         printf("/\* Expressions are evaluated in a %s %s %d %s *\/\n",
  136.             eprec>dprec ? "higher" : "lower (tut!)",
  137.             "precision than double, using", eprec, "base digits");
  138.     else printf("/\* Expressions are evaluated in double precision *\/\n");
  139.  
  140.     /* An extra goody: the approximate amount of data-space */
  141.     /* Allocate store until no more available */
  142.     size=1<<((bits*sizeof(int))-2);
  143.     total=0;
  144.     while (size!=0) {
  145.         while (malloc(size)!=(char *)NULL) total+=(size/2);
  146.         size/=2;
  147.     }
  148.  
  149.     printf("\n/\* Memory mallocatable ~= %ld Kbytes *\/\n",
  150.                         (total+511)/512);
  151. }
  152.  
  153. int basic() {
  154.     /* The properties of the basic types.
  155.        Returns number of bits per sizeof unit */
  156.  
  157.     char c; int bits;
  158.  
  159.     if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  160.  
  161.     /* Calculate number of bits per character *************************/
  162.     c=1; bits=0;
  163.     do { c=c<<1; bits++; } while(c!=0);
  164.     c= (char)(-1);
  165.     printf("/\* Char = %d bits, %ssigned *\/\n", sizeof(c)*bits,
  166.             ((int)c)<0?"":"un");
  167.  
  168.     /* Shorts, ints and longs *****************************************/
  169.     sprop();
  170.     iprop();
  171.     lprop();
  172.  
  173.     if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  174.  
  175.     /* Alignment constants ********************************************/
  176.     printf("/\* Alignments for char=%d short=%d int=%d long=%d *\/\n",
  177.         sizeof(struct{char i; char c;})-sizeof(char),
  178.         sizeof(struct{short i; char c;})-sizeof(short),
  179.         sizeof(struct{int i; char c;})-sizeof(int),
  180.         sizeof(struct{long i; char c;})-sizeof(long));
  181.  
  182.     /* Pointers *******************************************************/
  183.     printf("/\* Char pointers = %d bits%s *\/\n", sizeof(char *)*bits,
  184.         sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"");
  185.     printf("/\* Int pointers = %d bits%s *\/\n", sizeof(int *)*bits,
  186.         sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"");
  187.  
  188.     return bits;
  189. }
  190.  
  191. int log(base, x) int base; double x; {
  192.     int r=0;
  193.     while (x>=base) { r++; x/=base; }
  194.     return r;
  195. }
  196.  
  197. int eprop() { /* See if expressions are evaluated in extended precision */
  198.     int imant;
  199.     double a, b, base;
  200.  
  201.     if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  202.  
  203.     /* Size of mantissa **************************************/
  204.     a=1.0;
  205.     do { a=a+a; } while ((((a+1.0)-a)-1.0) == 0.0);
  206.     b=1.0;
  207.     do { b=b+b; } while ((base=((a+b)-a)) == 0.0);
  208.  
  209.     imant=0; b=1.0;
  210.     do { imant++; b=b*base; }
  211.     while ((((b+1.0)-b)-1.0) == 0.0);
  212.     return imant;
  213. }
  214.  
  215. #define fabs(x) (((x)<0.0)?(-x):(x))
  216.  
  217. #endif /* ifndef PASS */
  218.  
  219. /* As I said, I apologise for the contortions below. The procedures are
  220.    expanded twice (for float and double) or three times (for short, int and
  221.    long) by the preprocessor. That way, I never make a change to one that
  222.    I forget to make to the other. #undef on an already undefined thing
  223.    is (wrongly) flagged as an error by some compilers, therefore the #ifdef
  224.    that follows: 
  225. */
  226.  
  227. #ifdef Number
  228. #undef Number
  229. #undef THING
  230. #undef FPROP
  231. #undef Store
  232. #undef Sum
  233. #undef Diff
  234. #undef Mul
  235. #undef Div
  236. #endif
  237.  
  238. #ifdef Integer
  239. #undef Integer
  240. #undef INT
  241. #undef IPROP
  242. #endif
  243.  
  244. #if PASS == 1
  245.  
  246. #define Number float
  247. #define THING "float"
  248. #define FPROP fprop
  249. #define Store fStore
  250. #define Sum fSum
  251. #define Diff fDiff
  252. #define Mul fMul
  253. #define Div fDiv
  254.  
  255. #define Integer short
  256. #define INT "short"
  257. #define IPROP sprop
  258.  
  259. #endif /* PASS == 1 */
  260.  
  261. #if PASS == 2
  262.  
  263. #define Number double
  264. #define THING "double"
  265. #define FPROP dprop
  266. #define Store dStore
  267. #define Sum dSum
  268. #define Diff dDiff
  269. #define Mul dMul
  270. #define Div dDiv
  271.  
  272. #define Integer int
  273. #define INT "int"
  274. #define IPROP iprop
  275.  
  276. #endif /* if PASS == 2 */
  277.  
  278. #if PASS == 3
  279.  
  280. #define Integer long
  281. #define INT "long"
  282. #define IPROP lprop
  283.  
  284. #endif /* if PASS == 3 */
  285.  
  286. IPROP() {
  287.     Integer newi, maxi, maxeri;
  288.     int ibits, ipower, two=2;
  289.  
  290.     /* Calculate max short/int/long ***********************************/
  291.     /* Calculate 2**n-1 until overflow - then use the previous value  */
  292.  
  293.     newi=1; maxi=0;
  294.  
  295.     if (setjmp(lab)==0)
  296.         for(ipower=0; newi>maxi; ipower++) {
  297.             maxi=newi;
  298.             newi=newi*two+1;
  299.         }
  300.  
  301.     /* Now for those daft Cybers: */
  302.  
  303.     maxeri=0; newi=maxi;
  304.  
  305.     if (setjmp(lab)==0)
  306.         for(ibits=ipower; newi>maxeri; ibits++) {
  307.             maxeri=newi;
  308.             newi=newi+newi+1;
  309.         }
  310.  
  311.     printf("/\* Maximum %s = %ld (= 2**%d-1) *\/\n",
  312.                 INT, (long)maxi, ipower);
  313.  
  314.     if (maxeri>maxi) {
  315.         printf("/\* There is a larger %s, %ld (= 2**%d-1), %s *\/\n",
  316.             INT, (long)maxeri, ibits, 
  317.             "but only for addition, not multiplication");
  318.     }
  319. }
  320.  
  321. #ifdef Number
  322.  
  323. /* These routines are intended to defeat any attempt at optimisation */
  324. Store(a, b) Number a, *b; { *b=a; }
  325. Number Sum(a, b) Number a, b; { Number r; Store(a+b, &r); return (r); }
  326. Number Diff(a, b) Number a, b; { Number r; Store(a-b, &r); return (r); }
  327. Number Mul(a, b) Number a, b; { Number r; Store(a*b, &r); return (r); }
  328. Number Div(a, b) Number a, b; { Number r; Store(a/b, &r); return (r); }
  329.  
  330. int FPROP(bits) int bits; {
  331.     /* Properties of floating types, using algorithms by Cody and Waite
  332.        from MA Malcolm, as modified by WM Gentleman and SB Marovich.
  333.        Further extended by S Pemberton.
  334.  
  335.        Returns the number of digits in the fraction.
  336.     */
  337.  
  338.     int i, ibase, iexp, irnd, imant, iz, k, machep, maxexp, minexp,
  339.         mx, negeps, mantbits;
  340.     Number a, b, base, basein, basem1, eps, epsneg, xmax, newxmax,
  341.            xmin, xminner, y, y1, z, z1, z2;
  342.  
  343.     if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  344.  
  345.     printf("\n/\* Properties of %s: *\/\n", THING);
  346.  
  347.     /* Base and size of mantissa **************************************/
  348.     a=1.0;
  349.     do { a=Sum(a, a); } while (Diff(Diff(Sum(a, 1.0), a), 1.0) == 0.0);
  350.     b=1.0;
  351.     do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == 0.0);
  352.     ibase=base;
  353.     printf("/\* Base = %d *\/\n", ibase);
  354.  
  355.     imant=0; b=1.0;
  356.     do { imant++; b=Mul(b, base); }
  357.     while (Diff(Diff(Sum(b,1.0),b),1.0) == 0.0);
  358.     printf("/\* Significant base digits = %d %s %d %s *\/\n",
  359.             imant, "(= at least", log(10, (double)b),
  360.             "decimal digits)");
  361.  
  362.     /* Various flavours of epsilon ************************************/
  363.     basem1=Diff(base,1.0);
  364.     if (Diff(Sum(a, basem1), a) != 0.0) irnd=1; 
  365.     else irnd=0;
  366.  
  367.     negeps=imant+imant;
  368.     basein=1.0/base;
  369.     a=1.0;
  370.     for(i=1; i<=negeps; i++) a*=basein;
  371.  
  372.     b=a;
  373.     while (Diff(Diff(1.0, a), 1.0) == 0.0) {
  374.         a*=base;
  375.         negeps--;
  376.     }
  377.     negeps= -negeps;
  378.     printf("/\* Smallest x such that 1.0-base**x != 1.0 = %d *\/\n", negeps);
  379.  
  380.     epsneg=a;
  381.     if ((ibase!=2) && (irnd==1)) {
  382.     /*    a=(a*(1.0+a))/(1.0+1.0); => */
  383.         a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
  384.     /*    if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
  385.         if (Diff(Diff(1.0, a), 1.0) != 0.0) epsneg=a;
  386.     }
  387.     printf("/\* Small x such that 1.0-x != 1.0 = %g *\/\n", epsneg);
  388.     /* it may not be the smallest */
  389.  
  390.     machep= -imant-imant;
  391.     a=b;
  392.     while (Diff(Sum(1.0, a), 1.0) == 0.0) { a*=base; machep++; }
  393.     printf("/\* Smallest x such that 1.0+base**x != 1.0 = %d *\/\n", machep);
  394.  
  395.     eps=a;
  396.     if ((ibase!=2) && (irnd==1)) {
  397.     /*    a=(a*(1.0+a))/(1.0+1.0); => */
  398.         a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
  399.     /*    if ((1.0+a)-1.0 != 0.0) eps=a; => */
  400.         if (Diff(Sum(1.0, a), 1.0) != 0.0) eps=a;
  401.     }
  402.     printf("/\* Smallest x such that 1.0+x != 1.0 = %g *\/\n", eps);
  403.  
  404.     /* Round or chop **************************************************/
  405.     if (irnd == 1) { printf("/\* Arithmetic rounds *\/\n"); }
  406.     else { 
  407.         printf("/\* Arithmetic chops");
  408.         if (Diff(Mul(Sum(1.0,eps),1.0),1.0) !=  0.0) {
  409.             printf(" but uses guard digits");
  410.         }
  411.         printf(" *\/\n");
  412.     }
  413.  
  414.     /* Size of and minimum normalised exponent ************************/
  415.     y=0; i=0; k=1; z=basein; z1=(1.0+eps)/base;
  416.  
  417.     /* Coarse search for the largest power of two */
  418.     if (setjmp(lab)==0) /* in case of underflow trap */
  419.         do {
  420.             y=z; y1=z1;
  421.             z=Mul(y,y); z1=Mul(z1, y);
  422.             a=Mul(z,1.0);
  423.             z2=Div(z1,y);
  424.             if (z2 != y1) break;
  425.             if ((Sum(a,a) == 0.0) || (fabs(z) >= y)) break;
  426.             i++;
  427.             k+=k;
  428.         } while(1);
  429.  
  430.     if (ibase != 10) {
  431.         iexp=i+1; /* for the sign */
  432.         mx=k+k;
  433.     } else {
  434.         iexp=2;
  435.         iz=ibase;
  436.         while (k >= iz) { iz*=ibase; iexp++; }
  437.         mx=iz+iz-1;
  438.     }
  439.  
  440.     /* Fine tune starting with y and y1 */
  441.     if (setjmp(lab)==0) /* in case of underflow trap */
  442.         do {
  443.             xmin=y; z1=y1;
  444.             y=Div(y,base); y1=Div(y1,base);
  445.             a=Mul(y,1.0);
  446.             z2=Mul(y1,base);
  447.             if (z2 != z1) break;
  448.             if ((Sum(a,a) == 0.0) || (fabs(y) >= xmin)) break;
  449.             k++;
  450.         } while (1);
  451.  
  452.     if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  453.  
  454.     minexp=(-k)+1;
  455.  
  456.     if ((mx <= k+k-3) && (ibase != 10)) { mx+=mx; iexp+=1; }
  457.     printf("/\* Number of bits used for exponent = %d *\/\n", iexp);
  458.     printf("/\* Minimum normalised exponent = %d *\/\n", minexp);
  459.     printf("/\* Minimum normalised positive number = %g *\/\n", xmin);
  460.  
  461.     /* Minimum exponent ************************************************/
  462.     if (setjmp(lab)==0) /* in case of underflow trap */
  463.         do {
  464.             xminner=y;
  465.             y=Div(y,base);
  466.             a=Mul(y,1.0);
  467.             if ((Sum(a,a) == 0.0) || (fabs(y) >= xminner)) break;
  468.         } while (1);
  469.  
  470.     if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  471.  
  472.     if (xminner != 0.0 && xminner != xmin) {
  473.         printf("/\* The smallest numbers are not kept normalised *\/\n");
  474.         printf("/\* Smallest unnormalised positive number = %g *\/\n",
  475.             xminner);
  476.     } else printf("/\* The smallest numbers are normalised *\/\n");
  477.  
  478.     /* Maximum exponent ************************************************/
  479.     maxexp=2; xmax=1.0; newxmax=base+1.0;
  480.     if (setjmp(lab) == 0) {
  481.         while (xmax<newxmax) {
  482.             xmax=newxmax;
  483.             newxmax=Mul(newxmax, base);
  484.             if (Div(newxmax, base) != xmax) break; /* ieee infinity */
  485.             maxexp++;
  486.         }
  487.     }
  488.     if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  489.  
  490.     printf("/\* Maximum exponent = %d *\/\n", maxexp);
  491.  
  492.     /* Largest number ***************************************************/
  493.     xmax=Diff(1.0, epsneg);
  494.     if (Mul(xmax,1.0) != xmax) xmax=Diff(1.0, Mul(base,epsneg));
  495.     for (i=1; i<=maxexp; i++) xmax=Mul(xmax, base);
  496.     printf("/\* Maximum number = %g *\/\n", xmax);
  497.  
  498.     /* Hidden bit + sanity check ****************************************/
  499.     if (ibase != 10) {
  500.         mantbits=log(2, (double)ibase)*imant;
  501.         if (mantbits+iexp+1 == sizeof(Number)*bits+1) {
  502.             printf("/\* Arithmetic uses a hidden bit *\/\n");
  503.         } else if (mantbits+iexp+1 == sizeof(Number)*bits) {
  504.             printf("/\* Arithmetic doesn't use a hidden bit *\/\n");
  505.         } else {
  506.             printf("/\* Something fishy here! %s %s %s *\/\n",
  507.                 "Exponent size + mantissa size doesn't match",
  508.                 "with the size of a", THING);
  509.         }
  510.     }
  511.     return imant;
  512. }
  513.  
  514. #endif /* ifdef Number */
  515.  
  516. #if PASS == 3
  517. #undef PASS
  518. #define PASS 4
  519. #endif
  520.  
  521. #if PASS == 2
  522. #undef PASS
  523. #define PASS 3
  524. #endif
  525.  
  526. #if PASS == 1
  527. #undef PASS
  528. #define PASS 2
  529. #endif
  530.  
  531. #if PASS < 4
  532. #include __FILE__
  533. #endif
  534.  
  535.  
  536.