simfac.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* Simplify factorials
  2. The following script
  3. F(n,k) = k binomial(n,k)
  4. (F(n,k) + F(n,k-1)) / F(n+1,k)
  5. generates
  6. k! n! n! (1 - k + n)! k! n!
  7. -------------------- + -------------------- - ----------------------
  8. (-1 + k)! (1 + n)! (1 + n)! (-k + n)! k (-1 + k)! (1 + n)!
  9. Simplify each term to get
  10. k 1 - k + n 1
  11. ------- + ----------- - -------
  12. 1 + n 1 + n 1 + n
  13. Then simplify the sum to get
  14. n
  15. -------
  16. 1 + n
  17. */
  18. #include "stdafx.h"
  19. #include "defs.h"
  20. void simfac(void);
  21. static void simfac_term(void);
  22. static int yysimfac(int);
  23. // simplify factorials term-by-term
  24. void
  25. eval_simfac(void)
  26. {
  27. push(cadr(p1));
  28. eval();
  29. simfac();
  30. }
  31. #if 1
  32. void
  33. simfac(void)
  34. {
  35. int h;
  36. save();
  37. p1 = pop();
  38. if (car(p1) == symbol(ADD)) {
  39. h = tos;
  40. p1 = cdr(p1);
  41. while (p1 != symbol(NIL)) {
  42. push(car(p1));
  43. simfac_term();
  44. p1 = cdr(p1);
  45. }
  46. add_all(tos - h);
  47. } else {
  48. push(p1);
  49. simfac_term();
  50. }
  51. restore();
  52. }
  53. #else
  54. void
  55. simfac(void)
  56. {
  57. int h;
  58. save();
  59. p1 = pop();
  60. if (car(p1) == symbol(ADD)) {
  61. h = tos;
  62. p1 = cdr(p1);
  63. while (p1 != symbol(NIL)) {
  64. push(car(p1));
  65. simfac_term();
  66. p1 = cdr(p1);
  67. }
  68. addk(tos - h);
  69. p1 = pop();
  70. if (find(p1, symbol(FACTORIAL))) {
  71. push(p1);
  72. if (car(p1) == symbol(ADD)) {
  73. Condense();
  74. simfac_term();
  75. }
  76. }
  77. } else {
  78. push(p1);
  79. simfac_term();
  80. }
  81. restore();
  82. }
  83. #endif
  84. static void
  85. simfac_term(void)
  86. {
  87. int h;
  88. save();
  89. p1 = pop();
  90. // if not a product of factors then done
  91. if (car(p1) != symbol(MULTIPLY)) {
  92. push(p1);
  93. restore();
  94. return;
  95. }
  96. // push all factors
  97. h = tos;
  98. p1 = cdr(p1);
  99. while (p1 != symbol(NIL)) {
  100. push(car(p1));
  101. p1 = cdr(p1);
  102. }
  103. // keep trying until no more to do
  104. while (yysimfac(h))
  105. ;
  106. multiply_all_noexpand(tos - h);
  107. restore();
  108. }
  109. // try all pairs of factors
  110. static int
  111. yysimfac(int h)
  112. {
  113. int i, j;
  114. for (i = h; i < tos; i++) {
  115. p1 = stack[i];
  116. for (j = h; j < tos; j++) {
  117. if (i == j)
  118. continue;
  119. p2 = stack[j];
  120. // n! / n -> (n - 1)!
  121. if (car(p1) == symbol(FACTORIAL)
  122. && car(p2) == symbol(POWER)
  123. && isminusone(caddr(p2))
  124. && equal(cadr(p1), cadr(p2))) {
  125. push(cadr(p1));
  126. push(one);
  127. subtract();
  128. factorial();
  129. stack[i] = pop();
  130. stack[j] = one;
  131. return 1;
  132. }
  133. // n / n! -> 1 / (n - 1)!
  134. if (car(p2) == symbol(POWER)
  135. && isminusone(caddr(p2))
  136. && caadr(p2) == symbol(FACTORIAL)
  137. && equal(p1, cadadr(p2))) {
  138. push(p1);
  139. push_integer(-1);
  140. add();
  141. factorial();
  142. reciprocate();
  143. stack[i] = pop();
  144. stack[j] = one;
  145. return 1;
  146. }
  147. // (n + 1) n! -> (n + 1)!
  148. if (car(p2) == symbol(FACTORIAL)) {
  149. push(p1);
  150. push(cadr(p2));
  151. subtract();
  152. p3 = pop();
  153. if (isplusone(p3)) {
  154. push(p1);
  155. factorial();
  156. stack[i] = pop();
  157. stack[j] = one;
  158. return 1;
  159. }
  160. }
  161. // 1 / ((n + 1) n!) -> 1 / (n + 1)!
  162. if (car(p1) == symbol(POWER)
  163. && isminusone(caddr(p1))
  164. && car(p2) == symbol(POWER)
  165. && isminusone(caddr(p2))
  166. && caadr(p2) == symbol(FACTORIAL)) {
  167. push(cadr(p1));
  168. push(cadr(cadr(p2)));
  169. subtract();
  170. p3 = pop();
  171. if (isplusone(p3)) {
  172. push(cadr(p1));
  173. factorial();
  174. reciprocate();
  175. stack[i] = pop();
  176. stack[j] = one;
  177. return 1;
  178. }
  179. }
  180. // (n + 1)! / n! -> n + 1
  181. // n! / (n + 1)! -> 1 / (n + 1)
  182. if (car(p1) == symbol(FACTORIAL)
  183. && car(p2) == symbol(POWER)
  184. && isminusone(caddr(p2))
  185. && caadr(p2) == symbol(FACTORIAL)) {
  186. push(cadr(p1));
  187. push(cadr(cadr(p2)));
  188. subtract();
  189. p3 = pop();
  190. if (isplusone(p3)) {
  191. stack[i] = cadr(p1);
  192. stack[j] = one;
  193. return 1;
  194. }
  195. if (isminusone(p3)) {
  196. push(cadr(cadr(p2)));
  197. reciprocate();
  198. stack[i] = pop();
  199. stack[j] = one;
  200. return 1;
  201. }
  202. if (equaln(p3, 2)) {
  203. stack[i] = cadr(p1);
  204. push(cadr(p1));
  205. push_integer(-1);
  206. add();
  207. stack[j] = pop();
  208. return 1;
  209. }
  210. if (equaln(p3, -2)) {
  211. push(cadr(cadr(p2)));
  212. reciprocate();
  213. stack[i] = pop();
  214. push(cadr(cadr(p2)));
  215. push_integer(-1);
  216. add();
  217. reciprocate();
  218. stack[j] = pop();
  219. return 1;
  220. }
  221. }
  222. }
  223. }
  224. return 0;
  225. }