Пример #1
0
int test_defaults_dp() {
  dgs_disc_gauss_dp_t *self;
  self = dgs_disc_gauss_dp_init(3.0, 0, 6, DGS_DISC_GAUSS_DEFAULT);
  if (self->algorithm != DGS_DISC_GAUSS_UNIFORM_TABLE)
    dgs_die("automatic choice of uniform table algorithm failed (%d)", self->algorithm);
  dgs_disc_gauss_dp_clear(self);

  self = dgs_disc_gauss_dp_init(3.0, 0, 1<<10, DGS_DISC_GAUSS_DEFAULT);
  if (self->algorithm != DGS_DISC_GAUSS_UNIFORM_TABLE)
    dgs_die("automatic choice of uniform table algorithm failed (%d)", self->algorithm);
  dgs_disc_gauss_dp_clear(self);

  self = dgs_disc_gauss_dp_init(3.0, 0, 1<<14, DGS_DISC_GAUSS_DEFAULT);
  if (self->algorithm != DGS_DISC_GAUSS_UNIFORM_LOGTABLE)
    dgs_die("automatic choice of uniform table algorithm failed (%d)", self->algorithm);
  dgs_disc_gauss_dp_clear(self);


  double sigma2 = sqrt(1.0/(2*log(2.0)));
  self = dgs_disc_gauss_dp_init(1024*sigma2, 0, 6, DGS_DISC_GAUSS_DEFAULT);
  if (self->algorithm != DGS_DISC_GAUSS_SIGMA2_LOGTABLE)
    dgs_die("automatic choice of uniform table algorithm failed (%d)", self->algorithm);
  dgs_disc_gauss_dp_clear(self);


  printf("passed\n");
  return 0;
}
Пример #2
0
int test_uniform_boundaries_dp(double sigma, double c, size_t tau, dgs_disc_gauss_alg_t algorithm) {
  dgs_disc_gauss_dp_t *self = dgs_disc_gauss_dp_init(sigma, c, tau, algorithm);

    printf("σ: %6.2f, c: %6.2f. τ: %2ld, precision: double, algorithm: %d\n", self->sigma, self->c, self->tau, self->algorithm);


  long lower_bound = ((long)self->c) - ceil(self->sigma * self->tau);
  long upper_bound = ((long)self->c) + ceil(self->sigma * self->tau);

  for(size_t i=0; i<NTRIALS; i++) {
    long r = self->call(self);
    if(__DGS_UNLIKELY(r < lower_bound))
      dgs_die("r (%ld) < lower_bound (%ld)", r, lower_bound);
    else if(__DGS_UNLIKELY(r > upper_bound))
      dgs_die("r (%ld) > upper_bound (%ld)", r, upper_bound);
  }
  return 0;
}
Пример #3
0
int test_mean_dp(double sigma, double c, size_t tau, dgs_disc_gauss_alg_t algorithm) {

  printf("σ: %6.2f, c: %6.2f. τ: %2ld, precision: double, algorithm: %d\n",sigma, c, tau, algorithm);

  dgs_disc_gauss_dp_t *self = dgs_disc_gauss_dp_init(sigma, c, tau, algorithm);

  double mean = 0.0;

  for(size_t i=0; i<NTRIALS; i++) {
    long r = self->call(self);
    mean += r;

  }

  mean /=NTRIALS;

  if(fabs(mean - c) > TOLERANCE)
    dgs_die("expected mean %6.2f but got %6.2f",c, mean);

  return 0;
}
Пример #4
0
int test_ratios_dp(double sigma, size_t tau, dgs_disc_gauss_alg_t algorithm) {
  printf("σ: %6.2f, c:    0.0. τ: %2ld, precision: double, algorithm: %d\n",sigma, tau, algorithm);

  dgs_disc_gauss_dp_t *self = dgs_disc_gauss_dp_init(sigma, 0, tau, algorithm);

  double ctr[2*BOUND+1];

  for(size_t i=0; i<NTRIALS; i++) {
    long r = self->call(self);
    if (abs(r) <= BOUND)
      ctr[r+BOUND] += 1;
  }

  for(long i=-BOUND; i<=BOUND; i++) {
    double left  = ctr[BOUND+1]/ctr[BOUND+i];
    double right = RHO(0)/RHO(i);
    if (fabs(log(left/right)) >= 0.4)
      dgs_die("exp(-((-c)²)/(2σ²))/exp(-((%d-c)²)/(2σ²)) = %7.5f != %7.5f (%7.5f)", i, right, left, fabs(log(left/right)));
  }
  return 0;
}
Пример #5
0
dgsl_rot_mp_t *dgsl_rot_mp_init(const long n, const fmpz_poly_t B, mpfr_t sigma, fmpq_poly_t c, const dgsl_alg_t algorithm, const oz_flag_t flags) {
  assert(mpfr_cmp_ui(sigma, 0) > 0);

  dgsl_rot_mp_t *self = (dgsl_rot_mp_t*)calloc(1, sizeof(dgsl_rot_mp_t));
  if(!self) dgs_die("out of memory");

  dgsl_alg_t alg = algorithm;

  self->n = n;

  self->prec = mpfr_get_prec(sigma);

  fmpz_poly_init(self->B);
  fmpz_poly_set(self->B, B);
  if(fmpz_poly_length(self->B) > n)
    dgs_die("polynomial is longer than length n");
  else
    fmpz_poly_realloc(self->B, n);


  fmpz_poly_init(self->c_z);
  fmpq_poly_init(self->c);

  mpfr_init2(self->sigma, self->prec);
  mpfr_set(self->sigma, sigma, MPFR_RNDN);

  if (alg == DGSL_DETECT) {
    if (fmpz_poly_is_one(self->B) && (c && fmpq_poly_is_zero(c))) {
      alg = DGSL_IDENTITY;
    } else if (c && fmpq_poly_is_zero(c))
      alg = DGSL_INLATTICE;
    else
      alg = DGSL_COSET; //TODO: we could test for lattice membership here
  }

  size_t tau = 3;
  if (2*ceil(sqrt(log2((double)n))) > tau)
    tau = 2*ceil(sqrt(log2((double)n)));

  switch(alg) {
  case DGSL_IDENTITY: {
    self->D = (dgs_disc_gauss_mp_t**)calloc(1, sizeof(dgs_disc_gauss_mp_t*));
    mpfr_t c_;
    mpfr_init2(c_, self->prec);
    mpfr_set_d(c_, 0.0, MPFR_RNDN);
    self->D[0] = dgs_disc_gauss_mp_init(self->sigma, c_, tau, DGS_DISC_GAUSS_DEFAULT);
    self->call = dgsl_rot_mp_call_identity;
    mpfr_clear(c_);
    break;
  }
  case DGSL_GPV_INLATTICE: {
    self->D = (dgs_disc_gauss_mp_t**)calloc(n, sizeof(dgs_disc_gauss_mp_t*));

    if (c && !fmpq_poly_is_zero(c)) {
      fmpq_t c_i;
      fmpq_init(c_i);
      for(int i=0; i<n; i++) {
        fmpq_poly_get_coeff_fmpq(c_i, c, i);
        fmpz_poly_set_coeff_fmpz(self->c_z, i, fmpq_numref(c_i));
      }
      fmpq_clear(c_i);
    }
    mpfr_mat_t G;
    mpfr_mat_init(G, n, n, self->prec);
    mpfr_mat_set_fmpz_poly(G, B);
    mpfr_mat_gso(G, MPFR_RNDN);

    mpfr_t sigma_;
    mpfr_init2(sigma_, self->prec);

    mpfr_t norm;
    mpfr_init2(norm, self->prec);

    mpfr_t c_;
    mpfr_init2(c_, self->prec);
    mpfr_set_d(c_, 0.0, MPFR_RNDN);

    for(long i=0; i<n; i++) {
      _mpfr_vec_2norm(norm, G->rows[i], n, MPFR_RNDN);
      assert(mpfr_cmp_d(norm, 0.0) > 0);
      mpfr_div(sigma_, self->sigma, norm, MPFR_RNDN);
      assert(mpfr_cmp_d(sigma_, 0.0) > 0);
      self->D[i] = dgs_disc_gauss_mp_init(sigma_, c_, tau, DGS_DISC_GAUSS_DEFAULT);
    }

    mpfr_clear(sigma_);
    mpfr_clear(norm);
    mpfr_clear(c_);
    mpfr_mat_clear(G);

    self->call = dgsl_rot_mp_call_gpv_inlattice;
    break;
  }
  case DGSL_INLATTICE: {
    fmpq_poly_init(self->sigma_sqrt);
    long r= 2*ceil(sqrt(log(n)));

    fmpq_poly_t Bq;    fmpq_poly_init(Bq);
    fmpq_poly_set_fmpz_poly(Bq, self->B);
    fmpq_poly_oz_invert_approx(self->B_inv, Bq, n, self->prec, flags);
    fmpq_poly_clear(Bq);

    _dgsl_rot_mp_sqrt_sigma_2(self->sigma_sqrt, self->B, sigma, r, n, self->prec, flags);

    mpfr_init2(self->r_f, self->prec);
    mpfr_set_ui(self->r_f, r, MPFR_RNDN);

    self->call = dgsl_rot_mp_call_inlattice;
    break;
  }
  case DGSL_COSET:
    dgs_die("not implemented");

  default:
    dgs_die("not implemented");
  }


  return self;
}
Пример #6
0
dgsl_mp_t *dgsl_mp_init(const fmpz_mat_t B, mpfr_t sigma,
                      mpfr_t *c, const dgsl_alg_t algorithm) {
  assert(mpfr_cmp_ui(sigma, 0) > 0);

  dgsl_mp_t *self = (dgsl_mp_t*)calloc(1, sizeof(dgsl_mp_t));
  if(!self) dgs_die("out of memory");

  dgsl_alg_t alg = algorithm;

  long m = fmpz_mat_nrows(B);
  long n = fmpz_mat_ncols(B);

  const mpfr_prec_t prec = mpfr_get_prec(sigma);

  fmpz_mat_init_set(self->B, B);
  self->c_z = _fmpz_vec_init(n);
  self->c   = _mpfr_vec_init(n, prec);
  mpfr_init2(self->sigma, prec);
  mpfr_set(self->sigma, sigma, MPFR_RNDN);

  if (alg == DGSL_DETECT) {
    if (fmpz_mat_is_one(self->B)) {
      alg = DGSL_IDENTITY;
    } else if (_mpfr_vec_is_zero(c, n))
      alg = DGSL_INLATTICE;
    else
      alg = DGSL_COSET; //TODO: we could test for lattice membership here
  }

  mpfr_t c_;
  mpfr_init2(c_, prec);

  size_t tau = 3;
  if (2*ceil(sqrt(log2((double)n))) > tau)
    tau = 2*ceil(sqrt(log2((double)n)));

  switch(alg) {
  case DGSL_IDENTITY:
    self->D = (dgs_disc_gauss_mp_t**)calloc(1, sizeof(dgs_disc_gauss_mp_t*));
    mpfr_set_d(c_, 0.0, MPFR_RNDN);
    self->D[0] = dgs_disc_gauss_mp_init(self->sigma, c_, tau, DGS_DISC_GAUSS_DEFAULT);

    self->call = dgsl_mp_call_identity;
    break;

  case DGSL_INLATTICE:
    self->D = (dgs_disc_gauss_mp_t**)calloc(m, sizeof(dgs_disc_gauss_mp_t*));

    if (c)
      _fmpz_vec_set_mpfr_vec(self->c_z, c, n);

    mpfr_mat_t G;
    mpfr_mat_init(G, m, n, prec);
    mpfr_mat_set_fmpz_mat(G, B);

    mpfr_mat_gso(G, MPFR_RNDN);

    mpfr_t sigma_;
    mpfr_init2(sigma_, prec);

    mpfr_t norm;
    mpfr_init2(norm, prec);

    mpfr_set_d(c_, 0.0, MPFR_RNDN);

    for(long i=0; i<m; i++) {
      _mpfr_vec_2norm(norm, G->rows[i], n, MPFR_RNDN);
      assert(mpfr_cmp_d(norm, 0.0) > 0);
      mpfr_div(sigma_, self->sigma, norm, MPFR_RNDN);
      assert(mpfr_cmp_d(sigma_, 0.0) > 0);
      self->D[i] = dgs_disc_gauss_mp_init(sigma_, c_, tau, DGS_DISC_GAUSS_DEFAULT);
    }

    mpfr_clear(sigma_);
    mpfr_clear(norm);
    mpfr_mat_clear(G);

    self->call = dgsl_mp_call_inlattice;
    break;

  case DGSL_COSET:
    mpfr_mat_init(self->G, m, n, prec);
    mpfr_mat_set_fmpz_mat(self->G, B);
    mpfr_mat_gso(self->G, MPFR_RNDN);

    self->call = dgsl_mp_call_coset;
    break;
  default:
    dgs_die("not implemented");
  }

  mpfr_clear(c_);

  return self;
}
Пример #7
0
dgs_disc_gauss_dp_t *dgs_disc_gauss_dp_init(double sigma, double c, size_t tau, dgs_disc_gauss_alg_t algorithm) {
    if (sigma <= 0.0)
        dgs_die("sigma must be > 0");
    if (tau == 0)
        dgs_die("tau must be > 0");

    size_t upper_bound;

    dgs_disc_gauss_dp_t *self = (dgs_disc_gauss_dp_t*)calloc(sizeof(dgs_disc_gauss_dp_t),1);
    if (!self) dgs_die("out of memory");

    self->sigma = sigma;
    self->c   = c;
    self->c_z = (long)c;
    self->c_r = self->c - ((double)self->c_z);
    self->tau = tau;

    switch(algorithm) {

    case DGS_DISC_GAUSS_UNIFORM_ONLINE:
        self->call = dgs_disc_gauss_dp_call_uniform_online;

        upper_bound = ceil(self->sigma*tau) + 1;
        self->upper_bound = upper_bound;
        self->upper_bound_minus_one = upper_bound - 1;
        self->two_upper_bound_minus_one = 2*upper_bound - 1;
        self->f = -1.0/(2.0*(self->sigma*self->sigma));
        break;

    case DGS_DISC_GAUSS_UNIFORM_TABLE:
        self->call = dgs_disc_gauss_dp_call_uniform_table;

        upper_bound = ceil(self->sigma*tau) + 1;
        self->upper_bound = upper_bound;
        self->upper_bound_minus_one = upper_bound - 1;
        self->two_upper_bound_minus_one = 2*upper_bound - 1;
        self->B = dgs_bern_uniform_init(0);
        self->f = -1.0/(2.0*(sigma*sigma));

        if(self->c_r == 0) {
            self->call = dgs_disc_gauss_dp_call_uniform_table;
            self->rho = (double*)malloc(sizeof(double)*self->upper_bound);
            if (!self->rho) {
                dgs_disc_gauss_dp_clear(self);
                dgs_die("out of memory");
            }
            for(unsigned long x=0; x<self->upper_bound; x++) {
                self->rho[x] = exp( (((double)x) - self->c_r) * (((double)x) - self->c_r) * self->f);
            }
            self->rho[0]/= 2.0;
        } else {
            self->call = dgs_disc_gauss_dp_call_uniform_table_offset;
            self->rho = (double*)malloc(sizeof(double)*self->two_upper_bound_minus_one);
            if (!self->rho) {
                dgs_disc_gauss_dp_clear(self);
                dgs_die("out of memory");
            }
            long absmax = self->upper_bound_minus_one;
            for(long x=-absmax; x<=absmax; x++) {
                self->rho[x+self->upper_bound_minus_one] = exp( (((double)x) - self->c_r) * (((double)x) - self->c_r) * self->f);
            }
        }
        break;

    case DGS_DISC_GAUSS_UNIFORM_LOGTABLE:
        self->call = dgs_disc_gauss_dp_call_uniform_logtable;

        if (fabs(self->c_r) > DGS_DISC_GAUSS_INTEGER_CUTOFF) {
            dgs_disc_gauss_dp_clear(self);
            dgs_die("algorithm DGS_DISC_GAUSS_UNIFORM_LOGTABLE requires c%1 == 0");
        }
        upper_bound = ceil(self->sigma*tau) + 1;
        self->upper_bound = upper_bound;
        self->upper_bound_minus_one = upper_bound - 1;
        self->two_upper_bound_minus_one = 2*upper_bound - 1;

        _dgs_disc_gauss_dp_init_bexp(self, self->sigma, self->upper_bound);
        break;

    case DGS_DISC_GAUSS_SIGMA2_LOGTABLE: {
        self->call = dgs_disc_gauss_dp_call_sigma2_logtable;

        if (fabs(self->c_r) > DGS_DISC_GAUSS_INTEGER_CUTOFF) {
            dgs_disc_gauss_dp_clear(self);
            dgs_die("algorithm DGS_DISC_GAUSS_SIGMA2_LOGTABLE requires c%1 == 0");
        }

        double sigma2 = sqrt(1.0/(2*log(2.0)));
        double k = sigma/sigma2;
        self->k = round(k);
        self->sigma = self->k * sigma2;

        upper_bound = ceil(self->sigma*tau) + 1;
        self->upper_bound = upper_bound;
        self->upper_bound_minus_one = upper_bound - 1;
        self->two_upper_bound_minus_one = 2*upper_bound - 1;

        _dgs_disc_gauss_dp_init_bexp(self, self->sigma, self->upper_bound);
        self->B = dgs_bern_uniform_init(0);
        self->D2 = dgs_disc_gauss_sigma2p_init();
        break;
    }

    default:
        dgs_disc_gauss_dp_clear(self);
        dgs_die("unknown algorithm %d", algorithm);
    }
    return self;
}