1. /* ssqcpinv.h by K.Tsuru */
  2. // since ver. 2.18
  3. /***************************************************************
  4. SN library
  5. Template class of square coupling method for inverse R.
  6. This is a special case of binary splitting method.
  7. It evaluates power series
  8. S_L = A_0/R + A_1 / R^2 + A_2 / R^3 + ...
  9. It can be used to evaluate a polynomial of SLong or SInteger
  10. e.g. radix conversion of decimal.
  11. algorithm:
  12. (0.A[0]A[1]A[2]...)_R =
  13. A[k]
  14. S_L = \sum_{k=0}^{L-1}--------
  15. R^(k+1)
  16. A[2k] A[2k+1]
  17. = \sum_{k=0}^{L/2-1}{---------- + ----------- }
  18. R^(2k+1) R^(2k+2)
  19. A[2k] R + A[2k+1]
  20. = \sum_{k=0}^{L/2-1} -----------------------
  21. (R^2)^(k+1)
  22. Then repeating while L < 1
  23. L/2 <-- L
  24. R <-- R*R
  25. A[k] <-- A[2k]*R+A[2k+1]
  26. yields
  27. S_L = A[0]/R
  28. ***************************************************************/
  29. #ifndef SQUARE_COUPLING_INV_TEMPLATE_H
  30. #define SQUARE_COUPLING_INV_TEMPLATE_H
  31. template <class SqCType> class SquareCouplingInverseR {
  32. private:
  33. const SqCType ZERO;
  34. void abort(); // abort by syntax error
  35. void freeHalf(ulong from, ulong to); // free memory of disused elements.
  36. bool isOk;
  37. SqCType *A, R;
  38. ulong L, userL; // L/2 < userL =< L
  39. void setL(ulong s) {
  40. L = userL = s;
  41. if ( userL & (userL - 1) ) L = ceilpow2(userL); // L != 2^n It changes into 2^n.
  42. SCalcInfo::upToTerm = L;
  43. }
  44. SqCType element(ulong k) {
  45. return (k < userL) ? A[k] : ZERO;
  46. }
  47. public:
  48. // A function sets coefficients A[].
  49. // caution : The content of a[] is destroied.
  50. void setAR(SqCType *a, const SqCType& r, ulong size) {
  51. isOk = false; // reset for second usage
  52. A = a; R = r; setL(size);
  53. }
  54. SquareCouplingInverseR() : ZERO(0.0), isOk(false), L(0), userL(0) {}
  55. SquareCouplingInverseR(SqCType *a, const SqCType& r, ulong size)
  56. : ZERO(0.0), isOk(false), A(a), R(r) {
  57. setL(size);
  58. }
  59. virtual ~SquareCouplingInverseR(){}
  60. void putTogether();
  61. bool isOK() const { return isOk; }
  62. // sum is obtained S_L = A[0]/R
  63. // It returns the value of A[0].
  64. SqCType getA() {
  65. if(!isOk) putTogether();
  66. return A[0];
  67. }
  68. // It returns the value of R.
  69. SqCType getR() {
  70. if(!isOk) putTogether();
  71. return R;
  72. }
  73. };
  74. /***************************************
  75. * Implementation of class SquareCouplingInverseR
  76. ****************************************/
  77. template <class SqCType> void SquareCouplingInverseR<SqCType> ::freeHalf(ulong from, ulong to) {
  78. for (ulong i = from; i < to; i++) A[i].SizeZero();
  79. }
  80. template <class SqCType> void SquareCouplingInverseR<SqCType>::abort() {
  81. R.SetError(R.SYNTAX_ERR, "class SquareCouplingInverseR", 1602);
  82. }
  83. template <class SqCType> void SquareCouplingInverseR<SqCType>::putTogether() {
  84. if (L == 0) abort();
  85. // First step "element()" is used because A[i] (userL =< i < L) are undecided.
  86. #if 1
  87. ulong j, uj = userL;
  88. if (userL & 1) uj++;
  89. for ( j = 0; j < uj - 2; j += 2) A[j/2] = A[j] * R + A[j+1];
  90. // here j == uj-2
  91. A[j/2] = element(j) * R + element(j+1);
  92. j += 2;
  93. for ( ; j< L ; j += 2) A[j/2].SetZero();
  94. #else
  95. // simple version
  96. for (ulong i = 0; i < L; i += 2) A[i/2] = element(i) * R + element(i+1);
  97. #endif
  98. ulong n = L / 2;
  99. freeHalf(n, userL);
  100. R *= R;
  101. while (n > 1uL) {
  102. for (ulong i = 0; i < n ; i += 2) A[i/2] = A[i] * R + A[i+1];
  103. n /= 2;
  104. freeHalf(n, 2 * n - 1);
  105. R *= R;
  106. }
  107. isOk = true;
  108. }
  109. #endif // SQUARE_COUPLING_INV_TEMPLATE_H

ssqcpinv.h : last modifiled at 2017/04/10 16:44:54(3,513 bytes)
created at 2016/04/11 11:18:59
The creation time of this html file is 2017/10/11 16:07:52 (Wed Oct 11 16:07:52 2017).