#include <gmp.h>
#include "profiler.h"
#include "fmpz.h"
#include "fmpz_vec.h"
#include "gmpcompat.h"
#define ntests 30
#define OLD_ALBIN 1
#if OLD_ALBIN
static void
_fmpz_add_mpn_1(fmpz_t f, const ulong * glimbs, slong gsz, ulong x);
static void
_fmpz_sub_mpn_1(fmpz_t f, const ulong * glimbs, slong gsz, ulong x);
void
fmpz_add_ui_old(fmpz_t f, const fmpz_t g, ulong x)
{
mpz_ptr mf;
slong g1 = *g;
slong f1 = *f;
if (!COEFF_IS_MPZ(g1))
{
slong sz = 2;
if (g1 >= 0)
{
{
ulong tmp = g1;
g1 += x;
if (((ulong) g1) < tmp)
goto carry;
}
if (((ulong) g1) <= COEFF_MAX)
{
if (COEFF_IS_MPZ(f1))
_fmpz_clear_mpz(f1);
*f = g1;
return;
}
nocarry: sz = 1;
carry: if (COEFF_IS_MPZ(f1))
mf = COEFF_TO_PTR(f1);
else
{
mf = _fmpz_new_mpz();
*f = PTR_TO_COEFF(mf);
}
mf->_mp_size = sz;
mf->_mp_d[0] = g1;
mf->_mp_d[1] = 1;
}
else
{
g1 += x;
if (((slong) x) >= 0 && g1 <= COEFF_MAX)
{
if (COEFF_IS_MPZ(f1))
_fmpz_clear_mpz(f1);
*f = g1;
return;
}
else
{
goto nocarry;
}
}
}
else
{
mpz_ptr mg = COEFF_TO_PTR(g1);
slong gsz = mg->_mp_size;
ulong * glimbs = mg->_mp_d;
if (gsz > 0)
_fmpz_add_mpn_1(f, glimbs, gsz, x);
else
_fmpz_sub_mpn_1(f, glimbs, gsz, x);
}
}
static void
_fmpz_add_mpn_1(fmpz_t f, const ulong * glimbs, slong gsz, ulong x)
{
mpz_ptr mf;
ulong * flimbs;
slong gabssz = FLINT_ABS(gsz);
if (COEFF_IS_MPZ(*f))
mf = COEFF_TO_PTR(*f);
else
{
mf = _fmpz_new_mpz();
*f = PTR_TO_COEFF(mf);
}
flimbs = mf->_mp_d;
if (mf->_mp_alloc < (gabssz + 1))
{
ulong * tmp = flimbs;
flimbs = _mpz_realloc(mf, gabssz + 1);
if (tmp == glimbs)
glimbs = flimbs;
}
flimbs[gabssz] = mpn_add_1(flimbs, glimbs, gabssz, x);
mf->_mp_size = gabssz + flimbs[gabssz];
if (gsz < 0)
{
mf->_mp_size = -mf->_mp_size;
}
}
static void
_fmpz_sub_mpn_1(fmpz_t f, const ulong * glimbs, slong gsz, ulong x)
{
mpz_ptr mf;
ulong * flimbs;
slong gabssz = FLINT_ABS(gsz);
if (gabssz == 1)
{
if (x <= glimbs[0])
{
x = glimbs[0] - x;
L1: if (x <= COEFF_MAX)
{
if (COEFF_IS_MPZ(*f))
_fmpz_clear_mpz(*f);
*f = (gsz > 0) ? x : -x;
}
else
{
if (COEFF_IS_MPZ(*f))
mf = COEFF_TO_PTR(*f);
else
{
mf = _fmpz_new_mpz();
*f = PTR_TO_COEFF(mf);
}
mf->_mp_d[0] = x;
mf->_mp_size = gsz;
}
}
else
{
x -= glimbs[0];
gsz = -gsz;
goto L1;
}
return;
}
if (COEFF_IS_MPZ(*f))
mf = COEFF_TO_PTR(*f);
else
{
mf = _fmpz_new_mpz();
*f = PTR_TO_COEFF(mf);
}
flimbs = mf->_mp_d;
if (gabssz == 2)
{
sub_ddmmss(flimbs[1], flimbs[0], glimbs[1], glimbs[0], 0, x);
if (flimbs[1] != 0)
{
mf->_mp_size = gsz;
}
else if (flimbs[0] > COEFF_MAX)
{
mf->_mp_size = (gsz > 0) ? 1 : -1;
}
else
{
slong tmp = flimbs[0];
_fmpz_clear_mpz(*f);
*f = (gsz > 0) ? tmp : -tmp;
}
}
else
{
if (mf->_mp_alloc < gabssz)
{
flimbs = _mpz_realloc(mf, gabssz);
}
mpn_sub_1(flimbs, glimbs, gabssz, x);
mf->_mp_size = gabssz - (flimbs[gabssz - 1] == 0);
if (gsz < 0)
mf->_mp_size = -mf->_mp_size;
}
}
void
fmpz_sub_ui_old(fmpz_t f, const fmpz_t g, ulong x)
{
mpz_ptr mf;
slong g1 = *g;
slong f1 = *f;
if (!COEFF_IS_MPZ(g1))
{
slong sz = -2;
if (g1 <= 0)
{
g1 = x - g1;
if (((ulong) g1) < x)
goto carry;
if (((ulong) g1) <= COEFF_MAX)
{
if (COEFF_IS_MPZ(f1))
_fmpz_clear_mpz(f1);
*f = -g1;
return;
}
nocarry: sz = -1;
carry: if (COEFF_IS_MPZ(f1))
mf = COEFF_TO_PTR(f1);
else
{
mf = _fmpz_new_mpz();
*f = PTR_TO_COEFF(mf);
}
mf->_mp_size = sz;
mf->_mp_d[0] = g1;
mf->_mp_d[1] = 1;
}
else
{
g1 = x - g1;
if (((slong) x) >= 0 && g1 <= COEFF_MAX)
{
if (COEFF_IS_MPZ(f1))
_fmpz_clear_mpz(f1);
*f = -g1;
return;
}
else
{
goto nocarry;
}
}
}
else
{
mpz_ptr mg = COEFF_TO_PTR(g1);
slong gsz = mg->_mp_size;
ulong * glimbs = mg->_mp_d;
if (gsz > 0)
_fmpz_sub_mpn_1(f, glimbs, gsz, x);
else
_fmpz_add_mpn_1(f, glimbs, gsz, x);
}
}
#else
void fmpz_add_ui_old(fmpz_t f, const fmpz_t g, ulong x)
{
fmpz c = *g;
if (!COEFF_IS_MPZ(c))
{
ulong sum[2];
if (c >= WORD(0))
{
add_ssaaaa(sum[1], sum[0], 0, c, 0, x);
fmpz_set_uiui(f, sum[1], sum[0]);
}
else
{
if (-c > x)
fmpz_set_si(f, x + c);
else
fmpz_set_ui(f, x + c);
}
}
else
{
mpz_ptr mf = _fmpz_promote(f);
mpz_ptr mc = COEFF_TO_PTR(c);
flint_mpz_add_ui(mf, mc, x);
_fmpz_demote_val(f);
}
}
void
fmpz_sub_ui_old(fmpz_t f, const fmpz_t g, ulong x)
{
fmpz c = *g;
if (!COEFF_IS_MPZ(c))
{
ulong sum[2];
if (c < WORD(0))
{
add_ssaaaa(sum[1], sum[0], 0, -c, 0, x);
fmpz_neg_uiui(f, sum[1], sum[0]);
}
else
{
if (x < c)
fmpz_set_ui(f, c - x);
else
fmpz_neg_ui(f, x - c);
}
}
else
{
mpz_ptr mc, mf;
mf = _fmpz_promote(f);
mc = COEFF_TO_PTR(c);
flint_mpz_sub_ui(mf, mc, x);
_fmpz_demote_val(f);
}
}
#endif
void
sample_add_new(void * arg, ulong count)
{
fmpz *res, *a;
ulong *b;
ulong ix, jx;
int bits = *((int *) arg);
FLINT_TEST_INIT(state);
res = _fmpz_vec_init(ntests);
a = _fmpz_vec_init(ntests);
b = flint_malloc(sizeof(ulong) * ntests);
for (ix = 0; ix < 10 * count; ix++)
{
for (jx = 0; jx < ntests; jx++)
{
fmpz_randtest(a + jx, state, bits);
fmpz_randtest(res + jx, state, bits);
b[jx] = n_randtest(state);
}
prof_start();
for (jx = 0; jx < ntests; jx++)
fmpz_add_ui(res + jx, a + jx, b[jx]);
prof_stop();
}
_fmpz_vec_clear(res, ntests);
_fmpz_vec_clear(a, ntests);
flint_free(b);
FLINT_TEST_CLEAR(state);
}
void
sample_add_old(void * arg, ulong count)
{
fmpz *res, *a;
ulong *b;
ulong ix, jx;
int bits = *((int *) arg);
FLINT_TEST_INIT(state);
res = _fmpz_vec_init(ntests);
a = _fmpz_vec_init(ntests);
b = flint_malloc(sizeof(ulong) * ntests);
for (ix = 0; ix < 10 * count; ix++)
{
for (jx = 0; jx < ntests; jx++)
{
fmpz_randtest(a + jx, state, bits);
fmpz_randtest(res + jx, state, bits);
b[jx] = n_randtest(state);
}
prof_start();
for (jx = 0; jx < ntests; jx++)
fmpz_add_ui_old(res + jx, a + jx, b[jx]);
prof_stop();
}
_fmpz_vec_clear(res, ntests);
_fmpz_vec_clear(a, ntests);
flint_free(b);
FLINT_TEST_CLEAR(state);
}
void
sample_sub_new(void * arg, ulong count)
{
fmpz *res, *a;
ulong *b;
ulong ix, jx;
int bits = *((int *) arg);
FLINT_TEST_INIT(state);
res = _fmpz_vec_init(ntests);
a = _fmpz_vec_init(ntests);
b = flint_malloc(sizeof(ulong) * ntests);
for (ix = 0; ix < 10 * count; ix++)
{
for (jx = 0; jx < ntests; jx++)
{
fmpz_randtest(a + jx, state, bits);
fmpz_randtest(res + jx, state, bits);
b[jx] = n_randtest(state);
}
prof_start();
for (jx = 0; jx < ntests; jx++)
fmpz_sub_ui(res + jx, a + jx, b[jx]);
prof_stop();
}
_fmpz_vec_clear(res, ntests);
_fmpz_vec_clear(a, ntests);
flint_free(b);
FLINT_TEST_CLEAR(state);
}
void
sample_sub_old(void * arg, ulong count)
{
fmpz *res, *a;
ulong *b;
ulong ix, jx;
int bits = *((int *) arg);
FLINT_TEST_INIT(state);
res = _fmpz_vec_init(ntests);
a = _fmpz_vec_init(ntests);
b = flint_malloc(sizeof(ulong) * ntests);
for (ix = 0; ix < 10 * count; ix++)
{
for (jx = 0; jx < ntests; jx++)
{
fmpz_randtest(a + jx, state, bits);
fmpz_randtest(res + jx, state, bits);
b[jx] = n_randtest(state);
}
prof_start();
for (jx = 0; jx < ntests; jx++)
fmpz_sub_ui_old(res + jx, a + jx, b[jx]);
prof_stop();
}
_fmpz_vec_clear(res, ntests);
_fmpz_vec_clear(a, ntests);
flint_free(b);
FLINT_TEST_CLEAR(state);
}
slong sizes[] = { 10, 30, 60, 62, 64, 66, 80, 128, 160, 256, 512, 1024, 4096, 0 };
int
main(void)
{
double minnew, maxnew, minold, maxold;
int i, bits;
flint_printf("ADD\n");
for (i = 0; (bits = sizes[i]) != 0; i++)
{
prof_repeat(&minnew, &maxnew, sample_add_new, &bits);
prof_repeat(&minold, &maxold, sample_add_old, &bits);
flint_printf("%d bits: min %.2fx, max %.2fx\n",
bits, minold / minnew, maxold / maxnew);
}
flint_printf("\nSUB\n");
for (i = 0; (bits = sizes[i]) != 0; i++)
{
prof_repeat(&minnew, &maxnew, sample_sub_new, &bits);
prof_repeat(&minold, &maxold, sample_sub_old, &bits);
flint_printf("%d bits: min %.2fx, max %.2fx\n",
bits, minold / minnew, maxold / maxnew);
}
return 0;
}