factorial.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. extern void bignum_factorial(int);
  4. void
  5. factorial(void)
  6. {
  7. int n;
  8. save();
  9. p1 = pop();
  10. push(p1);
  11. n = pop_integer();
  12. if (n < 0 || n == (int) 0x80000000) {
  13. push_symbol(FACTORIAL);
  14. push(p1);
  15. list(2);
  16. restore();
  17. return;
  18. }
  19. bignum_factorial(n);
  20. restore();
  21. }
  22. void sfac_product(void);
  23. void sfac_product_f(U **, int, int);
  24. // simplification rules for factorials (m < n)
  25. //
  26. // (e + 1) * factorial(e) -> factorial(e + 1)
  27. //
  28. // factorial(e) / e -> factorial(e - 1)
  29. //
  30. // e / factorial(e) -> 1 / factorial(e - 1)
  31. //
  32. // factorial(e + n)
  33. // ---------------- -> (e + m + 1)(e + m + 2)...(e + n)
  34. // factorial(e + m)
  35. //
  36. // factorial(e + m) 1
  37. // ---------------- -> --------------------------------
  38. // factorial(e + n) (e + m + 1)(e + m + 2)...(e + n)
  39. void
  40. simplifyfactorials(void)
  41. {
  42. int x;
  43. save();
  44. x = expanding;
  45. expanding = 0;
  46. p1 = pop();
  47. if (car(p1) == symbol(ADD)) {
  48. push(zero);
  49. p1 = cdr(p1);
  50. while (iscons(p1)) {
  51. push(car(p1));
  52. simplifyfactorials();
  53. add();
  54. p1 = cdr(p1);
  55. }
  56. expanding = x;
  57. restore();
  58. return;
  59. }
  60. if (car(p1) == symbol(MULTIPLY)) {
  61. sfac_product();
  62. expanding = x;
  63. restore();
  64. return;
  65. }
  66. push(p1);
  67. expanding = x;
  68. restore();
  69. }
  70. void
  71. sfac_product(void)
  72. {
  73. int i, j, n;
  74. U **s;
  75. s = stack + tos;
  76. p1 = cdr(p1);
  77. n = 0;
  78. while (iscons(p1)) {
  79. push(car(p1));
  80. p1 = cdr(p1);
  81. n++;
  82. }
  83. for (i = 0; i < n - 1; i++) {
  84. if (s[i] == symbol(NIL))
  85. continue;
  86. for (j = i + 1; j < n; j++) {
  87. if (s[j] == symbol(NIL))
  88. continue;
  89. sfac_product_f(s, i, j);
  90. }
  91. }
  92. push(one);
  93. for (i = 0; i < n; i++) {
  94. if (s[i] == symbol(NIL))
  95. continue;
  96. push(s[i]);
  97. multiply();
  98. }
  99. p1 = pop();
  100. tos -= n;
  101. push(p1);
  102. }
  103. void
  104. sfac_product_f(U **s, int a, int b)
  105. {
  106. int i, n;
  107. p1 = s[a];
  108. p2 = s[b];
  109. if (ispower(p1)) {
  110. p3 = caddr(p1);
  111. p1 = cadr(p1);
  112. } else
  113. p3 = one;
  114. if (ispower(p2)) {
  115. p4 = caddr(p2);
  116. p2 = cadr(p2);
  117. } else
  118. p4 = one;
  119. if (isfactorial(p1) && isfactorial(p2)) {
  120. // Determine if the powers cancel.
  121. push(p3);
  122. push(p4);
  123. add();
  124. yyexpand();
  125. n = pop_integer();
  126. if (n != 0)
  127. return;
  128. // Find the difference between the two factorial args.
  129. // For example, the difference between (a + 2)! and a! is 2.
  130. push(cadr(p1));
  131. push(cadr(p2));
  132. subtract();
  133. yyexpand(); // to simplify
  134. n = pop_integer();
  135. if (n == 0 || n == (int) 0x80000000)
  136. return;
  137. if (n < 0) {
  138. n = -n;
  139. p5 = p1;
  140. p1 = p2;
  141. p2 = p5;
  142. p5 = p3;
  143. p3 = p4;
  144. p4 = p5;
  145. }
  146. push(one);
  147. for (i = 1; i <= n; i++) {
  148. push(cadr(p2));
  149. push_integer(i);
  150. add();
  151. push(p3);
  152. power();
  153. multiply();
  154. }
  155. s[a] = pop();
  156. s[b] = symbol(NIL);
  157. }
  158. }