convolute.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 "bits.h"
  30. #include "constants.h"
  31. #include "fnt.h"
  32. #include "fourstep.h"
  33. #include "numbertheory.h"
  34. #include "sixstep.h"
  35. #include "umodarith.h"
  36. #include "convolute.h"
  37. /* Convolute the data in c1 and c2. Result is in c1. */
  38. int
  39. fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
  40. {
  41. int (*fnt)(mpd_uint_t *, mpd_size_t, int);
  42. int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
  43. #ifdef PPRO
  44. double dmod;
  45. uint32_t dinvmod[3];
  46. #endif
  47. mpd_uint_t n_inv, umod;
  48. mpd_size_t i;
  49. SETMODULUS(modnum);
  50. n_inv = POWMOD(n, (umod-2));
  51. if (ispower2(n)) {
  52. if (n > SIX_STEP_THRESHOLD) {
  53. fnt = six_step_fnt;
  54. inv_fnt = inv_six_step_fnt;
  55. }
  56. else {
  57. fnt = std_fnt;
  58. inv_fnt = std_inv_fnt;
  59. }
  60. }
  61. else {
  62. fnt = four_step_fnt;
  63. inv_fnt = inv_four_step_fnt;
  64. }
  65. if (!fnt(c1, n, modnum)) {
  66. return 0;
  67. }
  68. if (!fnt(c2, n, modnum)) {
  69. return 0;
  70. }
  71. for (i = 0; i < n-1; i += 2) {
  72. mpd_uint_t x0 = c1[i];
  73. mpd_uint_t y0 = c2[i];
  74. mpd_uint_t x1 = c1[i+1];
  75. mpd_uint_t y1 = c2[i+1];
  76. MULMOD2(&x0, y0, &x1, y1);
  77. c1[i] = x0;
  78. c1[i+1] = x1;
  79. }
  80. if (!inv_fnt(c1, n, modnum)) {
  81. return 0;
  82. }
  83. for (i = 0; i < n-3; i += 4) {
  84. mpd_uint_t x0 = c1[i];
  85. mpd_uint_t x1 = c1[i+1];
  86. mpd_uint_t x2 = c1[i+2];
  87. mpd_uint_t x3 = c1[i+3];
  88. MULMOD2C(&x0, &x1, n_inv);
  89. MULMOD2C(&x2, &x3, n_inv);
  90. c1[i] = x0;
  91. c1[i+1] = x1;
  92. c1[i+2] = x2;
  93. c1[i+3] = x3;
  94. }
  95. return 1;
  96. }
  97. /* Autoconvolute the data in c1. Result is in c1. */
  98. int
  99. fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
  100. {
  101. int (*fnt)(mpd_uint_t *, mpd_size_t, int);
  102. int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
  103. #ifdef PPRO
  104. double dmod;
  105. uint32_t dinvmod[3];
  106. #endif
  107. mpd_uint_t n_inv, umod;
  108. mpd_size_t i;
  109. SETMODULUS(modnum);
  110. n_inv = POWMOD(n, (umod-2));
  111. if (ispower2(n)) {
  112. if (n > SIX_STEP_THRESHOLD) {
  113. fnt = six_step_fnt;
  114. inv_fnt = inv_six_step_fnt;
  115. }
  116. else {
  117. fnt = std_fnt;
  118. inv_fnt = std_inv_fnt;
  119. }
  120. }
  121. else {
  122. fnt = four_step_fnt;
  123. inv_fnt = inv_four_step_fnt;
  124. }
  125. if (!fnt(c1, n, modnum)) {
  126. return 0;
  127. }
  128. for (i = 0; i < n-1; i += 2) {
  129. mpd_uint_t x0 = c1[i];
  130. mpd_uint_t x1 = c1[i+1];
  131. MULMOD2(&x0, x0, &x1, x1);
  132. c1[i] = x0;
  133. c1[i+1] = x1;
  134. }
  135. if (!inv_fnt(c1, n, modnum)) {
  136. return 0;
  137. }
  138. for (i = 0; i < n-3; i += 4) {
  139. mpd_uint_t x0 = c1[i];
  140. mpd_uint_t x1 = c1[i+1];
  141. mpd_uint_t x2 = c1[i+2];
  142. mpd_uint_t x3 = c1[i+3];
  143. MULMOD2C(&x0, &x1, n_inv);
  144. MULMOD2C(&x2, &x3, n_inv);
  145. c1[i] = x0;
  146. c1[i+1] = x1;
  147. c1[i+2] = x2;
  148. c1[i+3] = x3;
  149. }
  150. return 1;
  151. }