This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
9fe8ea34325dd9168822d8f4c98a1350311d8f1e
[metaconfig.git] / U / perl / longdblfio.U
1 ?RCS: $Id$
2 ?RCS:
3 ?RCS: Copyright (c) 1999 Jarkko Hietaniemi
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:d_PRIfldbl sPRIfldbl d_PRIgldbl d_PRIFUldbl sPRIGUldbl d_PRIEUldbl \
9         sPRIgldbl d_PRIeldbl sPRIeldbl sPRIFUldbl d_PRIGUldbl sPRIEUldbl \
10         d_SCNfldbl \
11         sSCNfldbl doublekind: \
12         d_longdbl longdblsize doublesize uselongdouble test echo cat rm_try \
13         Setvar Compile run i_stdlib osname gccversion ccflags
14 ?MAKE:  -pick add $@ %<
15 ?S:doublekind:
16 ?S:     This variable, if defined, encodes the type of a double:
17 ?S:      1 = IEEE 754 32-bit little endian,
18 ?S:      2 = IEEE 754 32-bit big endian,
19 ?S:      3 = IEEE 754 64-bit little endian,
20 ?S:      4 = IEEE 754 64-bit big endian,
21 ?S:      5 = IEEE 754 128-bit little endian,
22 ?S:      6 = IEEE 754 128-bit big endian,
23 ?S:      7 = IEEE 754 64-bit mixed endian le-be,
24 ?S:      8 = IEEE 754 64-bit mixed endian be-le,
25 ?S:     -1 = unknown format.
26 ?S:.
27 ?S:d_PRIfldbl:
28 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
29 ?S:     indicates that stdio has a symbol to print long doubles.
30 ?S:.
31 ?S:d_PRIgldbl:
32 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
33 ?S:     indicates that stdio has a symbol to print long doubles.
34 ?S:.
35 ?S:d_PRIeldbl:
36 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
37 ?S:     indicates that stdio has a symbol to print long doubles.
38 ?S:.
39 ?S:d_PRIFUldbl:
40 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
41 ?S:     indicates that stdio has a symbol to print long doubles.
42 ?S:     The 'U' in the name is to separate this from d_PRIfldbl so that even
43 ?S:     case-blind systems can see the difference.
44 ?S:.
45 ?S:d_PRIGUldbl:
46 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
47 ?S:     indicates that stdio has a symbol to print long doubles.
48 ?S:     The 'U' in the name is to separate this from d_PRIgldbl so that even
49 ?S:     case-blind systems can see the difference.
50 ?S:.
51 ?S:d_PRIEUldbl:
52 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
53 ?S:     indicates that stdio has a symbol to print long doubles.
54 ?S:     The 'U' in the name is to separate this from d_PRIeldbl so that even
55 ?S:     case-blind systems can see the difference.
56 ?S:.
57 ?S:d_SCNfldbl:
58 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
59 ?S:     indicates that stdio has a symbol to scan long doubles.
60 ?S:.
61 ?S:sPRIfldbl:
62 ?S:     This variable, if defined, contains the string used by stdio to
63 ?S:     format long doubles (format 'f') for output.
64 ?S:.
65 ?S:sPRIgldbl:
66 ?S:     This variable, if defined, contains the string used by stdio to
67 ?S:     format long doubles (format 'g') for output.
68 ?S:.
69 ?S:sPRIeldbl:
70 ?S:     This variable, if defined, contains the string used by stdio to
71 ?S:     format long doubles (format 'e') for output.
72 ?S:.
73 ?S:sPRIFUldbl:
74 ?S:     This variable, if defined, contains the string used by stdio to
75 ?S:     format long doubles (format 'F') for output.
76 ?S:     The 'U' in the name is to separate this from sPRIfldbl so that even
77 ?S:     case-blind systems can see the difference.
78 ?S:.
79 ?S:sPRIGUldbl:
80 ?S:     This variable, if defined, contains the string used by stdio to
81 ?S:     format long doubles (format 'G') for output.
82 ?S:     The 'U' in the name is to separate this from sPRIgldbl so that even
83 ?S:     case-blind systems can see the difference.
84 ?S:.
85 ?S:sPRIEUldbl:
86 ?S:     This variable, if defined, contains the string used by stdio to
87 ?S:     format long doubles (format 'E') for output.
88 ?S:     The 'U' in the name is to separate this from sPRIeldbl so that even
89 ?S:     case-blind systems can see the difference.
90 ?S:.
91 ?S:sSCNfldbl:
92 ?S:     This variable, if defined, contains the string used by stdio to
93 ?S:     format long doubles (format 'f') for input.
94 ?S:.
95 ?C:PERL_PRIfldbl:
96 ?C:     This symbol, if defined, contains the string used by stdio to
97 ?C:     format long doubles (format 'f') for output.
98 ?C:.
99 ?C:PERL_PRIgldbl:
100 ?C:     This symbol, if defined, contains the string used by stdio to
101 ?C:     format long doubles (format 'g') for output.
102 ?C:.
103 ?C:PERL_PRIeldbl:
104 ?C:     This symbol, if defined, contains the string used by stdio to
105 ?C:     format long doubles (format 'e') for output.
106 ?C:.
107 ?C:PERL_PRIFldbl:
108 ?C:     This symbol, if defined, contains the string used by stdio to
109 ?C:     format long doubles (format 'f') for output.
110 ?C:.
111 ?C:PERL_PRIGldbl:
112 ?C:     This symbol, if defined, contains the string used by stdio to
113 ?C:     format long doubles (format 'g') for output.
114 ?C:.
115 ?C:PERL_PRIEldbl:
116 ?C:     This symbol, if defined, contains the string used by stdio to
117 ?C:     format long doubles (format 'e') for output.
118 ?C:.
119 ?C:PERL_SCNfldbl:
120 ?C:     This symbol, if defined, contains the string used by stdio to
121 ?C:     format long doubles (format 'f') for input.
122 ?C:.
123 ?C:DOUBLEKIND:
124 ?C:     DOUBLEKIND will be one of
125 ?C:     DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN
126 ?C:     DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN
127 ?C:     DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN
128 ?C:     DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN
129 ?C:     DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
130 ?C:     DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN
131 ?C:     DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE
132 ?C:     DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE
133 ?C:     DOUBLE_IS_UNKNOWN_FORMAT
134 ?C:.
135 ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN
136 ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN
137 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN
138 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN
139 ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
140 ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN
141 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE
142 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE
143 ?LINT:known DOUBLE_IS_UNKNOWN_FORMAT
144 ?H:#define DOUBLEKIND $doublekind               /**/
145 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN  1
146 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN     2
147 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN  3
148 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN     4
149 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN 5
150 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN    6
151 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE     7
152 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE     8
153 ?H:?DOUBLEKIND:#define DOUBLE_IS_UNKNOWN_FORMAT         -1
154 ?H:#$d_PRIfldbl PERL_PRIfldbl   $sPRIfldbl      /**/
155 ?H:#$d_PRIgldbl PERL_PRIgldbl   $sPRIgldbl      /**/
156 ?H:#$d_PRIeldbl PERL_PRIeldbl   $sPRIeldbl      /**/
157 ?H:#$d_PRIFUldbl PERL_PRIFldbl  $sPRIFUldbl     /**/
158 ?H:#$d_PRIGUldbl PERL_PRIGldbl  $sPRIGUldbl     /**/
159 ?H:#$d_PRIEUldbl PERL_PRIEldbl  $sPRIEUldbl     /**/
160 ?H:#$d_SCNfldbl PERL_SCNfldbl   $sSCNfldbl      /**/
161 ?H:.
162 ?T:yyy message saveccflags
163 ?F:!try
164 ?LINT:change ccflags
165 ?LINT:change uselongdouble
166 : Check what kind of doubles your system has
167 $echo "Checking the kind of doubles you have..." >&4
168 $cat >try.c <<EOP
169 #$i_stdlib I_STDLIB
170 #define DOUBLESIZE $doublesize
171 #ifdef I_STDLIB
172 #include <stdlib.h>
173 #endif
174 #include <stdio.h>
175 static const double d = -0.1;
176 int main() {
177   unsigned const char* b = (unsigned const char*)(&d);
178 #if DOUBLESIZE == 4
179   if (b[0] == 0xCD && b[3] == 0xBD) {
180     /* IEEE 754 32-bit little-endian */
181     printf("1\n");
182     exit(0);
183   }
184   if (b[0] == 0xBD && b[3] == 0xCD) {
185     /* IEEE 754 32-bit big-endian */
186     printf("2\n");
187     exit(0);
188   }
189 #endif
190 #if DOUBLESIZE == 8
191   if (b[0] == 0x9A && b[7] == 0xBF) {
192     /* IEEE 754 64-bit little-endian */
193     printf("3\n");
194     exit(0);
195   }
196   if (b[0] == 0xBF && b[7] == 0x9A) {
197     /* IEEE 754 64-bit big-endian */
198     printf("4\n");
199     exit(0);
200   }
201   if (b[0] == 0x99 && b[3] == 0xBF && b[4] == 0x9A && b[7] == 0x99) {
202    /* ARM mixed endian: two little-endian 32-bit floats, in big endian order:
203     * 4 5 6 7 0 1 2 3 (MSB = 7, LSB = 0)
204     * 99 99 b9 bf 9a 99 99 99 */
205     printf("7\n");
206     exit(0);
207   }
208   if (b[0] == 0x99 && b[3] == 0x9A && b[4] == 0xBF && b[7] == 0x99) {
209    /* The opposite of case 7, mixed endian: two big-endian 32-bit floats,
210     * in little endian order: 3 2 1 0 7 6 5 4 (MSB = 7, LSB = 0)
211     * 99 99 99 9a bf b9 99 99 */
212     printf("8\n");
213     exit(0);
214   }
215 #endif
216 #if DOUBLESIZE == 16
217   if (b[0] == 0x9A && b[15] == 0xBF) {
218     /* IEEE 754 128-bit little-endian */
219     printf("5\n");
220     exit(0);
221   }
222   if (b[0] == 0xBF && b[15] == 0x9A) {
223     /* IEEE 754 128-bit big-endian */
224     printf("6\n");
225     exit(0);
226   }
227 #endif
228   /* Then there are old mainframe/miniframe formats like VAX, IBM, and CRAY.
229    * Whether those environments can still build Perl is debatable. */
230   printf("-1\n"); /* unknown */
231   exit(0);
232 }
233 EOP
234 set try
235 if eval $compile; then
236     doublekind=`$run ./try`
237 else
238     doublekind=-1
239 fi
240 case "$doublekind" in
241 1) echo "You have IEEE 754 32-bit little endian doubles." >&4 ;;
242 2) echo "You have IEEE 754 32-bit big endian doubles." >&4 ;;
243 3) echo "You have IEEE 754 64-bit little endian doubles." >&4 ;;
244 4) echo "You have IEEE 754 64-bit big endian doubles." >&4 ;;
245 5) echo "You have IEEE 754 128-bit little endian doubles." >&4 ;;
246 6) echo "You have IEEE 754 128-bit big endian doubles." >&4 ;;
247 7) echo "You have IEEE 754 64-bit mixed endian doubles (32-bit LEs in BE)." >&4 ;;
248 8) echo "You have IEEE 754 64-bit mixed endian doubles (32-bit BEs in LE)." >&4 ;;
249 *) echo "Cannot figure out your double.  You VAX, or something?" >&4 ;;
250 esac
251 $rm_try
252
253 : Check print/scan long double stuff
254 echo " "
255
256 if $test X"$d_longdbl" = X"$define"; then
257
258 echo "Checking how to print long doubles..." >&4
259
260 if $test X"$sPRIfldbl" = X -a X"$doublesize" = X"$longdblsize"; then
261         $cat >try.c <<'EOCP'
262 #include <sys/types.h>
263 #include <stdio.h>
264 int main() {
265   double d = 123.456;
266   printf("%.3f\n", d);
267 }
268 EOCP
269         set try
270         if eval $compile; then
271                 yyy=`$run ./try`
272                 case "$yyy" in
273                 123.456)
274                         sPRIfldbl='"f"'; sPRIgldbl='"g"'; sPRIeldbl='"e"';
275                         sPRIFUldbl='"F"'; sPRIGUldbl='"G"'; sPRIEUldbl='"E"';
276                         echo "We will use %f."
277                         ;;
278                 esac
279         fi
280 fi
281
282 if $test X"$sPRIfldbl" = X; then
283         $cat >try.c <<'EOCP'
284 #include <sys/types.h>
285 #include <stdio.h>
286 int main() {
287   long double d = 123.456;
288   printf("%.3Lf\n", d);
289 }
290 EOCP
291         set try
292         if eval $compile; then
293                 yyy=`$run ./try`
294                 case "$yyy" in
295                 123.456)
296                         sPRIfldbl='"Lf"'; sPRIgldbl='"Lg"'; sPRIeldbl='"Le"';
297                         sPRIFUldbl='"LF"'; sPRIGUldbl='"LG"'; sPRIEUldbl='"LE"';
298                         echo "We will use %Lf."
299                         ;;
300                 esac
301         fi
302 fi
303
304 if $test X"$sPRIfldbl" = X; then
305         $cat >try.c <<'EOCP'
306 #include <sys/types.h>
307 #include <stdio.h>
308 int main() {
309   long double d = 123.456;
310   printf("%.3llf\n", d);
311 }
312 EOCP
313         set try
314         if eval $compile; then
315                 yyy=`$run ./try`
316                 case "$yyy" in
317                 123.456)
318                         sPRIfldbl='"llf"'; sPRIgldbl='"llg"'; sPRIeldbl='"lle"';
319                         sPRIFUldbl='"llF"'; sPRIGUldbl='"llG"'; sPRIEUldbl='"llE"';
320                         echo "We will use %llf."
321                         ;;
322                 esac
323         fi
324 fi
325
326 if $test X"$sPRIfldbl" = X; then
327         $cat >try.c <<'EOCP'
328 #include <sys/types.h>
329 #include <stdio.h>
330 int main() {
331   long double d = 123.456;
332   printf("%.3lf\n", d);
333 }
334 EOCP
335         set try
336         if eval $compile; then
337                 yyy=`$run ./try`
338                 case "$yyy" in
339                 123.456)
340                         sPRIfldbl='"lf"'; sPRIgldbl='"lg"'; sPRIeldbl='"le"';
341                         sPRIFUldbl='"lF"'; sPRIGUldbl='"lG"'; sPRIEUldbl='"lE"';
342                         echo "We will use %lf."
343                         ;;
344                 esac
345         fi
346 fi
347
348 if $test X"$sPRIfldbl" = X; then
349         echo "Cannot figure out how to print long doubles." >&4
350 else
351         sSCNfldbl=$sPRIfldbl    # expect consistency
352 fi
353
354 $rm_try
355
356 fi # d_longdbl
357
358 case "$sPRIfldbl" in
359 '')     d_PRIfldbl="$undef"; d_PRIgldbl="$undef"; d_PRIeldbl="$undef";
360         d_PRIFUldbl="$undef"; d_PRIGUldbl="$undef"; d_PRIEUldbl="$undef";
361         d_SCNfldbl="$undef";
362         ;;
363 *)      d_PRIfldbl="$define"; d_PRIgldbl="$define"; d_PRIeldbl="$define";
364         d_PRIFUldbl="$define"; d_PRIGUldbl="$define"; d_PRIEUldbl="$define";
365         d_SCNfldbl="$define";
366         ;;
367 esac
368
369 : Before committing on uselongdouble, see whether that looks sane.
370 if $test "$uselongdouble" = "$define"; then
371     message=""
372     echo " "
373     echo "Checking if your long double math functions work right..." >&4
374     $cat > try.c <<EOF
375 #include <math.h>
376 #include <stdio.h>
377 int main() {
378   printf("%"$sPRIgldbl"\n", sqrtl(logl(expl(cosl(sinl(0.0L))))+powl(2.0L, 3.0L)));
379 }
380 EOF
381     case "$osname:$gccversion" in
382     aix:)       saveccflags="$ccflags"
383                 ccflags="$ccflags -qlongdouble" ;; # to avoid core dump
384     esac
385     set try
386     if eval $compile_ok; then
387       yyy=`$run ./try`
388     fi
389     case "$yyy" in
390     3) echo "Your long double math functions are working correctly." >&4 ;;
391     *) echo "Your long double math functions are broken, not using long doubles." >&4
392        uselongdouble=$undef
393        ;;
394     esac
395     $rm_try
396     case "$osname:$gccversion" in
397     aix:)       ccflags="$saveccflags" ;; # restore
398     esac
399 fi
400