simplify.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. extern int trigmode;
  4. static void simplify_tensor(void);
  5. static int count(U *);
  6. static int nterms(U *);
  7. static void f1(void);
  8. static void f2(void);
  9. static void f3(void);
  10. static void f4(void);
  11. static void f5(void);
  12. static void f9(void);
  13. void
  14. eval_simplify(void)
  15. {
  16. push(cadr(p1));
  17. eval();
  18. simplify();
  19. }
  20. void
  21. simplify(void)
  22. {
  23. save();
  24. simplify_main();
  25. restore();
  26. }
  27. void
  28. simplify_main(void)
  29. {
  30. p1 = pop();
  31. if (istensor(p1)) {
  32. simplify_tensor();
  33. return;
  34. }
  35. if (find(p1, symbol(FACTORIAL))) {
  36. push(p1);
  37. simfac();
  38. p2 = pop();
  39. push(p1);
  40. rationalize();
  41. simfac();
  42. p3 = pop();
  43. if (count(p2) < count(p3))
  44. p1 = p2;
  45. else
  46. p1 = p3;
  47. }
  48. f1();
  49. f2();
  50. f3();
  51. f4();
  52. f5();
  53. f9();
  54. push(p1);
  55. }
  56. static void
  57. simplify_tensor(void)
  58. {
  59. int i;
  60. p2 = alloc_tensor(p1->u.tensor->nelem);
  61. p2->u.tensor->ndim = p1->u.tensor->ndim;
  62. for (i = 0; i < p1->u.tensor->ndim; i++)
  63. p2->u.tensor->dim[i] = p1->u.tensor->dim[i];
  64. for (i = 0; i < p1->u.tensor->nelem; i++) {
  65. push(p1->u.tensor->elem[i]);
  66. simplify();
  67. p2->u.tensor->elem[i] = pop();
  68. }
  69. if (iszero(p2))
  70. p2 = zero; // null tensor becomes scalar zero
  71. push(p2);
  72. }
  73. static int
  74. count(U *p)
  75. {
  76. int n;
  77. if (iscons(p)) {
  78. n = 0;
  79. while (iscons(p)) {
  80. n += count(car(p)) + 1;
  81. p = cdr(p);
  82. }
  83. } else
  84. n = 1;
  85. return n;
  86. }
  87. // try rationalizing
  88. static void
  89. f1(void)
  90. {
  91. if (car(p1) != symbol(ADD))
  92. return;
  93. push(p1);
  94. rationalize();
  95. p2 = pop();
  96. if (count(p2) < count(p1))
  97. p1 = p2;
  98. }
  99. // try condensing
  100. static void
  101. f2(void)
  102. {
  103. if (car(p1) != symbol(ADD))
  104. return;
  105. push(p1);
  106. Condense();
  107. p2 = pop();
  108. if (count(p2) <= count(p1))
  109. p1 = p2;
  110. }
  111. // this simplifies forms like (A-B) / (B-A)
  112. static void
  113. f3(void)
  114. {
  115. push(p1);
  116. rationalize();
  117. negate();
  118. rationalize();
  119. negate();
  120. rationalize();
  121. p2 = pop();
  122. if (count(p2) < count(p1))
  123. p1 = p2;
  124. }
  125. // try expanding denominators
  126. static void
  127. f4(void)
  128. {
  129. if (iszero(p1))
  130. return;
  131. push(p1);
  132. rationalize();
  133. inverse();
  134. rationalize();
  135. inverse();
  136. rationalize();
  137. p2 = pop();
  138. if (count(p2) < count(p1))
  139. p1 = p2;
  140. }
  141. // simplifies trig forms
  142. void
  143. simplify_trig(void)
  144. {
  145. save();
  146. p1 = pop();
  147. f5();
  148. push(p1);
  149. restore();
  150. }
  151. static void
  152. f5(void)
  153. {
  154. if (find(p1, symbol(SIN)) == 0 && find(p1, symbol(COS)) == 0)
  155. return;
  156. p2 = p1;
  157. trigmode = 1;
  158. push(p2);
  159. eval();
  160. p3 = pop();
  161. trigmode = 2;
  162. push(p2);
  163. eval();
  164. p4 = pop();
  165. trigmode = 0;
  166. if (count(p4) < count(p3) || nterms(p4) < nterms(p3))
  167. p3 = p4;
  168. if (count(p3) < count(p1) || nterms(p3) < nterms(p1))
  169. p1 = p3;
  170. }
  171. // if it's a sum then try to simplify each term
  172. static void
  173. f9(void)
  174. {
  175. if (car(p1) != symbol(ADD))
  176. return;
  177. push_integer(0);
  178. p2 = cdr(p1);
  179. while (iscons(p2)) {
  180. push(car(p2));
  181. simplify();
  182. add();
  183. p2 = cdr(p2);
  184. }
  185. p2 = pop();
  186. if (count(p2) < count(p1))
  187. p1 = p2;
  188. }
  189. static int
  190. nterms(U *p)
  191. {
  192. if (car(p) != symbol(ADD))
  193. return 1;
  194. else
  195. return length(p) - 1;
  196. }
  197. #if SELFTEST
  198. static char *s[] = {
  199. "simplify(A)",
  200. "A",
  201. "simplify(A+B)",
  202. "A+B",
  203. "simplify(A B)",
  204. "A*B",
  205. "simplify(A^B)",
  206. "A^B",
  207. "simplify(A/(A+B)+B/(A+B))",
  208. "1",
  209. "simplify((A-B)/(B-A))",
  210. "-1",
  211. "A=((A11,A12),(A21,A22))",
  212. "",
  213. "simplify(det(A) inv(A) - adj(A))",
  214. "0",
  215. "A=quote(A)",
  216. "",
  217. // this shows need for <= in try_factoring
  218. // "x*(1+a)",
  219. // "x+a*x",
  220. // "simplify(last)",
  221. // "x*(1+a)",
  222. "simplify(-3 exp(-1/3 r + i phi) cos(theta) / sin(theta)"
  223. " + 3 exp(-1/3 r + i phi) cos(theta) sin(theta)"
  224. " + 3 exp(-1/3 r + i phi) cos(theta)^3 / sin(theta))",
  225. "0",
  226. "simplify((A^2 C^2 + A^2 D^2 + B^2 C^2 + B^2 D^2)/(A^2+B^2)/(C^2+D^2))",
  227. "1",
  228. "simplify(d(arctan(y/x),y))",
  229. "x/(x^2+y^2)",
  230. "simplify(d(arctan(y/x),x))",
  231. "-y/(x^2+y^2)",
  232. "simplify(1-sin(x)^2)",
  233. "cos(x)^2",
  234. "simplify(1-cos(x)^2)",
  235. "sin(x)^2",
  236. "simplify(sin(x)^2-1)",
  237. "-cos(x)^2",
  238. "simplify(cos(x)^2-1)",
  239. "-sin(x)^2",
  240. /*
  241. "simfac(n!/n)-(n-1)!",
  242. "0",
  243. "simfac(n/n!)-1/(n-1)!",
  244. "0",
  245. "simfac(rationalize((n+k+1)/(n+k+1)!))-1/(n+k)!",
  246. "0",
  247. "simfac(condense((n+1)*n!))-(n+1)!",
  248. "0",
  249. "simfac(1/((n+1)*n!))-1/(n+1)!",
  250. "0",
  251. "simfac((n+1)!/n!)-n-1",
  252. "0",
  253. "simfac(n!/(n+1)!)-1/(n+1)",
  254. "0",
  255. "simfac(binomial(n+1,k)/binomial(n,k))",
  256. "(1+n)/(1-k+n)",
  257. "simfac(binomial(n,k)/binomial(n+1,k))",
  258. "(1-k+n)/(1+n)",
  259. "F(nn,kk)=kk*binomial(nn,kk)",
  260. "",
  261. "simplify(simfac((F(n,k)+F(n,k-1))/F(n+1,k))-n/(n+1))",
  262. "0",
  263. "F=quote(F)",
  264. "",
  265. */
  266. "simplify(n!/n)-(n-1)!",
  267. "0",
  268. "simplify(n/n!)-1/(n-1)!",
  269. "0",
  270. "simplify(rationalize((n+k+1)/(n+k+1)!))-1/(n+k)!",
  271. "0",
  272. "simplify(condense((n+1)*n!))-(n+1)!",
  273. "0",
  274. "simplify(1/((n+1)*n!))-1/(n+1)!",
  275. "0",
  276. "simplify((n+1)!/n!)-n-1",
  277. "0",
  278. "simplify(n!/(n+1)!)-1/(n+1)",
  279. "0",
  280. "simplify(binomial(n+1,k)/binomial(n,k))",
  281. "(1+n)/(1-k+n)",
  282. "simplify(binomial(n,k)/binomial(n+1,k))",
  283. "(1-k+n)/(1+n)",
  284. "F(nn,kk)=kk*binomial(nn,kk)",
  285. "",
  286. "simplify((F(n,k)+F(n,k-1))/F(n+1,k))-n/(n+1)",
  287. "0",
  288. "F=quote(F)",
  289. "",
  290. "simplify((n+1)/(n+1)!)-1/n!",
  291. "0",
  292. "simplify(a*b+a*c)",
  293. "a*(b+c)",
  294. // Symbol's binding is evaluated, undoing simplify
  295. "x=simplify(a*b+a*c)",
  296. "",
  297. "x",
  298. "a*b+a*c",
  299. };
  300. void
  301. test_simplify(void)
  302. {
  303. test(__FILE__, s, sizeof s / sizeof (char *));
  304. }
  305. #endif