This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Zero out high bytes of 80-bit ldnan
[metaconfig.git] / U / perl / infnan.U
CommitLineData
8998a849
MBT
1?RCS: $Id$
2?RCS:
3?RCS: Copyright (c) 2015 Jarkko Hietaniemi, H.Merijn Brand
4?RCS:
5?RCS: You may distribute under the terms of either the GNU General Public
6?RCS: License or the Artistic License, as specified in the README file.
7?RCS:
8?MAKE:longdblinfbytes longdblnanbytes doubleinfbytes doublenanbytes: Inlibc \
9 cat i_math Compile run rm_try Setvar echo d_longdbl \
10 doublekind doublesize longdblkind longdblsize
bf106bfe 11?MAKE: -pick add $@ %<
8998a849
MBT
12?S:longdblinfbytes:
13?S: This variable contains comma-separated list of hexadecimal bytes
5ca72400 14?S: for the long double precision infinity.
8998a849
MBT
15?S:.
16?S:longdblnanbytes:
17?S: This variable contains comma-separated list of hexadecimal bytes
5ca72400 18?S: for the long double precision not-a-number.
8998a849
MBT
19?S:.
20?S:doubleinfbytes:
21?S: This variable contains comma-separated list of hexadecimal bytes
5ca72400 22?S: for the double precision infinity.
8998a849
MBT
23?S:.
24?S:doublenanbytes:
25?S: This variable contains comma-separated list of hexadecimal bytes
5ca72400 26?S: for the double precision not-a-number.
8998a849
MBT
27?S:.
28?C:DOUBLEINFBYTES:
29?C: This symbol, if defined, is a comma-separated list of
30?C: hexadecimal bytes for the double precision infinity.
31?C:.
32?C:DOUBLENANBYTES:
33?C: This symbol, if defined, is a comma-separated list of
34?C: hexadecimal bytes (0xHH) for the double precision not-a-number.
35?C:.
36?C:LONGDBLINFBYTES:
37?C: This symbol, if defined, is a comma-separated list of
38?C: hexadecimal bytes for the long double precision infinity.
39?C:.
40?C:LONGDBLNANBYTES:
41?C: This symbol, if defined, is a comma-separated list of
42?C: hexadecimal bytes (0xHH) for the long double precision not-a-number.
43?C:.
44?H:#define DOUBLEINFBYTES $doubleinfbytes /**/
45?H:#define DOUBLENANBYTES $doublenanbytes /**/
46?H:#define LONGDBLINFBYTES $longdblinfbytes /**/
47?H:#define LONGDBLNANBYTES $longdblnanbytes /**/
48?H:.
49?F:!try
50: Check what kind of inf/nan your system has
51$echo "Checking the kind of infinities and nans you have..." >&4
7253d5da 52$echo "(The following tests may crash. That's okay.)" >&4
8998a849
MBT
53$cat >try.c <<EOP
54#define DOUBLESIZE $doublesize
55#$d_longdbl HAS_LONG_DOUBLE
56#ifdef HAS_LONG_DOUBLE
2b190d47
MBT
57#define LONG_DOUBLESIZE $longdblsize
58#define LONG_DOUBLEKIND $longdblkind
8998a849
MBT
59#endif
60#$i_math I_MATH
61#ifdef I_MATH
62#include <math.h>
63#endif
64#include <stdio.h>
65/* Note that whether the sign bit is on or off
66 * for NaN depends on the CPU/FPU, and possibly
67 * can be affected by the build toolchain.
68 *
69 * For example for older MIPS and HP-PA 2.0 the quiet NaN is:
70 * 0x7f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
71 * 0x7f, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
72 * (respectively) as opposed to the more usual
73 * 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3db366a3
MBT
74 *
75 * Pre-IEEE-754 floating point format do not even have inf/nan support
76 * at all. They might have a "max" value (DBL_MAX), which may be deadly
77 * to even mention, causing immediate SIGFPE or equivalent: this is
78 * the case with VAX floating point, for example.
8998a849
MBT
79 */
80static void bytes(unsigned char *p, unsigned int n) {
81 int i;
82 for (i = 0; i < n; i++) {
83 printf("0x%02x%s", p[i], i < n - 1 ? ", " : "\n");
84 }
85}
86int main(int argc, char *argv[]) {
87 /* We cannot use 1.0/0.0 and 0.0/0.0 (with L suffixes for long double)
88 * because some compilers are 'smart' and not only warn but refuse to
89 * compile such 'illegal' values. */
90 double dinf = exp(1e9);
91 double dnan = sqrt(-1.0);
92#ifdef HAS_LONG_DOUBLE
93 long double ldinf = (long double)exp(1e9);
94 long double ldnan = (long double)sqrt(-1.0);
8998a849
MBT
95# if LONG_DOUBLEKIND == 3 || LONG_DOUBLEKIND == 4
96/* the 80-bit long doubles might have garbage in their excess bytes */
97 memset((char *)&ldinf + 10, '\0', LONG_DOUBLESIZE - 10);
2b190d47 98 memset((char *)&ldnan + 10, '\0', LONG_DOUBLESIZE - 10);
8998a849 99# endif
2b190d47
MBT
100 if (argc == 2) {
101 switch (argv[1][0]) {
102 case '1': bytes(&dinf, sizeof(dinf)); break;
103 case '2': bytes(&dnan, sizeof(dnan)); break;
8998a849
MBT
104 case '3': bytes(&ldinf, sizeof(ldinf)); break;
105 case '4': bytes(&ldnan, sizeof(ldnan)); break;
106#endif
107 }
108 }
109 return 0;
110}
111EOP
112set try
113if eval $compile; then
114 doubleinfbytes=`$run ./try 1`
115 doublenanbytes=`$run ./try 2`
116 case "$d_longdbl" in
117 $define)
118 longdblinfbytes=`$run ./try 3`
119 longdblnanbytes=`$run ./try 4`
120 ;;
121 esac
122else
123 # Defaults in case the above test program failed.
124 case "$doublekind" in
125 1) # IEEE 754 32-bit LE
126 doubleinfbytes='0x00, 0x00, 0xf0, 0x7f'
127 doublenanbytes='0x00, 0x00, 0xf8, 0x7f'
128 ;;
129 2) # IEEE 754 32-bit BE
130 doubleinfbytes='0x7f, 0xf0, 0x00, 0x00'
131 doublenanbytes='0x7f, 0xf8, 0x00, 0x00'
132 ;;
133 3) # IEEE 754 64-bit LE
134 doubleinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f'
135 doublenanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f'
136 ;;
137 4) # IEEE 754 64-bit BE
138 doubleinfbytes='0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
139 doublenanbytes='0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
140 ;;
141 5) # IEEE 754 128-bit LE
142 doubleinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f'
143 doublenanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f'
144 ;;
145 6) # IEEE 754 128-bit BE
146 doubleinfbytes='0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
147 doublenanbytes='0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
148 ;;
149 7) # IEEE 754 64-bit mixed: 32-bit LEs in BE
150 doubleinfbytes='0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00'
151 doublenanbytes='0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00'
152 ;;
153 8) # IEEE 754 64-bit mixed: 32-bit BEs in LE
154 doubleinfbytes='0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00'
155 doublenanbytes='0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00'
156 ;;
3db366a3
MBT
157 9|10|11|12|13|14) # VAX/Cray/IBM floating point formats, no inf/nan.
158 doubleinfbytes=$undef
159 doublenanbytes=$undef
160 ;;
8998a849
MBT
161 *) # No idea.
162 doubleinfbytes=$undef
163 doublenanbytes=$undef
164 ;;
165 esac
166 case "$longdblkind" in
167 1) # IEEE 754 128-bit LE
168 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f'
169 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f'
170 ;;
171 2) # IEEE 754 128-bit BE
172 longdblinfbytes='0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
173 longdblnanbytes='0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
174 ;;
175 3) # IEEE 754 80-bit LE, 12 or 16 bytes (x86)
176 case "$longdblsize" in
177 12) # x86 32-bit (96 bits, or 4 x 32, or 12 x 8)
178 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00'
179 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00'
180 ;;
181 16) # x86_64
182 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
183 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
184 ;;
185 *) # No idea.
186 longdblinfbytes=$undef
187 longdblnanbytes=$undef
188 ;;
189 esac
190 ;;
191 4) # IEEE 754 80-bit BE, 12 or 16 bytes
192 case "$longdblsize" in
193 12) # 32-bit system
194 longdblinfbytes='0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
195 longdblnanbytes='0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
196 ;;
197 16) # 64-bit system
198 longdblinfbytes='0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
199 longdblnanbytes='0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
200 ;;
201 *) # No idea.
202 longdblinfbytes=$undef
203 longdblnanbytes=$undef
204 ;;
205 esac
206 ;;
5f2a9443 207 5) # 128-bit LE-LE "double double"
8998a849
MBT
208 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f'
209 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f'
210 ;;
5f2a9443 211 6) # 128-bit BE-BE "double double"
8998a849
MBT
212 longdblinfbytes='0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
213 longdblnanbytes='0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
214 ;;
5f2a9443
AC
215 7) # 128-bit LE-BE "double double"
216 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
217 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
218 ;;
219 8) # 128-bit BE-LE "double double"
220 longdblinfbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
221 longdblnanbytes='0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'
222 ;;
3db366a3
MBT
223 9|10|11|12|13|14) # VAX/Cray/IBM floating point formats, no inf/nan.
224 longdblinfbytes=$undef
225 longdblnanbytes=$undef
226 ;;
8998a849
MBT
227 *) # No idea.
228 longdblinfbytes=$undef
229 longdblnanbytes=$undef
230 ;;
231 esac
232fi
3db366a3
MBT
233# In case the program crashed the values are empty, turn them undef.
234case "$doubleinfbytes" in
235'') doubleinfbytes=$undef ;;
236esac
237case "$doublenanbytes" in
238'') doublenanbytes=$undef ;;
239esac
240case "$longdblinfbytes" in
241'') longdblinfbytes=$undef ;;
242esac
243case "$longdblnanbytes" in
244'') longdblnanbytes=$undef ;;
245esac
8998a849
MBT
246$rm_try
247