mpexp.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include "os.h"
  2. #include <mp.h>
  3. #include "dat.h"
  4. // res = b**e
  5. //
  6. // knuth, vol 2, pp 398-400
  7. enum {
  8. Freeb= 0x1,
  9. Freee= 0x2,
  10. Freem= 0x4,
  11. };
  12. //int expdebug;
  13. void
  14. mpexp(mpint *b, mpint *e, mpint *m, mpint *res)
  15. {
  16. mpint *t[2];
  17. int tofree;
  18. mpdigit d, bit;
  19. int i, j;
  20. i = mpcmp(e,mpzero);
  21. if(i==0){
  22. mpassign(mpone, res);
  23. return;
  24. }
  25. if(i<0)
  26. sysfatal("mpexp: negative exponent");
  27. t[0] = mpcopy(b);
  28. t[1] = res;
  29. tofree = 0;
  30. if(res == b){
  31. b = mpcopy(b);
  32. tofree |= Freeb;
  33. }
  34. if(res == e){
  35. e = mpcopy(e);
  36. tofree |= Freee;
  37. }
  38. if(res == m){
  39. m = mpcopy(m);
  40. tofree |= Freem;
  41. }
  42. // skip first bit
  43. i = e->top-1;
  44. d = e->p[i];
  45. for(bit = mpdighi; (bit & d) == 0; bit >>= 1)
  46. ;
  47. bit >>= 1;
  48. j = 0;
  49. for(;;){
  50. for(; bit != 0; bit >>= 1){
  51. mpmul(t[j], t[j], t[j^1]);
  52. if(bit & d)
  53. mpmul(t[j^1], b, t[j]);
  54. else
  55. j ^= 1;
  56. if(m != nil && t[j]->top > m->top){
  57. mpmod(t[j], m, t[j^1]);
  58. j ^= 1;
  59. }
  60. }
  61. if(--i < 0)
  62. break;
  63. bit = mpdighi;
  64. d = e->p[i];
  65. }
  66. if(m != nil){
  67. mpmod(t[j], m, t[j^1]);
  68. j ^= 1;
  69. }
  70. if(t[j] == res){
  71. mpfree(t[j^1]);
  72. } else {
  73. mpassign(t[j], res);
  74. mpfree(t[j]);
  75. }
  76. if(tofree){
  77. if(tofree & Freeb)
  78. mpfree(b);
  79. if(tofree & Freee)
  80. mpfree(e);
  81. if(tofree & Freem)
  82. mpfree(m);
  83. }
  84. }