basearith.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include "mpdecimal.h"
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <assert.h>
  32. #include "constants.h"
  33. #include "memory.h"
  34. #include "typearith.h"
  35. #include "basearith.h"
  36. /*********************************************************************/
  37. /* Calculations in base MPD_RADIX */
  38. /*********************************************************************/
  39. /*
  40. * Knuth, TAOCP, Volume 2, 4.3.1:
  41. * w := sum of u (len m) and v (len n)
  42. * n > 0 and m >= n
  43. * The calling function has to handle a possible final carry.
  44. */
  45. mpd_uint_t
  46. _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  47. mpd_size_t m, mpd_size_t n)
  48. {
  49. mpd_uint_t s;
  50. mpd_uint_t carry = 0;
  51. mpd_size_t i;
  52. assert(n > 0 && m >= n);
  53. /* add n members of u and v */
  54. for (i = 0; i < n; i++) {
  55. s = u[i] + (v[i] + carry);
  56. carry = (s < u[i]) | (s >= MPD_RADIX);
  57. w[i] = carry ? s-MPD_RADIX : s;
  58. }
  59. /* if there is a carry, propagate it */
  60. for (; carry && i < m; i++) {
  61. s = u[i] + carry;
  62. carry = (s == MPD_RADIX);
  63. w[i] = carry ? 0 : s;
  64. }
  65. /* copy the rest of u */
  66. for (; i < m; i++) {
  67. w[i] = u[i];
  68. }
  69. return carry;
  70. }
  71. /*
  72. * Add the contents of u to w. Carries are propagated further. The caller
  73. * has to make sure that w is big enough.
  74. */
  75. void
  76. _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
  77. {
  78. mpd_uint_t s;
  79. mpd_uint_t carry = 0;
  80. mpd_size_t i;
  81. if (n == 0) return;
  82. /* add n members of u to w */
  83. for (i = 0; i < n; i++) {
  84. s = w[i] + (u[i] + carry);
  85. carry = (s < w[i]) | (s >= MPD_RADIX);
  86. w[i] = carry ? s-MPD_RADIX : s;
  87. }
  88. /* if there is a carry, propagate it */
  89. for (; carry; i++) {
  90. s = w[i] + carry;
  91. carry = (s == MPD_RADIX);
  92. w[i] = carry ? 0 : s;
  93. }
  94. }
  95. /*
  96. * Add v to w (len m). The calling function has to handle a possible
  97. * final carry.
  98. */
  99. mpd_uint_t
  100. _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
  101. {
  102. mpd_uint_t s;
  103. mpd_uint_t carry = 0;
  104. mpd_size_t i;
  105. /* add v to u */
  106. s = w[0] + v;
  107. carry = (s < v) | (s >= MPD_RADIX);
  108. w[0] = carry ? s-MPD_RADIX : s;
  109. /* if there is a carry, propagate it */
  110. for (i = 1; carry && i < m; i++) {
  111. s = w[i] + carry;
  112. carry = (s == MPD_RADIX);
  113. w[i] = carry ? 0 : s;
  114. }
  115. return carry;
  116. }
  117. /* Increment u. The calling function has to handle a possible carry. */
  118. mpd_uint_t
  119. _mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
  120. {
  121. mpd_uint_t s;
  122. mpd_uint_t carry = 1;
  123. mpd_size_t i;
  124. assert(n > 0);
  125. /* if there is a carry, propagate it */
  126. for (i = 0; carry && i < n; i++) {
  127. s = u[i] + carry;
  128. carry = (s == MPD_RADIX);
  129. u[i] = carry ? 0 : s;
  130. }
  131. return carry;
  132. }
  133. /*
  134. * Knuth, TAOCP, Volume 2, 4.3.1:
  135. * w := difference of u (len m) and v (len n).
  136. * number in u >= number in v;
  137. */
  138. void
  139. _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  140. mpd_size_t m, mpd_size_t n)
  141. {
  142. mpd_uint_t d;
  143. mpd_uint_t borrow = 0;
  144. mpd_size_t i;
  145. assert(m > 0 && n > 0);
  146. /* subtract n members of v from u */
  147. for (i = 0; i < n; i++) {
  148. d = u[i] - (v[i] + borrow);
  149. borrow = (u[i] < d);
  150. w[i] = borrow ? d + MPD_RADIX : d;
  151. }
  152. /* if there is a borrow, propagate it */
  153. for (; borrow && i < m; i++) {
  154. d = u[i] - borrow;
  155. borrow = (u[i] == 0);
  156. w[i] = borrow ? MPD_RADIX-1 : d;
  157. }
  158. /* copy the rest of u */
  159. for (; i < m; i++) {
  160. w[i] = u[i];
  161. }
  162. }
  163. /*
  164. * Subtract the contents of u from w. w is larger than u. Borrows are
  165. * propagated further, but eventually w can absorb the final borrow.
  166. */
  167. void
  168. _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
  169. {
  170. mpd_uint_t d;
  171. mpd_uint_t borrow = 0;
  172. mpd_size_t i;
  173. if (n == 0) return;
  174. /* subtract n members of u from w */
  175. for (i = 0; i < n; i++) {
  176. d = w[i] - (u[i] + borrow);
  177. borrow = (w[i] < d);
  178. w[i] = borrow ? d + MPD_RADIX : d;
  179. }
  180. /* if there is a borrow, propagate it */
  181. for (; borrow; i++) {
  182. d = w[i] - borrow;
  183. borrow = (w[i] == 0);
  184. w[i] = borrow ? MPD_RADIX-1 : d;
  185. }
  186. }
  187. /* w := product of u (len n) and v (single word) */
  188. void
  189. _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
  190. {
  191. mpd_uint_t hi, lo;
  192. mpd_uint_t carry = 0;
  193. mpd_size_t i;
  194. assert(n > 0);
  195. for (i=0; i < n; i++) {
  196. _mpd_mul_words(&hi, &lo, u[i], v);
  197. lo = carry + lo;
  198. if (lo < carry) hi++;
  199. _mpd_div_words_r(&carry, &w[i], hi, lo);
  200. }
  201. w[i] = carry;
  202. }
  203. /*
  204. * Knuth, TAOCP, Volume 2, 4.3.1:
  205. * w := product of u (len m) and v (len n)
  206. * w must be initialized to zero
  207. */
  208. void
  209. _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  210. mpd_size_t m, mpd_size_t n)
  211. {
  212. mpd_uint_t hi, lo;
  213. mpd_uint_t carry;
  214. mpd_size_t i, j;
  215. assert(m > 0 && n > 0);
  216. for (j=0; j < n; j++) {
  217. carry = 0;
  218. for (i=0; i < m; i++) {
  219. _mpd_mul_words(&hi, &lo, u[i], v[j]);
  220. lo = w[i+j] + lo;
  221. if (lo < w[i+j]) hi++;
  222. lo = carry + lo;
  223. if (lo < carry) hi++;
  224. _mpd_div_words_r(&carry, &w[i+j], hi, lo);
  225. }
  226. w[j+m] = carry;
  227. }
  228. }
  229. /*
  230. * Knuth, TAOCP Volume 2, 4.3.1, exercise 16:
  231. * w := quotient of u (len n) divided by a single word v
  232. */
  233. mpd_uint_t
  234. _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
  235. {
  236. mpd_uint_t hi, lo;
  237. mpd_uint_t rem = 0;
  238. mpd_size_t i;
  239. assert(n > 0);
  240. for (i=n-1; i != MPD_SIZE_MAX; i--) {
  241. _mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
  242. lo = u[i] + lo;
  243. if (lo < u[i]) hi++;
  244. _mpd_div_words(&w[i], &rem, hi, lo, v);
  245. }
  246. return rem;
  247. }
  248. /*
  249. * Knuth, TAOCP Volume 2, 4.3.1:
  250. * q, r := quotient and remainder of uconst (len nplusm)
  251. * divided by vconst (len n)
  252. * nplusm > n
  253. *
  254. * If r is not NULL, r will contain the remainder. If r is NULL, the
  255. * return value indicates if there is a remainder: 1 for true, 0 for
  256. * false. A return value of -1 indicates an error.
  257. */
  258. int
  259. _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
  260. const mpd_uint_t *uconst, const mpd_uint_t *vconst,
  261. mpd_size_t nplusm, mpd_size_t n)
  262. {
  263. mpd_uint_t ustatic[MPD_MINALLOC_MAX];
  264. mpd_uint_t vstatic[MPD_MINALLOC_MAX];
  265. mpd_uint_t *u = ustatic;
  266. mpd_uint_t *v = vstatic;
  267. mpd_uint_t d, qhat, rhat, w2[2];
  268. mpd_uint_t hi, lo, x;
  269. mpd_uint_t carry;
  270. mpd_size_t i, j, m;
  271. int retval = 0;
  272. assert(n > 1 && nplusm >= n);
  273. m = sub_size_t(nplusm, n);
  274. /* D1: normalize */
  275. d = MPD_RADIX / (vconst[n-1] + 1);
  276. if (nplusm >= MPD_MINALLOC_MAX) {
  277. if ((u = mpd_calloc(nplusm+1, sizeof *u)) == NULL) {
  278. return -1;
  279. }
  280. }
  281. if (n >= MPD_MINALLOC_MAX) {
  282. if ((v = mpd_calloc(n+1, sizeof *v)) == NULL) {
  283. mpd_free(u);
  284. return -1;
  285. }
  286. }
  287. _mpd_shortmul(u, uconst, nplusm, d);
  288. _mpd_shortmul(v, vconst, n, d);
  289. /* D2: loop */
  290. rhat = 0;
  291. for (j=m; j != MPD_SIZE_MAX; j--) {
  292. /* D3: calculate qhat and rhat */
  293. rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
  294. qhat = w2[1] * MPD_RADIX + w2[0];
  295. while (1) {
  296. if (qhat < MPD_RADIX) {
  297. _mpd_singlemul(w2, qhat, v[n-2]);
  298. if (w2[1] <= rhat) {
  299. if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
  300. break;
  301. }
  302. }
  303. }
  304. qhat -= 1;
  305. rhat += v[n-1];
  306. if (rhat < v[n-1] || rhat >= MPD_RADIX) {
  307. break;
  308. }
  309. }
  310. /* D4: multiply and subtract */
  311. carry = 0;
  312. for (i=0; i <= n; i++) {
  313. _mpd_mul_words(&hi, &lo, qhat, v[i]);
  314. lo = carry + lo;
  315. if (lo < carry) hi++;
  316. _mpd_div_words_r(&hi, &lo, hi, lo);
  317. x = u[i+j] - lo;
  318. carry = (u[i+j] < x);
  319. u[i+j] = carry ? x+MPD_RADIX : x;
  320. carry += hi;
  321. }
  322. q[j] = qhat;
  323. /* D5: test remainder */
  324. if (carry) {
  325. q[j] -= 1;
  326. /* D6: add back */
  327. (void)_mpd_baseadd(u+j, u+j, v, n+1, n);
  328. }
  329. }
  330. /* D8: unnormalize */
  331. if (r != NULL) {
  332. _mpd_shortdiv(r, u, n, d);
  333. /* we are not interested in the return value here */
  334. retval = 0;
  335. }
  336. else {
  337. retval = !_mpd_isallzero(u, n);
  338. }
  339. if (u != ustatic) mpd_free(u);
  340. if (v != vstatic) mpd_free(v);
  341. return retval;
  342. }
  343. /* Leftshift of src by shift digits; src may equal dest. */
  344. void
  345. _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m,
  346. mpd_size_t shift)
  347. {
  348. #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
  349. /* spurious uninitialized warnings */
  350. mpd_uint_t l=l, lprev=lprev, h=h;
  351. #else
  352. mpd_uint_t l, lprev, h;
  353. #endif
  354. mpd_uint_t q, r;
  355. mpd_uint_t ph;
  356. assert(m > 0 && n >= m);
  357. _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
  358. if (r != 0) {
  359. ph = mpd_pow10[r];
  360. --m; --n;
  361. _mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
  362. if (h != 0) {
  363. dest[n--] = h;
  364. }
  365. for (; m != MPD_SIZE_MAX; m--,n--) {
  366. _mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
  367. dest[n] = ph * lprev + h;
  368. lprev = l;
  369. }
  370. dest[q] = ph * lprev;
  371. }
  372. else {
  373. while (--m != MPD_SIZE_MAX) {
  374. dest[m+q] = src[m];
  375. }
  376. }
  377. mpd_uint_zero(dest, q);
  378. }
  379. /* Rightshift of src by shift digits; src may equal dest. */
  380. mpd_uint_t
  381. _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
  382. mpd_size_t shift)
  383. {
  384. #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
  385. /* spurious uninitialized warnings */
  386. mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */
  387. #else
  388. mpd_uint_t l, h, hprev; /* low, high, previous high */
  389. #endif
  390. mpd_uint_t rnd, rest; /* rounding digit, rest */
  391. mpd_uint_t q, r;
  392. mpd_size_t i, j;
  393. mpd_uint_t ph;
  394. assert(slen > 0);
  395. _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
  396. rnd = rest = 0;
  397. if (r != 0) {
  398. ph = mpd_pow10[MPD_RDIGITS-r];
  399. _mpd_divmod_pow10(&hprev, &rest, src[q], r);
  400. _mpd_divmod_pow10(&rnd, &rest, rest, r-1);
  401. if (rest == 0 && q > 0) {
  402. rest = !_mpd_isallzero(src, q);
  403. }
  404. h = hprev;
  405. for (j=0,i=q+1; i<slen; i++,j++) {
  406. _mpd_divmod_pow10(&h, &l, src[i], r);
  407. dest[j] = ph * l + hprev;
  408. hprev = h;
  409. }
  410. if (hprev != 0) {
  411. dest[j] = hprev;
  412. }
  413. }
  414. else {
  415. if (q > 0) {
  416. _mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
  417. /* is there any non-zero digit below rnd? */
  418. if (rest == 0) rest = !_mpd_isallzero(src, q-1);
  419. }
  420. for (j = 0; j < slen-q; j++) {
  421. dest[j] = src[q+j];
  422. }
  423. }
  424. /* 0-4 ==> rnd+rest < 0.5 */
  425. /* 5 ==> rnd+rest == 0.5 */
  426. /* 6-9 ==> rnd+rest > 0.5 */
  427. return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
  428. }
  429. /*********************************************************************/
  430. /* Calculations in base b */
  431. /*********************************************************************/
  432. /*
  433. * Add v to w (len m). The calling function has to handle a possible
  434. * final carry.
  435. */
  436. mpd_uint_t
  437. _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b)
  438. {
  439. mpd_uint_t s;
  440. mpd_uint_t carry = 0;
  441. mpd_size_t i;
  442. /* add v to u */
  443. s = w[0] + v;
  444. carry = (s < v) | (s >= b);
  445. w[0] = carry ? s-b : s;
  446. /* if there is a carry, propagate it */
  447. for (i = 1; carry && i < m; i++) {
  448. s = w[i] + carry;
  449. carry = (s == b);
  450. w[i] = carry ? 0 : s;
  451. }
  452. return carry;
  453. }
  454. /* w := product of u (len n) and v (single word) */
  455. void
  456. _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  457. mpd_uint_t v, mpd_uint_t b)
  458. {
  459. mpd_uint_t hi, lo;
  460. mpd_uint_t carry = 0;
  461. mpd_size_t i;
  462. assert(n > 0);
  463. for (i=0; i < n; i++) {
  464. _mpd_mul_words(&hi, &lo, u[i], v);
  465. lo = carry + lo;
  466. if (lo < carry) hi++;
  467. _mpd_div_words(&carry, &w[i], hi, lo, b);
  468. }
  469. w[i] = carry;
  470. }
  471. /*
  472. * Knuth, TAOCP Volume 2, 4.3.1, exercise 16:
  473. * w := quotient of u (len n) divided by a single word v
  474. */
  475. mpd_uint_t
  476. _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  477. mpd_uint_t v, mpd_uint_t b)
  478. {
  479. mpd_uint_t hi, lo;
  480. mpd_uint_t rem = 0;
  481. mpd_size_t i;
  482. assert(n > 0);
  483. for (i=n-1; i != MPD_SIZE_MAX; i--) {
  484. _mpd_mul_words(&hi, &lo, rem, b);
  485. lo = u[i] + lo;
  486. if (lo < u[i]) hi++;
  487. _mpd_div_words(&w[i], &rem, hi, lo, v);
  488. }
  489. return rem;
  490. }