text: /* Check the values of some constants.
  
  Copyright 2000-2003, 2014 Free Software Foundation, Inc.
  
  This file is part of the GNU MP Library test suite.
  
  The GNU MP Library test suite is free software; you can redistribute it
  and/or modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 3 of the License,
  or (at your option) any later version.
  
  The GNU MP Library test suite is distributed in the hope that it will be
  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  Public License for more details.
  
  You should have received a copy of the GNU General Public License along with
  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
  
  #include <stdio.h>
  #include <stdlib.h>
  #include "gmp-impl.h"
  #include "tests.h"
  
  
  #ifdef ULONG_MAX
  const char *ulong_max_def = "defined";
  #else
  const char *ulong_max_def = "not defined";
  #endif
  #ifdef LONG_MAX
  const char *long_max_def = "defined";
  #else
  const char *long_max_def = "not defined";
  #endif
  
  #ifdef UINT_MAX
  const char *uint_max_def = "defined";
  #else
  const char *uint_max_def = "not defined";
  #endif
  #ifdef INT_MAX
  const char *int_max_def = "defined";
  #else
  const char *int_max_def = "not defined";
  #endif
  
  #ifdef USHRT_MAX
  const char *ushrt_max_def = "defined";
  #else
  const char *ushrt_max_def = "not defined";
  #endif
  #ifdef SHRT_MAX
  const char *shrt_max_def = "defined";
  #else
  const char *shrt_max_def = "not defined";
  #endif
  
  #include "gmp-impl.h"
  #include "longlong.h"
  
  
  #ifdef _LONG_LONG_LIMB
  #define LL(l,ll)  ll
  #else
  #define LL(l,ll)  l
  #endif
  
  #if __GMP_MP_SIZE_T_INT
  #define SS(i,l)   i
  #else
  #define SS(i,l)   l
  #endif
  
  
  #define CHECK_LIMB_S(x, xname, y, yname)                \
    do {                                                  \
      if ((x) != (y))                                     \
        {                                                 \
          printf (LL("%s == %lx, but %s == %lx\n",        \
                     "%s == %llx, but %s == %llx\n"),     \
                  xname, x, yname, y);                    \
          error = 1;                                      \
        }                                                 \
    } while (0)
  
  #define CHECK_INT_S(x, xname, y, yname)                                 \
    do {                                                                  \
      if ((x) != (y))                                                     \
        {                                                                 \
          printf ("%s == %d, but %s == %d\n", xname, x, yname, y);        \
          error = 1;                                                      \
        }                                                                 \
    } while (0)
  
  
  
  #define CHECK_CONDITION_S(x, xname)             \
    do {                                          \
      if (!(x))                                   \
        {                                         \
          printf ("%s is false\n", xname);        \
          error = 1;                              \
        }                                         \
    } while (0)
  
  
  /* How many bits seem to work in the given type. */
  #define CALC_BITS(result, type) \
    do {                          \
      type  n = 1;                \
      result = 0;                 \
      while (n != 0)              \
        {                         \
          n <<= 1;                \
          result++;               \
        }                         \
    } while (0)
  
  #define CHECK_BITS_S(constant, constant_name, type)     \
    do {                                                  \
      int   calculated;                                   \
      CALC_BITS (calculated, type);                       \
      if (calculated != constant)                         \
        {                                                 \
          printf ("%s == %d, but calculated %d\n",        \
                  constant_name, constant, calculated);   \
          error = 1;                                      \
        }                                                 \
    } while (0)
  
  
  #define CHECK_HIGHBIT_S(value, value_name, type, format)        \
    do {                                                          \
      type  n = value;                                            \
      if (n == 0)                                                 \
        {                                                         \
          printf ("%s == 0\n", value_name);                       \
          error = 1;                                              \
        }                                                         \
      n <<= 1;                                                    \
      if (n != 0)                                                 \
        {                                                         \
          printf ("%s << 1 = ", value_name);                      \
          printf (format, n);                                     \
          printf (" != 0\n");                                     \
          error = 1;                                              \
        }                                                         \
    } while (0)
  
  
  #define CHECK_MAX_S(max_val, max_name, min_val, min_name, type, format) \
    do {                                                                  \
      type  maxval = max_val;                                             \
      type  minval = min_val;                                             \
      type  n = maxval;                                                   \
      n++;                                                                \
      if (n != minval)                                                    \
        {                                                                 \
          printf ("%s + 1 = ", max_name);                                 \
          printf (format, n);                                             \
          printf (" != %s = ", min_name);                                 \
          printf (format, minval);                                        \
          printf ("\n");                                                  \
          error = 1;                                                      \
        }                                                                 \
      if (maxval <= minval)                                               \
        {                                                                 \
          printf ("%s = ", max_name);                                     \
          printf (format, maxval);                                        \
          printf (" <= %s = ", min_name);                                 \
          printf (format, minval);                                        \
          printf ("\n");                                                  \
          error = 1;                                                      \
        }                                                                 \
    } while (0)
  
  
  #define CHECK_LIMB(x,y)      CHECK_LIMB_S (x, #x, y, #y)
  #define CHECK_INT(x,y)       CHECK_INT_S (x, #x, y, #y)
  #define CHECK_CONDITION(x)   CHECK_CONDITION_S (x, #x)
  #define CHECK_BITS(c,t)      CHECK_BITS_S (c, #c, t)
  #define CHECK_MAX(m,n,t,f)   CHECK_MAX_S (m, #m, n, #n, t, f)
  #define CHECK_HIGHBIT(n,t,f) CHECK_HIGHBIT_S (n, #n, t, f)
  
  
  /* The tests below marked "Bad!" fail on Cray T90 systems, where int, short
     and mp_size_t are 48 bits or some such but don't wraparound in a plain
     twos complement fashion.  In particular,
  
         INT_HIGHBIT << 1 = 0xFFFFC00000000000 != 0
         INT_MAX + 1 = 35184372088832 != INT_MIN = -35184372088832
  
     This is a bit bizarre, but doesn't matter because GMP doesn't rely on any
     particular overflow behaviour for int or short, only for mp_limb_t.  */
  
  int
  main (int argc, char *argv[])
  {
    int  error = 0;
  
    CHECK_INT (GMP_LIMB_BYTES, (int) sizeof(mp_limb_t));
    CHECK_INT (mp_bits_per_limb, GMP_LIMB_BITS);
  
    CHECK_BITS (GMP_LIMB_BITS, mp_limb_t);
    CHECK_BITS (BITS_PER_ULONG, unsigned long);
  
    CHECK_HIGHBIT (GMP_LIMB_HIGHBIT, mp_limb_t,      LL("0x%lX","0x%llX"));
    CHECK_HIGHBIT (ULONG_HIGHBIT,     unsigned long,  "0x%lX");
    CHECK_HIGHBIT (UINT_HIGHBIT,      unsigned int,   "0x%X");
    CHECK_HIGHBIT (USHRT_HIGHBIT,     unsigned short, "0x%hX");
  #if 0 /* Bad! */
    CHECK_HIGHBIT (LONG_HIGHBIT,      long,           "0x%lX");
    CHECK_HIGHBIT (INT_HIGHBIT,       int,            "0x%X");
    CHECK_HIGHBIT (SHRT_HIGHBIT,      short,          "0x%hX");
  #endif
  
  #if 0 /* Bad! */
    CHECK_MAX (LONG_MAX,      LONG_MIN,      long,           "%ld");
    CHECK_MAX (INT_MAX,       INT_MIN,       int,            "%d");
    CHECK_MAX (SHRT_MAX,      SHRT_MIN,      short,          "%hd");
  #endif
    CHECK_MAX (ULONG_MAX,     0,             unsigned long,  "%lu");
    CHECK_MAX (UINT_MAX,      0,             unsigned int,   "%u");
    CHECK_MAX (USHRT_MAX,     0,             unsigned short, "%hu");
  #if 0 /* Bad! */
    CHECK_MAX (MP_SIZE_T_MAX, MP_SIZE_T_MIN, mp_size_t,      SS("%d","%ld"));
  #endif
  
    /* UHWtype should have at least enough bits for half a UWtype */
    {
      int  bits_per_UWtype, bits_per_UHWtype;
      CALC_BITS (bits_per_UWtype,  UWtype);
      CALC_BITS (bits_per_UHWtype, UHWtype);
      CHECK_CONDITION (2*bits_per_UHWtype >= bits_per_UWtype);
    }
  
    ASSERT_ALWAYS_LIMB (MODLIMB_INVERSE_3);
    {
      mp_limb_t  modlimb_inverse_3_calc;
      binvert_limb (modlimb_inverse_3_calc, CNST_LIMB(3));
      ASSERT_ALWAYS_LIMB (modlimb_inverse_3_calc);
      CHECK_LIMB (MODLIMB_INVERSE_3, modlimb_inverse_3_calc);
    }
    {
      mp_limb_t  MODLIMB_INVERSE_3_times_3
        = (MODLIMB_INVERSE_3 * CNST_LIMB(3)) & GMP_NUMB_MASK;
      CHECK_LIMB (MODLIMB_INVERSE_3_times_3, CNST_LIMB(1));
    }
  
    {
      mp_limb_t  hi, lo;
      hi = refmpn_umul_ppmm (&lo, GMP_NUMB_CEIL_MAX_DIV3-1,
                             CNST_LIMB(3) << GMP_NAIL_BITS);
      if (! (hi < 1))
        {
          printf ("GMP_NUMB_CEIL_MAX_DIV3 too big\n");
          error = 1;
        }
      hi = refmpn_umul_ppmm (&lo, GMP_NUMB_CEIL_MAX_DIV3,
                             CNST_LIMB(3) << GMP_NAIL_BITS);
      if (! (hi >= 1))
        {
          printf ("GMP_NUMB_CEIL_MAX_DIV3 too small\n");
          error = 1;
        }
    }
  
    {
      mp_limb_t  hi, lo;
      hi = refmpn_umul_ppmm (&lo, GMP_NUMB_CEIL_2MAX_DIV3-1,
                             CNST_LIMB(3) << GMP_NAIL_BITS);
      if (! (hi < 2))
        {
          printf ("GMP_NUMB_CEIL_2MAX_DIV3 too big\n");
          error = 1;
        }
      hi = refmpn_umul_ppmm (&lo, GMP_NUMB_CEIL_2MAX_DIV3,
                             CNST_LIMB(3) << GMP_NAIL_BITS);
      if (! (hi >= 2))
        {
          printf ("GMP_NUMB_CEIL_2MAX_DIV3 too small\n");
          error = 1;
        }
    }
  
  #ifdef PP_INVERTED
    {
      mp_limb_t  pp_inverted_calc;
      invert_limb (pp_inverted_calc, PP);
      CHECK_LIMB (PP_INVERTED, pp_inverted_calc);
    }
  #endif
  
    if (argc >= 2 || error)
      {
        int  bits;
  
        printf ("\n");
        printf ("After gmp.h,\n");
        printf ("  ULONG_MAX  %s\n", ulong_max_def);
        printf ("  LONG_MAX   %s\n", long_max_def);
        printf ("  UINT_MAX   %s\n", uint_max_def);
        printf ("  INT_MAX    %s\n", int_max_def);
        printf ("  USHRT_MAX  %s\n", ushrt_max_def);
        printf ("  SHRT_MAX   %s\n", shrt_max_def);
        printf ("\n");
  
  #ifdef _CRAY
        printf ("_CRAY is defined, so limits.h is being used\n");
  #endif
  
        printf ("ULONG_MAX      %lX\n", ULONG_MAX);
        printf ("ULONG_HIGHBIT  %lX\n", ULONG_HIGHBIT);
        printf ("LONG_MAX       %lX\n", LONG_MAX);
        printf ("LONG_MIN       %lX\n", LONG_MIN);
  
        printf ("UINT_MAX       %X\n", UINT_MAX);
        printf ("UINT_HIGHBIT   %X\n", UINT_HIGHBIT);
        printf ("INT_MAX        %X\n", INT_MAX);
        printf ("INT_MIN        %X\n", INT_MIN);
  
        printf ("USHRT_MAX      %X\n", USHRT_MAX);
        printf ("USHRT_HIGHBIT  %X\n", USHRT_HIGHBIT);
        printf ("SHRT_MAX       %X\n", SHRT_MAX);
        printf ("SHRT_MIN       %X\n", SHRT_MIN);
  
        printf ("\n");
        printf ("Bits\n");
        CALC_BITS (bits, long);           printf ("  long           %d\n", bits);
        CALC_BITS (bits, int);            printf ("  int            %d\n", bits);
        CALC_BITS (bits, short);          printf ("  short          %d\n", bits);
        CALC_BITS (bits, unsigned long);  printf ("  unsigned long  %d\n", bits);
        CALC_BITS (bits, unsigned int);   printf ("  unsigned int   %d\n", bits);
        CALC_BITS (bits, unsigned short); printf ("  unsigned short %d\n", bits);
        CALC_BITS (bits, mp_size_t);      printf ("  mp_size_t      %d\n", bits);
      }
  
    if (error)
      abort ();
  
    exit (0);
  }
  