progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / math / mpint.h
index f551980..a5ab3df 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <limits.h>
 
+#include <mLib/macros.h>
+
 #ifndef CATACOMB_MP_H
 #  include "mp.h"
 #endif
  *
  * GCC (at least) isn't clever enough to work out that the division in
  * @MP_FROMINT@ is actually safe (since it will only be executed if @_i >
- * MPW_MAX@, which would prove that @(type)MPW_MAX + 1 != 0@).  So here's
- * some machinery to shut it up.
+ * MPW_MAX@, which would prove that @(type)MPW_MAX + 1 != 0@).
  */
 
-#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
-#  define MP_FROMINT_MUFFLE_WARNING(x) do {                            \
-       _Pragma("GCC diagnostic push")                                  \
-       _Pragma("GCC diagnostic ignored \"-Wdiv-by-zero\"")             \
-       x                                                               \
-       _Pragma("GCC diagnostic pop")                                   \
-   } while (0)
-#else
-#  define MP_FROMINT_MUFFLE_WARNING(x) do { x } while (0)
-#endif
-
 /* --- @MP_FROMINT@ --- *
  *
  * Arguments:  @d@ = destination multiprecision integer
        MP_ENSURE(_d, _sz);                                             \
       }                                                                        \
       _d->v[_o++] = MPW(_i);                                           \
-      if (_i <= MPW_MAX)                                               \
+      if (MUFFLE_WARNINGS_EXPR(                                                \
+           CLANG_WARNING("-Wtautological-constant-out-of-range-compare"), \
+           _i <= MPW_MAX))                                             \
        break;                                                          \
       else                                                             \
-       MP_FROMINT_MUFFLE_WARNING({ _i /= (type)MPW_MAX + 1; });        \
+       MUFFLE_WARNINGS_STMT(GCC_WARNING("-Wdiv-by-zero")               \
+                            CLANG_WARNING("-Wdivision-by-zero"), {     \
+         _i /= (type)MPW_MAX + 1;                                      \
+       });                                                             \
     }                                                                  \
   } else {                                                             \
     _d->f |= MP_NEG;                                                   \
        MP_ENSURE(_d, _sz);                                             \
       }                                                                        \
       _d->v[_o++] = MPW(-_i);                                          \
-      if (_i >= -MPW_MAX)                                              \
+      if (MUFFLE_WARNINGS_EXPR(                                                \
+           CLANG_WARNING("-Wtautological-constant-out-of-range-compare"), \
+           _i >= -MPW_MAX))                                            \
        break;                                                          \
       else                                                             \
-       MP_FROMINT_MUFFLE_WARNING({ _i /= (type)MPW_MAX + 1; });        \
+       MUFFLE_WARNINGS_STMT(GCC_WARNING("-Wdiv-by-zero")               \
+                            CLANG_WARNING("-Wdivision-by-zero"), {     \
+         _i /= (type)MPW_MAX + 1;                                      \
+       });                                                             \
     }                                                                  \
   }                                                                    \
                                                                        \
   /* --- Do all the arithmetic in negative numbers --- */              \
                                                                        \
   while (_v < _vl && _max > 0) {                                       \
-    _i -= *_v << _s;                                                   \
+    _i -= (type)*_v << _s;                                             \
     _s += MPW_BITS;                                                    \
     _v++;                                                              \
     _max /= (mpd)MPW_MAX + 1;                                          \
 
 /*----- Functions provided ------------------------------------------------*/
 
+/* --- Build up the list of conversions to be supplied --- */
+
+#ifdef ULLONG_MAX
+#  ifndef LLONG_MAX
+#    define LLONG_MAX LONG_LONG_MAX
+#  endif
+#  define MPINT_CONV_LLONG(_)                                          \
+  _(llong, long long, LLONG_MAX)                                       \
+  _(ullong, unsigned long long, ULLONG_MAX)
+#else
+#  define MPINT_CONV_LLONG(_)
+#endif
+
+#ifdef INTMAX_MAX
+#  define MPINT_CONV_INTMAX(_)                                         \
+  _(intmax, intmax_t, INTMAX_MAX)                                      \
+  _(uintmax, uintmax_t, UINTMAX_MAX)
+#else
+#  define MPINT_CONV_INTMAX(_)
+#endif
+
+#ifdef HAVE_UINT64
+#  define MPINT_CONV_U64(_) _(uint64, uint64, MASK64)
+#else
+#  define MPINT_CONV_U64(_)
+#endif
+
+#define MPINT_CONVERSIONS(_)                                           \
+  _(short, short, SHRT_MAX)                                            \
+  _(ushort, unsigned short, USHRT_MAX)                                 \
+  _(int, int, INT_MAX)                                                 \
+  _(uint, unsigned, UINT_MAX)                                          \
+  _(long, long, LONG_MAX)                                              \
+  _(ulong, unsigned long, ULONG_MAX)                                   \
+  MPINT_CONV_LLONG(_)                                                  \
+  _(uint8, uint8, MASK8)                                               \
+  _(uint16, uint16, MASK16)                                            \
+  _(uint24, uint24, MASK24)                                            \
+  _(uint32, uint32, MASK32)                                            \
+  MPINT_CONV_U64(_)                                                    \
+  MPINT_CONV_INTMAX(_)                                                 \
+  _(sizet, size_t, (size_t)-1)
+
 /* --- @mp_fromINT@ --- *
  *
  * Arguments:  @mp *d@ = pointer to destination multiprecision integer
  * Use:                Converts a standard C integer to a multiprecision integer.
  */
 
-#define mp_fromINT(name, type)                                         \
-  extern mp *mp_from##name(mp */*d*/, type /*i*/)
-
-mp_fromINT(short, short);
-mp_fromINT(ushort, unsigned short);
-mp_fromINT(int, int);
-mp_fromINT(uint, unsigned);
-mp_fromINT(uint32, uint32);
-mp_fromINT(long, long);
-mp_fromINT(ulong, unsigned long);
-
+#define mp_fromINT(name, type, max)                                    \
+  extern mp *mp_from##name(mp */*d*/, type /*i*/);
+MPINT_CONVERSIONS(mp_fromINT)
 #undef mp_fromINT
 
 /* --- @mp_toINT@ --- *
@@ -187,17 +222,9 @@ mp_fromINT(ulong, unsigned long);
  *             type is signed, the behaviour is undefined.
  */
 
-#define mp_toINT(name, type)                                           \
-  extern type mp_to##name(const mp */*m*/)
-
-mp_toINT(short, short);
-mp_toINT(ushort, unsigned short);
-mp_toINT(int, int);
-mp_toINT(uint, unsigned);
-mp_toINT(uint32, uint32);
-mp_toINT(long, long);
-mp_toINT(ulong, unsigned long);
-
+#define mp_toINT(name, type, max)                                      \
+  extern type mp_to##name(const mp */*m*/);
+MPINT_CONVERSIONS(mp_toINT)
 #undef mp_toINT
 
 /*----- That's all, folks -------------------------------------------------*/