📄 gmp-impl.h
字号:
/* ASSERT_CODE includes code when assertion checking is wanted. This is the
same as writing "#if WANT_ASSERT", but more compact. */
#if WANT_ASSERT
#define ASSERT_CODE(expr) expr
#else
#define ASSERT_CODE(expr)
#endif
/* Test that an mpq_t is in fully canonical form. This can be used as
protection on routines like mpq_equal which give wrong results on
non-canonical inputs. */
#if WANT_ASSERT
#define ASSERT_MPQ_CANONICAL(q) \
do { \
ASSERT (q->_mp_den._mp_size > 0); \
if (q->_mp_num._mp_size == 0) \
{ \
/* zero should be 0/1 */ \
ASSERT (mpz_cmp_ui (mpq_denref(q), 1L) == 0); \
} \
else \
{ \
/* no common factors */ \
mpz_t __g; \
mpz_init (__g); \
mpz_gcd (__g, mpq_numref(q), mpq_denref(q)); \
ASSERT (mpz_cmp_ui (__g, 1) == 0); \
mpz_clear (__g); \
} \
} while (0)
#else
#define ASSERT_MPQ_CANONICAL(q) do {} while (0)
#endif
/* Check that the nail parts are zero. */
#define ASSERT_ALWAYS_LIMB(limb) \
do { \
mp_limb_t __nail = (limb) & GMP_NAIL_MASK; \
ASSERT_ALWAYS (__nail == 0); \
} while (0)
#define ASSERT_ALWAYS_MPN(ptr, size) \
do { \
/* let whole loop go dead when no nails */ \
if (GMP_NAIL_BITS != 0) \
{ \
mp_size_t __i; \
for (__i = 0; __i < (size); __i++) \
ASSERT_ALWAYS_LIMB ((ptr)[__i]); \
} \
} while (0)
#if WANT_ASSERT
#define ASSERT_LIMB(limb) ASSERT_ALWAYS_LIMB (limb)
#define ASSERT_MPN(ptr, size) ASSERT_ALWAYS_MPN (ptr, size)
#else
#define ASSERT_LIMB(limb) do {} while (0)
#define ASSERT_MPN(ptr, size) do {} while (0)
#endif
/* Assert that an mpn region {ptr,size} is zero, or non-zero.
size==0 is allowed, and in that case {ptr,size} considered to be zero. */
#if WANT_ASSERT
#define ASSERT_MPN_ZERO_P(ptr,size) \
do { \
mp_size_t __i; \
ASSERT ((size) >= 0); \
for (__i = 0; __i < (size); __i++) \
ASSERT ((ptr)[__i] == 0); \
} while (0)
#define ASSERT_MPN_NONZERO_P(ptr,size) \
do { \
mp_size_t __i; \
int __nonzero = 0; \
ASSERT ((size) >= 0); \
for (__i = 0; __i < (size); __i++) \
if ((ptr)[__i] != 0) \
{ \
__nonzero = 1; \
break; \
} \
ASSERT (__nonzero); \
} while (0)
#else
#define ASSERT_MPN_ZERO_P(ptr,size) do {} while (0)
#define ASSERT_MPN_NONZERO_P(ptr,size) do {} while (0)
#endif
#if HAVE_NATIVE_mpn_com_n
#define mpn_com_n __MPN(com_n)
void mpn_com_n _PROTO ((mp_ptr, mp_srcptr, mp_size_t));
#else
#define mpn_com_n(d,s,n) \
do { \
mp_ptr __d = (d); \
mp_srcptr __s = (s); \
mp_size_t __n = (n); \
ASSERT (__n >= 1); \
ASSERT (MPN_SAME_OR_SEPARATE_P (__d, __s, __n)); \
do \
*__d++ = (~ *__s++) & GMP_NUMB_MASK; \
while (--__n); \
} while (0)
#endif
#define MPN_LOGOPS_N_INLINE(d, s1, s2, n, operation) \
do { \
mp_ptr __d = (d); \
mp_srcptr __s1 = (s1); \
mp_srcptr __s2 = (s2); \
mp_size_t __n = (n); \
ASSERT (__n >= 1); \
ASSERT (MPN_SAME_OR_SEPARATE_P (__d, __s1, __n)); \
ASSERT (MPN_SAME_OR_SEPARATE_P (__d, __s2, __n)); \
do \
operation; \
while (--__n); \
} while (0)
#if HAVE_NATIVE_mpn_and_n
#define mpn_and_n __MPN(and_n)
void mpn_and_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_and_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = *__s1++ & *__s2++)
#endif
#if HAVE_NATIVE_mpn_andn_n
#define mpn_andn_n __MPN(andn_n)
void mpn_andn_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_andn_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = *__s1++ & ~*__s2++)
#endif
#if HAVE_NATIVE_mpn_nand_n
#define mpn_nand_n __MPN(nand_n)
void mpn_nand_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_nand_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = ~ (*__s1++ & *__s2++))
#endif
#if HAVE_NATIVE_mpn_ior_n
#define mpn_ior_n __MPN(ior_n)
void mpn_ior_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_ior_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = *__s1++ | *__s2++)
#endif
#if HAVE_NATIVE_mpn_iorn_n
#define mpn_iorn_n __MPN(iorn_n)
void mpn_iorn_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_iorn_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = *__s1++ | ~*__s2++)
#endif
#if HAVE_NATIVE_mpn_nior_n
#define mpn_nior_n __MPN(nior_n)
void mpn_nior_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_nior_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = ~ (*__s1++ | *__s2++))
#endif
#if HAVE_NATIVE_mpn_xor_n
#define mpn_xor_n __MPN(xor_n)
void mpn_xor_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_xor_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = *__s1++ ^ *__s2++)
#endif
#if HAVE_NATIVE_mpn_xnor_n
#define mpn_xnor_n __MPN(xnor_n)
void mpn_xnor_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
#else
#define mpn_xnor_n(d, s1, s2, n) \
MPN_LOGOPS_N_INLINE (d, s1, s2, n, *__d++ = ~ (*__s1++ ^ *__s2++))
#endif
/* SUBC_LIMB sets w=x-y and cout to 0 or 1 for a borrow from that
subtract. */
#if GMP_NAIL_BITS == 0
#define SUBC_LIMB(cout, w, x, y) \
do { \
mp_limb_t __x = (x); \
mp_limb_t __y = (y); \
mp_limb_t __w = __x - __y; \
(w) = __w; \
(cout) = __w > __x; \
} while (0)
#else
#define SUBC_LIMB(cout, w, x, y) \
do { \
mp_limb_t __w = (x) - (y); \
(w) = __w & GMP_NUMB_MASK; \
(cout) = __w >> (GMP_LIMB_BITS-1); \
} while (0)
#endif
/* MPN_INCR_U does {ptr,size} += n, MPN_DECR_U does {ptr,size} -= n, both
expecting no carry (or borrow) from that.
The size parameter is only for the benefit of assertion checking. In a
normal build it's unused and the carry/borrow is just propagated as far
as it needs to go.
On random data, usually only one or two limbs of {ptr,size} get updated,
so there's no need for any sophisticated looping, just something compact
and sensible.
FIXME: Do the generic MPN_{INCR,DECR}_U with a block of code like
mpn_incr_u but with the assertions built in, rather than the separate
add_1 and sub_1 when assertion checking.
FIXME: Switch all code from mpn_{incr,decr}_u to MPN_{INCR,DECR}_U,
declaring their operand sizes, then remove the former. This is purely
for the benefit of assertion checking. */
#if defined (__GNUC__) && HAVE_HOST_CPU_FAMILY_x86 && GMP_NAIL_BITS == 0 \
&& BITS_PER_MP_LIMB == 32 && ! defined (NO_ASM) && ! WANT_ASSERT
/* Better flags handling than the generic C gives on i386, saving a few
bytes of code and maybe a cycle or two. */
#define MPN_IORD_U(ptr, incr, aors) \
do { \
mp_ptr __ptr_dummy; \
if (__builtin_constant_p (incr) && (incr) == 1) \
{ \
__asm__ __volatile__ \
("\n" ASM_L(top) ":\n" \
"\t" aors " $1, (%0)\n" \
"\tleal 4(%0),%0\n" \
"\tjc " ASM_L(top) \
: "=r" (__ptr_dummy) \
: "0" (ptr) \
: "memory"); \
} \
else \
{ \
__asm__ __volatile__ \
( aors " %2,(%0)\n" \
"\tjnc " ASM_L(done) "\n" \
ASM_L(top) ":\n" \
"\t" aors " $1,4(%0)\n" \
"\tleal 4(%0),%0\n" \
"\tjc " ASM_L(top) "\n" \
ASM_L(done) ":\n" \
: "=r" (__ptr_dummy) \
: "0" (ptr), \
"ri" (incr) \
: "memory"); \
} \
} while (0)
#define MPN_INCR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "addl")
#define MPN_DECR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "subl")
#define mpn_incr_u(ptr, incr) MPN_INCR_U (ptr, 0, incr)
#define mpn_decr_u(ptr, incr) MPN_DECR_U (ptr, 0, incr)
#endif
#if GMP_NAIL_BITS == 0
#ifndef mpn_incr_u
#define mpn_incr_u(p,incr) \
do { \
mp_limb_t __x; \
mp_ptr __p = (p); \
if (__builtin_constant_p (incr) && (incr) == 1) \
{ \
while (++(*(__p++)) == 0) \
; \
} \
else \
{ \
__x = *__p + (incr); \
*__p = __x; \
if (__x < (incr)) \
while (++(*(++__p)) == 0) \
; \
} \
} while (0)
#endif
#ifndef mpn_decr_u
#define mpn_decr_u(p,incr) \
do { \
mp_limb_t __x; \
mp_ptr __p = (p); \
if (__builtin_constant_p (incr) && (incr) == 1) \
{ \
while ((*(__p++))-- == 0) \
; \
} \
else \
{ \
__x = *__p; \
*__p = __x - (incr); \
if (__x < (incr)) \
while ((*(++__p))-- == 0) \
; \
} \
} while (0)
#endif
#endif
#if GMP_NAIL_BITS >= 1
#ifndef mpn_incr_u
#define mpn_incr_u(p,incr) \
do { \
mp_limb_t __x; \
mp_ptr __p = (p); \
if (__builtin_constant_p (incr) && (incr) == 1) \
{ \
do \
{ \
__x = (*__p + 1) & GMP_NUMB_MASK; \
*__p++ = __x; \
} \
while (__x == 0); \
} \
else \
{ \
__x = (*__p + (incr)); \
*__p++ = __x & GMP_NUMB_MASK; \
if (__x >> GMP_NUMB_BITS != 0) \
{ \
do \
{ \
__x = (*__p + 1) & GMP_NUMB_MASK; \
*__p++ = __x; \
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -