bgn_util.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. #include "sec_osal_light.h"
  2. #include "sec_osal.h"
  3. #include "sec_cust_struct.h"
  4. #include "bgn_internal.h"
  5. #define MOD "BGN"
  6. /**************************************************************************
  7. * FUNCTIONS
  8. **************************************************************************/
  9. int bgn_grow(bgn *P_X, int nbl)
  10. {
  11. ulong *p;
  12. if (P_X->n < nbl) {
  13. p = (ulong *) osal_kmalloc(nbl * ciL);
  14. if (p == NULL)
  15. return 1;
  16. memset(p, 0, nbl * ciL);
  17. if (P_X->p != NULL) {
  18. memcpy(p, P_X->p, P_X->n * ciL);
  19. memset(P_X->p, 0, P_X->n * ciL);
  20. osal_kfree(P_X->p);
  21. }
  22. P_X->n = nbl;
  23. P_X->p = p;
  24. }
  25. return 0;
  26. }
  27. int bgn_copy(bgn *P_X, const bgn *Y)
  28. {
  29. int ret, i;
  30. if (P_X == Y)
  31. return 0;
  32. for (i = Y->n - 1; i > 0; i--)
  33. if (Y->p[i] != 0)
  34. break;
  35. i++;
  36. P_X->s = Y->s;
  37. ret = bgn_grow(P_X, i);
  38. if (0 != ret)
  39. goto _exit;
  40. memset(P_X->p, 0, P_X->n * ciL);
  41. memcpy(P_X->p, Y->p, i * ciL);
  42. _exit:
  43. return ret;
  44. }
  45. void bgn_swap(bgn *P_X, bgn *Y)
  46. {
  47. bgn T;
  48. memcpy(&T, P_X, sizeof(bgn));
  49. memcpy(P_X, Y, sizeof(bgn));
  50. memcpy(Y, &T, sizeof(bgn));
  51. }
  52. int bgn_lset(bgn *P_X, int z)
  53. {
  54. int ret;
  55. ret = bgn_grow(P_X, 1);
  56. if (0 != ret)
  57. goto _exit;
  58. memset(P_X->p, 0, P_X->n * ciL);
  59. P_X->p[0] = (z < 0) ? -z : z;
  60. P_X->s = (z < 0) ? -1 : 1;
  61. _exit:
  62. return ret;
  63. }
  64. int bgn_lsb(const bgn *P_X)
  65. {
  66. int i, j, count = 0;
  67. for (i = 0; i < P_X->n; i++)
  68. for (j = 0; j < (int)biL; j++, count++)
  69. if (((P_X->p[i] >> j) & 1) != 0)
  70. return count;
  71. return 0;
  72. }
  73. int bgn_msb(const bgn *P_X)
  74. {
  75. int i, j;
  76. for (i = P_X->n - 1; i > 0; i--)
  77. if (P_X->p[i] != 0)
  78. break;
  79. for (j = biL - 1; j >= 0; j--)
  80. if (((P_X->p[i] >> j) & 1) != 0)
  81. break;
  82. return (i * biL) + j + 1;
  83. }
  84. int bgn_size(const bgn *P_X)
  85. {
  86. return (bgn_msb(P_X) + 7) >> 3;
  87. }
  88. int bgn_shift_l(bgn *P_X, int count)
  89. {
  90. int ret, i, v0, t1;
  91. ulong r0 = 0, r1;
  92. v0 = count / (biL);
  93. t1 = count & (biL - 1);
  94. i = bgn_msb(P_X) + count;
  95. if (P_X->n * (int)biL < i) {
  96. ret = bgn_grow(P_X, B_T_L(i));
  97. if (0 != ret)
  98. goto _exit;
  99. }
  100. ret = 0;
  101. if (v0 > 0) {
  102. for (i = P_X->n - 1; i >= v0; i--)
  103. P_X->p[i] = P_X->p[i - v0];
  104. for (; i >= 0; i--)
  105. P_X->p[i] = 0;
  106. }
  107. if (t1 > 0) {
  108. for (i = v0; i < P_X->n; i++) {
  109. r1 = P_X->p[i] >> (biL - t1);
  110. P_X->p[i] <<= t1;
  111. P_X->p[i] |= r0;
  112. r0 = r1;
  113. }
  114. }
  115. _exit:
  116. return ret;
  117. }
  118. int bgn_shift_r(bgn *P_X, int count)
  119. {
  120. int i, v0, v1;
  121. ulong r0 = 0, r1;
  122. v0 = count / biL;
  123. v1 = count & (biL - 1);
  124. if (v0 > 0) {
  125. for (i = 0; i < P_X->n - v0; i++)
  126. P_X->p[i] = P_X->p[i + v0];
  127. for (; i < P_X->n; i++)
  128. P_X->p[i] = 0;
  129. }
  130. if (v1 > 0) {
  131. for (i = P_X->n - 1; i >= 0; i--) {
  132. r1 = P_X->p[i] << (biL - v1);
  133. P_X->p[i] >>= v1;
  134. P_X->p[i] |= r0;
  135. r0 = r1;
  136. }
  137. }
  138. return 0;
  139. }
  140. int bgn_cmp_abs(const bgn *P_X, const bgn *Y)
  141. {
  142. int i, j;
  143. for (i = P_X->n - 1; i >= 0; i--) {
  144. if (P_X->p[i] != 0)
  145. break;
  146. }
  147. for (j = Y->n - 1; j >= 0; j--) {
  148. if (Y->p[j] != 0)
  149. break;
  150. }
  151. if (i < 0 && j < 0)
  152. return 0;
  153. if (i > j)
  154. return 1;
  155. if (j > i)
  156. return -1;
  157. for (; i >= 0; i--) {
  158. if (P_X->p[i] > Y->p[i])
  159. return 1;
  160. if (P_X->p[i] < Y->p[i])
  161. return -1;
  162. }
  163. return 0;
  164. }
  165. int bgn_cmp_num(const bgn *P_X, const bgn *Y)
  166. {
  167. int i, j;
  168. for (i = P_X->n - 1; i >= 0; i--) {
  169. if (P_X->p[i] != 0)
  170. break;
  171. }
  172. for (j = Y->n - 1; j >= 0; j--) {
  173. if (Y->p[j] != 0)
  174. break;
  175. }
  176. if (i < 0 && j < 0)
  177. return 0;
  178. if (i > j)
  179. return P_X->s;
  180. if (j > i)
  181. return -P_X->s;
  182. if (P_X->s > 0 && Y->s < 0)
  183. return 1;
  184. if (Y->s > 0 && P_X->s < 0)
  185. return -1;
  186. for (; i >= 0; i--) {
  187. if (P_X->p[i] > Y->p[i])
  188. return P_X->s;
  189. if (P_X->p[i] < Y->p[i])
  190. return -P_X->s;
  191. }
  192. return 0;
  193. }
  194. int bgn_cmp_int(const bgn *P_X, int z)
  195. {
  196. bgn Y;
  197. ulong p[1];
  198. *p = (z < 0) ? -z : z;
  199. Y.s = (z < 0) ? -1 : 1;
  200. Y.n = 1;
  201. Y.p = p;
  202. return bgn_cmp_num(P_X, &Y);
  203. }
  204. int bgn_add_abs(bgn *P_X, const bgn *P_A, const bgn *P_B)
  205. {
  206. int ret, i, j;
  207. ulong *o, *p, c;
  208. if (P_X == P_B) {
  209. const bgn *T = P_A;
  210. P_A = P_X;
  211. P_B = T;
  212. }
  213. if (P_X != P_A) {
  214. ret = bgn_copy(P_X, P_A);
  215. if (0 != ret)
  216. goto _exit;
  217. }
  218. P_X->s = 1;
  219. for (j = P_B->n - 1; j >= 0; j--) {
  220. if (P_B->p[j] != 0)
  221. break;
  222. }
  223. ret = bgn_grow(P_X, j + 1);
  224. if (0 != ret)
  225. goto _exit;
  226. o = P_B->p;
  227. p = P_X->p;
  228. c = 0;
  229. for (i = 0; i <= j; i++, o++, p++) {
  230. *p += c;
  231. c = (*p < c);
  232. *p += *o;
  233. c += (*p < *o);
  234. }
  235. while (c != 0) {
  236. if (i >= P_X->n) {
  237. ret = bgn_grow(P_X, i + 1);
  238. if (0 != ret)
  239. goto _exit;
  240. p = P_X->p + i;
  241. }
  242. *p += c;
  243. c = (*p < c);
  244. i++;
  245. }
  246. _exit:
  247. return ret;
  248. }
  249. void bgn_sub_hlp(int n, ulong *s, ulong *d)
  250. {
  251. int i;
  252. ulong c, z;
  253. for (i = c = 0; i < n; i++, s++, d++) {
  254. z = (*d < c);
  255. *d -= c;
  256. c = (*d < *s) + z;
  257. *d -= *s;
  258. }
  259. while (c != 0) {
  260. z = (*d < c);
  261. *d -= c;
  262. c = z;
  263. i++;
  264. d++;
  265. }
  266. }
  267. int bgn_sub_abs(bgn *P_X, const bgn *P_A, const bgn *P_B)
  268. {
  269. bgn TB;
  270. int ret, n;
  271. if (bgn_cmp_abs(P_A, P_B) < 0)
  272. return E_BGN_NEGATIVE_VALUE;
  273. bgn_init(&TB);
  274. if (P_X == P_B) {
  275. ret = bgn_copy(&TB, P_B);
  276. if (0 != ret)
  277. goto _exit;
  278. P_B = &TB;
  279. }
  280. if (P_X != P_A) {
  281. ret = bgn_copy(P_X, P_A);
  282. if (0 != ret)
  283. goto _exit;
  284. }
  285. P_X->s = 1;
  286. ret = 0;
  287. for (n = P_B->n - 1; n >= 0; n--) {
  288. if (P_B->p[n] != 0)
  289. break;
  290. }
  291. bgn_sub_hlp(n + 1, P_B->p, P_X->p);
  292. _exit:
  293. bgn_free(&TB);
  294. return ret;
  295. }
  296. int bgn_add_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
  297. {
  298. int ret, s = P_A->s;
  299. if (P_A->s * P_B->s < 0) {
  300. if (bgn_cmp_abs(P_A, P_B) >= 0) {
  301. ret = bgn_sub_abs(P_X, P_A, P_B);
  302. if (0 != ret)
  303. goto _exit;
  304. P_X->s = s;
  305. } else {
  306. ret = bgn_sub_abs(P_X, P_B, P_A);
  307. if (0 != ret)
  308. goto _exit;
  309. P_X->s = -s;
  310. }
  311. } else {
  312. ret = bgn_add_abs(P_X, P_A, P_B);
  313. if (0 != ret)
  314. goto _exit;
  315. P_X->s = s;
  316. }
  317. _exit:
  318. return ret;
  319. }
  320. int bgn_sub_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
  321. {
  322. int ret, s = P_A->s;
  323. if (P_A->s * P_B->s > 0) {
  324. if (bgn_cmp_abs(P_A, P_B) >= 0) {
  325. ret = bgn_sub_abs(P_X, P_A, P_B);
  326. if (0 != ret)
  327. goto _exit;
  328. P_X->s = s;
  329. } else {
  330. ret = bgn_sub_abs(P_X, P_B, P_A);
  331. if (0 != ret)
  332. goto _exit;
  333. P_X->s = -s;
  334. }
  335. } else {
  336. ret = bgn_add_abs(P_X, P_A, P_B);
  337. if (0 != ret)
  338. goto _exit;
  339. P_X->s = s;
  340. }
  341. _exit:
  342. return ret;
  343. }
  344. int bgn_add_int(bgn *P_X, const bgn *P_A, int b)
  345. {
  346. bgn _B;
  347. ulong p[1];
  348. p[0] = (b < 0) ? -b : b;
  349. _B.s = (b < 0) ? -1 : 1;
  350. _B.n = 1;
  351. _B.p = p;
  352. return bgn_add_bgn(P_X, P_A, &_B);
  353. }
  354. int bgn_sub_int(bgn *P_X, const bgn *P_A, int b)
  355. {
  356. bgn _B;
  357. ulong p[1];
  358. p[0] = (b < 0) ? -b : b;
  359. _B.s = (b < 0) ? -1 : 1;
  360. _B.n = 1;
  361. _B.p = p;
  362. return bgn_sub_bgn(P_X, P_A, &_B);
  363. }
  364. void bgn_alu(ulong **s, ulong **d, ulong b, ulong c, unsigned int loop_count)
  365. {
  366. unsigned int i;
  367. unsigned long s_0, s_1, b_0, b_1;
  368. unsigned long r_0, r_1, r_x, r_y;
  369. b_0 = (b << biH) >> biH;
  370. b_1 = (b >> biH);
  371. for (i = 0; i < loop_count; i++) {
  372. s_0 = (**s << biH) >> biH;
  373. s_1 = (**s >> biH); (*s)++;
  374. r_x = s_0 * b_1; r_0 = s_0 * b_0;
  375. r_y = s_1 * b_0; r_1 = s_1 * b_1;
  376. r_1 += (r_x >> biH);
  377. r_1 += (r_y >> biH);
  378. r_x <<= biH; r_y <<= biH;
  379. r_0 += r_x; r_1 += (r_0 < r_x);
  380. r_0 += r_y; r_1 += (r_0 < r_y);
  381. r_0 += c; r_1 += (r_0 < c);
  382. r_0 += (unsigned long)*d;
  383. r_1 += (r_0 < (unsigned long) *d);
  384. c = r_1; *((*d)++) = r_0;
  385. }
  386. }
  387. void bgn_mul_hlp(int i, ulong *s, ulong *d, ulong b)
  388. {
  389. ulong c = 0, t = 0;
  390. for (; i >= 16; i -= 16)
  391. bgn_alu(&s, &d, b, c, 16);
  392. for (; i >= 8; i -= 8)
  393. bgn_alu(&s, &d, b, c, 8);
  394. for (; i > 0; i--)
  395. bgn_alu(&s, &d, b, c, 1);
  396. t++;
  397. do {
  398. *d += c;
  399. c = (*d < c);
  400. d++;
  401. } while (c != 0);
  402. }
  403. int bgn_mul_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
  404. {
  405. int ret, i, j;
  406. bgn TA, TB;
  407. bgn_init(&TA);
  408. bgn_init(&TB);
  409. if (P_X == P_A) {
  410. ret = bgn_copy(&TA, P_A);
  411. if (0 != ret)
  412. goto _exit;
  413. P_A = &TA;
  414. }
  415. if (P_X == P_B) {
  416. ret = bgn_copy(&TB, P_B);
  417. if (0 != ret)
  418. goto _exit;
  419. P_B = &TB;
  420. }
  421. for (i = P_A->n - 1; i >= 0; i--) {
  422. if (P_A->p[i] != 0)
  423. break;
  424. }
  425. for (j = P_B->n - 1; j >= 0; j--) {
  426. if (P_B->p[j] != 0)
  427. break;
  428. }
  429. ret = bgn_grow(P_X, i + j + 2);
  430. if (0 != ret)
  431. goto _exit;
  432. ret = bgn_lset(P_X, 0);
  433. if (0 != ret)
  434. goto _exit;
  435. for (i++; j >= 0; j--)
  436. bgn_mul_hlp(i, P_A->p, P_X->p + j, P_B->p[j]);
  437. P_X->s = P_A->s * P_B->s;
  438. _exit:
  439. bgn_free(&TB);
  440. bgn_free(&TA);
  441. return ret;
  442. }
  443. int bgn_mul_int(bgn *P_X, const bgn *P_A, ulong b)
  444. {
  445. bgn _B;
  446. ulong p[1];
  447. _B.s = 1;
  448. _B.n = 1;
  449. _B.p = p;
  450. p[0] = b;
  451. return bgn_mul_bgn(P_X, P_A, &_B);
  452. }
  453. int bgn_div_bgn(bgn *P_Q, bgn *P_R, const bgn *P_A, const bgn *P_B)
  454. {
  455. int ret, i, n, t, k;
  456. bgn X, Y, Z, T1, T2;
  457. if (bgn_cmp_int(P_B, 0) == 0)
  458. return E_BGN_DIVISION_BY_ZERO;
  459. bgn_init(&X);
  460. bgn_init(&Y);
  461. bgn_init(&Z);
  462. bgn_init(&T1);
  463. bgn_init(&T2);
  464. if (bgn_cmp_abs(P_A, P_B) < 0) {
  465. if (P_Q != NULL) {
  466. ret = bgn_lset(P_Q, 0);
  467. if (0 != ret)
  468. goto _exit;
  469. }
  470. if (P_R != NULL) {
  471. ret = bgn_copy(P_R, P_A);
  472. if (0 != ret)
  473. goto _exit;
  474. }
  475. return 0;
  476. }
  477. ret = bgn_copy(&X, P_A);
  478. if (0 != ret)
  479. goto _exit;
  480. ret = bgn_copy(&Y, P_B);
  481. if (0 != ret)
  482. goto _exit;
  483. X.s = Y.s = 1;
  484. ret = bgn_grow(&Z, P_A->n + 2);
  485. if (0 != ret)
  486. goto _exit;
  487. ret = bgn_lset(&Z, 0);
  488. if (0 != ret)
  489. goto _exit;
  490. ret = bgn_grow(&T1, 2);
  491. if (0 != ret)
  492. goto _exit;
  493. ret = bgn_grow(&T2, 3);
  494. if (0 != ret)
  495. goto _exit;
  496. k = bgn_msb(&Y) % biL;
  497. if (k < (int)biL - 1) {
  498. k = biL - 1 - k;
  499. ret = bgn_shift_l(&X, k);
  500. if (0 != ret)
  501. goto _exit;
  502. ret = bgn_shift_l(&Y, k);
  503. if (0 != ret)
  504. goto _exit;
  505. } else {
  506. k = 0;
  507. }
  508. n = X.n - 1;
  509. t = Y.n - 1;
  510. bgn_shift_l(&Y, biL * (n - t));
  511. while (bgn_cmp_num(&X, &Y) >= 0) {
  512. Z.p[n - t]++;
  513. bgn_sub_bgn(&X, &X, &Y);
  514. }
  515. bgn_shift_r(&Y, biL * (n - t));
  516. for (i = n; i > t; i--) {
  517. if (X.p[i] >= Y.p[t]) {
  518. Z.p[i - t - 1] = ~0;
  519. } else {
  520. ulong q0, q1, r0, r1;
  521. ulong d0, d1, d, m;
  522. d = Y.p[t];
  523. d0 = (d << biH) >> biH;
  524. d1 = (d >> biH);
  525. q1 = X.p[i] / d1;
  526. r1 = X.p[i] - d1 * q1;
  527. r1 <<= biH;
  528. r1 |= (X.p[i - 1] >> biH);
  529. m = q1 * d0;
  530. if (r1 < m) {
  531. q1--, r1 += d;
  532. while (r1 >= d && r1 < m)
  533. q1--, r1 += d;
  534. }
  535. r1 -= m;
  536. q0 = r1 / d1;
  537. r0 = r1 - d1 * q0;
  538. r0 <<= biH;
  539. r0 |= (X.p[i - 1] << biH) >> biH;
  540. m = q0 * d0;
  541. if (r0 < m) {
  542. q0--, r0 += d;
  543. while (r0 >= d && r0 < m)
  544. q0--, r0 += d;
  545. }
  546. r0 -= m;
  547. Z.p[i - t - 1] = (q1 << biH) | q0;
  548. }
  549. Z.p[i - t - 1]++;
  550. do {
  551. Z.p[i - t - 1]--;
  552. ret = bgn_lset(&T1, 0);
  553. if (0 != ret)
  554. goto _exit;
  555. T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
  556. T1.p[1] = Y.p[t];
  557. ret = bgn_mul_int(&T1, &T1, Z.p[i - t - 1]);
  558. if (0 != ret)
  559. goto _exit;
  560. ret = bgn_lset(&T2, 0);
  561. if (0 != ret)
  562. goto _exit;
  563. T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
  564. T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
  565. T2.p[2] = X.p[i];
  566. } while (bgn_cmp_num(&T1, &T2) > 0);
  567. ret = bgn_mul_int(&T1, &Y, Z.p[i - t - 1]);
  568. if (0 != ret)
  569. goto _exit;
  570. ret = bgn_shift_l(&T1, biL * (i - t - 1));
  571. if (0 != ret)
  572. goto _exit;
  573. ret = bgn_sub_bgn(&X, &X, &T1);
  574. if (0 != ret)
  575. goto _exit;
  576. if (bgn_cmp_int(&X, 0) < 0) {
  577. ret = bgn_copy(&T1, &Y);
  578. if (0 != ret)
  579. goto _exit;
  580. ret = bgn_shift_l(&T1, biL * (i - t - 1));
  581. if (0 != ret)
  582. goto _exit;
  583. ret = bgn_add_bgn(&X, &X, &T1);
  584. if (0 != ret)
  585. goto _exit;
  586. Z.p[i - t - 1]--;
  587. }
  588. }
  589. if (P_Q != NULL) {
  590. bgn_copy(P_Q, &Z);
  591. P_Q->s = P_A->s * P_B->s;
  592. }
  593. if (P_R != NULL) {
  594. bgn_shift_r(&X, k);
  595. bgn_copy(P_R, &X);
  596. P_R->s = P_A->s;
  597. if (bgn_cmp_int(P_R, 0) == 0)
  598. P_R->s = 1;
  599. }
  600. _exit:
  601. bgn_free(&X);
  602. bgn_free(&Y);
  603. bgn_free(&Z);
  604. bgn_free(&T1);
  605. bgn_free(&T2);
  606. return ret;
  607. }
  608. int bgn_div_int(bgn *P_Q, bgn *P_R, const bgn *P_A, int b)
  609. {
  610. bgn _B;
  611. ulong p[1];
  612. p[0] = (b < 0) ? -b : b;
  613. _B.s = (b < 0) ? -1 : 1;
  614. _B.n = 1;
  615. _B.p = p;
  616. return bgn_div_bgn(P_Q, P_R, P_A, &_B);
  617. }
  618. int bgn_mod_bgn(bgn *P_R, const bgn *P_A, const bgn *P_B)
  619. {
  620. int ret;
  621. if (bgn_cmp_int(P_B, 0) < 0)
  622. return E_BGN_NEGATIVE_VALUE;
  623. ret = bgn_div_bgn(NULL, P_R, P_A, P_B);
  624. if (0 != ret)
  625. goto _exit;
  626. while (bgn_cmp_int(P_R, 0) < 0) {
  627. ret = bgn_add_bgn(P_R, P_R, P_B);
  628. if (0 != ret)
  629. goto _exit;
  630. }
  631. while (bgn_cmp_num(P_R, P_B) >= 0) {
  632. ret = bgn_sub_bgn(P_R, P_R, P_B);
  633. if (0 != ret)
  634. goto _exit;
  635. }
  636. _exit:
  637. return ret;
  638. }
  639. int bgn_mod_int(ulong *r, const bgn *P_A, int b)
  640. {
  641. int i;
  642. ulong x, y, z;
  643. if (b == 0)
  644. return E_BGN_DIVISION_BY_ZERO;
  645. if (b < 0)
  646. return E_BGN_NEGATIVE_VALUE;
  647. if (b == 1) {
  648. *r = 0;
  649. return 0;
  650. }
  651. if (b == 2) {
  652. *r = P_A->p[0] & 1;
  653. return 0;
  654. }
  655. for (i = P_A->n - 1, y = 0; i >= 0; i--) {
  656. x = P_A->p[i];
  657. y = (y << biH) | (x >> biH);
  658. z = y / b;
  659. y -= z * b;
  660. x <<= biH;
  661. y = (y << biH) | (x >> biH);
  662. z = y / b;
  663. y -= z * b;
  664. }
  665. if (P_A->s < 0 && y != 0)
  666. y = b - y;
  667. *r = y;
  668. return 0;
  669. }