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

  1. From: steven@cwi.nl.UUCP (Steven Pemberton)
  2. Newsgroups: comp.sources.misc
  3. Subject: A C configuration enquirer
  4. Message-ID: <3748@ncoast.UUCP>
  5. Date: 5 Aug 87 00:29:07 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Organization: CWI, Amsterdam
  8. Lines: 621
  9. Approved: allbery@ncoast.UUCP
  10. X-Archive: comp.sources.misc/8708/3
  11.  
  12. config.c - a C configuration enquirer
  13. Author: Steven Pemberton, CWI, Amsterdam
  14.  
  15. This program determines properties of your machine and C compiler, such as
  16. the number of bits used for certain data-types, the accuracy of float and
  17. double, and so on.
  18.  
  19. The original purpose of the program was to generate a header-file for a
  20. large piece of software that must be as portable as possible. However, it is
  21. also a good check for a new compiler. It is the descendent of a similar
  22. program I posted a year or so ago. However it is completely rewritten, and
  23. incorporates much experience with the use of that program, and ideas from
  24. users of it.
  25.  
  26. Output is produced as C style comments so that the program can be used to
  27. produce a .h file with minimum upheaval.
  28.  
  29. Any ideas for future enhancements, and all fixes to make it run on machines
  30. where it doesn't currently run, will be gratefully received. Please mail me
  31. at
  32.     steven@cwi.nl (new style) or seismo!mcvax!steven (old style)
  33.  
  34. Steven Pemberton, Centre for Mathematics and Computer Science
  35. Amsterdam, The Netherlands
  36.  
  37. : This is a shell archive.
  38. : Extract with 'sh this_file'.
  39. echo 'Start of pack.out, part 01 out of 01:'
  40. echo 'x - Makefile'
  41. sed 's/^X//' > 'Makefile' << 'EOF'
  42. Xconfig:
  43. X    cc config.c -o config
  44. EOF
  45. echo 'x - READ.ME'
  46. sed 's/^X//' > 'READ.ME' << 'EOF'
  47. X        config.c - a C configuration enquirer
  48. X        Author: Steven Pemberton, CWI, Amsterdam
  49. X
  50. XThis program determines properties of your machine and C compiler, such as
  51. Xthe number of bits used for certain data-types, the accuracy of float and
  52. Xdouble, and so on.
  53. X
  54. XThe original purpose of the program was to generate a header-file for a
  55. Xlarge piece of software that must be as portable as possible. However, it is
  56. Xalso a good check for a new compiler. It is the descendent of a similar
  57. Xprogram I posted a year or so ago. However it is completely rewritten, and
  58. Xincorporates much experience with the use of that program, and ideas from
  59. Xusers of it.
  60. X
  61. XThe program only works if overflows are ignored by the C system or are
  62. Xcatchable by signal().
  63. X
  64. XIf your C system is not unix but does have signal/setjmp, compile with
  65. X    cc -DSIGNAL config.c
  66. Xotherwise with
  67. X    cc config.c
  68. XDon't use any optimisation flags.
  69. XSome compilers need a -f flag for floating point.
  70. X
  71. XYou may need to add some calls to signal() for other sorts of exception on
  72. Xyour machine than SIGFPE, and SIGOVER. See lines beginning #ifdef SIGNAL
  73. Xlater in the program.
  74. X
  75. XOutput is produced as C style comments so that the program can be used to
  76. Xproduce a .h file with minimum upheaval.
  77. X
  78. XI apologise unreservedly for the contorted use of the preprocessor...
  79. X
  80. XIf your C preprocessor doesn't have the predefined __FILE__ macro, and you
  81. Xwant to call the file anything other than config.c, change the first
  82. X#define command accordingly.
  83. X
  84. XAny ideas for future enhancements, and all fixes to make it run on machines
  85. Xwhere it doesn't currently run, will be gratefully received. Please mail me
  86. Xat
  87. X    steven@cwi.nl (new style) or seismo!mcvax!steven (old style)
  88. X
  89. XSteven Pemberton, Centre for Mathematics and Computer Science
  90. XAmsterdam, The Netherlands
  91. EOF
  92. echo 'x - config.1'
  93. sed 's/^X//' > 'config.1' << 'EOF'
  94. X.TH config 8 local
  95. X.SH NAME
  96. Xconfig \(em print details of your machine and C compiler configuration
  97. X.SH SYNOPSIS
  98. Xconfig
  99. X.SH DESCRIPTION
  100. XConfig determines and prints out several properties of the C compiler it is
  101. Xcompiled with and the machine it is run on.
  102. XAmong the properties it gives are
  103. X.br
  104. X.in +1c
  105. X\(em the number of bits in a char, and whether chars are signed or not;
  106. X.br
  107. X\(em the maximum short, int, and long;
  108. X.br
  109. X\(em alignment values for char, short, int and long;
  110. X.br
  111. X\(em number of bits for char and int pointers, with a warning if they are longer
  112. Xthan int;
  113. X.in -1c
  114. X.sp
  115. Xand then for float and double:
  116. X.br
  117. X.in +1c
  118. X\(em the base used;
  119. X.br
  120. X\(em number of significant digits;
  121. X.br
  122. X\(em certain minumum and maximum values;
  123. X.br
  124. X\(em whether arithmetic rounds or chops;
  125. X.br
  126. X\(em whether a hidden bit is used or not;
  127. X.br
  128. X\(em etc.
  129. X.in -1c
  130. X.sp
  131. XFinally the total amount of memory that can be allocated by malloc(3) is
  132. Xprinted.
  133. X.SH DIAGNOSTICS
  134. XThe output is printed as a series of C comments, so that the program can be
  135. Xused to produce header files for C programs without too much upheaval.
  136. X.SH BUGS
  137. XThe program won't work if overflow causes a trap,
  138. Xand the trap can't be caught by signal(2).
  139. EOF
  140. echo 'x - config.c'
  141. sed 's/^X//' > 'config.c' << 'EOF'
  142. X/* Determine some properties of C types on your machine/compiler
  143. X   Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
  144. X   Bugfixes and upgrades gratefully received.
  145. X
  146. X   The program only works if overflows are ignored by the C system or are
  147. X   catchable by signal().
  148. X
  149. X   If your C system is not unix but does have signal/setjmp, compile with
  150. X    cc -DSIGNAL config.c
  151. X   otherwise with
  152. X    cc config.c
  153. X   Don't use any optimisation flags: the program won't work if you do.
  154. X   Some compilers need a -f flag for floating point.
  155. X
  156. X   You may need to add some calls to signal() for other sorts of exception
  157. X   on your machine than SIGFPE, and SIGOVER. See lines beginning #ifdef
  158. X   SIGNAL later in the program.
  159. X
  160. X   Output is produced as C style comments so that the program can be used to
  161. X   produce a .h file with minimum upheaval.
  162. X
  163. X   I apologise unreservedly for the contorted use of the preprocessor...
  164. X
  165. X   If your C preprocessor doesn't have the predefined __FILE__ macro, and
  166. X   you want to call this file anything other than config.c, change the
  167. X   following #define command accordingly.
  168. X*/
  169. X
  170. X#ifndef __FILE__
  171. X#define __FILE__ "config.c"
  172. X#endif
  173. X
  174. X#ifndef PASS
  175. X#define PASS 1
  176. X
  177. X#include <stdio.h>
  178. X
  179. X#ifndef SIGNAL
  180. X#ifdef unix
  181. X#define SIGNAL
  182. X#endif /*unix*/
  183. X#endif /*SIGNAL*/
  184. X
  185. X#ifdef SIGNAL
  186. X
  187. X#include <signal.h>
  188. X#include <setjmp.h>
  189. X
  190. X    jmp_buf lab;
  191. X    overflow(sig) int sig; { /* what to do on overflow/underflow */
  192. X        (void) signal(sig, overflow);
  193. X        longjmp(lab, 1);
  194. X    }
  195. X
  196. X#else /*!SIGNAL*/
  197. X    /* Dummy routines instead */
  198. X    int lab=1;
  199. X    int setjmp(lab) int lab; { return(0); }
  200. X
  201. X#endif /*SIGNAL*/
  202. X
  203. Xmain() {
  204. X    int bits; /* the number of bits per unit returned by sizeof() */
  205. X    int dprec, eprec, basic(), fprop(), dprop(), eprop();
  206. X    char *malloc();
  207. X    unsigned int size;
  208. X    long total;
  209. X
  210. X#ifdef SIGNAL
  211. X#ifdef SIGFPE
  212. X    (void) signal(SIGFPE, overflow);
  213. X#endif
  214. X#ifdef SIGOVER
  215. X    (void) signal(SIGOVER, overflow);
  216. X#endif
  217. X/* Add more calls as necessary */
  218. X#endif /* SIGNAL */
  219. X
  220. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  221. X
  222. X    bits=  basic();
  223. X    (void) fprop(bits);
  224. X    dprec= dprop(bits);
  225. X    eprec= eprop();
  226. X    printf("\n");
  227. X    if (eprec!=dprec)
  228. X        printf("/\* Expressions are evaluated in a %s %s %d %s *\/\n",
  229. X            eprec>dprec ? "higher" : "lower (tut!)",
  230. X            "precision than double, using", eprec, "base digits");
  231. X    else printf("/\* Expressions are evaluated in double precision *\/\n");
  232. X
  233. X    /* An extra goody: the approximate amount of data-space */
  234. X    /* Allocate store until no more available */
  235. X    size=1<<((bits*sizeof(int))-2);
  236. X    total=0;
  237. X    while (size!=0) {
  238. X        while (malloc(size)!=(char *)NULL) total+=(size/2);
  239. X        size/=2;
  240. X    }
  241. X
  242. X    printf("\n/\* Memory mallocatable ~= %ld Kbytes *\/\n",
  243. X                        (total+511)/512);
  244. X}
  245. X
  246. Xint basic() {
  247. X    /* The properties of the basic types.
  248. X       Returns number of bits per sizeof unit */
  249. X
  250. X    char c; int bits;
  251. X
  252. X    if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  253. X
  254. X    /* Calculate number of bits per character *************************/
  255. X    c=1; bits=0;
  256. X    do { c=c<<1; bits++; } while(c!=0);
  257. X    c= (char)(-1);
  258. X    printf("/\* Char = %d bits, %ssigned *\/\n", sizeof(c)*bits,
  259. X            ((int)c)<0?"":"un");
  260. X
  261. X    /* Shorts, ints and longs *****************************************/
  262. X    sprop();
  263. X    iprop();
  264. X    lprop();
  265. X
  266. X    if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  267. X
  268. X    /* Alignment constants ********************************************/
  269. X    printf("/\* Alignments for char=%d short=%d int=%d long=%d *\/\n",
  270. X        sizeof(struct{char i; char c;})-sizeof(char),
  271. X        sizeof(struct{short i; char c;})-sizeof(short),
  272. X        sizeof(struct{int i; char c;})-sizeof(int),
  273. X        sizeof(struct{long i; char c;})-sizeof(long));
  274. X
  275. X    /* Pointers *******************************************************/
  276. X    printf("/\* Char pointers = %d bits%s *\/\n", sizeof(char *)*bits,
  277. X        sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"");
  278. X    printf("/\* Int pointers = %d bits%s *\/\n", sizeof(int *)*bits,
  279. X        sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"");
  280. X
  281. X    return bits;
  282. X}
  283. X
  284. Xint log(base, x) int base; double x; {
  285. X    int r=0;
  286. X    while (x>=base) { r++; x/=base; }
  287. X    return r;
  288. X}
  289. X
  290. Xint eprop() { /* See if expressions are evaluated in extended precision */
  291. X    int imant;
  292. X    double a, b, base;
  293. X
  294. X    if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  295. X
  296. X    /* Size of mantissa **************************************/
  297. X    a=1.0;
  298. X    do { a=a+a; } while ((((a+1.0)-a)-1.0) == 0.0);
  299. X    b=1.0;
  300. X    do { b=b+b; } while ((base=((a+b)-a)) == 0.0);
  301. X
  302. X    imant=0; b=1.0;
  303. X    do { imant++; b=b*base; }
  304. X    while ((((b+1.0)-b)-1.0) == 0.0);
  305. X    return imant;
  306. X}
  307. X
  308. X#define fabs(x) (((x)<0.0)?(-x):(x))
  309. X
  310. X#endif /* ifndef PASS */
  311. X
  312. X/* As I said, I apologise for the contortions below. The procedures are
  313. X   expanded twice (for float and double) or three times (for short, int and
  314. X   long) by the preprocessor. That way, I never make a change to one that
  315. X   I forget to make to the other. #undef on an already undefined thing
  316. X   is (wrongly) flagged as an error by some compilers, therefore the #ifdef
  317. X   that follows: 
  318. X*/
  319. X
  320. X#ifdef Number
  321. X#undef Number
  322. X#undef THING
  323. X#undef FPROP
  324. X#undef Store
  325. X#undef Sum
  326. X#undef Diff
  327. X#undef Mul
  328. X#undef Div
  329. X#endif
  330. X
  331. X#ifdef Integer
  332. X#undef Integer
  333. X#undef INT
  334. X#undef IPROP
  335. X#endif
  336. X
  337. X#if PASS == 1
  338. X
  339. X#define Number float
  340. X#define THING "float"
  341. X#define FPROP fprop
  342. X#define Store fStore
  343. X#define Sum fSum
  344. X#define Diff fDiff
  345. X#define Mul fMul
  346. X#define Div fDiv
  347. X
  348. X#define Integer short
  349. X#define INT "short"
  350. X#define IPROP sprop
  351. X
  352. X#endif /* PASS == 1 */
  353. X
  354. X#if PASS == 2
  355. X
  356. X#define Number double
  357. X#define THING "double"
  358. X#define FPROP dprop
  359. X#define Store dStore
  360. X#define Sum dSum
  361. X#define Diff dDiff
  362. X#define Mul dMul
  363. X#define Div dDiv
  364. X
  365. X#define Integer int
  366. X#define INT "int"
  367. X#define IPROP iprop
  368. X
  369. X#endif /* if PASS == 2 */
  370. X
  371. X#if PASS == 3
  372. X
  373. X#define Integer long
  374. X#define INT "long"
  375. X#define IPROP lprop
  376. X
  377. X#endif /* if PASS == 3 */
  378. X
  379. XIPROP() {
  380. X    Integer newi, maxi, maxeri;
  381. X    int ibits, ipower, two=2;
  382. X
  383. X    /* Calculate max short/int/long ***********************************/
  384. X    /* Calculate 2**n-1 until overflow - then use the previous value  */
  385. X
  386. X    newi=1; maxi=0;
  387. X
  388. X    if (setjmp(lab)==0)
  389. X        for(ipower=0; newi>maxi; ipower++) {
  390. X            maxi=newi;
  391. X            newi=newi*two+1;
  392. X        }
  393. X
  394. X    /* Now for those daft Cybers: */
  395. X
  396. X    maxeri=0; newi=maxi;
  397. X
  398. X    if (setjmp(lab)==0)
  399. X        for(ibits=ipower; newi>maxeri; ibits++) {
  400. X            maxeri=newi;
  401. X            newi=newi+newi+1;
  402. X        }
  403. X
  404. X    printf("/\* Maximum %s = %ld (= 2**%d-1) *\/\n",
  405. X                INT, (long)maxi, ipower);
  406. X
  407. X    if (maxeri>maxi) {
  408. X        printf("/\* There is a larger %s, %ld (= 2**%d-1), %s *\/\n",
  409. X            INT, (long)maxeri, ibits, 
  410. X            "but only for addition, not multiplication");
  411. X    }
  412. X}
  413. X
  414. X#ifdef Number
  415. X
  416. X/* These routines are intended to defeat any attempt at optimisation */
  417. XStore(a, b) Number a, *b; { *b=a; }
  418. XNumber Sum(a, b) Number a, b; { Number r; Store(a+b, &r); return (r); }
  419. XNumber Diff(a, b) Number a, b; { Number r; Store(a-b, &r); return (r); }
  420. XNumber Mul(a, b) Number a, b; { Number r; Store(a*b, &r); return (r); }
  421. XNumber Div(a, b) Number a, b; { Number r; Store(a/b, &r); return (r); }
  422. X
  423. Xint FPROP(bits) int bits; {
  424. X    /* Properties of floating types, using algorithms by Cody and Waite
  425. X       from MA Malcolm, as modified by WM Gentleman and SB Marovich.
  426. X       Further extended by S Pemberton.
  427. X
  428. X       Returns the number of digits in the fraction.
  429. X    */
  430. X
  431. X    int i, ibase, iexp, irnd, imant, iz, k, machep, maxexp, minexp,
  432. X        mx, negeps, mantbits;
  433. X    Number a, b, base, basein, basem1, eps, epsneg, xmax, newxmax,
  434. X           xmin, xminner, y, y1, z, z1, z2;
  435. X
  436. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  437. X
  438. X    printf("\n/\* Properties of %s: *\/\n", THING);
  439. X
  440. X    /* Base and size of mantissa **************************************/
  441. X    a=1.0;
  442. X    do { a=Sum(a, a); } while (Diff(Diff(Sum(a, 1.0), a), 1.0) == 0.0);
  443. X    b=1.0;
  444. X    do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == 0.0);
  445. X    ibase=base;
  446. X    printf("/\* Base = %d *\/\n", ibase);
  447. X
  448. X    imant=0; b=1.0;
  449. X    do { imant++; b=Mul(b, base); }
  450. X    while (Diff(Diff(Sum(b,1.0),b),1.0) == 0.0);
  451. X    printf("/\* Significant base digits = %d %s %d %s *\/\n",
  452. X            imant, "(= at least", log(10, (double)b),
  453. X            "decimal digits)");
  454. X
  455. X    /* Various flavours of epsilon ************************************/
  456. X    basem1=Diff(base,1.0);
  457. X    if (Diff(Sum(a, basem1), a) != 0.0) irnd=1; 
  458. X    else irnd=0;
  459. X
  460. X    negeps=imant+imant;
  461. X    basein=1.0/base;
  462. X    a=1.0;
  463. X    for(i=1; i<=negeps; i++) a*=basein;
  464. X
  465. X    b=a;
  466. X    while (Diff(Diff(1.0, a), 1.0) == 0.0) {
  467. X        a*=base;
  468. X        negeps--;
  469. X    }
  470. X    negeps= -negeps;
  471. X    printf("/\* Smallest x such that 1.0-base**x != 1.0 = %d *\/\n", negeps);
  472. X
  473. X    epsneg=a;
  474. X    if ((ibase!=2) && (irnd==1)) {
  475. X    /*    a=(a*(1.0+a))/(1.0+1.0); => */
  476. X        a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
  477. X    /*    if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
  478. X        if (Diff(Diff(1.0, a), 1.0) != 0.0) epsneg=a;
  479. X    }
  480. X    printf("/\* Small x such that 1.0-x != 1.0 = %g *\/\n", epsneg);
  481. X    /* it may not be the smallest */
  482. X
  483. X    machep= -imant-imant;
  484. X    a=b;
  485. X    while (Diff(Sum(1.0, a), 1.0) == 0.0) { a*=base; machep++; }
  486. X    printf("/\* Smallest x such that 1.0+base**x != 1.0 = %d *\/\n", machep);
  487. X
  488. X    eps=a;
  489. X    if ((ibase!=2) && (irnd==1)) {
  490. X    /*    a=(a*(1.0+a))/(1.0+1.0); => */
  491. X        a=Div(Mul(a, Sum(1.0, a)), Sum(1.0, 1.0));
  492. X    /*    if ((1.0+a)-1.0 != 0.0) eps=a; => */
  493. X        if (Diff(Sum(1.0, a), 1.0) != 0.0) eps=a;
  494. X    }
  495. X    printf("/\* Smallest x such that 1.0+x != 1.0 = %g *\/\n", eps);
  496. X
  497. X    /* Round or chop **************************************************/
  498. X    if (irnd == 1) { printf("/\* Arithmetic rounds *\/\n"); }
  499. X    else { 
  500. X        printf("/\* Arithmetic chops");
  501. X        if (Diff(Mul(Sum(1.0,eps),1.0),1.0) !=  0.0) {
  502. X            printf(" but uses guard digits");
  503. X        }
  504. X        printf(" *\/\n");
  505. X    }
  506. X
  507. X    /* Size of and minimum normalised exponent ************************/
  508. X    y=0; i=0; k=1; z=basein; z1=(1.0+eps)/base;
  509. X
  510. X    /* Coarse search for the largest power of two */
  511. X    if (setjmp(lab)==0) /* in case of underflow trap */
  512. X        do {
  513. X            y=z; y1=z1;
  514. X            z=Mul(y,y); z1=Mul(z1, y);
  515. X            a=Mul(z,1.0);
  516. X            z2=Div(z1,y);
  517. X            if (z2 != y1) break;
  518. X            if ((Sum(a,a) == 0.0) || (fabs(z) >= y)) break;
  519. X            i++;
  520. X            k+=k;
  521. X        } while(1);
  522. X
  523. X    if (ibase != 10) {
  524. X        iexp=i+1; /* for the sign */
  525. X        mx=k+k;
  526. X    } else {
  527. X        iexp=2;
  528. X        iz=ibase;
  529. X        while (k >= iz) { iz*=ibase; iexp++; }
  530. X        mx=iz+iz-1;
  531. X    }
  532. X
  533. X    /* Fine tune starting with y and y1 */
  534. X    if (setjmp(lab)==0) /* in case of underflow trap */
  535. X        do {
  536. X            xmin=y; z1=y1;
  537. X            y=Div(y,base); y1=Div(y1,base);
  538. X            a=Mul(y,1.0);
  539. X            z2=Mul(y1,base);
  540. X            if (z2 != z1) break;
  541. X            if ((Sum(a,a) == 0.0) || (fabs(y) >= xmin)) break;
  542. X            k++;
  543. X        } while (1);
  544. X
  545. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  546. X
  547. X    minexp=(-k)+1;
  548. X
  549. X    if ((mx <= k+k-3) && (ibase != 10)) { mx+=mx; iexp+=1; }
  550. X    printf("/\* Number of bits used for exponent = %d *\/\n", iexp);
  551. X    printf("/\* Minimum normalised exponent = %d *\/\n", minexp);
  552. X    printf("/\* Minimum normalised positive number = %g *\/\n", xmin);
  553. X
  554. X    /* Minimum exponent ************************************************/
  555. X    if (setjmp(lab)==0) /* in case of underflow trap */
  556. X        do {
  557. X            xminner=y;
  558. X            y=Div(y,base);
  559. X            a=Mul(y,1.0);
  560. X            if ((Sum(a,a) == 0.0) || (fabs(y) >= xminner)) break;
  561. X        } while (1);
  562. X
  563. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  564. X
  565. X    if (xminner != 0.0 && xminner != xmin) {
  566. X        printf("/\* The smallest numbers are not kept normalised *\/\n");
  567. X        printf("/\* Smallest unnormalised positive number = %g *\/\n",
  568. X            xminner);
  569. X    } else printf("/\* The smallest numbers are normalised *\/\n");
  570. X
  571. X    /* Maximum exponent ************************************************/
  572. X    maxexp=2; xmax=1.0; newxmax=base+1.0;
  573. X    if (setjmp(lab) == 0) {
  574. X        while (xmax<newxmax) {
  575. X            xmax=newxmax;
  576. X            newxmax=Mul(newxmax, base);
  577. X            if (Div(newxmax, base) != xmax) break; /* ieee infinity */
  578. X            maxexp++;
  579. X        }
  580. X    }
  581. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  582. X
  583. X    printf("/\* Maximum exponent = %d *\/\n", maxexp);
  584. X
  585. X    /* Largest number ***************************************************/
  586. X    xmax=Diff(1.0, epsneg);
  587. X    if (Mul(xmax,1.0) != xmax) xmax=Diff(1.0, Mul(base,epsneg));
  588. X    for (i=1; i<=maxexp; i++) xmax=Mul(xmax, base);
  589. X    printf("/\* Maximum number = %g *\/\n", xmax);
  590. X
  591. X    /* Hidden bit + sanity check ****************************************/
  592. X    if (ibase != 10) {
  593. X        mantbits=log(2, (double)ibase)*imant;
  594. X        if (mantbits+iexp+1 == sizeof(Number)*bits+1) {
  595. X            printf("/\* Arithmetic uses a hidden bit *\/\n");
  596. X        } else if (mantbits+iexp+1 == sizeof(Number)*bits) {
  597. X            printf("/\* Arithmetic doesn't use a hidden bit *\/\n");
  598. X        } else {
  599. X            printf("/\* Something fishy here! %s %s %s *\/\n",
  600. X                "Exponent size + mantissa size doesn't match",
  601. X                "with the size of a", THING);
  602. X        }
  603. X    }
  604. X    return imant;
  605. X}
  606. X
  607. X#endif /* ifdef Number */
  608. X
  609. X#if PASS == 3
  610. X#undef PASS
  611. X#define PASS 4
  612. X#endif
  613. X
  614. X#if PASS == 2
  615. X#undef PASS
  616. X#define PASS 3
  617. X#endif
  618. X
  619. X#if PASS == 1
  620. X#undef PASS
  621. X#define PASS 2
  622. X#endif
  623. X
  624. X#if PASS < 4
  625. X#include __FILE__
  626. X#endif
  627. EOF
  628. echo 'Part 01 out of 01 of pack.out complete.'
  629. exit 0
  630. -- 
  631.  
  632. Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
  633.  
  634.  
  635.