Home | History | Annotate | Line # | Download | only in gdtoa
      1 /* $NetBSD: arithchk.c,v 1.4 2012/06/24 15:26:03 christos Exp $ */
      2 
      3 /****************************************************************
      4 Copyright (C) 1997, 1998 Lucent Technologies
      5 All Rights Reserved
      6 
      7 Permission to use, copy, modify, and distribute this software and
      8 its documentation for any purpose and without fee is hereby
      9 granted, provided that the above copyright notice appear in all
     10 copies and that both that the copyright notice and this
     11 permission notice and warranty disclaimer appear in supporting
     12 documentation, and that the name of Lucent or any of its entities
     13 not be used in advertising or publicity pertaining to
     14 distribution of the software without specific, written prior
     15 permission.
     16 
     17 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     18 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     19 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
     20 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     21 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     22 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     23 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     24 THIS SOFTWARE.
     25 ****************************************************************/
     26 
     27 /* Try to deduce arith.h from arithmetic properties. */
     28 
     29 #include <stdio.h>
     30 
     31 static int dalign;
     32 typedef struct
     33 Akind {
     34 	char *name;
     35 	int   kind;
     36 	} Akind;
     37 
     38 static Akind
     39 IEEE_LITTLE_ENDIAN	= { "IEEE_LITTLE_ENDIAN", 1 },
     40 IEEE_BIG_ENDIAN		= { "IEEE_BIG_ENDIAN", 2 },
     41 IBM			= { "IBM", 3 },
     42 VAX			= { "VAX", 4 },
     43 CRAY			= { "CRAY", 5};
     44 
     45 static Akind *
     46 Lcheck(void)
     47 {
     48 	union {
     49 		double d;
     50 		long L[2];
     51 		} u;
     52 	struct {
     53 		double d;
     54 		long L;
     55 		} x[2];
     56 
     57 	if (sizeof(x) > 2*(sizeof(double) + sizeof(long)))
     58 		dalign = 1;
     59 	u.L[0] = u.L[1] = 0;
     60 	u.d = 1e13;
     61 	if (u.L[0] == 1117925532 && u.L[1] == -448790528)
     62 		return &IEEE_BIG_ENDIAN;
     63 	if (u.L[1] == 1117925532 && u.L[0] == -448790528)
     64 		return &IEEE_LITTLE_ENDIAN;
     65 	if (u.L[0] == -2065213935 && u.L[1] == 10752)
     66 		return &VAX;
     67 	if (u.L[0] == 1267827943 && u.L[1] == 704643072)
     68 		return &IBM;
     69 	return 0;
     70 	}
     71 
     72 static Akind *
     73 icheck(void)
     74 {
     75 	union {
     76 		double d;
     77 		int L[2];
     78 		} u;
     79 	struct {
     80 		double d;
     81 		int L;
     82 		} x[2];
     83 
     84 	if (sizeof(x) > 2*(sizeof(double) + sizeof(int)))
     85 		dalign = 1;
     86 	u.L[0] = u.L[1] = 0;
     87 	u.d = 1e13;
     88 	if (u.L[0] == 1117925532 && u.L[1] == -448790528)
     89 		return &IEEE_BIG_ENDIAN;
     90 	if (u.L[1] == 1117925532 && u.L[0] == -448790528)
     91 		return &IEEE_LITTLE_ENDIAN;
     92 	if (u.L[0] == -2065213935 && u.L[1] == 10752)
     93 		return &VAX;
     94 	if (u.L[0] == 1267827943 && u.L[1] == 704643072)
     95 		return &IBM;
     96 	return 0;
     97 	}
     98 
     99 char *emptyfmt = "";	/* avoid possible warning message with printf("") */
    100 
    101 static Akind *
    102 ccheck(void)
    103 {
    104 	union {
    105 		double d;
    106 		long L;
    107 		} u;
    108 	long Cray1;
    109 
    110 	/* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
    111 	Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762;
    112 	if (printf(emptyfmt, Cray1) >= 0)
    113 		Cray1 = 1000000*Cray1 + 693716;
    114 	if (printf(emptyfmt, Cray1) >= 0)
    115 		Cray1 = 1000000*Cray1 + 115456;
    116 	u.d = 1e13;
    117 	if (u.L == Cray1)
    118 		return &CRAY;
    119 	return 0;
    120 	}
    121 
    122 static int
    123 fzcheck(void)
    124 {
    125 	double a, b;
    126 	int i;
    127 
    128 	a = 1.;
    129 	b = .1;
    130 	for(i = 155;; b *= b, i >>= 1) {
    131 		if (i & 1) {
    132 			a *= b;
    133 			if (i == 1)
    134 				break;
    135 			}
    136 		}
    137 	b = a * a;
    138 	return b == 0.;
    139 	}
    140 
    141 int
    142 main(void)
    143 {
    144 	Akind *a = 0;
    145 	int Ldef = 0;
    146 	FILE *f;
    147 
    148 #ifdef WRITE_ARITH_H	/* for Symantec's buggy "make" */
    149 	f = fopen("arith.h", "w");
    150 	if (!f) {
    151 		printf("Cannot open arith.h\n");
    152 		return 1;
    153 		}
    154 #else
    155 	f = stdout;
    156 #endif
    157 
    158 	if (sizeof(double) == 2*sizeof(long))
    159 		a = Lcheck();
    160 	else if (sizeof(double) == 2*sizeof(int)) {
    161 		Ldef = 1;
    162 		a = icheck();
    163 		}
    164 	else if (sizeof(double) == sizeof(long))
    165 		a = ccheck();
    166 	if (a) {
    167 		fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
    168 			a->name, a->kind);
    169 		if (Ldef)
    170 			fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
    171 		if (dalign)
    172 			fprintf(f, "#define Double_Align\n");
    173 		if (sizeof(char*) == 8)
    174 			fprintf(f, "#define X64_bit_pointers\n");
    175 #ifndef NO_LONG_LONG
    176 		if (sizeof(long long) < 8)
    177 #endif
    178 			fprintf(f, "#define NO_LONG_LONG\n");
    179 		if (a->kind <= 2 && fzcheck())
    180 			fprintf(f, "#define Sudden_Underflow\n");
    181 #ifdef WRITE_ARITH_H
    182 		fclose(f);
    183 #endif
    184 		return 0;
    185 		}
    186 	fprintf(f, "/* Unknown arithmetic */\n");
    187 #ifdef WRITE_ARITH_H
    188 	fclose(f);
    189 #endif
    190 	return 1;
    191 	}
    192