home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / forum7.lzh / RICO / C / CONFIG / config.c next >
C/C++ Source or Header  |  2009-11-06  |  13KB  |  507 lines

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