mpfactorial.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #include "os.h"
  2. #include <mp.h>
  3. #include <libsec.h>
  4. #include "dat.h"
  5. mpint*
  6. mpfactorial(ulong n)
  7. {
  8. int i;
  9. ulong k;
  10. unsigned cnt;
  11. int max, mmax;
  12. mpdigit p, pp[2];
  13. mpint *r, *s, *stk[31];
  14. cnt = 0;
  15. max = mmax = -1;
  16. p = 1;
  17. r = mpnew(0);
  18. for(k=2; k<=n; k++){
  19. pp[0] = 0;
  20. pp[1] = 0;
  21. mpvecdigmuladd(&p, 1, (mpdigit)k, pp);
  22. if(pp[1] == 0) /* !overflow */
  23. p = pp[0];
  24. else{
  25. cnt++;
  26. if((cnt & 1) == 0){
  27. s = stk[max];
  28. mpbits(r, Dbits*(s->top+1+1));
  29. memset(r->p, 0, Dbytes*(s->top+1+1));
  30. mpvecmul(s->p, s->top, &p, 1, r->p);
  31. r->sign = 1;
  32. r->top = s->top+1+1; /* XXX: norm */
  33. mpassign(r, s);
  34. for(i=4; (cnt & (i-1)) == 0; i=i<<1){
  35. mpmul(stk[max], stk[max-1], r);
  36. mpassign(r, stk[max-1]);
  37. max--;
  38. }
  39. }else{
  40. max++;
  41. if(max > mmax){
  42. mmax++;
  43. if(max > nelem(stk))
  44. abort();
  45. stk[max] = mpnew(Dbits);
  46. }
  47. stk[max]->top = 1;
  48. stk[max]->p[0] = p;
  49. }
  50. p = (mpdigit)k;
  51. }
  52. }
  53. if(max < 0){
  54. mpbits(r, Dbits);
  55. r->top = 1;
  56. r->sign = 1;
  57. r->p[0] = p;
  58. }else{
  59. s = stk[max--];
  60. mpbits(r, Dbits*(s->top+1+1));
  61. memset(r->p, 0, Dbytes*(s->top+1+1));
  62. mpvecmul(s->p, s->top, &p, 1, r->p);
  63. r->sign = 1;
  64. r->top = s->top+1+1; /* XXX: norm */
  65. }
  66. while(max >= 0)
  67. mpmul(r, stk[max--], r);
  68. for(max=mmax; max>=0; max--)
  69. mpfree(stk[max]);
  70. mpnorm(r);
  71. return r;
  72. }