Guest User

Untitled

a guest
May 24th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.25 KB | None | 0 0
  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <vector>
  6. #include <cmath>
  7.  
  8.  
  9. #include "gmp.h"
  10. #include <gmpxx.h>
  11.  
  12. using namespace std;
  13.  
  14. struct factorBaseElement
  15. {
  16. double logp;
  17. int prime;
  18. int start1, start2;
  19. };
  20.  
  21. const int EXTRA = 5;
  22. int factorBaseSize = 8;
  23. int interValSize = 300;
  24.  
  25. vector<factorBaseElement> factorBase(factorBaseSize);
  26. vector<int> interval(interValSize);
  27. vector<int> intervalOrig(interValSize);
  28.  
  29.  
  30. vector<double> intervalLog(interValSize, 0);
  31.  
  32. mpz_t matrix[8+5];
  33. mpz_t tal[8+5];
  34. mpz_t talOrig[8+5];
  35.  
  36.  
  37. mpz_t N;
  38. double THRESHOLD;
  39. int STARVALUE;
  40.  
  41.  
  42. void shanksTonelliAlg(mpz_t res, mpz_t prime, mpz_t n);
  43. bool trialDivision2(mpz_t res, mpz_t tal);
  44. void trialDivision(int tal);
  45.  
  46.  
  47. void init()
  48. {
  49. mpz_array_init(matrix[0], factorBaseSize + EXTRA, factorBaseSize*2 + EXTRA);
  50. mpz_array_init(tal[0], factorBaseSize + EXTRA, factorBaseSize*2 + EXTRA);
  51. mpz_array_init(talOrig[0], factorBaseSize + EXTRA, factorBaseSize*2 + EXTRA);
  52.  
  53.  
  54. mpz_t n, tmp, tmp2, tmp3;
  55. mpz_init(tmp); mpz_init(tmp2); mpz_init(tmp3);
  56.  
  57. mpz_sqrtrem(tmp, tmp2, N);
  58. STARVALUE = mpz_get_ui(tmp);
  59. if(mpz_cmp_ui(tmp2, 0) != 0)
  60. STARVALUE++;
  61. cout << "STARVALUE: " << STARVALUE << endl;
  62.  
  63. mpz_sqrt(tmp, N);
  64. THRESHOLD = log(mpz_get_ui(N))/log(2.0) - log(100);
  65. cout << "THRESHOLD: " << THRESHOLD << endl;
  66.  
  67.  
  68. ///////////////////////////////// init interval values
  69. mpz_set_ui(tmp, STARVALUE);
  70. for(int i = 0; i < interValSize; i++)
  71. {
  72.  
  73. mpz_add_ui(tmp2, tmp, i);
  74. intervalOrig[i] = mpz_get_ui(tmp2);
  75. mpz_mul(tmp2, tmp2, tmp2);
  76. mpz_sub(tmp2, tmp2, N);
  77. interval[i] = mpz_get_ui(tmp2);;
  78. }
  79. //////////////////////////////////////
  80.  
  81. }
  82.  
  83. void initFactorBase()
  84. {
  85. mpz_t p;
  86. mpz_init_set_ui(p, 3);
  87. factorBase[0].prime = 2;
  88. factorBase[0].logp = log(2.0)/log(2.0);
  89. factorBase[0].start1 = factorBase[0].start2 = 0;
  90.  
  91. for(int i = 1; i < factorBaseSize; mpz_nextprime(p, p))
  92. {
  93. if(mpz_legendre(N, p) != 1)
  94. continue;
  95. int prime = mpz_get_ui(p);
  96. factorBase[i].prime = prime;
  97. factorBase[i].logp = log(prime)/log(2.0);
  98.  
  99. mpz_t res; mpz_init(res);
  100. shanksTonelliAlg(res, p, N);
  101.  
  102. int start1 = mpz_get_ui(res);
  103. int start2 = prime - start1;
  104. start1 = (int)ceil((STARVALUE - start1)/(double)prime)*prime + start1;
  105. start2 = (int)ceil((STARVALUE - start2)/(double)prime)*prime + start2;
  106.  
  107. factorBase[i].start1 = start1 - STARVALUE;
  108. factorBase[i].start2 = start2 - STARVALUE;
  109. i++;
  110. }
  111. }
  112.  
  113. void shanksTonelliAlg(mpz_t res, mpz_t prime, mpz_t n)
  114. {
  115. if (mpz_legendre(n, prime) == -1)
  116. return;
  117. int s;
  118. mpz_t tmp, Q, W, R, V;
  119. mpz_init(tmp); mpz_sub_ui(tmp, prime, 1);
  120. mpz_init(Q); mpz_init(W); mpz_init(R); mpz_init(V);
  121.  
  122. s = mpz_scan1 (tmp, 0); // p-1 = Q2^s
  123. mpz_div_2exp(Q, tmp, s);
  124.  
  125.  
  126. while(true)
  127. {
  128. mpz_random(W, 2);
  129. mpz_mod(W, W, prime);
  130. if(mpz_legendre(W, prime) == -1)
  131. {
  132. mpz_set_ui(res, 0);
  133. break;
  134. }
  135. }
  136.  
  137.  
  138. mpz_add_ui(tmp, Q, 1);
  139. mpz_div_2exp(tmp, tmp, 1);
  140. mpz_powm(R, n, tmp, prime); // X = n^(Q-1)/2 mod p
  141.  
  142. mpz_powm(V, W, Q, prime); // Y = w^Q mod p
  143.  
  144. mpz_t inv, RR;
  145. mpz_init_set(inv, n); mpz_init(RR);
  146. mpz_invert(inv, inv, prime);
  147.  
  148. while(true)
  149. {
  150. mpz_mul(RR, R, R);
  151. mpz_mul(RR, RR, inv);
  152. int i;
  153. for(i = 0; i < s; i++)
  154. {
  155. mpz_mod(RR, RR, prime);
  156. if(mpz_cmp_ui(RR, 1) == 0)
  157. break;
  158. mpz_mul(RR, RR, RR);
  159. }
  160. if(i == 0)
  161. break;
  162.  
  163. mpz_set_ui(tmp, 1);
  164. mpz_mul_2exp(tmp, tmp, s-i-1);
  165.  
  166. mpz_powm(tmp, V, tmp, prime);
  167. mpz_mul(R, R, tmp);
  168. mpz_mod(R, R, prime);
  169. }
  170. mpz_set(res, R);
  171. }
  172.  
  173. void sieving()
  174. {
  175. mpz_t tmp, tmp2;
  176. mpz_init(tmp); mpz_init(tmp2);
  177. for(int i = 1; i < factorBaseSize; i++)
  178. {
  179. for(int j = 0; j < 2; j++)
  180. {
  181. int index = (j == 0)? factorBase[i].start1: factorBase[i].start2;
  182. for(; index < interValSize; index += factorBase[i].prime)
  183. {
  184. int tmp = interval[index];
  185. while(tmp % factorBase[i].prime == 0)
  186. {
  187. tmp /= factorBase[i].prime;
  188. intervalLog[index] += factorBase[i].logp;
  189. }
  190. }
  191.  
  192. }
  193. }
  194. }
  195.  
  196. void gauss_eliminate()
  197. {
  198. int size = factorBaseSize+EXTRA;
  199. bool found;
  200. /* Initialize the identity matrix */
  201. for(int i = 0; i < size; i++)
  202. mpz_setbit(matrix[i], factorBaseSize+i);
  203. int i;
  204. for(i = 0; i < size; i++)
  205. {
  206. /* Does this row contain only zeros */
  207. if(mpz_cmp_ui(matrix[i], 0) == 0)
  208. {
  209. /* If there is an all zero row below this one then swap the rows */
  210. found = false;
  211. for(int j = i+1; j < size; j++)
  212. {
  213. if (mpz_cmp_ui(matrix[j], 0) != 0)
  214. {
  215. found = true;
  216. break;
  217. }
  218. if(found == false)
  219. return;
  220. else
  221. mpz_swap(matrix[i], matrix[j]);
  222. }
  223. }
  224. /* Find the index of the first non-zero entry in this row and if there is a non-zero entry in the matrix below and to the left then swap */
  225. found = true;
  226. int j, l;
  227. while(found)
  228. {
  229. found = false;
  230. j = mpz_scan1(matrix[i], 0);
  231. if(j > 0)
  232. {
  233. for (int k = i+1; k < size; k++)
  234. {
  235. l = mpz_scan1(matrix[k], 0);
  236. if (l < j)
  237. {
  238. mpz_swap(matrix[i], matrix[k]);
  239. found = 1;
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. /* Change every other rows j'th entry to 0 */
  246. for (int k = 0; k < size; k++)
  247. {
  248. if (i != k)
  249. {
  250. l = mpz_scan1(matrix[k], 0);
  251. if (l == j)
  252. mpz_xor(matrix[k], matrix[i], matrix[k]);
  253. }
  254. }
  255. }
  256. }
  257. void createMatrix()
  258. {
  259. mpz_t res; mpz_init(res);
  260. mpz_t tmp; mpz_init(tmp);
  261. mpz_t tmp2; mpz_init(tmp2);
  262. int cols = 0;
  263. for(int i = 0; i < interValSize; i++)
  264. {
  265. if(intervalLog[i] >= THRESHOLD)
  266. {
  267. mpz_set_ui(tmp, interval[i]);
  268.  
  269. if(trialDivision2(res, tmp))
  270. {
  271. mpz_set_ui(tmp2, interval[i]);
  272. mpz_set(tal[cols], tmp2);
  273.  
  274. mpz_set_ui(tmp2, intervalOrig[i]);
  275. mpz_set(talOrig[cols], tmp2);
  276.  
  277. mpz_set(matrix[cols], res);
  278. cols++;
  279. if(cols >= factorBaseSize+EXTRA)
  280. {
  281. gauss_eliminate();
  282. return;
  283. }
  284. }
  285. }
  286. }
  287. }
  288.  
  289. void findFactors()
  290. {
  291.  
  292.  
  293. int first, retries, success;
  294. mpz_t x, y;
  295. mpz_t tmp, tmp2;
  296. mpz_t q, p, gcd;
  297.  
  298. mpz_init(x); mpz_init(y); mpz_init(tmp); mpz_init(tmp2);
  299. mpz_init(q); mpz_init(p); mpz_init(gcd);
  300. mpz_set_ui(y, 0);
  301. for(int i = 1; i < factorBaseSize; i++)
  302. mpz_setbit(y, i);
  303.  
  304. first = retries = success = 0;
  305. for (int i = factorBaseSize + EXTRA - 1; i > 0; i--)
  306. {
  307. mpz_and(x, matrix[i], y);
  308. if (mpz_cmp_ui(x, 0) != 0)
  309. {
  310. first = i + 1;
  311. break;
  312. }
  313. }
  314. /* Loop through all possible solutions */
  315. for (int i = first; i < factorBaseSize + EXTRA; i++)
  316. {
  317. mpz_set_ui(y, 1);
  318. mpz_set_ui(x, 1);
  319. for (int j = 0; j < factorBaseSize + EXTRA; j++)
  320. {
  321. if (mpz_tstbit(matrix[i], factorBaseSize + j))
  322. {
  323. cout << "j: "<< j << endl;
  324. mpz_set(tmp, tal[j]);
  325. mpz_set(tmp2, talOrig[j]);
  326. cout << "tmp: " << tmp << endl;
  327. mpz_mul(y, y, tmp);
  328. mpz_mul(x, x, tmp2);
  329. }
  330. }
  331. cout << "y: " << y << endl;
  332. mpz_sqrt(y, y);
  333. mpz_sub(gcd, y, x);
  334. mpz_gcd(p, gcd, N);
  335.  
  336. cout << "y: " << y << endl;
  337. if (mpz_cmp_ui(p, 1) == 0 || mpz_cmp(p, N) == 0)
  338. /* We got the trivial solution. Let's try again */
  339. retries++;
  340. else {
  341. /* We found the non-trivial factorization */
  342. mpz_add(gcd, y, x);
  343. mpz_gcd(q, gcd, N);
  344. success = 1;
  345. break;
  346. }
  347. }
  348.  
  349. if(!success)
  350. {
  351. printf("Unable to find a factorization of ");
  352. cout << N << endl;
  353. }
  354. else
  355. cout << N << " = " << q << " * " << p << endl;
  356. }
  357.  
  358. void trialDivision(int tal)
  359. {
  360. for(int i = 2; i <= tal; i++)
  361. {
  362. while(tal%i == 0)
  363. {
  364. cout << i << " ";
  365. tal /= i;
  366. }
  367. }
  368. cout << endl;
  369. }
  370.  
  371. bool trialDivision2(mpz_t res, mpz_t tal)
  372. {
  373. mpz_t tmp; mpz_init(tmp);
  374. mpz_set_ui(res, 0);
  375.  
  376. for(int i = 0; i < factorBase.size(); i++)
  377. {
  378. while(mpz_cdiv_q_ui(tmp, tal, factorBase[i].prime) == 0)
  379. {
  380. //cout << factorBase[i].prime << " ";
  381. mpz_set(tal, tmp);
  382. mpz_combit(res, i);
  383. }
  384. if(mpz_cmp_ui(tal, 1) == 0)
  385. {
  386. //cout << endl;
  387. return true;
  388. }
  389. }
  390. //cout << endl;
  391. return false;
  392. }
  393.  
  394.  
  395. int main()
  396. {
  397. mpz_t tmp; mpz_init(tmp);
  398. mpz_t tmp2; mpz_init(tmp2);
  399. gmp_scanf("%Zd", N);
  400.  
  401. init();
  402. initFactorBase();
  403. cout << "primes: " << endl;
  404. for(int i = 0; i < factorBase.size(); i++)
  405. cout << factorBase[i].prime << " ";
  406. cout << endl;
  407. sieving();
  408. createMatrix();
  409. findFactors();
  410.  
  411.  
  412. return 0;
  413. }
Add Comment
Please, Sign In to add comment