?RCS: $Id$ ?RCS: ?RCS: Copyright (c) 1999-2016 Jarkko Hietaniemi ?RCS: ?RCS: You may distribute under the terms of either the GNU General Public ?RCS: License or the Artistic License, as specified in the README file. ?RCS: ?MAKE:d_PRIfldbl sPRIfldbl d_PRIgldbl d_PRIFUldbl sPRIGUldbl d_PRIEUldbl \ sPRIgldbl d_PRIeldbl sPRIeldbl sPRIFUldbl d_PRIGUldbl sPRIEUldbl \ d_SCNfldbl d_double_style_vax d_double_style_ieee \ d_double_style_ibm d_double_style_cray d_double_has_subnormals \ d_double_has_inf d_double_has_nan d_double_has_negative_zero \ sSCNfldbl doublekind: \ d_longdbl longdblsize doublesize uselongdouble test echo cat rm_try \ Setvar Compile run i_stdlib osname gccversion ccflags ?MAKE: -pick add $@ %< ?S:doublekind: ?S: This variable, if defined, encodes the type of a double: ?S: 1 = IEEE 754 32-bit little endian, ?S: 2 = IEEE 754 32-bit big endian, ?S: 3 = IEEE 754 64-bit little endian, ?S: 4 = IEEE 754 64-bit big endian, ?S: 5 = IEEE 754 128-bit little endian, ?S: 6 = IEEE 754 128-bit big endian, ?S: 7 = IEEE 754 64-bit mixed endian le-be, ?S: 8 = IEEE 754 64-bit mixed endian be-le, ?S: 9 = VAX 32bit little endian F float format ?S: 10 = VAX 64bit little endian D float format ?S: 11 = VAX 64bit little endian G float format ?S: 12 = IBM 32bit format ?S: 13 = IBM 64bit format ?S: 14 = Cray 64bit format ?S: -1 = unknown format. ?S:. ?S:d_PRIfldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S:. ?S:d_PRIgldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S:. ?S:d_PRIeldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S:. ?S:d_PRIFUldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S: The 'U' in the name is to separate this from d_PRIfldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:d_PRIGUldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S: The 'U' in the name is to separate this from d_PRIgldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:d_PRIEUldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to print long doubles. ?S: The 'U' in the name is to separate this from d_PRIeldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:d_SCNfldbl: ?S: This variable conditionally defines the PERL_PRIfldbl symbol, which ?S: indicates that stdio has a symbol to scan long doubles. ?S:. ?S:sPRIfldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'f') for output. ?S:. ?S:sPRIgldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'g') for output. ?S:. ?S:sPRIeldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'e') for output. ?S:. ?S:sPRIFUldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'F') for output. ?S: The 'U' in the name is to separate this from sPRIfldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:sPRIGUldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'G') for output. ?S: The 'U' in the name is to separate this from sPRIgldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:sPRIEUldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'E') for output. ?S: The 'U' in the name is to separate this from sPRIeldbl so that even ?S: case-blind systems can see the difference. ?S:. ?S:sSCNfldbl: ?S: This variable, if defined, contains the string used by stdio to ?S: format long doubles (format 'f') for input. ?S:. ?S:d_double_has_inf: ?S: This variable conditionally defines the symbol DOUBLE_HAS_INF ?S: which indicates that the double type has an infinity. ?S:. ?S:d_double_has_nan: ?S: This variable conditionally defines the symbol DOUBLE_HAS_NAN ?S: which indicates that the double type has a not-a-number. ?S:. ?S:d_double_has_negative_zero: ?S: This variable conditionally defines the symbol DOUBLE_HAS_NEGATIVE_ZERO ?S: which indicates that the double type has a negative zero. ?S:. ?S:d_double_has_subnormals: ?S: This variable conditionally defines the symbol DOUBLE_HAS_SUBNORMALS ?S: which indicates that the double type has subnormals (denormals). ?S:. ?S:d_double_style_cray: ?S: This variable conditionally defines the symbol DOUBLE_STYLE_CRAY ?S: which indicates that the double is the 64-bit CRAY mainframe format. ?S:. ?S:d_double_style_ibm: ?S: This variable conditionally defines the symbol DOUBLE_STYLE_IBM, ?S: which indicates that the double is the 64-bit IBM mainframe format. ?S:. ?S:d_double_style_ieee: ?S: This variable conditionally defines the symbol DOUBLE_STYLE_IEEE, ?S: which indicates that the double is the 64-bit IEEE 754. ?S:. ?S:d_double_style_vax: ?S: This variable conditionally defines the symbol DOUBLE_STYLE_VAX, ?S: which indicates that the double is the 64-bit VAX format D or G. ?S:. ?C:PERL_PRIfldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'f') for output. ?C:. ?C:PERL_PRIgldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'g') for output. ?C:. ?C:PERL_PRIeldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'e') for output. ?C:. ?C:PERL_PRIFldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'f') for output. ?C:. ?C:PERL_PRIGldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'g') for output. ?C:. ?C:PERL_PRIEldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'e') for output. ?C:. ?C:PERL_SCNfldbl: ?C: This symbol, if defined, contains the string used by stdio to ?C: format long doubles (format 'f') for input. ?C:. ?C:DOUBLEKIND: ?C: DOUBLEKIND will be one of ?C: DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN ?C: DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN ?C: DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN ?C: DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN ?C: DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN ?C: DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN ?C: DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE ?C: DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE ?C: DOUBLE_IS_VAX_F_FLOAT ?C: DOUBLE_IS_VAX_D_FLOAT ?C: DOUBLE_IS_VAX_G_FLOAT ?C: DOUBLE_IS_IBM_SINGLE_32_BIT ?C: DOUBLE_IS_IBM_DOUBLE_64_BIT ?C: DOUBLE_IS_CRAY_SINGLE_64_BIT ?C: DOUBLE_IS_UNKNOWN_FORMAT ?C:. ?C:DOUBLE_HAS_INF: ?C: This symbol, if defined, indicates that the double has ?C: the infinity. ?C:. ?C:DOUBLE_HAS_NAN: ?C: This symbol, if defined, indicates that the double has ?C: the not-a-number. ?C:. ?C:DOUBLE_HAS_NEGATIVE_ZERO: ?C: This symbol, if defined, indicates that the double has ?C: the negative_zero. ?C:. ?C:DOUBLE_HAS_SUBNORMALS: ?C: This symbol, if defined, indicates that the double has ?C: the subnormals (denormals). ?C:. ?C:DOUBLE_STYLE_CRAY: ?C: This symbol, if defined, indicates that the double is ?C: the 64-bit CRAY mainframe format. ?C:. ?C:DOUBLE_STYLE_IBM: ?C: This symbol, if defined, indicates that the double is ?C: the 64-bit IBM mainframe format. ?C:. ?C:DOUBLE_STYLE_IEEE: ?C: This symbol, if defined, indicates that the double is ?C: the 64-bit IEEE 754. ?C:. ?C:DOUBLE_STYLE_VAX: ?C: This symbol, if defined, indicates that the double is ?C: the 64-bit VAX format D or G. ?C:. ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE ?LINT:known DOUBLE_IS_VAX_F_FLOAT ?LINT:known DOUBLE_IS_VAX_D_FLOAT ?LINT:known DOUBLE_IS_VAX_G_FLOAT ?LINT:known DOUBLE_IS_IBM_SINGLE_32_BIT ?LINT:known DOUBLE_IS_IBM_DOUBLE_64_BIT ?LINT:known DOUBLE_IS_CRAY_SINGLE_64_BIT ?LINT:known DOUBLE_IS_UNKNOWN_FORMAT ?H:#define DOUBLEKIND $doublekind /**/ ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN 1 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN 2 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN 3 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN 4 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN 5 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN 6 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE 7 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE 8 ?H:?DOUBLEKIND:#define DOUBLE_IS_VAX_F_FLOAT 9 ?H:?DOUBLEKIND:#define DOUBLE_IS_VAX_D_FLOAT 10 ?H:?DOUBLEKIND:#define DOUBLE_IS_VAX_G_FLOAT 11 ?H:?DOUBLEKIND:#define DOUBLE_IS_IBM_SINGLE_32_BIT 12 ?H:?DOUBLEKIND:#define DOUBLE_IS_IBM_DOUBLE_64_BIT 13 ?H:?DOUBLEKIND:#define DOUBLE_IS_CRAY_SINGLE_64_BIT 14 ?H:?DOUBLEKIND:#define DOUBLE_IS_UNKNOWN_FORMAT -1 ?H:#$d_PRIfldbl PERL_PRIfldbl $sPRIfldbl /**/ ?H:#$d_PRIgldbl PERL_PRIgldbl $sPRIgldbl /**/ ?H:#$d_PRIeldbl PERL_PRIeldbl $sPRIeldbl /**/ ?H:#$d_PRIFUldbl PERL_PRIFldbl $sPRIFUldbl /**/ ?H:#$d_PRIGUldbl PERL_PRIGldbl $sPRIGUldbl /**/ ?H:#$d_PRIEUldbl PERL_PRIEldbl $sPRIEUldbl /**/ ?H:#$d_SCNfldbl PERL_SCNfldbl $sSCNfldbl /**/ ?H:#$d_double_has_inf DOUBLE_HAS_INF ?H:#$d_double_has_nan DOUBLE_HAS_NAN ?H:#$d_double_has_negative_zero DOUBLE_HAS_NEGATIVE_ZERO ?H:#$d_double_has_subnormals DOUBLE_HAS_SUBNORMALS ?H:#$d_double_style_cray DOUBLE_STYLE_CRAY ?H:#$d_double_style_ibm DOUBLE_STYLE_IBM ?H:#$d_double_style_ieee DOUBLE_STYLE_IEEE ?H:#$d_double_style_vax DOUBLE_STYLE_VAX ?H:. ?T:yyy message saveccflags ?F:!try ?LINT:change ccflags ?LINT:change uselongdouble : Check what kind of doubles your system has $echo "Checking the kind of doubles you have..." >&4 $cat >try.c < #endif #include static const double d = -0.1; int main() { unsigned const char* b = (unsigned const char*)(&d); #if DOUBLESIZE == 4 if (b[0] == 0xCD && b[3] == 0xBD) { /* IEEE 754 32-bit little-endian */ printf("1\n"); exit(0); } if (b[0] == 0xBD && b[3] == 0xCD) { /* IEEE 754 32-bit big-endian */ printf("2\n"); exit(0); } if (b[0] == 0xCC && b[3] == 0xCC) { /* VAX format F, 32-bit PDP-style mixed endian. */ printf("9\n"); exit(0); } if (b[0] == 0xC0 && b[3] == 0x9A) { /* IBM single 32-bit */ printf("12\n"); exit(0); } #endif #if DOUBLESIZE == 8 if (b[0] == 0x9A && b[7] == 0xBF) { /* IEEE 754 64-bit little-endian */ printf("3\n"); exit(0); } if (b[0] == 0xBF && b[7] == 0x9A) { /* IEEE 754 64-bit big-endian */ printf("4\n"); exit(0); } if (b[0] == 0x99 && b[3] == 0xBF && b[4] == 0x9A && b[7] == 0x99) { /* ARM mixed endian: two little-endian 32-bit floats, in big endian order: * 4 5 6 7 0 1 2 3 (MSB = 7, LSB = 0) * 99 99 b9 bf 9a 99 99 99 */ printf("7\n"); exit(0); } if (b[0] == 0x99 && b[3] == 0x9A && b[4] == 0xBF && b[7] == 0x99) { /* The opposite of case 7, mixed endian: two big-endian 32-bit floats, * in little endian order: 3 2 1 0 7 6 5 4 (MSB = 7, LSB = 0) * 99 99 99 9a bf b9 99 99 */ printf("8\n"); exit(0); } if (b[0] == 0xCC && b[7] == 0xCC) { /* VAX format D, 64-bit PDP-style mixed endian. */ printf("10\n"); exit(0); } if (b[0] == 0xD9 && b[7] == 0x99) { /* VAX format G, 64-bit PDP-style mixed endian. */ printf("11\n"); exit(0); } if (b[0] == 0xC0 && b[7] == 0x9A) { /* IBM double 64-bit */ printf("13\n"); exit(0); } if (b[0] == 0xBF && b[7] == 0xCD) { /* CRAY single 64-bit */ printf("14\n"); exit(0); } #endif #if DOUBLESIZE == 16 if (b[0] == 0x9A && b[15] == 0xBF) { /* IEEE 754 128-bit little-endian */ printf("5\n"); exit(0); } if (b[0] == 0xBF && b[15] == 0x9A) { /* IEEE 754 128-bit big-endian */ printf("6\n"); exit(0); } #endif /* Then there are old mainframe/miniframe formats like IBM and CRAY. * Whether those environments can still build Perl is debatable. */ printf("-1\n"); /* unknown */ exit(0); } EOP set try if eval $compile; then doublekind=`$run ./try` else doublekind=-1 fi case "$doublekind" in 1) echo "You have IEEE 754 32-bit little endian doubles." >&4 ;; 2) echo "You have IEEE 754 32-bit big endian doubles." >&4 ;; 3) echo "You have IEEE 754 64-bit little endian doubles." >&4 ;; 4) echo "You have IEEE 754 64-bit big endian doubles." >&4 ;; 5) echo "You have IEEE 754 128-bit little endian doubles." >&4 ;; 6) echo "You have IEEE 754 128-bit big endian doubles." >&4 ;; 7) echo "You have IEEE 754 64-bit mixed endian doubles (32-bit LEs in BE)." >&4 ;; 8) echo "You have IEEE 754 64-bit mixed endian doubles (32-bit BEs in LE)." >&4 ;; 9) echo "You have VAX format F 32-bit PDP-style mixed endian doubles." >&4 ;; 10) echo "You have VAX format D 64-bit PDP-style mixed endian doubles." >&4 ;; 11) echo "You have VAX format G 64-bit PDP-style mixed endian doubles." >&4 ;; 12) echo "You have IBM short 32-bit doubles." >&4 ;; 13) echo "You have IBM long 64-bit doubles." >&4 ;; 14) echo "You have Cray single 64-bit doubles." >&4 ;; *) echo "Cannot figure out your double. You Cyber, or something?" >&4 ;; esac d_double_style_ieee=$undef d_double_style_vax=$undef d_double_style_ibm=$undef d_double_style_cray=$undef case "$doublekind" in 1|2|3|4|5|6|7|8) d_double_style_ieee=$define ;; 9|10|11) d_double_style_vax=$define ;; 12|13) d_double_style_ibm=$define ;; 14) d_double_style_cray=$define ;; esac case "$d_double_style_ieee" in $define) d_double_has_inf=$define d_double_has_nan=$define d_double_has_negative_zero=$define d_double_has_subnormals=$define ;; *) d_double_has_inf=$undef d_double_has_nan=$undef d_double_has_negative_zero=$undef d_double_has_subnormals=$undef ;; esac $rm_try : Check print/scan long double stuff echo " " if $test X"$d_longdbl" = X"$define"; then echo "Checking how to print long doubles..." >&4 if $test X"$sPRIfldbl" = X -a X"$doublesize" = X"$longdblsize"; then $cat >try.c <<'EOCP' #include #include int main() { double d = 123.456; printf("%.3f\n", d); } EOCP set try if eval $compile; then yyy=`$run ./try` case "$yyy" in 123.456) sPRIfldbl='"f"'; sPRIgldbl='"g"'; sPRIeldbl='"e"'; sPRIFUldbl='"F"'; sPRIGUldbl='"G"'; sPRIEUldbl='"E"'; echo "We will use %f." ;; esac fi fi if $test X"$sPRIfldbl" = X; then $cat >try.c <<'EOCP' #include #include int main() { long double d = 123.456; printf("%.3Lf\n", d); } EOCP set try if eval $compile; then yyy=`$run ./try` case "$yyy" in 123.456) sPRIfldbl='"Lf"'; sPRIgldbl='"Lg"'; sPRIeldbl='"Le"'; sPRIFUldbl='"LF"'; sPRIGUldbl='"LG"'; sPRIEUldbl='"LE"'; echo "We will use %Lf." ;; esac fi fi if $test X"$sPRIfldbl" = X; then $cat >try.c <<'EOCP' #include #include int main() { long double d = 123.456; printf("%.3llf\n", d); } EOCP set try if eval $compile; then yyy=`$run ./try` case "$yyy" in 123.456) sPRIfldbl='"llf"'; sPRIgldbl='"llg"'; sPRIeldbl='"lle"'; sPRIFUldbl='"llF"'; sPRIGUldbl='"llG"'; sPRIEUldbl='"llE"'; echo "We will use %llf." ;; esac fi fi if $test X"$sPRIfldbl" = X; then $cat >try.c <<'EOCP' #include #include int main() { long double d = 123.456; printf("%.3lf\n", d); } EOCP set try if eval $compile; then yyy=`$run ./try` case "$yyy" in 123.456) sPRIfldbl='"lf"'; sPRIgldbl='"lg"'; sPRIeldbl='"le"'; sPRIFUldbl='"lF"'; sPRIGUldbl='"lG"'; sPRIEUldbl='"lE"'; echo "We will use %lf." ;; esac fi fi if $test X"$sPRIfldbl" = X; then echo "Cannot figure out how to print long doubles." >&4 else sSCNfldbl=$sPRIfldbl # expect consistency fi $rm_try fi # d_longdbl case "$sPRIfldbl" in '') d_PRIfldbl="$undef"; d_PRIgldbl="$undef"; d_PRIeldbl="$undef"; d_PRIFUldbl="$undef"; d_PRIGUldbl="$undef"; d_PRIEUldbl="$undef"; d_SCNfldbl="$undef"; ;; *) d_PRIfldbl="$define"; d_PRIgldbl="$define"; d_PRIeldbl="$define"; d_PRIFUldbl="$define"; d_PRIGUldbl="$define"; d_PRIEUldbl="$define"; d_SCNfldbl="$define"; ;; esac : Before committing on uselongdouble, see whether that looks sane. if $test "$uselongdouble" = "$define"; then message="" echo " " echo "Checking if your long double math functions work right..." >&4 $cat > try.c < #include int main() { printf("%"$sPRIgldbl"\n", sqrtl(logl(expl(cosl(sinl(0.0L))))+powl(2.0L, 3.0L))); } EOF case "$osname:$gccversion" in aix:) saveccflags="$ccflags" ccflags="$ccflags -qlongdouble" ;; # to avoid core dump esac set try if eval $compile_ok; then yyy=`$run ./try` fi case "$yyy" in 3) echo "Your long double math functions are working correctly." >&4 ;; *) echo "Your long double math functions are broken, not using long doubles." >&4 uselongdouble=$undef ;; esac $rm_try case "$osname:$gccversion" in aix:) ccflags="$saveccflags" ;; # restore esac fi