/* @(#)computer.c 14.2 (ESO-DMD) 10/12/00 16:50:42 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COPYRIGHT (c) 1992 European Southern Observatory .TYPE Program .NAME computer.c .LANGUAGE C .AUTHOR F.Ochsenbein, IPG/ESO .CATEGORY Computer-dependant constants .COMMENTS This module generates a suitable computer.h file using some simple tests. .ENVIRONMENT UNIX .VERSION 0.0 19-Oct-1988 : Creation , FO .VERSION 0.1 18-Aug-1989 : Correct SWAPLONG for PCs, PJG .VERSION 0.2 09-Jan-1990 : Check IEEE by dividing NaN by itself (FO) .VERSION 0.3 18-Jan-1991 : DEC reverses the order for IEEE double !!! .VERSION 0.4 30-Jan-1991 : Double byteswap and NULL, PJG .VERSION 0.4 12-Feb-1991 : Change VAX NULL to -Inf, PJG .VERSION 0.5 07-Mar-1991 : Output to file computer.h by default. CG .VERSION 0.6 11-Sep-1991 : Continuing the test in the interrupt routine. CG. .VERSION 0.7 21-Sep-1992 : Add Null definitions for tables, PJG. .VERSION 0.7 28-Mar-1993 : Use definitions in values.h if exists. CG. .VERSION 0.8 28-Oct-1994 : Use POSIX definitions if exists. CG. 001016 KB 1) use casts to cleanup code 2) assign the pe*, pf* pointers AFTER their target values have been declared (we had big problems with: OSF1 V4.0 1229 alpha - multivac.aip.de) 3) including gave problems on INtel-Linux ... ------------------------------------------------------------*/ /* * Define _POSIX_SOURCE to indicate * that this is a POSIX program */ #define _POSIX_SOURCE 1 #include #include #ifndef NO_FLOAT_H #include #endif #ifndef NO_LIMITS_H #include #endif #ifndef NO_VALUES_H #include #endif #ifndef DEBUG #define DEBUG 0 /* Switch to 1 to get hexa patterns */ #endif double ldexp(); static char c[80]; /* ... Must be aligned ... */ static int ieee; static int junk; static char *com0 = "/*"; static char *com1 = "*/"; static unsigned char byte; /*============================================================================*/ #ifdef __STDC__ static int bit_count(unsigned long u) #else static int bit_count(u) /* Count number of bits set to 1 */ unsigned long u; #endif { int i; for (i=0; u; u >>= 1) i += u & 1L; return(i); } #ifdef __STDC__ static void on_fpe(int sig) #else static void on_fpe(sig) /* If Floating point fault, assume IEEE... */ int sig; #endif { #ifndef vms struct sigaction act, oact; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = on_fpe; sigaction(SIGFPE,&act,&oact); #else signal(SIGFPE, on_fpe); #endif if (ieee != 1) { /* Return if already ieee */ ieee = 1; contin(); exit(0); } } /*============================================================================*/ double df, f, f1, f2; float e, e1, e2; unsigned int *pf1, *pe1; unsigned int *pf2, *pe2; unsigned int usgm, uexp, uman, u; int n, l2e, l2f, nb[3], bitsperbyte; long int dxb; main(argc,argv) int argc; char **argv; { double dval1, dval2; int i; #ifndef vms struct sigaction act, oact; /* Setup pointer to float */ #endif if (argc > 1) freopen(argv[1],"w",stdout); else freopen("computer.h","w",stdout); /* Generate Header */ printf("%s+++++++++++++++++++++++++++++\n", com0); puts(".TYPE \t\tHeader"); puts(".NAME \t\tcomputer.h"); puts(".LANGUAGE \tC"); puts(".AUTHOR\t\tESO -- IPG"); puts(".CATEGORY\tComputer-dependant constants"); puts(".COMMENTS \tThis module includes constants depending on the computer:"); puts("\t\tnumber of bits per char,"); puts("\t\tbyte swapping, description of floating-point numbers. "); puts("\t\tLimits also provided for each type of atomic data."); puts("\t\tNULL numbers are also defined via isNULL (test) and"); puts("\t\ttoNULL"); puts("\t\t********* Generated by computer.c program **************"); puts(".ENVIRON\tUNIX and VAX/VMS"); puts(".VERSION \t1.1\t18-Jan-1991 (check Floating Pattern)"); puts(".VERSION \t2.1\t25-Mar-1994 (using values.h if exists)"); puts(".VERSION \t3.1\t28-Oct-1994 (POSIX definitions if exists)"); printf("-----------------------%s\n\n", com1); puts("#ifndef COMPUTER_H"); puts("#define COMPUTER_H\n"); puts("/*"); puts(" * Define _POSIX_SOURCE to indicate"); puts(" * that this is a POSIX program"); puts(" */"); puts("#ifndef _POSIX_SOURCE"); puts("#define _POSIX_SOURCE 1"); puts("#endif\n"); #ifndef NO_FLOAT_H puts("#include "); #endif #ifndef NO_LIMITS_H puts("#include "); #endif #ifndef NO_VALUES_H puts("#include "); #endif /* Check first the number of bits per byte */ for (byte=1, bitsperbyte=0; byte; bitsperbyte++) { i = byte << 1; byte = i; } #ifndef BITSPERBYTE puts("\n#undef BITSPERBYTE"); printf("#define BITSPERBYTE\t%d\n", bitsperbyte); #endif #ifndef BITS puts("#define BITS(type)\t(BITSPERBYTE*((int)sizeof(type)))\n"); #endif puts("#define ONES_COMP\t1"); puts("#define TWOS_COMP\t2\n"); puts("#define IEEEFLOAT\t0"); puts("#define VAXFLOAT\t1"); puts("#define VAXGFLOAT\t2"); puts("#define HPFLOAT\t\t3\n"); /* Check 1 or 2's Complement */ i = -1; if (i&1) /* 2's Complement */ printf("#define INTFMT\t\t2\t%s 2's Complement Integers\t%s\n\n", com0,com1); else printf("#define INTFMT\t\t1\t%s 1's Complement Integers\t%s\n\n", com0,com1); puts("#define MAXIO1\t\t(512*90)\n\n"); /* Maximum allowed for single i/o */ #if DEBUG e1 = f1 = 1.e0; e2 = f2 = -1.e0; pf1 = (unsigned int *)&f1; pf2 = (unsigned int *)&f2; pe1 = (unsigned int *)&e1; pe2 = (unsigned int *)&e2; printf("%s Hexa pattern of -1.e0 (float)%08X", com0,*pe2), printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1); printf("%s Hexa pattern of 1.e0 (float)%08X", com0,*pe1), printf(" (double)%08X %08X\t%s\n",pf1[0],pf1[1], com1); e2 = f2 = 2.e0; printf("%s Hexa pattern of 2.e0 (float)%08X", com0,*pe2), printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1); e2 = f2 = .5e0; printf("%s Hexa pattern of .5e0 (float)%08X", com0,*pe2), printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1); e2 = f2 = .25e0; printf("%s Hexa pattern of .25e0 (float)%08X", com0,*pe2), printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1); e2 = f2 =.125e0; printf("%s Hexa pattern of.125e0 (float)%08X", com0,*pe2), printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1); #endif /* Check Swapping */ i = ('1'< 1; l2e += bitsperbyte, i--) { e1 += i*ldexp(1., l2e); #if DEBUG printf("%s(float) i=%ld l2e=%d\tHexa pattern=%08X\t%s\n", com0,i,l2e,*pe1,com1); #endif } for (i=8, f1 = 1.0; i > 1; l2f += bitsperbyte, i--) { f1 += i*ldexp(1., l2f); #if DEBUG printf("%s(double) i=%ld l2f=%d\tHexa pattern=%08X %08X\t%s\n", com0,i,l2f,pf1[0],pf1[1],com1); #endif } n = sizeof(float); *(float *)c = e1, c[n] = 0; for (i=0; i < n; i++) if (c[i] >= 1 && c[i] <= n) c[i] += '0'; else if ((c[i] & 0xf) == 2) c[i] = '2'; else c[i] = '1'; printf("#define SWAPFLOAT\t%s\n", c); n = sizeof(double); *(double *)c = f1, c[n] = 0; for (i=0; i < n; i++) if (c[i] >= 1 && c[i] <= n) c[i] += '0'; else if ((c[i] & 0xf) == 2) c[i] = '2'; else c[i] = '1'; printf("#define SWAPDOUBLE\t%s\n\n", c); /* Find Integer min / max */ #ifndef NO_LIMITS_H puts("#undef MINCHAR"); puts("#define MINCHAR\t\tCHAR_MIN"); puts("#undef MINSHORT"); puts("#define MINSHORT\tSHRT_MIN"); puts("#undef MININT"); puts("#define MININT\t\tINT_MIN"); puts("#undef MINLONG"); puts("#define MINLONG\t\tLONG_MIN"); puts("#undef MAXCHAR"); puts("#define MAXCHAR\t\tCHAR_MAX"); puts("#undef MAXSHORT"); puts("#define MAXSHORT\tSHRT_MAX"); puts("#undef MAXINT"); puts("#define MAXINT\t\tINT_MAX"); puts("#undef MAXLONG"); puts("#define MAXLONG\t\tLONG_MAX"); puts("#undef MAXUCHAR"); puts("#define MAXUCHAR\tUCHAR_MAX"); puts("#undef MAXUSHORT"); puts("#define MAXUSHORT\tUSHRT_MAX"); puts("#undef MAXUINT"); puts("#define MAXUINT\t\tUINT_MAX"); puts("#undef MAXULONG"); puts("#define MAXULONG\tULONG_MAX\n"); #else puts("#define MINCHAR\t\t((char) (1 << (BITS(char) - 1)))"); # ifndef MINSHORT puts("#define MINSHORT\t((short)(1 << (BITS(short) - 1)))"); # endif # ifndef MININT puts("#define MININT\t\t((unsigned int)1 << (BITS(int) - 1))"); # endif # ifndef MINLONG puts("#define MINLONG\t\t((unsigned long)1L << (BITS(long) - 1))\n"); # endif puts("#define MAXCHAR\t\t((char) (~MINCHAR ))"); # ifndef MAXSHORT puts("#define MAXSHORT\t((short) (~MINSHORT))"); # endif # ifndef MAXINT puts("#define MAXINT\t\t((int) (~MININT))"); # endif # ifndef MAXLONG puts("#define MAXLONG\t\t((long) (~MINLONG))\n"); # endif puts("#define MAXUCHAR\t((unsigned char) (MINCHAR | MAXCHAR ))"); puts("#define MAXUSHORT\t((unsigned short)(MINSHORT| MAXSHORT))"); puts("#define MAXUINT\t\t((unsigned int) (MININT | MAXINT ))"); puts("#define MAXULONG\t((unsigned long) (MINLONG | MAXLONG ))\n"); #endif /* NO_LIMITS_H */ /* Floating-Point Format */ /* Floating-Point Format: determine where are bits for exponent, mantissa, sign, when floating-point number seen as a long int. */ e1 = 1.e0, e2 = -1.e0; pe1 = (unsigned int *)&e1; pe2 = (unsigned int *)&e2; usgm = (*pe1) ^ (*pe2); /* Sign mask */ e1 = 1.e0; nb[1] = bit_count(*pe1); /* Bit Count of 1.e0 */ e2 = 2.e0; nb[2] = bit_count(*pe2); /* Bit count of 2.e0 */ uexp = *pe1 | *pe2; e2 = .5e0; nb[0] = bit_count(*pe2); /* Bit count of .5e0 */ uexp |= *pe2; e2 = .25e0; uexp |= *pe2; e2 = .125e0; uexp |= *pe2; e2 = .0625e0; uexp |= *pe2; n = (nb[0] < nb[1] ? nb[0] : nb[1]); n = (n < nb[2] ? n : nb[2]); /* Minimum */ if (n > 1) /* No hidden bit */ { if (n == nb[0]) e1 = .5e0; if (n == nb[1]) e1 = 1.e0; if (n == nb[2]) e1 = 2.e0; e2 = e1 / 16.e0; uexp &= ~(*pe2 & *pe2); n = 0; } uman = ~(usgm|uexp); /* Check IEEE : Divide a number by itself... */ e1 = .1e0; *pe1 |= uexp; /* This gives a number in the NaN range */ ieee = 0; e2 = e1; #ifndef vms sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = on_fpe; sigaction(SIGFPE,&act,&oact); #else signal(SIGFPE, on_fpe); #endif #if DEBUG printf("%s Edited floating-point NULL number is %e %s\n", com0, e1,com1); printf("%s Edited floating-point NULL number is %e %s\n", com0, e2,com1); printf("%s Ratio is NULL ? is %e %s\n\n", com0,e1/e2,com1); #endif e2 = e1/e2; if ( ieee == 1) exit(0); /* Interrrupt already arrived, so exit */ contin(); exit(0); } contin() { if (ieee == 0) ieee = (e2 != 1.e0); #ifndef _IEEE printf("#define _IEEE\t\t%d\t%s NULL edited as %e %s\n", ieee, com0, e1, com1); #endif #ifndef _HIDDENBIT printf("#define _HIDDENBIT\t%d\n", n); #endif e1 = 1.e0; e2 = 2.e0; pf1 = (unsigned int *)&f1; pf2 = (unsigned int *)&f2; pe1 = (unsigned int *)&e1; pe2 = (unsigned int *)&e2; #ifndef _EXPBASE if ((*pe1 & uman) == (*pe2 & uman)) puts("#define _EXPBASE\t2\n"); else puts("#define _EXPBASE\t16\n"); #endif #ifndef _FEXPLEN printf("#define _FEXPLEN\t%d\n", bit_count(uexp)); #endif printf("#define FMASKSGM\t0x%08X\n", usgm); printf("#define FMASKEXP\t0x%08X\n", uexp); printf("#define FMASKMAN\t0x%08X\n\n", uman); #ifndef NO_FLOAT_H puts("#undef MAXFLOAT"); puts("#define MAXFLOAT\tFLT_MAX"); puts("#undef MINFLOAT"); puts("#define MINFLOAT\tFLT_MIN"); #else # ifndef MAXFLOAT if (ieee) puts("#define MAXFLOAT\t((float)3.40282346638528860e+38)"), puts("#define MINFLOAT\t((float)1.40129846432481707e-45)\n"); else { *pe1 = uexp | uman; printf("#define MAXFLOAT\t(float)%24.17e\n", e1); for (u=uexp, i=0; (u&1) == 0; i++, u >>= 1); *pe1 = (1L) << i; printf("#define MINFLOAT\t(float)%24.17e\n\n", e1); } # endif /* MAXFLOAT */ #endif /* NO_FLOAT_H */ #if DEBUG f1 = 1.0e0; f2 = -1.0e0; pf1 = (unsigned int *)&f1; pf2 = (unsigned int *)&f2; printf("%s\t==== Double Precision Numbers ====%s\n",com0,com1); printf("%s Hexa pattern of -1.e0: %08X %08X%s \n", com0,*pf2, pf2[1],com1); printf("%s Hexa pattern of 1.e0: %08X %08X%s \n", com0,*pf1, pf1[1],com1); f2 = 2.e0; printf("%s Hexa pattern of 2.e0: %08X %08X%s \n", com0,*pf2, pf2[1],com1); f2 = .5e0; printf("%s Hexa pattern of .5e0: %08X %08X%s \n", com0,*pf2, pf2[1],com1); f2 = .25e0; printf("%s Hexa pattern of .25e0: %08X %08X%s \n", com0,*pf2, pf2[1],com1); f2 =.125e0; printf("%s Hexa pattern of.125e0: %08X %08X%s \n", com0,*pf2,pf2[1],com1); #endif f1 = 1.e0, f2 = -1.e0; pf1 = (unsigned int *)&f1; pf2 = (unsigned int *)&f2; dxb = (pf1[0] ? 0 : 1); usgm = pf1[dxb] ^ pf2[dxb]; nb[1] = bit_count(pf1[dxb]); /* Bit Count of 1.e0 */ f2 = 2.e0; nb[2] = bit_count(pf2[dxb]); /* Bit count of 2.e0 */ uexp = pf2[dxb] | pf2[dxb]; f2 = .5e0; nb[0] = bit_count(pf2[dxb]); /* Bit count of .5e0 */ uexp |= pf2[dxb]; f2 = .25e0; uexp |= pf2[dxb]; f2 = .125e0; uexp |= pf2[dxb]; f2 = .0625e0; uexp |= pf2[dxb]; #ifndef _DEXPLEN printf("#define _DEXPLEN\t%d\n", bit_count(uexp)); #endif printf("#define DINTEXP\t%ld\t%s Exponent is in longword #%ld\t%s\n", dxb,com0,dxb,com1); printf("#define DMASKSGM\t0x%08X\n", usgm); printf("#define DMASKEXP\t0x%08X\n", uexp); printf("#define DMASKMAN\t0x%08X\n\n", ~(usgm|uexp)); #ifndef NO_FLOAT_H puts("#undef MAXDOUBLE"); puts("#define MAXDOUBLE\tDBL_MAX"); puts("#undef MINDOUBLE"); puts("#define MINDOUBLE\tDBL_MIN\n"); #else # ifndef MAXDOUBLE if (ieee) puts("#define MAXDOUBLE\t1.79769313486231166e+308"), puts("#define MINDOUBLE\t4.94065645841246544e-324\n"); else { *pf1 = uexp | uman; *(pf1+1) = ~0; printf("#define MAXDOUBLE\t%24.17e\n", f1); for (u=uexp, i=0; (u&1) == 0; i++, u >>= 1); *pf1 = (1L) << i; *(pf1+1) = 0; printf("#define MINDOUBLE\t%24.17e\n\n", f1); } # endif /* MAXDOUBLE */ #endif /* NO_FLOAT_H */ /* Definitions of NULL's */ printf("%s\t Definition of NULL's \t%s\n\n",com0,com1); puts("#define asaUINT(x)\t(unsigned int *)(&(x))"); puts("#define asaULONG(x)\t(unsigned long *)(&(x))\n"); puts("#define NULL1\t\t(MINCHAR)"); puts("#define NULL2\t\t(MINSHORT)"); puts("#define NULL4\t\t(MININT)\n"); puts("#define isNULLSHORT(x)\t((short)(x) == MINSHORT)"); puts("#define toNULLSHORT(x)\tx = MINSHORT\n"); puts("#define isNULLINT(x)\t((int)(x) == MININT)"); puts("#define toNULLINT(x)\tx = MININT\n"); puts("#define isNULLLONG(x)\t((long)(x) == MINLONG)"); puts("#define toNULLLONG(x)\tx = MINLONG\n"); if (ieee) { printf("%s\t Use -Inf as NULL for IEEE fp \t%s\n\n",com0,com1); e1 = -1.0; e2 = e1 + 1.0; e = e1/e2; printf("#define NULLF\t\t(FMASKSGM | FMASKEXP)\n"); printf("#define isNULLFLOAT(x)\t((*asaUINT(x) & FMASKEXP) == FMASKEXP)\n"); printf("#define toNULLFLOAT(x)\t *asaUINT(x) = NULLF\n"); f1 = -1.0; f2 = f1 + 1.0; f = f1/f2; printf("#define NULLD\t\t(DMASKSGM | DMASKEXP)\n"); printf("#define isNULLDOUBLE(x)\t"); printf("((*(asaUINT(x)+DINTEXP) & DMASKEXP) == DMASKEXP)\n"); printf("#define toNULLDOUBLE(x)\t"); printf("*(asaUINT(x)+DINTEXP) = NULLD, \\\n"); printf("\t\t\t *(asaUINT(x)+(DINTEXP^1)) = 0\n\n"); } else { printf("#define NULLF\t\t(~FMASKSGM)\n"); printf("#define NULLD\t\t(DMASKSGM | DMASKEXP)\n"); puts("#define isNULLFLOAT(x)\t(*asaUINT(x) == NULLF)"); puts("#define toNULLFLOAT(x)\t*asaUINT(x) = NULLF"); printf("#define isNULLDOUBLE(x)\t"); printf("((*(asaUINT(x)+DINTEXP) == NULLD) && \\\n"); printf("\t\t\t (*(asaUINT(x)+(DINTEXP^1)) == 0))\n"); printf("#define toNULLDOUBLE(x)\t"); printf("*(asaUINT(x)+DINTEXP) = NULLD, \\\n"); printf("\t\t\t *(asaUINT(x)+(DINTEXP^1)) = 0\n\n"); } #ifndef FSIGNIF puts("#define FSIGNIF\t\t(BITS(float) - _FEXPLEN + _HIDDENBIT - 1)"); #endif #ifndef DSIGNIF puts("#define DSIGNIF\t\t(BITS(double) - _DEXPLEN + _HIDDENBIT - 1)"); #endif #ifndef FMAXEXP puts("#define FMAXEXP\t\t((1 << (_FEXPLEN - 1)) - 1 + _IEEE)"); #endif #ifndef DMAXEXP puts("#define DMAXEXP\t\t((1 << (_DEXPLEN - 1)) - 1 + _IEEE)\n\n"); #endif if (ieee) puts("#define FLOATFMT\tIEEEFLOAT"); else if ( (uexp == 0x7f80) || (uexp == 0x7ff0) ) { if ( bit_count(uexp) < 10 ) puts("#define FLOATFMT\tVAXFLOAT"); else puts("#define FLOATFMT\tVAXGFLOAT"); } else { fputs("ERROR: Undefined floating point format\n",stderr); exit(1); } puts("\n#endif"); exit(0); }