?RCS: License or the Artistic License, as specified in the README file.
?RCS:
?MAKE:ivtype uvtype nvtype ivsize uvsize nvsize \
- i8type u8type i16type u16type i32type u32type i64type u64type \
- i8size u8size i16size u16size i32size u32size i64size u64size \
- d_nv_preserves_uv d_nv_preserves_uv_bits: \
- echo rm use64bitint d_quad quadtype uquadtype \
- d_longdbl uselongdouble longdblsize doublesize \
- charsize shortsize intsize longsize \
- cat Compile i_inttypes exe_ext test d_volatile signal_t
+ i8type u8type i16type u16type i32type u32type i64type u64type \
+ i8size u8size i16size u16size i32size u32size i64size u64size \
+ d_nv_preserves_uv nv_preserves_uv_bits nv_overflows_integers_at \
+ d_nv_zero_is_allbits_zero: \
+ echo rm_try use64bitint d_quad quadtype uquadtype usequadmath \
+ d_longdbl uselongdouble longdblsize doublesize i_quadmath \
+ shortsize intsize longsize i_stdlib libs gccversion \
+ cat Compile i_inttypes test signal_t run
?MAKE: -pick add $@ %<
?S:ivtype:
?S: This variable contains the C type used for Perl's IV.
?S: This variable is the size of an U64 in bytes.
?S:.
?S:nvsize:
-?S: This variable is the size of an NV in bytes.
+?S: This variable is the size of a Perl NV in bytes.
+?S: Note that some floating point formats have unused bytes.
?S:.
?S:d_nv_preserves_uv:
?S: This variable indicates whether a variable of type nvtype
?S: can preserve all the bits a variable of type uvtype.
?S:.
-?S:d_nv_preserves_uv_bits:
+?S:nv_preserves_uv_bits:
?S: This variable indicates how many of bits type uvtype
?S: a variable nvtype can preserve.
?S:.
+?S:nv_overflows_integers_at:
+?S: This variable gives the largest integer value that NVs can hold
+?S: as a constant floating point expression.
+?S: If it could not be determined, it holds the value 0.
+?S:.
+?S:d_nv_zero_is_allbits_zero:
+?S: This variable indicates whether a variable of type nvtype
+?S: stores 0.0 in memory as all bits zero.
+?S:.
?C:IVTYPE:
?C: This symbol defines the C type used for Perl's IV.
?C:.
?C:.
?C:NVSIZE:
?C: This symbol contains the sizeof(NV).
+?C: Note that some floating point formats have unused bytes.
+?C: The most notable example is the x86* 80-bit extended precision
+?C: which comes in byte sizes of 12 and 16 (for 32 and 64 bit
+?C: platforms, respectively), but which only uses 10 bytes.
+?C: Perl compiled with -Duselongdouble on x86* is like this.
?C:.
?C:NV_PRESERVES_UV:
?C: This symbol, if defined, indicates that a variable of type NVTYPE
?C: This symbol contains the number of bits a variable of type NVTYPE
?C: can preserve of a variable of type UVTYPE.
?C:.
+?C:NV_OVERFLOWS_INTEGERS_AT:
+?C: This symbol gives the largest integer value that NVs can hold. This
+?C: value + 1.0 cannot be stored accurately. It is expressed as constant
+?C: floating point expression to reduce the chance of decimal/binary
+?C: conversion issues. If it can not be determined, the value 0 is given.
+?C:.
+?C:NV_ZERO_IS_ALLBITS_ZERO:
+?C: This symbol, if defined, indicates that a variable of type NVTYPE
+?C: stores 0.0 in memory as all bits zero.
+?C:.
?H:#define IVTYPE $ivtype /**/
?H:#define UVTYPE $uvtype /**/
?H:#define I8TYPE $i8type /**/
?H:?%<:#endif
?H:#define NVSIZE $nvsize /**/
?H:#$d_nv_preserves_uv NV_PRESERVES_UV
-?H:#define NV_PRESERVES_UV_BITS $d_nv_preserves_uv_bits
+?H:#define NV_PRESERVES_UV_BITS $nv_preserves_uv_bits
+?H:#define NV_OVERFLOWS_INTEGERS_AT ($nv_overflows_integers_at)
+?H:#$d_nv_zero_is_allbits_zero NV_ZERO_IS_ALLBITS_ZERO
+?H:?%<:#if UVSIZE == 8
+?H:?%<:# ifdef BYTEORDER
+?H:?%<:# if BYTEORDER == 0x1234
+?H:?%<:# undef BYTEORDER
+?H:?%<:# define BYTEORDER 0x12345678
+?H:?%<:# else
+?H:?%<:# if BYTEORDER == 0x4321
+?H:?%<:# undef BYTEORDER
+?H:?%<:# define BYTEORDER 0x87654321
+?H:?%<:# endif
+?H:?%<:# endif
+?H:?%<:# endif
+?H:?%<:#endif
?H:.
+?T:xxx
+?T:d
?F:!try
-?T:volatile
-
+: Check basic sizes
echo " "
$echo "Choosing the C types to be used for Perl's internal types..." >&4
;;
esac
+case "$usequadmath:$i_quadmath" in
+define:define)
+ nvtype="__float128"
+ nvsize=16
+ : libquadmath is not in the usual places, and the place
+ : changes if the compiler is upgraded. So ask the compiler if it
+ : can find it.
+ : We do not need to save this, if it fails we abort.
+ libs="$libs -lquadmath"
+ set try
+ $cat >try.c <<EOM
+#include <quadmath.h>
+#include <stdio.h>
+int main(int argc, char *argv[]) {
+ __float128 x = 1.0;
+ if (fabsq(logq(x)) > 1e-6) {
+ fputs("quadmath is broken\n", stderr);
+ return 1;
+ }
+ puts("define");
+ return 0;
+}
+EOM
+ yyy=''
+ if eval $compile_ok; then
+ yyy=`$run ./try`
+ case "$yyy" in
+ define) ;;
+ *) cat <<EOM >&4
+
+*** You requested the use of the quadmath library, but
+*** it appears to be nonfunctional.
+*** Cannot continue, aborting.
+
+EOM
+ exit 1
+ ;;
+ esac
+ else
+ $cat <<EOM >&4
+
+*** You requested the use of the quadmath library, but you
+*** do not seem to have the quadmath library installed.
+*** Cannot continue, aborting.
+EOM
+ exit 1
+ fi
+ ;;
+define:*) $cat <<EOM >&4
+
+*** You requested the use of the quadmath library, but you
+*** do not seem to have the required header, <quadmath.h>.
+EOM
+ case "$gccversion" in
+ [23].*|4.[0-5]*)
+ $cat <<EOM >&4
+*** Your gcc looks a bit old:
+*** $gccversion
+EOM
+ ;;
+ '')
+ $cat <<EOM >&4
+*** You are not running a gcc.
+EOM
+ ;;
+ esac
+ $cat <<EOM >&4
+*** For the quadmath library you need at least gcc 4.6.
+*** Cannot continue, aborting.
+EOM
+ exit 1
+ ;;
+esac
+
$echo "(IV will be "$ivtype", $ivsize bytes)"
$echo "(UV will be "$uvtype", $uvsize bytes)"
$echo "(NV will be "$nvtype", $nvsize bytes)"
#endif
#ifdef INT16
int16_t i = INT16_MAX;
- uint16_t i = UINT16_MAX;
+ uint16_t u = UINT16_MAX;
printf("int16_t\n");
#endif
#ifdef INT32
}
EOCP
-case "$i8type" in
-'') case "$charsize" in
- 1) i8type=char
- u8type="unsigned char"
- i8size=$charsize
- u8size=$charsize
- ;;
- esac
- ;;
-esac
-case "$i8type" in
-'') set try -DINT8
- if eval $compile; then
- case "`./try$exe_ext`" in
- int8_t) i8type=int8_t
- u8type=uint8_t
- i8size=1
- u8size=1
- ;;
- esac
- fi
- ;;
-esac
-case "$i8type" in
-'') if $test $charsize -ge 1; then
- i8type=char
- u8type="unsigned char"
- i8size=$charsize
- u8size=$charsize
- fi
- ;;
-esac
+i8type="signed char"
+u8type="unsigned char"
+i8size=1
+u8size=1
case "$i16type" in
'') case "$shortsize" in
case "$i16type" in
'') set try -DINT16
if eval $compile; then
- case "`./try$exe_ext`" in
+ case "`$run ./try`" in
int16_t)
i16type=int16_t
u16type=uint16_t
case "$i32type" in
'') set try -DINT32
if eval $compile; then
- case "`./try$exe_ext`" in
+ case "`$run ./try`" in
int32_t)
i32type=int32_t
u32type=uint32_t
esac
$echo "Checking how many bits of your UVs your NVs can preserve..." >&4
-: volatile so that the compiler has to store it out to memory.
-if test X"$d_volatile" = X"$define"; then
- volatile=volatile
-fi
$cat <<EOP >try.c
#include <stdio.h>
+#$i_stdlib I_STDLIB
+#ifdef I_STDLIB
+#include <stdlib.h>
+#endif
+#$i_inttypes I_INTTYPES
+#ifdef I_INTTYPES
+#include <inttypes.h>
+#endif
#include <sys/types.h>
#include <signal.h>
#ifdef SIGFPE
-$volatile int bletched = 0;
-$signal_t blech(s) int s; { bletched = 1; }
+/* volatile so that the compiler has to store it out to memory */
+volatile int bletched = 0;
+$signal_t blech(int s) { bletched = 1; }
#endif
int main() {
$uvtype u = 0;
if (($uvtype)d != (u - 1))
break;
#ifdef SIGFPE
- if (bletched) {
+ if (bletched)
break;
#endif
- }
}
printf("%d\n", ((i == n) ? -n : i));
exit(0);
d_nv_preserves_uv="$undef"
if eval $compile; then
- d_nv_preserves_uv_bits="`./try$exe_ext`"
+ nv_preserves_uv_bits="`$run ./try`"
fi
-case "$d_nv_preserves_uv_bits" in
-\-[1-9]*)
- d_nv_preserves_uv_bits=`expr 0 - $d_nv_preserves_uv_bits`
- $echo "Your NVs can preserve all $d_nv_preserves_uv_bits bits of your UVs." 2>&1
+case "$nv_preserves_uv_bits" in
+\-[1-9]*)
+ nv_preserves_uv_bits=`expr 0 - $nv_preserves_uv_bits`
+ $echo "Your NVs can preserve all $nv_preserves_uv_bits bits of your UVs." >&4
d_nv_preserves_uv="$define"
;;
-[1-9]*) $echo "Your NVs can preserve only $d_nv_preserves_uv_bits bits of your UVs." 2>&1
+[1-9]*) $echo "Your NVs can preserve only $nv_preserves_uv_bits bits of your UVs." >&4
d_nv_preserves_uv="$undef" ;;
-*) $echo "Can't figure out how many bits your NVs preserve." 2>&1
- d_nv_preserves_uv_bits="$undef" ;;
+*) $echo "Can't figure out how many bits your NVs preserve." >&4
+ nv_preserves_uv_bits="0" ;;
esac
+$rm_try
+
+$echo "Checking to find the largest integer value your NVs can hold..." >&4
+$cat <<EOP >try.c
+#include <stdio.h>
+
+typedef $nvtype NV;
+
+int
+main() {
+ NV value = 2;
+ int count = 1;
+
+ while(count < 256) {
+ /* volatile so that the compiler has to store it out to memory */
+ volatile NV up = value + 1.0;
+ volatile NV negated = -value;
+ volatile NV down = negated - 1.0;
+ volatile NV got_up = up - value;
+ int up_good = got_up == 1.0;
+ int got_down = down - negated;
+ int down_good = got_down == -1.0;
+
+ if (down_good != up_good) {
+ fprintf(stderr,
+ "Inconsistency - up %d %f; down %d %f; for 2**%d (%.20f)\n",
+ up_good, (double) got_up, down_good, (double) got_down,
+ count, (double) value);
+ return 1;
+ }
+ if (!up_good) {
+ while (1) {
+ if (count > 8) {
+ count -= 8;
+ fputs("256.0", stdout);
+ } else {
+ count--;
+ fputs("2.0", stdout);
+ }
+ if (!count) {
+ puts("");
+ return 0;
+ }
+ fputs("*", stdout);
+ }
+ }
+ value *= 2;
+ ++count;
+ }
+ fprintf(stderr, "Cannot overflow integer range, even at 2**%d (%.20f)\n",
+ count, (double) value);
+ return 1;
+}
+EOP
+set try
+
+nv_overflows_integers_at='0'
+if eval $compile; then
+ xxx="`$run ./try`"
+ case "$?" in
+ 0)
+ case "$xxx" in
+ 2*) cat >&4 <<EOM
+The largest integer your NVs can preserve is equal to $xxx
+EOM
+ nv_overflows_integers_at="$xxx"
+ ;;
+ *) cat >&4 <<EOM
+Cannot determine the largest integer value your NVs can hold, unexpected output
+'$xxx'
+EOM
+ ;;
+ esac
+ ;;
+ *) cat >&4 <<EOM
+Cannot determine the largest integer value your NVs can hold
+EOM
+ ;;
+ esac
+fi
+$rm_try
+
+$echo "Checking whether NV 0.0 is all bits zero in memory..." >&4
+$cat <<EOP >try.c
+#include <stdio.h>
+#$i_stdlib I_STDLIB
+#ifdef I_STDLIB
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <sys/types.h>
+#include <signal.h>
+#ifdef SIGFPE
+/* volatile so that the compiler has to store it out to memory */
+volatile int bletched = 0;
+$signal_t blech(int s) { bletched = 1; }
+#endif
+
+int checkit($nvtype d, const char *where) {
+ void *v = &d;
+ unsigned char *p = (unsigned char *)v;
+ unsigned char *end = p + sizeof(d);
+ int fail = 0;
+
+ while (p < end)
+ fail += *p++;
+
+ if (!fail)
+ return 0;
+
+ p = (unsigned char *)v;
+ printf("No - %s: 0x", where);
+ while (p < end)
+ printf ("%02X", *p++);
+ printf("\n");
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ $nvtype d = 0.0;
+ int fail = 0;
+ fail += checkit(d, "0.0");
+
+ /* The compiler shouldn't be assuming that bletched is 0 */
+ d = bletched;
-$rm -f try.* try
+ fail += checkit(d, "bleched");
+
+#ifdef SIGFPE
+ signal(SIGFPE, blech);
+#endif
+
+ /* Paranoia - the compiler should have no way of knowing that ANSI says
+ that argv[argc] will always be NULL. Actually, if it did assume this it
+ would be buggy, as this is C and main() can be called from elsewhere in
+ the program. */
+ d = argv[argc] ? 1 : 0;
+
+ if (d) {
+ printf("Odd argv[argc]=%p, d=%g\n", argv[argc], d);
+ }
+
+ fail += checkit(d, "ternary");
+
+ memset(&d, sizeof(d), argv[argc] ? 1 : 0);
+
+ if (d != 0.0) {
+ printf("No - memset doesn't give 0.0\n");
+ /* This might just blow up: */
+ printf("(gives %g)\n", d);
+ return 1;
+ }
+
+#ifdef SIGFPE
+ if (bletched) {
+ printf("No - something bleched\n");
+ return 1;
+ }
+#endif
+ if (fail) {
+ printf("No - %d fail(s)\n", fail);
+ return 1;
+ }
+ printf("Yes\n");
+ return 0;
+}
+EOP
+set try
+
+d_nv_zero_is_allbits_zero="$undef"
+if eval $compile; then
+ xxx="`$run ./try`"
+ case "$?" in
+ 0)
+ case "$xxx" in
+ Yes) cat >&4 <<EOM
+0.0 is represented as all bits zero in memory
+EOM
+ d_nv_zero_is_allbits_zero="$define"
+ ;;
+ *) cat >&4 <<EOM
+0.0 is not represented as all bits zero in memory
+EOM
+ d_nv_zero_is_allbits_zero="$undef"
+ ;;
+ esac
+ ;;
+ *) cat >&4 <<EOM
+0.0 is not represented as all bits zero in memory
+EOM
+ d_nv_zero_is_allbits_zero="$undef"
+ ;;
+ esac
+fi
+$rm_try