Home | History | Annotate | Line # | Download | only in m4
      1      1.1  christos # exponentl.m4 serial 5
      2  1.1.1.2  christos dnl Copyright (C) 2007-2022 Free Software Foundation, Inc.
      3      1.1  christos dnl This file is free software; the Free Software Foundation
      4      1.1  christos dnl gives unlimited permission to copy and/or distribute it,
      5      1.1  christos dnl with or without modifications, as long as this notice is preserved.
      6      1.1  christos AC_DEFUN([gl_LONG_DOUBLE_EXPONENT_LOCATION],
      7      1.1  christos [
      8      1.1  christos   AC_REQUIRE([gl_BIGENDIAN])
      9      1.1  christos   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
     10      1.1  christos   AC_CACHE_CHECK([where to find the exponent in a 'long double'],
     11      1.1  christos     [gl_cv_cc_long_double_expbit0],
     12      1.1  christos     [
     13      1.1  christos       AC_RUN_IFELSE(
     14      1.1  christos         [AC_LANG_SOURCE([[
     15      1.1  christos #include <float.h>
     16      1.1  christos #include <stddef.h>
     17      1.1  christos #include <stdio.h>
     18      1.1  christos #include <string.h>
     19      1.1  christos #define NWORDS \
     20      1.1  christos   ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
     21      1.1  christos typedef union { long double value; unsigned int word[NWORDS]; }
     22      1.1  christos         memory_long_double;
     23      1.1  christos static unsigned int ored_words[NWORDS];
     24      1.1  christos static unsigned int anded_words[NWORDS];
     25      1.1  christos static void add_to_ored_words (long double *x)
     26      1.1  christos {
     27      1.1  christos   memory_long_double m;
     28      1.1  christos   size_t i;
     29      1.1  christos   /* Clear it first, in case
     30      1.1  christos      sizeof (long double) < sizeof (memory_long_double).  */
     31      1.1  christos   memset (&m, 0, sizeof (memory_long_double));
     32      1.1  christos   m.value = *x;
     33      1.1  christos   for (i = 0; i < NWORDS; i++)
     34      1.1  christos     {
     35      1.1  christos       ored_words[i] |= m.word[i];
     36      1.1  christos       anded_words[i] &= m.word[i];
     37      1.1  christos     }
     38      1.1  christos }
     39      1.1  christos int main ()
     40      1.1  christos {
     41      1.1  christos   static long double samples[5] = { 0.25L, 0.5L, 1.0L, 2.0L, 4.0L };
     42      1.1  christos   size_t j;
     43      1.1  christos   FILE *fp = fopen ("conftest.out", "w");
     44      1.1  christos   if (fp == NULL)
     45      1.1  christos     return 1;
     46      1.1  christos   for (j = 0; j < NWORDS; j++)
     47      1.1  christos     anded_words[j] = ~ (unsigned int) 0;
     48      1.1  christos   for (j = 0; j < 5; j++)
     49      1.1  christos     add_to_ored_words (&samples[j]);
     50      1.1  christos   /* Remove bits that are common (e.g. if representation of the first mantissa
     51      1.1  christos      bit is explicit).  */
     52      1.1  christos   for (j = 0; j < NWORDS; j++)
     53      1.1  christos     ored_words[j] &= ~anded_words[j];
     54      1.1  christos   /* Now find the nonzero word.  */
     55      1.1  christos   for (j = 0; j < NWORDS; j++)
     56      1.1  christos     if (ored_words[j] != 0)
     57      1.1  christos       break;
     58      1.1  christos   if (j < NWORDS)
     59      1.1  christos     {
     60      1.1  christos       size_t i;
     61      1.1  christos       for (i = j + 1; i < NWORDS; i++)
     62      1.1  christos         if (ored_words[i] != 0)
     63      1.1  christos           {
     64      1.1  christos             fprintf (fp, "unknown");
     65      1.1  christos             return (fclose (fp) != 0);
     66      1.1  christos           }
     67      1.1  christos       for (i = 0; ; i++)
     68      1.1  christos         if ((ored_words[j] >> i) & 1)
     69      1.1  christos           {
     70      1.1  christos             fprintf (fp, "word %d bit %d", (int) j, (int) i);
     71      1.1  christos             return (fclose (fp) != 0);
     72      1.1  christos           }
     73      1.1  christos     }
     74      1.1  christos   fprintf (fp, "unknown");
     75      1.1  christos   return (fclose (fp) != 0);
     76      1.1  christos }
     77      1.1  christos         ]])],
     78      1.1  christos         [gl_cv_cc_long_double_expbit0=`cat conftest.out`],
     79      1.1  christos         [gl_cv_cc_long_double_expbit0="unknown"],
     80      1.1  christos         [
     81      1.1  christos           dnl When cross-compiling, in general we don't know. It depends on the
     82      1.1  christos           dnl ABI and compiler version. There are too many cases.
     83      1.1  christos           gl_cv_cc_long_double_expbit0="unknown"
     84      1.1  christos           case "$host_os" in
     85      1.1  christos             mingw*) # On native Windows (little-endian), we know the result
     86      1.1  christos                     # in two cases: mingw, MSVC.
     87      1.1  christos               AC_EGREP_CPP([Known], [
     88      1.1  christos #ifdef __MINGW32__
     89      1.1  christos  Known
     90      1.1  christos #endif
     91      1.1  christos                 ], [gl_cv_cc_long_double_expbit0="word 2 bit 0"])
     92      1.1  christos               AC_EGREP_CPP([Known], [
     93      1.1  christos #ifdef _MSC_VER
     94      1.1  christos  Known
     95      1.1  christos #endif
     96      1.1  christos                 ], [gl_cv_cc_long_double_expbit0="word 1 bit 20"])
     97      1.1  christos               ;;
     98      1.1  christos           esac
     99      1.1  christos         ])
    100      1.1  christos       rm -f conftest.out
    101      1.1  christos     ])
    102      1.1  christos   case "$gl_cv_cc_long_double_expbit0" in
    103      1.1  christos     word*bit*)
    104      1.1  christos       word=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
    105      1.1  christos       bit=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word.*bit //'`
    106      1.1  christos       AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_WORD], [$word],
    107      1.1  christos         [Define as the word index where to find the exponent of 'long double'.])
    108      1.1  christos       AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_BIT], [$bit],
    109      1.1  christos         [Define as the bit index in the word where to find bit 0 of the exponent of 'long double'.])
    110      1.1  christos       ;;
    111      1.1  christos   esac
    112      1.1  christos ])
    113