basearith.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. #ifndef BASEARITH_H
  28. #define BASEARITH_H
  29. #include "mpdecimal.h"
  30. #include <stdio.h>
  31. #include "typearith.h"
  32. mpd_uint_t _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  33. mpd_size_t m, mpd_size_t n);
  34. void _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n);
  35. mpd_uint_t _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v);
  36. mpd_uint_t _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v,
  37. mpd_uint_t b);
  38. mpd_uint_t _mpd_baseincr(mpd_uint_t *u, mpd_size_t n);
  39. void _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  40. mpd_size_t m, mpd_size_t n);
  41. void _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n);
  42. void _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
  43. mpd_size_t m, mpd_size_t n);
  44. void _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  45. mpd_uint_t v);
  46. void _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  47. mpd_uint_t v, mpd_uint_t b);
  48. mpd_uint_t _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  49. mpd_uint_t v);
  50. mpd_uint_t _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
  51. mpd_uint_t v, mpd_uint_t b);
  52. int _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r, const mpd_uint_t *uconst,
  53. const mpd_uint_t *vconst, mpd_size_t nplusm, mpd_size_t n);
  54. void _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n,
  55. mpd_size_t m, mpd_size_t shift);
  56. mpd_uint_t _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
  57. mpd_size_t shift);
  58. #ifdef CONFIG_64
  59. extern const mpd_uint_t mprime_rdx;
  60. /*
  61. * Algorithm from: Division by Invariant Integers using Multiplication,
  62. * T. Granlund and P. L. Montgomery, Proceedings of the SIGPLAN '94
  63. * Conference on Programming Language Design and Implementation.
  64. *
  65. * http://gmplib.org/~tege/divcnst-pldi94.pdf
  66. */
  67. static inline void
  68. _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
  69. {
  70. mpd_uint_t n_adj, h, l, t;
  71. mpd_uint_t n1_neg;
  72. n1_neg = (lo & (1ULL<<63)) ? MPD_UINT_MAX : 0;
  73. n_adj = lo + (n1_neg & MPD_RADIX);
  74. _mpd_mul_words(&h, &l, mprime_rdx, hi-n1_neg);
  75. l = l + n_adj;
  76. if (l < n_adj) h++;
  77. t = h + hi; /* q1 */
  78. t = MPD_UINT_MAX - t;
  79. _mpd_mul_words(&h, &l, t, MPD_RADIX);
  80. l = l + lo;
  81. if (l < lo) h++;
  82. h += hi;
  83. h -= MPD_RADIX;
  84. *q = (h - t);
  85. *r = l + (MPD_RADIX & h);
  86. }
  87. #else
  88. static inline void
  89. _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
  90. {
  91. _mpd_div_words(q, r, hi, lo, MPD_RADIX);
  92. }
  93. #endif
  94. /* Multiply two single base b words, store result in array w[2]. */
  95. static inline void
  96. _mpd_singlemul(mpd_uint_t w[2], mpd_uint_t u, mpd_uint_t v)
  97. {
  98. mpd_uint_t hi, lo;
  99. _mpd_mul_words(&hi, &lo, u, v);
  100. _mpd_div_words_r(&w[1], &w[0], hi, lo);
  101. }
  102. /* Multiply u (len 2) and v (len 1 or 2). */
  103. static inline void
  104. _mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
  105. {
  106. mpd_uint_t hi, lo;
  107. _mpd_mul_words(&hi, &lo, u[0], v[0]);
  108. _mpd_div_words_r(&w[1], &w[0], hi, lo);
  109. _mpd_mul_words(&hi, &lo, u[1], v[0]);
  110. lo = w[1] + lo;
  111. if (lo < w[1]) hi++;
  112. _mpd_div_words_r(&w[2], &w[1], hi, lo);
  113. if (m == 1) return;
  114. _mpd_mul_words(&hi, &lo, u[0], v[1]);
  115. lo = w[1] + lo;
  116. if (lo < w[1]) hi++;
  117. _mpd_div_words_r(&w[3], &w[1], hi, lo);
  118. _mpd_mul_words(&hi, &lo, u[1], v[1]);
  119. lo = w[2] + lo;
  120. if (lo < w[2]) hi++;
  121. lo = w[3] + lo;
  122. if (lo < w[3]) hi++;
  123. _mpd_div_words_r(&w[3], &w[2], hi, lo);
  124. }
  125. /*
  126. * Test if all words from data[len-1] to data[0] are zero. If len is 0, nothing
  127. * is tested and the coefficient is regarded as "all zero".
  128. */
  129. static inline int
  130. _mpd_isallzero(const mpd_uint_t *data, mpd_ssize_t len)
  131. {
  132. while (--len >= 0) {
  133. if (data[len] != 0) return 0;
  134. }
  135. return 1;
  136. }
  137. /*
  138. * Test if all words from data[len-1] to data[0] are MPD_RADIX-1 (all nines).
  139. * Assumes that len > 0.
  140. */
  141. static inline int
  142. _mpd_isallnine(const mpd_uint_t *data, mpd_ssize_t len)
  143. {
  144. while (--len >= 0) {
  145. if (data[len] != MPD_RADIX-1) return 0;
  146. }
  147. return 1;
  148. }
  149. #endif /* BASEARITH_H */