mmul.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Bignum multiplication and division
  2. #include "stdafx.h"
  3. #include "defs.h"
  4. extern int ge(unsigned int *, unsigned int *, int);
  5. static void mulf(unsigned int *, unsigned int *, int, unsigned int);
  6. static void addf(unsigned int *, unsigned int *, int);
  7. static void subf(unsigned int *, unsigned int *, int);
  8. unsigned int *
  9. mmul(unsigned int *a, unsigned int *b)
  10. {
  11. int alen, blen, i, n;
  12. unsigned int *t, *x;
  13. if (MZERO(a) || MZERO(b))
  14. return mint(0);
  15. if (MLENGTH(a) == 1 && a[0] == 1) {
  16. t = mcopy(b);
  17. MSIGN(t) *= MSIGN(a);
  18. return t;
  19. }
  20. if (MLENGTH(b) == 1 && b[0] == 1) {
  21. t = mcopy(a);
  22. MSIGN(t) *= MSIGN(b);
  23. return t;
  24. }
  25. alen = MLENGTH(a);
  26. blen = MLENGTH(b);
  27. n = alen + blen;
  28. x = mnew(n);
  29. t = mnew(alen + 1);
  30. for (i = 0; i < n; i++)
  31. x[i] = 0;
  32. /* sum of partial products */
  33. for (i = 0; i < blen; i++) {
  34. mulf(t, a, alen, b[i]);
  35. addf(x + i, t, alen + 1);
  36. }
  37. mfree(t);
  38. /* length of product */
  39. for (i = n - 1; i > 0; i--)
  40. if (x[i])
  41. break;
  42. MLENGTH(x) = i + 1;
  43. MSIGN(x) = MSIGN(a) * MSIGN(b);
  44. return x;
  45. }
  46. unsigned int *
  47. mdiv(unsigned int *a, unsigned int *b)
  48. {
  49. int alen, blen, i, n;
  50. unsigned int c, *t, *x, *y;
  51. unsigned long long jj, kk;
  52. if (MZERO(b))
  53. stop("divide by zero");
  54. if (MZERO(a))
  55. return mint(0);
  56. alen = MLENGTH(a);
  57. blen = MLENGTH(b);
  58. n = alen - blen;
  59. if (n < 0)
  60. return mint(0);
  61. x = mnew(alen + 1);
  62. for (i = 0; i < alen; i++)
  63. x[i] = a[i];
  64. x[i] = 0;
  65. y = mnew(n + 1);
  66. t = mnew(blen + 1);
  67. /* Add 1 here to round up in case the remaining words are non-zero. */
  68. kk = (unsigned long long) b[blen - 1] + 1;
  69. for (i = 0; i <= n; i++) {
  70. y[n - i] = 0;
  71. for (;;) {
  72. /* estimate the partial quotient */
  73. if (little_endian()) {
  74. ((unsigned int *) &jj)[0] = x[alen - i - 1];
  75. ((unsigned int *) &jj)[1] = x[alen - i - 0];
  76. } else {
  77. ((unsigned int *) &jj)[1] = x[alen - i - 1];
  78. ((unsigned int *) &jj)[0] = x[alen - i - 0];
  79. }
  80. c = (unsigned int) (jj / kk);
  81. if (c == 0) {
  82. if (ge(x + n - i, b, blen)) { /* see note 1 */
  83. y[n - i]++;
  84. subf(x + n - i, b, blen);
  85. }
  86. break;
  87. }
  88. y[n - i] += c;
  89. mulf(t, b, blen, c);
  90. subf(x + n - i, t, blen + 1);
  91. }
  92. }
  93. mfree(t);
  94. mfree(x);
  95. /* length of quotient */
  96. for (i = n; i > 0; i--)
  97. if (y[i])
  98. break;
  99. if (i == 0 && y[0] == 0) {
  100. mfree(y);
  101. y = mint(0);
  102. } else {
  103. MLENGTH(y) = i + 1;
  104. MSIGN(y) = MSIGN(a) * MSIGN(b);
  105. }
  106. return y;
  107. }
  108. // a = a + b
  109. static void
  110. addf(unsigned int *a, unsigned int *b, int len)
  111. {
  112. int i;
  113. long long t = 0; /* can be signed or unsigned */
  114. for (i = 0; i < len; i++) {
  115. t += (long long) a[i] + b[i];
  116. a[i] = (unsigned int) t;
  117. t >>= 32;
  118. }
  119. }
  120. // a = a - b
  121. static void
  122. subf(unsigned int *a, unsigned int *b, int len)
  123. {
  124. int i;
  125. long long t = 0; /* must be signed */
  126. for (i = 0; i < len; i++) {
  127. t += (long long) a[i] - b[i];
  128. a[i] = (unsigned int) t;
  129. t >>= 32;
  130. }
  131. }
  132. // a = b * c
  133. // 0xffffffff + 0xffffffff * 0xffffffff == 0xffffffff00000000
  134. static void
  135. mulf(unsigned int *a, unsigned int *b, int len, unsigned int c)
  136. {
  137. int i;
  138. unsigned long long t = 0; /* must be unsigned */
  139. for (i = 0; i < len; i++) {
  140. t += (unsigned long long) b[i] * c;
  141. a[i] = (unsigned int) t;
  142. t >>= 32;
  143. }
  144. a[i] = (unsigned int) t;
  145. }
  146. unsigned int *
  147. mmod(unsigned int *a, unsigned int *b)
  148. {
  149. int alen, blen, i, n;
  150. unsigned int c, *t, *x, *y;
  151. unsigned long long jj, kk;
  152. if (MZERO(b))
  153. stop("divide by zero");
  154. if (MZERO(a))
  155. return mint(0);
  156. alen = MLENGTH(a);
  157. blen = MLENGTH(b);
  158. n = alen - blen;
  159. if (n < 0)
  160. return mcopy(a);
  161. x = mnew(alen + 1);
  162. for (i = 0; i < alen; i++)
  163. x[i] = a[i];
  164. x[i] = 0;
  165. y = mnew(n + 1);
  166. t = mnew(blen + 1);
  167. kk = (unsigned long long) b[blen - 1] + 1;
  168. for (i = 0; i <= n; i++) {
  169. y[n - i] = 0;
  170. for (;;) {
  171. /* estimate the partial quotient */
  172. if (little_endian()) {
  173. ((unsigned int *) &jj)[0] = x[alen - i - 1];
  174. ((unsigned int *) &jj)[1] = x[alen - i - 0];
  175. } else {
  176. ((unsigned int *) &jj)[1] = x[alen - i - 1];
  177. ((unsigned int *) &jj)[0] = x[alen - i - 0];
  178. }
  179. c = (int) (jj / kk);
  180. if (c == 0) {
  181. if (ge(x + n - i, b, blen)) { /* see note 1 */
  182. y[n - i]++;
  183. subf(x + n - i, b, blen);
  184. }
  185. break;
  186. }
  187. y[n - i] += c;
  188. mulf(t, b, blen, c);
  189. subf(x + n - i, t, blen + 1);
  190. }
  191. }
  192. mfree(t);
  193. mfree(y);
  194. /* length of remainder */
  195. for (i = blen - 1; i > 0; i--)
  196. if (x[i])
  197. break;
  198. if (i == 0 && x[0] == 0) {
  199. mfree(x);
  200. x = mint(0);
  201. } else {
  202. MLENGTH(x) = i + 1;
  203. MSIGN(x) = MSIGN(a);
  204. }
  205. return x;
  206. }
  207. // return both quotient and remainder of a/b
  208. void
  209. mdivrem(unsigned int **q, unsigned int **r, unsigned int *a, unsigned int *b)
  210. {
  211. int alen, blen, i, n;
  212. unsigned int c, *t, *x, *y;
  213. unsigned long long jj, kk;
  214. if (MZERO(b))
  215. stop("divide by zero");
  216. if (MZERO(a)) {
  217. *q = mint(0);
  218. *r = mint(0);
  219. return;
  220. }
  221. alen = MLENGTH(a);
  222. blen = MLENGTH(b);
  223. n = alen - blen;
  224. if (n < 0) {
  225. *q = mint(0);
  226. *r = mcopy(a);
  227. return;
  228. }
  229. x = mnew(alen + 1);
  230. for (i = 0; i < alen; i++)
  231. x[i] = a[i];
  232. x[i] = 0;
  233. y = mnew(n + 1);
  234. t = mnew(blen + 1);
  235. kk = (unsigned long long) b[blen - 1] + 1;
  236. for (i = 0; i <= n; i++) {
  237. y[n - i] = 0;
  238. for (;;) {
  239. /* estimate the partial quotient */
  240. if (little_endian()) {
  241. ((unsigned int *) &jj)[0] = x[alen - i - 1];
  242. ((unsigned int *) &jj)[1] = x[alen - i - 0];
  243. } else {
  244. ((unsigned int *) &jj)[1] = x[alen - i - 1];
  245. ((unsigned int *) &jj)[0] = x[alen - i - 0];
  246. }
  247. c = (int) (jj / kk);
  248. if (c == 0) {
  249. if (ge(x + n - i, b, blen)) { /* see note 1 */
  250. y[n - i]++;
  251. subf(x + n - i, b, blen);
  252. }
  253. break;
  254. }
  255. y[n - i] += c;
  256. mulf(t, b, blen, c);
  257. subf(x + n - i, t, blen + 1);
  258. }
  259. }
  260. mfree(t);
  261. /* length of quotient */
  262. for (i = n; i > 0; i--)
  263. if (y[i])
  264. break;
  265. if (i == 0 && y[0] == 0) {
  266. mfree(y);
  267. y = mint(0);
  268. } else {
  269. MLENGTH(y) = i + 1;
  270. MSIGN(y) = MSIGN(a) * MSIGN(b);
  271. }
  272. /* length of remainder */
  273. for (i = blen - 1; i > 0; i--)
  274. if (x[i])
  275. break;
  276. if (i == 0 && x[0] == 0) {
  277. mfree(x);
  278. x = mint(0);
  279. } else {
  280. MLENGTH(x) = i + 1;
  281. MSIGN(x) = MSIGN(a);
  282. }
  283. *q = y;
  284. *r = x;
  285. }