Exemplo n.º 1
0
/* p-adic logarithm */
void padiclog(mpz_t ans, const mpz_t a, unsigned long p, unsigned long prec, const mpz_t modulo) {
    /*  Compute the p-adic logarithm of a,
        which is supposed to be congruent to 1 mod p

        Algorithm:
         1. we raise a at the power p^(v-1) (for a suitable v) in order
            to make it closer to 1
         2. we write the new a as a product
              1/a = (1 - a_0*p^v) (1 - a_1*p^(2*v) (1 - a_2*p^(4*v) ...
            with 0 <= a_i < p^(v*2^i).
         3. we compute each log(1 - a_i*p^(v*2^i)) using Taylor expansion
            and a binary spliting strategy.                                */

    unsigned long i, v, e, N, saveN, Np, tmp, trunc, step;
    double den = log(p);
    mpz_t f, arg, trunc_mod, h, hpow, mpz_tmp, mpz_tmp2, d, inv, mod2;
    mpz_t *num, *denom;

    mpz_init(mpz_tmp);
    mpz_init(mpz_tmp2);
    mpz_init(arg);
    mpz_set_ui(ans, 0);

    mpz_fdiv_r_ui(mpz_tmp, a, p);
    mpz_set(arg, a);

    /* First we make the argument closer to 1 by raising it to the p^(v-1) */
    if (prec < p) {
        v = 0; e = 1;
    } else {
        v = (unsigned long)(log(prec)/den);  // v here is v-1
        e = pow(p,v);
        mpz_mul_ui(mpz_tmp, modulo, e);
        mpz_powm_ui(arg, arg, e, mpz_tmp);
        prec += v;
    }

    /* Where do we need to truncate the Taylor expansion */
    N = prec+v; N /= ++v;                 // note the ++v
    Np = N;
    den *= v;
    while(1) {
        tmp = Np + (unsigned long)(log(N)/den);
        if (tmp == N) break;
        N = tmp;
    }

    /* We allocate memory and initialize variables */
    mpz_init(f); mpz_init(mod2);
    mpz_init(h); mpz_init(hpow);
    mpz_init(d); mpz_init(inv);
    sig_block();
    num = (mpz_t*)malloc(N*sizeof(mpz_t));
    denom = (mpz_t*)malloc(N*sizeof(mpz_t));
    sig_unblock();
    for (i = 0; i < N; i++) {
        mpz_init(num[i]);
        mpz_init(denom[i]);
    }

    trunc = v << 1;
    mpz_init(trunc_mod);
    mpz_ui_pow_ui(trunc_mod, p, trunc);
    while(1) {
        /* We compute f = 1 - a_i*p^((v+1)*2^i)
           trunc_mod is p^((v+1)*2^(i+1)) */
        mpz_fdiv_r(f, arg, trunc_mod);

        if (mpz_cmp_ui(f, 1) != 0) {

            mpz_ui_sub(f, 2, f);
            mpz_mul(arg, arg, f);

            /* We compute the Taylor expansion of log(f)
               For now, computations are carried out over the rationals */
            for (i = 0; i < N; i++) {
                mpz_set_ui(num[i], 1);
                mpz_set_ui(denom[i], i+1);
            }
            step = 1;
            mpz_ui_sub(h, 1, f);   // we write f = 1 - h, i.e. h = a_i*p^(2^i)
            mpz_set(hpow, h);
            while(step < N) {
                for (i = 0; i < N - step; i += step << 1) {
                    mpz_mul(mpz_tmp2, hpow, num[i+step]);
                    mpz_mul(mpz_tmp, mpz_tmp2, denom[i]);
                    mpz_mul(num[i], num[i], denom[i+step]);
                    mpz_add(num[i], num[i], mpz_tmp);
                    mpz_mul(denom[i], denom[i], denom[i+step]);
                }
                step <<= 1;
                mpz_mul(hpow, hpow, hpow);
            }

            /* We simplify the fraction */
            Np = N; tmp = 0;
            while(Np > 0) { Np /= p; tmp += Np; }
            mpz_ui_pow_ui(d, p, tmp);
            mpz_divexact(mpz_tmp, num[0], d);
            mpz_divexact(denom[0], denom[0], d);

            mpz_divexact_ui(h, h, e);
            mpz_mul(mpz_tmp, h, mpz_tmp);

            /* We coerce the result from Q to Zp */
            mpz_gcdext(d, inv, NULL, denom[0], modulo);
            mpz_mul(mpz_tmp, mpz_tmp, inv);

            /* We add this contribution to log(f) */
            mpz_add(ans, ans, mpz_tmp);

        }

        if (trunc > prec) break;

        /* We update the variables for the next step */
        mpz_mul(trunc_mod, trunc_mod, trunc_mod);
        trunc <<= 1;
        for (i = N >> 1; i < N; i++) {
            mpz_clear(num[i]);
            mpz_clear(denom[i]);
        }
        N >>= 1;
    }

    mpz_fdiv_r(ans, ans, modulo);

    /* We clear memory */
    mpz_clear(arg);
    mpz_clear(f);
    mpz_clear(trunc_mod);
    mpz_clear(h);
    mpz_clear(hpow);
    mpz_clear(mpz_tmp);
    mpz_clear(d);
    mpz_clear(inv);
    mpz_clear(mod2);
    for (i = 0; i < N; i++) {
        mpz_clear(num[i]);
        mpz_clear(denom[i]);
    }
    sig_block();
    free(num);
    free(denom);
    sig_unblock();
}
Exemplo n.º 2
0
void
try_op_si (int c)
{
  long  si, oi;
  mpz_t sz, oz;

  si = c;
  mpz_init_set_si (sz, si);

  oi = si;
  mpz_init_set (oz, sz);

  do {
    si *= 2; /* c * 2^k */
    mpz_mul_2exp (sz, sz, 1);

    if (check_si (sz, oz, si, oi, c))
      {
	mpz_set (oz, sz);
	break;
      }

    oi = si + c; /* c * (2^k + 1) */
    if (c == -1)
      mpz_sub_ui (oz, sz, 1);
    else
      mpz_add_ui (oz, sz, 1);

    if (check_si (oz, sz, oi, si, c))
      break;

    oi = (si - c) * 2 + c; /* c * (2^K - 1) */
    mpz_mul_si (oz, sz, 2*c);
    if (c == -1)
      mpz_ui_sub (oz, 1, oz); /* oz = sz * 2 + 1 */
    else
      mpz_sub_ui (oz, oz, 1); /* oz = sz * 2 - 1 */
  } while (check_si (oz, sz, oi, si, c) == 0);

  mpz_clear (sz);

  if (mpz_fits_slong_p (oz))
    {
      printf ("Should not fit a signed long any more.\n");
      printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
      abort ();
    }

  if (mpz_cmp_si (oz, -c) != c)
      {
	printf ("mpz_cmp_si (oz, %i) != %i.\n", c, c);
	printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
	abort ();
      }

  mpz_mul_2exp (oz, oz, 1);
  if (mpz_cmp_si (oz, -c) != c)
      {
	printf ("mpz_cmp_si (oz, %i) != %i.\n", c, c);
	printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
	abort ();
      }

  mpz_clear (oz);
}
Exemplo n.º 3
0
int
main (int argc, char **argv)
{
    mpz_t op1, op2, r1, r2;
    mp_size_t op1n, op2n;
    unsigned long int op2long;
    int i;
    int reps = 100000;
    gmp_randstate_ptr rands;
    mpz_t bs;
    unsigned long bsi, size_range;

    tests_start ();
    rands = RANDS;

    mpz_init (bs);

    if (argc == 2)
        reps = atoi (argv[1]);

    mpz_init (op1);
    mpz_init (op2);
    mpz_init (r1);
    mpz_init (r2);

    for (i = 0; i < reps; i++)
    {
        mpz_urandomb (bs, rands, 32);
        size_range = mpz_get_ui (bs) % 10 + 2;

        mpz_urandomb (bs, rands, size_range);
        op1n = mpz_get_ui (bs);
        mpz_rrandomb (op1, rands, op1n);

        mpz_urandomb (bs, rands, size_range);
        op2n = mpz_get_ui (bs);
        mpz_rrandomb (op2, rands, op2n);

        mpz_urandomb (bs, rands, 2);
        bsi = mpz_get_ui (bs);
        if ((bsi & 1) != 0)
            mpz_neg (op1, op1);
        if ((bsi & 2) != 0)
            mpz_neg (op2, op2);

        /* printf ("%ld %ld\n", SIZ (multiplier), SIZ (multiplicand)); */

        mpz_add (r1, op1, op2);
        mpz_sub (r2, r1, op2);
        if (mpz_cmp (r2, op1) != 0)
            dump_abort (i, "mpz_add or mpz_sub incorrect", op1, op2);

        if (mpz_fits_ulong_p (op2))
        {
            op2long = mpz_get_ui (op2);
            mpz_add_ui (r1, op1, op2long);
            mpz_sub_ui (r2, r1, op2long);
            if (mpz_cmp (r2, op1) != 0)
                dump_abort (i, "mpz_add_ui or mpz_sub_ui incorrect", op1, op2);

            mpz_ui_sub (r1, op2long, op1);
            mpz_sub_ui (r2, op1, op2long);
            mpz_neg (r2, r2);
            if (mpz_cmp (r1, r2) != 0)
                dump_abort (i, "mpz_add_ui or mpz_ui_sub incorrect", op1, op2);
        }
    }

    mpz_clear (bs);
    mpz_clear (op1);
    mpz_clear (op2);
    mpz_clear (r1);
    mpz_clear (r2);

    tests_end ();
    exit (0);
}
Exemplo n.º 4
0
static PyObject *
GMPy_Integer_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
    MPZ_Object *result;

    if (!(result = GMPy_MPZ_New(context)))
        return NULL;

    if (CHECK_MPZANY(x)) {
        if (PyIntOrLong_Check(y)) {
            int error;
            long temp = GMPy_Integer_AsLongAndError(y, &error);
            
            if (!error) {
                if (temp >= 0) {
                    mpz_sub_ui(result->z, MPZ(x), temp);
                }
                else {
                    mpz_add_ui(result->z, MPZ(x), -temp);
                }
            }
            else {
                mpz_t tempz;
                mpz_inoc(tempz);
                mpz_set_PyIntOrLong(tempz, y);
                mpz_sub(result->z, MPZ(x), tempz);
                mpz_cloc(tempz);
            }
            return (PyObject*)result;
        }

        if (CHECK_MPZANY(y)) {
            mpz_sub(result->z, MPZ(x), MPZ(y));
            return (PyObject*)result;
        }
    }

    if (CHECK_MPZANY(y)) {
        if (PyIntOrLong_Check(x)) {
            int error;
            long temp = GMPy_Integer_AsLongAndError(x, &error);
            
            if (!error) {
                if (temp >= 0) {
                    mpz_ui_sub(result->z, temp, MPZ(y));
                }
                else {
                    mpz_add_ui(result->z, MPZ(y), -temp);
                    mpz_neg(result->z, result->z);
                }
            }
            else {
                mpz_t tempz;
                mpz_inoc(tempz);
                mpz_set_PyIntOrLong(tempz, x);
                mpz_sub(result->z, tempz, MPZ(y));
                mpz_cloc(tempz);
            }
            return (PyObject*)result;
        }
    }

    if (IS_INTEGER(x) && IS_INTEGER(y)) {
        MPZ_Object *tempx, *tempy;

        tempx = GMPy_MPZ_From_Integer(x, context);
        tempy = GMPy_MPZ_From_Integer(y, context);
        if (!tempx || !tempy) {
            Py_XDECREF((PyObject*)tempx);
            Py_XDECREF((PyObject*)tempy);
            Py_DECREF((PyObject*)result);
            return NULL;
        }

        mpz_sub(result->z, tempx->z, tempy->z);
        Py_DECREF((PyObject*)tempx);
        Py_DECREF((PyObject*)tempy);
        return (PyObject*)result;
    }

    Py_DECREF((PyObject*)result);
    Py_RETURN_NOTIMPLEMENTED;
}