roots.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. extern void sort_stack(int);
  4. void roots(void);
  5. static void roots2(void);
  6. static void roots3(void);
  7. static void mini_solve(void);
  8. #define POLY p1
  9. #define X p2
  10. #define A p3
  11. #define B p4
  12. #define C p5
  13. #define Y p6
  14. void
  15. eval_roots(void)
  16. {
  17. // A == B -> A - B
  18. p2 = cadr(p1);
  19. if (car(p2) == symbol(SETQ) || car(p2) == symbol(TESTEQ)) {
  20. push(cadr(p2));
  21. eval();
  22. push(caddr(p2));
  23. eval();
  24. subtract();
  25. } else {
  26. push(p2);
  27. eval();
  28. p2 = pop();
  29. if (car(p2) == symbol(SETQ) || car(p2) == symbol(TESTEQ)) {
  30. push(cadr(p2));
  31. eval();
  32. push(caddr(p2));
  33. eval();
  34. subtract();
  35. } else
  36. push(p2);
  37. }
  38. // 2nd arg, x
  39. push(caddr(p1));
  40. eval();
  41. p2 = pop();
  42. if (p2 == symbol(NIL))
  43. guess();
  44. else
  45. push(p2);
  46. p2 = pop();
  47. p1 = pop();
  48. if (!ispoly(p1, p2))
  49. stop("roots: 1st argument is not a polynomial");
  50. push(p1);
  51. push(p2);
  52. roots();
  53. }
  54. void
  55. roots(void)
  56. {
  57. int h, i, n;
  58. h = tos - 2;
  59. roots2();
  60. n = tos - h;
  61. if (n == 0)
  62. stop("roots: the polynomial is not factorable, try nroots");
  63. if (n == 1)
  64. return;
  65. sort_stack(n);
  66. save();
  67. p1 = alloc_tensor(n);
  68. p1->u.tensor->ndim = 1;
  69. p1->u.tensor->dim[0] = n;
  70. for (i = 0; i < n; i++)
  71. p1->u.tensor->elem[i] = stack[h + i];
  72. tos = h;
  73. push(p1);
  74. restore();
  75. }
  76. static void
  77. roots2(void)
  78. {
  79. save();
  80. p2 = pop();
  81. p1 = pop();
  82. push(p1);
  83. push(p2);
  84. factorpoly();
  85. p1 = pop();
  86. if (car(p1) == symbol(MULTIPLY)) {
  87. p1 = cdr(p1);
  88. while (iscons(p1)) {
  89. push(car(p1));
  90. push(p2);
  91. roots3();
  92. p1 = cdr(p1);
  93. }
  94. } else {
  95. push(p1);
  96. push(p2);
  97. roots3();
  98. }
  99. restore();
  100. }
  101. static void
  102. roots3(void)
  103. {
  104. save();
  105. p2 = pop();
  106. p1 = pop();
  107. if (car(p1) == symbol(POWER) && ispoly(cadr(p1), p2) && isposint(caddr(p1))) {
  108. push(cadr(p1));
  109. push(p2);
  110. mini_solve();
  111. } else if (ispoly(p1, p2)) {
  112. push(p1);
  113. push(p2);
  114. mini_solve();
  115. }
  116. restore();
  117. }
  118. //-----------------------------------------------------------------------------
  119. //
  120. // Input: stack[tos - 2] polynomial
  121. //
  122. // stack[tos - 1] dependent symbol
  123. //
  124. // Output: stack roots on stack
  125. //
  126. // (input args are popped first)
  127. //
  128. //-----------------------------------------------------------------------------
  129. static void
  130. mini_solve(void)
  131. {
  132. int n;
  133. save();
  134. X = pop();
  135. POLY = pop();
  136. push(POLY);
  137. push(X);
  138. n = coeff();
  139. // AX + B, X = -B/A
  140. if (n == 2) {
  141. A = pop();
  142. B = pop();
  143. push(B);
  144. push(A);
  145. divide();
  146. negate();
  147. restore();
  148. return;
  149. }
  150. // AX^2 + BX + C, X = (-B +/- (B^2 - 4AC)^(1/2)) / (2A)
  151. if (n == 3) {
  152. A = pop();
  153. B = pop();
  154. C = pop();
  155. push(B);
  156. push(B);
  157. multiply();
  158. push_integer(4);
  159. push(A);
  160. multiply();
  161. push(C);
  162. multiply();
  163. subtract();
  164. push_rational(1, 2);
  165. power();
  166. Y = pop();
  167. push(Y); // 1st root
  168. push(B);
  169. subtract();
  170. push(A);
  171. divide();
  172. push_rational(1, 2);
  173. multiply();
  174. push(Y); // 2nd root
  175. push(B);
  176. add();
  177. negate();
  178. push(A);
  179. divide();
  180. push_rational(1, 2);
  181. multiply();
  182. restore();
  183. return;
  184. }
  185. tos -= n;
  186. restore();
  187. }
  188. #if SELFTEST
  189. static char *s[] = {
  190. "roots(x)",
  191. "0",
  192. "roots(x^2)",
  193. "0",
  194. "roots(x^3)",
  195. "0",
  196. "roots(2 x)",
  197. "0",
  198. "roots(2 x^2)",
  199. "0",
  200. "roots(2 x^3)",
  201. "0",
  202. "roots(6+11*x+6*x^2+x^3)",
  203. "(-3,-2,-1)",
  204. "roots(a*x^2+b*x+c)",
  205. "(-b/(2*a)-(-4*a*c+b^2)^(1/2)/(2*a),-b/(2*a)+(-4*a*c+b^2)^(1/2)/(2*a))",
  206. "roots(3+7*x+5*x^2+x^3)",
  207. "(-3,-1)",
  208. "roots(x^3+x^2+x+1)",
  209. "(-1,-i,i)",
  210. "roots(x^4+1)",
  211. "Stop: roots: the polynomial is not factorable, try nroots",
  212. "roots(x^2==1)",
  213. "(-1,1)",
  214. "roots(3 x + 12 == 24)",
  215. "4",
  216. "y=roots(x^2+b*x+c/k)[1]",
  217. "",
  218. "y^2+b*y+c/k",
  219. "0",
  220. "y=roots(x^2+b*x+c/k)[2]",
  221. "",
  222. "y^2+b*y+c/k",
  223. "0",
  224. "y=roots(a*x^2+b*x+c/4)[1]",
  225. "",
  226. "a*y^2+b*y+c/4",
  227. "0",
  228. "y=roots(a*x^2+b*x+c/4)[2]",
  229. "",
  230. "a*y^2+b*y+c/4",
  231. "0",
  232. "y=quote(y)",
  233. "",
  234. };
  235. void
  236. test_roots(void)
  237. {
  238. test(__FILE__, s, sizeof s / sizeof (char *));
  239. }
  240. #endif