/* **************************************************************** * Imprime uma tabela sobre a biblioteca * **************************************************************** */ int do_table (const char *argv[]) { const MOD *mp; const char *mod_nm; /* * Lê o arquivo de sinopse */ read_sinop_file (0); /* * Verifica se foram dados nomes de módulos */ if (*argv == NOSTR) { for (mp = mod_first; mp != NOMOD; mp = mp->m_next) list_mod (mp); } else /* Lista apenas os modulos dados */ { while ((mod_nm = *argv++) != NOSTR) { if ((mp = mod_search (mod_nm)) == NOMOD) error ("Não encontrei o módulo \"%s\"", mod_nm); else list_mod (mp); } } vflag = 0; /* Não escreve a mensagem sobre a sinopse */ return (0); /* Não escreve a sinopse */ } /* end do_table */
/* puts in G[0]..G[k-1] the coefficients from (x+a[0])...(x+a[k-1]) Warning: doesn't fill the coefficient 1 of G[k], which is implicit. Needs k + list_mul_mem(k/2) cells in T. The product tree is stored in: G[0..k-1] (degree k) Tree[0][0..k-1] (degree k/2) Tree[1][0..k-1] (degree k/4), ..., Tree[lgk-1][0..k-1] (degree 1) (then we should have initially Tree[lgk-1] = a). The parameter dolvl signals that only level 'dolvl' of the tree should be computed (dolvl < 0 means all levels). Either Tree <> NULL and TreeFile == NULL, and we write the tree to memory, or Tree == NULL and TreeFile <> NULL, and we write the tree to disk. */ int PolyFromRoots_Tree (listz_t G, listz_t a, unsigned int k, listz_t T, int dolvl, mpz_t n, listz_t *Tree, FILE *TreeFile, unsigned int sh) { unsigned int l, m; listz_t H1, *NextTree; ASSERT (k >= 1); if (k == 1) { /* we consider x + a[0], which mean we consider negated roots */ mpz_mod (G[0], a[0], n); return 0; } if (Tree == NULL) /* -treefile case */ { H1 = G; NextTree = NULL; } else { H1 = Tree[0] + sh; NextTree = Tree + 1; } m = k / 2; l = k - m; if (dolvl != 0) /* either dolvl < 0 and we need to compute all levels, or dolvl > 0 and we need first to compute lower levels */ { PolyFromRoots_Tree (H1, a, l, T, dolvl - 1, n, NextTree, TreeFile, sh); PolyFromRoots_Tree (H1 + l, a + l, m, T, dolvl - 1, n, NextTree, TreeFile, sh + l); } if (dolvl <= 0) { /* Write this level to disk, if requested */ if (TreeFile != NULL) { if (list_out_raw (TreeFile, H1, l) == ECM_ERROR || list_out_raw (TreeFile, H1 + l, m) == ECM_ERROR) { outputf (OUTPUT_ERROR, "Error writing product tree of F\n"); return ECM_ERROR; } } list_mul (T, H1, l, 1, H1 + l, m, 1, T + k); list_mod (G, T, k, n); } return 0; }
/* Multiplies b[0..k-1] by c[0..k-1], stores the result in a[0..2k-2], and stores the reduced product in a2[0..2k-2]. (Here, there is no implicit monic leading monomial.) Requires at least list_mul_mem(k) cells in t. */ void list_mulmod (listz_t a2, listz_t a, listz_t b, listz_t c, unsigned int k, listz_t t, mpz_t n) { int i; for (i = k; (i & 1) == 0; i >>= 1); ASSERTD(list_check(b,k,n)); ASSERTD(list_check(c,k,n)); if (i == 1 && Fermat) F_mul (a, b, c, k, DEFAULT, Fermat, t); else LIST_MULT_N (a, b, c, k, t); /* set a[0]...a[2l-2] */ list_mod (a2, a, 2 * k - 1, n); }
/* puts in G[0]..G[k-1] the coefficients from (x+a[0])...(x+a[k-1]) Warning: doesn't fill the coefficient 1 of G[k], which is implicit. Needs k + list_mul_mem(k/2) cells in T. G == a is allowed. T must not overlap with anything else. */ void PolyFromRoots (listz_t G, listz_t a, unsigned int k, listz_t T, mpz_t n) { unsigned int l, m; ASSERT (T != G && T != a); ASSERT (k >= 1); if (k == 1) { /* we consider x + a[0], which mean we consider negated roots */ mpz_mod (G[0], a[0], n); return; } m = k / 2; /* m >= 1 */ l = k - m; /* l >= 1 */ PolyFromRoots (G, a, l, T, n); PolyFromRoots (G + l, a + l, m, T, n); list_mul (T, G, l, 1, G + l, m, 1, T + k); list_mod (G, T, k, n); }
/* Returns in a[0]+a[1]*x+...+a[K-1]*x^(K-1) the remainder of the division of A = a[0]+a[1]*x+...+a[2K-2]*x^(2K-2) by B = b[0]+b[1]*x+...+b[K-1]*x^(K-1)+b[K]*x^K with b[K]=1 *explicit*. (We have A = Q*B + R with deg(Q)=K-2 and deg(R)=K-1.) Assumes invb[0]+invb[1]*x+...+invb[K-2]*x^(K-2) equals Quo(x^(2K-2), B). Assumes K >= 2. Requires 2K-1 + list_mul_mem(K) cells in t. Notations: R = r[0..K-1], A = a[0..2K-2], low(A) = a[0..K-1], high(A) = a[K..2K-2], Q = t[0..K-2] Return non-zero iff an error occurred. */ int PrerevertDivision (listz_t a, listz_t b, listz_t invb, unsigned int K, listz_t t, mpz_t n) { int po2, wrap; listz_t t2 = NULL; #ifdef WRAP wrap = ks_wrapmul_m (K + 1, K + 1, n) <= 2 * K - 1 + list_mul_mem (K); #else wrap = 0; #endif /* Q <- high(high(A) * INVB) with a short product */ for (po2 = K; (po2 & 1) == 0; po2 >>= 1); po2 = (po2 == 1); if (Fermat && po2) { mpz_set_ui (a[2 * K - 1], 0); if (K <= 4 * Fermat) { F_mul (t, a + K, invb, K, DEFAULT, Fermat, t + 2 * K); /* Put Q in T, as we still need high(A) later on */ list_mod (t, t + K - 2, K, n); } else { F_mul (t, a + K, invb, K, DEFAULT, Fermat, t + 2 * K); list_mod (a + K, t + K - 2, K, n); } } else /* non-Fermat case */ { list_mul_high (t, a + K, invb, K - 1, t + 2 * K - 3); /* the high part of A * INVB is now in {t+K-2, K-1} */ if (wrap) { MEMORY_TAG; t2 = init_list2 (K - 1, mpz_sizeinbase (n, 2)); MEMORY_UNTAG; if (t2 == NULL) { fprintf (ECM_STDERR, "Error, not enough memory\n"); return ECM_ERROR; } list_mod (t2, t + K - 2, K - 1, n); } else /* we can store in high(A) which is no longer needed */ list_mod (a + K, t + K - 2, K - 1, n); } /* the quotient Q = trunc(A / B) has degree K-2, i.e. K-1 terms */ /* T <- low(Q * B) with a short product */ mpz_set_ui (a[2 * K - 1], 0); if (Fermat && po2) { if (K <= 4 * Fermat) { /* Multiply without zero padding, result is (mod x^K - 1) */ F_mul (t + K, t, b, K, NOPAD, Fermat, t + 2 * K); /* Take the leading monomial x^K of B into account */ list_add (t, t + K, t, K); /* Subtract high(A) */ list_sub(t, t, a + K, K); } else F_mul (t, a + K, b, K, DEFAULT, Fermat, t + 2 * K); } else /* non-Fermat case */ { #ifdef KS_MULTIPLY /* ks is faster */ if (wrap) /* Q = {t2, K-1}, B = {b, K+1} We know that Q*B vanishes with the coefficients of degree K to 2K-2 of {A, 2K-1} */ { unsigned int m; m = ks_wrapmul (t, K + 1, b, K + 1, t2, K - 1, n); clear_list (t2, K - 1); /* coefficients of degree m..2K-2 wrap around, i.e. were subtracted to 0..2K-2-m */ if (m < 2 * K - 1) /* otherwise product is exact */ list_add (t, t, a + m, 2 * K - 1 - m); } else LIST_MULT_N (t, a + K, b, K, t + 2 * K - 1); #else list_mul_low (t, a + K, b, K, t + 2 * K - 1, n); #endif } /* now {t, K} contains the low K terms from Q*B */ list_sub (a, a, t, K); list_mod (a, a, K, n); return 0; }
/* divides a[0]+a[1]*x+...+a[2K-1]*x^(2K-1) By b[0]+b[1]*x+...+b[K-1]*x^(K-1)+x^K i.e. a polynomial of 2K coefficients divided by a monic polynomial with K+1 coefficients (b[K]=1 is implicit). Puts the quotient in q[0]+q[1]*x+...+q[K-1]*x^(K-1) and the remainder in a[0]+a[1]*x+...+a[K-1]*x^(K-1) Needs space for list_mul_mem(K) coefficients in t. If top is non-zero, a[0]..a[K-1] are reduced mod n. */ void RecursiveDivision (listz_t q, listz_t a, listz_t b, unsigned int K, listz_t t, mpz_t n, int top) { if (K == 1) /* a0+a1*x = a1*(b0+x) + a0-a1*b0 */ { mpz_mod (a[1], a[1], n); mpz_mul (q[0], a[1], b[0]); mpz_mod (q[0], q[0], n); mpz_sub (a[0], a[0], q[0]); if (top) mpz_mod (a[0], a[0], n); mpz_set (q[0], a[1]); } else { unsigned int k, l, i, po2; k = K / 2; l = K - k; for (po2 = K; (po2 && 1) == 0; po2 >>= 1); po2 = (po2 == 1); /* first perform a (2l) / l division */ RecursiveDivision (q + k, a + 2 * k, b + k, l, t, n, 0); /* subtract q[k..k+l-1] * b[0..k-1] */ ASSERTD(list_check(q+l,k,n) && list_check(b,k,n)); if (po2 && Fermat) F_mul (t, q + l, b, k, DEFAULT, Fermat, t + K); /* sets t[0..2*k-2]*/ else LIST_MULT_N (t, q + l, b, k, t + K - 1); /* sets t[0..2*k-2] */ list_sub (a + l, a + l, t, 2 * k - 1); if (k < l) /* don't forget to subtract q[k] * b[0..k-1] */ { for (i=0; i<k; i++) { mpz_mul (t[0], q[k], b[i]); /* TODO: need to reduce t[0]? */ mpz_sub (a[k+i], a[k+i], t[0]); } } /* remainder is in a[0..K+k-1] */ /* then perform a (2k) / k division */ RecursiveDivision (q, a + l, b + l, k, t, n, 0); /* subtract q[0..k-1] * b[0..l-1] */ ASSERTD(list_check(q,k,n) && list_check(b,k,n)); if (po2 && Fermat) F_mul (t, q, b, k, DEFAULT, Fermat, t + K); else LIST_MULT_N (t, q, b, k, t + K - 1); list_sub (a, a, t, 2 * k - 1); if (k < l) /* don't forget to subtract q[0..k-1] * b[k] */ { for (i=0; i<k; i++) { mpz_mul (t[0], q[i], b[k]); /* TODO: need to reduce t[0]? */ mpz_sub (a[k+i], a[k+i], t[0]); } } /* normalizes the remainder wrt n */ if (top) list_mod (a, a, K, n); } }
/* puts in q[0..K-1] the quotient of x^(2K-2) by B where B = b[0]+b[1]*x+...+b[K-1]*x^(K-1) with b[K-1]=1. */ void PolyInvert (listz_t q, listz_t b, unsigned int K, listz_t t, mpz_t n) { if (K == 1) { mpz_set_ui (q[0], 1); return; } else { int k, l, po2, use_middle_product = 0; #ifdef KS_MULTIPLY use_middle_product = 1; #endif k = K / 2; l = K - k; for (po2 = K; (po2 & 1) == 0; po2 >>= 1); po2 = (po2 == 1 && Fermat != 0); /* first determine l most-significant coeffs of Q */ PolyInvert (q + k, b + k, l, t, n); /* Q1 = {q+k, l} */ /* now Q1 * B = x^(2K-2) + O(x^(2K-2-l)) = x^(2K-2) + O(x^(K+k-2)). We need the coefficients of degree K-1 to K+k-2 of Q1*B */ ASSERTD(list_check(q+k,l,n) && list_check(b,l,n)); if (po2 == 0 && use_middle_product) { TMulKS (t, k - 1, q + k, l - 1, b, K - 1, n, 0); list_neg (t, t, k, n); } else if (po2) { list_revert (q + k, l); /* This expects the leading monomials explicitly in q[2k-1] and b[k+l-1] */ F_mul_trans (t, q + k, b, K / 2, K, Fermat, t + k); list_revert (q + k, l); list_neg (t, t, k, n); } else { LIST_MULT_N (t, q + k, b, l, t + 2 * l - 1); /* t[0..2l-1] = Q1 * B0 */ list_neg (t, t + l - 1, k, n); if (k > 1) { list_mul (t + k, q + k, l - 1, 1, b + l, k - 1, 1, t + k + K - 2); /* Q1 * B1 */ list_sub (t + 1, t + 1, t + k, k - 1); } } list_mod (t, t, k, n); /* high(1-B*Q1) */ ASSERTD(list_check(t,k,n) && list_check(q+l,k,n)); if (po2) F_mul (t + k, t, q + l, k, DEFAULT, Fermat, t + 3 * k); else LIST_MULT_N (t + k, t, q + l, k, t + 3 * k - 1); list_mod (q, t + 2 * k - 1, k, n); } }
int main(int argc, char **argv) { /* pipe descriptors */ int pd_rd[2], pd_wr[2]; pid_t pid; char *pppd = STD_PPPD_PATH; char *log_path = STD_LOG_PATH; char *ip = NULL; char *mod_name = NULL; int mod_idx; int i; int need_arg = 0; int mod_argc = 0; char **mod_argv = NULL; prog_name = argv[0]; /* parsing arguments */ if (argc < 2) help(argv[0]); for (i = 1; i < argc; i++) { if (need_arg) { switch (need_arg) { case ARG_MODULE: mod_name = argv[i]; break; case ARG_LOG_PATH: log_path = argv[i]; break; default: fprintf(stderr, "there is internal problem with parsing arguments\n"); return 1; } need_arg = 0; continue; } if (argv[i][0] != '-') { /* <local_ip>:<remote_ip> */ ip = argv[i]; continue; } if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i])) /* print help and exit */ help(argv[0]); if (!strcmp("-l", argv[i]) || !strcmp("--list", argv[i])) /* print list of available modules and exit */ list_mod(); if (!strcmp("-L", argv[i])) { /* specify file for logging */ need_arg = ARG_LOG_PATH; continue; } if (!strcmp("-m", argv[i])) { /* choose module */ need_arg = ARG_MODULE; continue; } if (!strcmp("-q", argv[i]) || !strcmp("--quiet", argv[i])) { /* quiet mode */ quiet = 1; continue; } if (!strcmp("--", argv[i])) { /* TODO: set pointer to i+1, the rest options are for pppd */ mod_argv = argv + i; mod_argc = argc - i; break; } /* unrecognized options may be addressed for the module */ } if (need_arg) { fprintf(stderr, "incomplete arguments, see %s --help\n", argv[0]); return 2; } /* check whether required arguments are set */ if (!mod_name) { fprintf(stderr, "you must choose a module, see %s --help\n", argv[0]); return 2; } /* redirect logs to a file */ redirect_logs(log_path); /* check whether module name is correct */ if ((mod_idx = is_mod(mod_name)) < 0) { fprintf(stderr, "there isn't such a module: %s\n", mod_name); return 2; } /* create pipes for communication with pppd */ if (pipe(pd_rd) < 0) err_exit("pipe"); if (pipe(pd_wr) < 0) err_exit("pipe"); /* exec pppd */ if ((pid = fork()) < 0) err_exit("fork"); if (!pid) { if (dup2(pd_rd[1], 1) < 0) err_exit("dup2"); if (dup2(pd_wr[0], 0) < 0) err_exit("dup2"); close(pd_rd[0]); close(pd_rd[1]); close(pd_wr[0]); close(pd_wr[1]); execl(pppd, pppd, "nodetach", "noauth", "notty", "passive", ip, NULL); err_exit("execl"); } close(pd_rd[1]); close(pd_wr[0]); /* run appropriate module's function */ return mod_tbl[mod_idx].func(mod_argc, mod_argv, pd_rd[0], pd_wr[1]); }