poly_t * poly_sqrtmod_init(poly_t g) { int i, t; poly_t * sqrt, aux, p, q, * sq_aux; t = poly_deg(g); sq_aux = malloc(t * sizeof (poly_t)); for (i = 0; i < t; ++i) sq_aux[i] = poly_alloc(t - 1); poly_sqmod_init(g, sq_aux); q = poly_alloc(t - 1); p = poly_alloc(t - 1); poly_set_deg(p, 1); poly_set_coeff(p, 1, gf_unit()); // q(z) = 0, p(z) = z for (i = 0; i < t * gf_extd() - 1; ++i) { // q(z) <- p(z)^2 mod g(z) poly_sqmod(q, p, sq_aux, t); // q(z) <-> p(z) aux = q; q = p; p = aux; } // p(z) = z^(2^(tm-1)) mod g(z) = sqrt(z) mod g(z) sqrt = malloc(t * sizeof (poly_t)); for (i = 0; i < t; ++i) sqrt[i] = poly_alloc(t - 1); poly_set(sqrt[1], p); poly_calcule_deg(sqrt[1]); for(i = 3; i < t; i += 2) { poly_set(sqrt[i], sqrt[i - 2]); poly_shiftmod(sqrt[i], g); poly_calcule_deg(sqrt[i]); } for (i = 0; i < t; i += 2) { poly_set_to_zero(sqrt[i]); sqrt[i]->coeff[i / 2] = gf_unit(); sqrt[i]->deg = i / 2; } for (i = 0; i < t; ++i) poly_free(sq_aux[i]); free(sq_aux); poly_free(p); poly_free(q); return sqrt; }
static bool poly_approximate_1(ap_manager_t* man, pk_t* po, pk_t* pa) { bool change; pk_internal_t* pk = (pk_internal_t*)man->internal; poly_obtain_C(man,pa,NULL); if (!pa->C){ poly_set(po,pa); return false; } if (po!=pa){ po->C = matrix_copy(pa->C); } change = matrix_approximate_constraint_1(pk,po->C); if (change){ if (po==pa){ if (po->F){ matrix_free(po->F); po->F = NULL; } if (po->satC){ satmat_free(po->satC); po->satC = NULL; } if (po->satF){ satmat_free(po->satF); po->satF = NULL; } } po->status = 0; man->result.flag_exact = false; } else { poly_set_save_C(po,pa); man->result.flag_exact = true; } return change; }
/* ---------------------------------------------------------------------- */ static bool poly_approximate_n1(ap_manager_t* man, pk_t* po, pk_t* pa, int algorithm) { if (po->intdim>0){ pk_internal_t* pk = (pk_internal_t*)man->internal; bool change; poly_obtain_C(man,pa,NULL); if (!pa->C){ poly_set(po,pa); return false; } if (po!=pa){ po->C = matrix_copy(pa->C); } change = matrix_normalize_constraint_int(pk,po->C,po->intdim,po->realdim); if (change){ { /* Add positivity and strictness that may not be implied any more */ size_t nbrows = po->C->nbrows; matrix_resize_rows_lazy(po->C,nbrows+pk->dec-1); matrix_fill_constraint_top(pk,po->C,nbrows); } if (po==pa){ if (po->F){ matrix_free(po->F); po->F = NULL; } if (po->satC){ satmat_free(po->satC); po->satC = NULL; } if (po->satF){ satmat_free(po->satF); po->satF = NULL; } } po->status = 0; po->C->_sorted = false; man->result.flag_exact = false; } else { poly_set_save_C(po,pa); } return change; } else return false; }
/* ====================================================================== */ static pk_t* poly_asssub_linexpr(bool assign, bool lazy, ap_manager_t* man, bool destructive, pk_t* pa, ap_dim_t dim, ap_linexpr0_t* linexpr, pk_t* pb) { pk_t* po; pk_internal_t* pk = (pk_internal_t*)man->internal; pk_internal_realloc_lazy(pk,pa->intdim+pa->realdim+1); /* Minimize the argument if option say so */ if (!lazy){ poly_chernikova(man,pa,"of the argument"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (destructive){ poly_set_top(pk,pa); return pa; } else { return pk_top(man,pa->intdim,pa->realdim); } } } /* Return empty if empty */ if (!pa->C && !pa->F){ man->result.flag_best = man->result.flag_exact = true; return destructive ? pa : pk_bottom(man,pa->intdim,pa->realdim); } /* Choose the right technique */ if (ap_linexpr0_is_linear(linexpr)){ po = poly_asssub_linexpr_det(assign,man,destructive,pa,dim,linexpr); if (pb){ poly_meet(true,lazy,man,po,po,pb); } } else { po = ap_generic_asssub_linexpr_array(assign,man,destructive,pa,&dim,&linexpr,1,pb); } /* Minimize the result if option say so */ if (!lazy){ poly_chernikova(man,po,"of the result"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (pb) poly_set(po,pb); else poly_set_top(pk,po); return po; } } /* Is the result exact or best ? */ if (pk->funopt->flag_best_wanted || pk->funopt->flag_exact_wanted){ man->result.flag_best = man->result.flag_exact = (dim < pa->intdim || !ap_linexpr0_is_real(linexpr, pa->intdim)) ? false : true; } else { man->result.flag_best = man->result.flag_exact = (pa->intdim==0); } return po; }
/* ====================================================================== */ static pk_t* poly_asssub_texpr_array(bool assign, bool lazy, ap_manager_t* man, bool destructive, pk_t* pa, ap_dim_t* tdim, ap_texpr0_t** texpr, size_t size, pk_t* pb) { pk_t* po; pk_internal_t* pk = (pk_internal_t*)man->internal; /* Minimize the argument if option say so */ if (!lazy){ poly_chernikova(man,pa,"of the argument"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (destructive){ poly_set_top(pk,pa); return pa; } else { return pk_top(man,pa->intdim,pa->realdim); } } } /* Return empty if empty */ if (!pa->C && !pa->F){ man->result.flag_best = man->result.flag_exact = true; return destructive ? pa : pk_bottom(man,pa->intdim,pa->realdim); } /* Choose the right technique */ if (ap_texpr0_array_is_scalar(texpr,size) && ap_texpr0_array_is_interval_linear(texpr,size)){ ap_abstract0_t abs; abs.value = pa; abs.man = man; if (size==1){ ap_linexpr0_t* linexpr0 = ap_intlinearize_texpr0(man,&abs,texpr[0],NULL, AP_SCALAR_MPQ,false); po = poly_asssub_linexpr_det(assign,man,destructive, pa, tdim[0], linexpr0); ap_linexpr0_free(linexpr0); } else { ap_linexpr0_t** tlinexpr = ap_intlinearize_texpr0_array(man,&abs,texpr,size,NULL, AP_SCALAR_MPQ,false); po = poly_asssub_linexpr_array_det(assign,man,destructive, pa,tdim,tlinexpr,size); ap_linexpr0_array_free(tlinexpr,size); } if (pb){ poly_meet(true,lazy,man,po,po,pb); } } else { po = ap_generic_asssub_texpr_array(assign,man,destructive,pa,tdim,texpr,size,pb); } /* Minimize the result if option say so */ if (!lazy){ poly_chernikova(man,po,"of the result"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (pb) poly_set(po,pb); else poly_set_top(pk,po); return po; } } /* Is the result exact or best ? */ if (pk->funopt->flag_best_wanted || pk->funopt->flag_exact_wanted){ man->result.flag_best = ap_texpr0_array_is_interval_linear(texpr,size); man->result.flag_exact = man->result.flag_best; } else { man->result.flag_best = man->result.flag_exact = false; } return po; }
/* ====================================================================== */ static pk_t* poly_asssub_linexpr_array(bool assign, bool lazy, ap_manager_t* man, bool destructive, pk_t* pa, ap_dim_t* tdim, ap_linexpr0_t** texpr, size_t size, pk_t* pb) { pk_t* po; pk_internal_t* pk = (pk_internal_t*)man->internal; /* Minimize the argument if option say so */ if (!lazy){ poly_chernikova(man,pa,"of the argument"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (destructive){ poly_set_top(pk,pa); return pa; } else { return pk_top(man,pa->intdim,pa->realdim); } } } /* Return empty if empty */ if (!pa->C && !pa->F){ man->result.flag_best = man->result.flag_exact = true; return destructive ? pa : pk_bottom(man,pa->intdim,pa->realdim); } /* Choose the right technique */ if (ap_linexpr0_array_is_linear(texpr,size)){ po = poly_asssub_linexpr_array_det(assign,man,destructive,pa,tdim,texpr,size); if (pb){ poly_meet(true,lazy,man,po,po,pb); } } else { po = ap_generic_asssub_linexpr_array(assign,man,destructive,pa,tdim,texpr,size,pb); } /* Minimize the result if option say so */ if (!lazy){ poly_chernikova(man,po,"of the result"); if (pk->exn){ pk->exn = AP_EXC_NONE; man->result.flag_best = man->result.flag_exact = false; if (pb) poly_set(po,pb); else poly_set_top(pk,po); return po; } } /* Is the result exact or best ? */ if (pk->funopt->flag_best_wanted || pk->funopt->flag_exact_wanted){ size_t i; man->result.flag_best = true; for (i=0;i<size;i++){ if (tdim[i] < pa->intdim || !ap_linexpr0_is_real(texpr[i], pa->intdim)){ man->result.flag_best = false; break; } } man->result.flag_exact = man->result.flag_best; } else { man->result.flag_best = man->result.flag_exact = (pa->intdim==0); } return po; }
// On suppose deg(g) >= deg(p) void poly_eeaux(poly_t * u, poly_t * v, poly_t p, poly_t g, int t) { int i, j, dr, du, delta; gf_t a; poly_t aux, r0, r1, u0, u1; // initialisation des variables locales // r0 <- g, r1 <- p, u0 <- 0, u1 <- 1 dr = poly_deg(g); r0 = poly_alloc(dr); r1 = poly_alloc(dr - 1); u0 = poly_alloc(dr - 1); u1 = poly_alloc(dr - 1); poly_set(r0, g); poly_set(r1, p); poly_set_to_zero(u0); poly_set_to_zero(u1); poly_set_coeff(u1, 0, gf_unit()); poly_set_deg(u1, 0); // invariants: // r1 = u1 * p + v1 * g // r0 = u0 * p + v0 * g // et deg(u1) = deg(g) - deg(r0) // on s'arrĂȘte lorsque deg(r1) < t (et deg(r0) >= t) // et donc deg(u1) = deg(g) - deg(r0) < deg(g) - t du = 0; dr = poly_deg(r1); delta = poly_deg(r0) - dr; while (dr >= t) { for (j = delta; j >= 0; --j) { a = gf_div(poly_coeff(r0, dr + j), poly_coeff(r1, dr)); if (a != gf_zero()) { // u0(z) <- u0(z) + a * u1(z) * z^j for (i = 0; i <= du; ++i) { poly_addto_coeff(u0, i + j, gf_mul_fast(a, poly_coeff(u1, i))); } // r0(z) <- r0(z) + a * r1(z) * z^j for (i = 0; i <= dr; ++i) poly_addto_coeff(r0, i + j, gf_mul_fast(a, poly_coeff(r1, i))); } } // Ă©changes aux = r0; r0 = r1; r1 = aux; aux = u0; u0 = u1; u1 = aux; du = du + delta; delta = 1; while (poly_coeff(r1, dr - delta) == gf_zero()) delta++; dr -= delta; } poly_set_deg(u1, du); poly_set_deg(r1, dr); //return u1 and r1; *u=u1; *v=r1; poly_free(r0); poly_free(u0); }