Files
MiniGmp-Verification/projects/mini-gmp.c
2025-05-27 16:09:30 +08:00

276 lines
5.0 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mini-gmp.h"
mp_size_t gmp_abs(mp_size_t x) {
return x >= 0 ? x : -x;
}
mp_size_t gmp_max(mp_size_t a, mp_size_t b) {
return a > b ? a : b;
}
int gmp_cmp(mp_size_t a, mp_size_t b) {
return (a > b) - (a < b);
}
/* MPN interface */
/* 从 低地址向高地址 顺序复制 */
void
mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n)
{
mp_size_t i;
for (i = 0; i < n; i++)
d[i] = s[i];
}
/* 大于返回1小于返回-1等于返回0 */
int
mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n)
{
while (--n >= 0)
{
if (ap[n] != bp[n])
return ap[n] > bp[n] ? 1 : -1;
}
return 0;
}
/*处理位数不同的情况*/
static int
mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
{
if (an != bn)
return an < bn ? -1 : 1;
else
return mpn_cmp (ap, bp, an);
}
/*返回非0的位数*/
static mp_size_t
mpn_normalized_size (mp_srcptr xp, mp_size_t n)
{
while (n > 0 && xp[n-1] == 0)
--n;
return n;
}
/* 多精度数ap 加上单精度数b返回最后产生的进位 */
mp_limb_t
mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
{
mp_size_t i;
//assert (n > 0);
i = 0;
do
{
mp_limb_t r = ap[i] + b;
/* Carry out */
b = (r < b);
rp[i] = r;
}
while (++i < n);
return b;
}
/* 位数相同的多精度数ap 加上多精度数bp返回最后产生的进位 */
mp_limb_t
mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
{
mp_size_t i;
mp_limb_t cy;
for (i = 0, cy = 0; i < n; i++)
{
mp_limb_t a, b, r;
a = ap[i]; b = bp[i];
r = a + cy;
cy = (r < cy);
r += b;
cy += (r < b);
rp[i] = r;
}
return cy;
}
/*不同位数的多精度数相加,返回最后的进位*/
mp_limb_t
mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
{
mp_limb_t cy;
//assert (an >= bn);
cy = mpn_add_n (rp, ap, bp, bn);
if (an > bn)
cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy);
return cy;
}
mp_limb_t
mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
{
mp_size_t i;
//assert (n > 0);
i = 0;
do
{
mp_limb_t a = ap[i];
/* Carry out */
mp_limb_t cy = a < b;
rp[i] = a - b;
b = cy;
}
while (++i < n);
return b;
}
mp_limb_t
mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
{
mp_size_t i;
mp_limb_t cy;
for (i = 0, cy = 0; i < n; i++)
{
mp_limb_t a, b;
a = ap[i]; b = bp[i];
b += cy;
cy = (b < cy);
cy += (a < b);
rp[i] = a - b;
}
return cy;
}
mp_limb_t
mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
{
mp_limb_t cy;
//assert (an >= bn);
cy = mpn_sub_n (rp, ap, bp, bn);
if (an > bn)
cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy);
return cy;
}
/* MPZ interface */
void
mpz_clear (mpz_t r)
{
if (r->_mp_alloc)
gmp_free_limbs (r->_mp_d, r->_mp_alloc);
}
static mp_ptr
mpz_realloc (mpz_t r, mp_size_t size)
{
size = gmp_max (size, 1);
if (r->_mp_alloc)
r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
else
r->_mp_d = gmp_alloc_limbs (size);
r->_mp_alloc = size;
if (gmp_abs (r->_mp_size) > size)
r->_mp_size = 0;
return r->_mp_d;
}
/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */
mp_ptr mrz_realloc_if(mpz_t z,mp_size_t n) {
return n > z->_mp_alloc ? mpz_realloc(z, n) : z->_mp_d;
}
/* MPZ comparisons and the like. */
int
mpz_sgn (const mpz_t u)
{
return gmp_cmp (u->_mp_size, 0);
}
void
mpz_swap (mpz_t u, mpz_t v)
{
mp_size_t_swap (u->_mp_alloc, v->_mp_alloc);
mp_ptr_swap(u->_mp_d, v->_mp_d);
mp_size_t_swap (u->_mp_size, v->_mp_size);
}
/* MPZ addition and subtraction */
static mp_size_t
mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b)
{
mp_size_t an = gmp_abs (a->_mp_size);
mp_size_t bn = gmp_abs (b->_mp_size);
mp_ptr rp;
mp_limb_t cy;
if (an < bn)
{
mpz_srcptr_swap (a, b);
mp_size_t_swap (an, bn);
}
rp = mrz_realloc_if (r, an + 1);
cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn);
rp[an] = cy;
return an + cy;
}
static mp_size_t
mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b)
{
mp_size_t an = gmp_abs (a->_mp_size);
mp_size_t bn = gmp_abs (b->_mp_size);
int cmp;
mp_ptr rp;
cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn);
if (cmp > 0)
{
rp = mrz_realloc_if (r, an);
mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn);
return mpn_normalized_size (rp, an);
}
else if (cmp < 0)
{
rp = mrz_realloc_if (r, bn);
mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an);
return -mpn_normalized_size (rp, bn);
}
else
return 0;
}
void
mpz_add (mpz_t r, const mpz_t a, const mpz_t b)
{
mp_size_t rn;
if ( (a->_mp_size ^ b->_mp_size) >= 0)
rn = mpz_abs_add (r, a, b);
else
rn = mpz_abs_sub (r, a, b);
r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
}
void
mpz_sub (mpz_t r, const mpz_t a, const mpz_t b)
{
mp_size_t rn;
if ( (a->_mp_size ^ b->_mp_size) >= 0)
rn = mpz_abs_sub (r, a, b);
else
rn = mpz_abs_add (r, a, b);
r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
}