power.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /* Power function
  2. Input: push Base
  3. push Exponent
  4. Output: Result on stack
  5. */
  6. #include "stdafx.h"
  7. #include "defs.h"
  8. void
  9. eval_power(void)
  10. {
  11. push(cadr(p1));
  12. eval();
  13. push(caddr(p1));
  14. eval();
  15. power();
  16. }
  17. void
  18. power(void)
  19. {
  20. save();
  21. yypower();
  22. restore();
  23. }
  24. void
  25. yypower(void)
  26. {
  27. int n;
  28. p2 = pop();
  29. p1 = pop();
  30. // both base and exponent are rational numbers?
  31. if (isrational(p1) && isrational(p2)) {
  32. push(p1);
  33. push(p2);
  34. qpow();
  35. return;
  36. }
  37. // both base and exponent are either rational or double?
  38. if (isnum(p1) && isnum(p2)) {
  39. push(p1);
  40. push(p2);
  41. dpow();
  42. return;
  43. }
  44. if (istensor(p1)) {
  45. power_tensor();
  46. return;
  47. }
  48. if (p1 == symbol(E) && car(p2) == symbol(LOG)) {
  49. push(cadr(p2));
  50. return;
  51. }
  52. if (p1 == symbol(E) && isdouble(p2)) {
  53. push_double(exp(p2->u.d));
  54. return;
  55. }
  56. // 1 ^ a -> 1
  57. // a ^ 0 -> 1
  58. if (equal(p1, one) || iszero(p2)) {
  59. push(one);
  60. return;
  61. }
  62. // a ^ 1 -> a
  63. if (equal(p2, one)) {
  64. push(p1);
  65. return;
  66. }
  67. // (a * b) ^ c -> (a ^ c) * (b ^ c)
  68. if (car(p1) == symbol(MULTIPLY)) {
  69. p1 = cdr(p1);
  70. push(car(p1));
  71. push(p2);
  72. power();
  73. p1 = cdr(p1);
  74. while (iscons(p1)) {
  75. push(car(p1));
  76. push(p2);
  77. power();
  78. multiply();
  79. p1 = cdr(p1);
  80. }
  81. return;
  82. }
  83. // (a ^ b) ^ c -> a ^ (b * c)
  84. if (car(p1) == symbol(POWER)) {
  85. push(cadr(p1));
  86. push(caddr(p1));
  87. push(p2);
  88. multiply();
  89. power();
  90. return;
  91. }
  92. // (a + b) ^ n -> (a + b) * (a + b) ...
  93. if (expanding && isadd(p1) && isnum(p2)) {
  94. push(p2);
  95. n = pop_integer();
  96. if (n > 1) {
  97. power_sum(n);
  98. return;
  99. }
  100. }
  101. // sin(x) ^ 2n -> (1 - cos(x) ^ 2) ^ n
  102. if (trigmode == 1 && car(p1) == symbol(SIN) && iseveninteger(p2)) {
  103. push_integer(1);
  104. push(cadr(p1));
  105. cosine();
  106. push_integer(2);
  107. power();
  108. subtract();
  109. push(p2);
  110. push_rational(1, 2);
  111. multiply();
  112. power();
  113. return;
  114. }
  115. // cos(x) ^ 2n -> (1 - sin(x) ^ 2) ^ n
  116. if (trigmode == 2 && car(p1) == symbol(COS) && iseveninteger(p2)) {
  117. push_integer(1);
  118. push(cadr(p1));
  119. sine();
  120. push_integer(2);
  121. power();
  122. subtract();
  123. push(p2);
  124. push_rational(1, 2);
  125. multiply();
  126. power();
  127. return;
  128. }
  129. // complex number? (just number, not expression)
  130. if (iscomplexnumber(p1)) {
  131. // integer power?
  132. // n will be negative here, positive n already handled
  133. if (isinteger(p2)) {
  134. // / \ n
  135. // -n | a - ib |
  136. // (a + ib) = | -------- |
  137. // | 2 2 |
  138. // \ a + b /
  139. push(p1);
  140. conjugate();
  141. p3 = pop();
  142. push(p3);
  143. push(p3);
  144. push(p1);
  145. multiply();
  146. divide();
  147. push(p2);
  148. negate();
  149. power();
  150. return;
  151. }
  152. // noninteger or floating power?
  153. if (isnum(p2)) {
  154. #if 1 // use polar form
  155. push(p1);
  156. mag();
  157. push(p2);
  158. power();
  159. push_integer(-1);
  160. push(p1);
  161. arg();
  162. push(p2);
  163. multiply();
  164. push(symbol(PI));
  165. divide();
  166. power();
  167. multiply();
  168. #else // use exponential form
  169. push(p1);
  170. mag();
  171. push(p2);
  172. power();
  173. push(symbol(E));
  174. push(p1);
  175. arg();
  176. push(p2);
  177. multiply();
  178. push(imaginaryunit);
  179. multiply();
  180. power();
  181. multiply();
  182. #endif
  183. return;
  184. }
  185. }
  186. if (simplify_polar())
  187. return;
  188. push_symbol(POWER);
  189. push(p1);
  190. push(p2);
  191. list(3);
  192. }
  193. //-----------------------------------------------------------------------------
  194. //
  195. // Compute the power of a sum
  196. //
  197. // Input: p1 sum
  198. //
  199. // n exponent
  200. //
  201. // Output: Result on stack
  202. //
  203. // Note:
  204. //
  205. // Uses the multinomial series (see Math World)
  206. //
  207. // n n! n1 n2 nk
  208. // (a1 + a2 + ... + ak) = sum (--------------- a1 a2 ... ak )
  209. // n1! n2! ... nk!
  210. //
  211. // The sum is over all n1 ... nk such that n1 + n2 + ... + nk = n.
  212. //
  213. //-----------------------------------------------------------------------------
  214. // first index is the term number 0..k-1, second index is the exponent 0..n
  215. #define A(i, j) frame[(i) * (n + 1) + (j)]
  216. void
  217. power_sum(int n)
  218. {
  219. int *a, i, j, k;
  220. // number of terms in the sum
  221. k = length(p1) - 1;
  222. // local frame
  223. push_frame(k * (n + 1));
  224. // array of powers
  225. p1 = cdr(p1);
  226. for (i = 0; i < k; i++) {
  227. for (j = 0; j <= n; j++) {
  228. push(car(p1));
  229. push_integer(j);
  230. power();
  231. A(i, j) = pop();
  232. }
  233. p1 = cdr(p1);
  234. }
  235. push_integer(n);
  236. factorial();
  237. p1 = pop();
  238. a = (int *) malloc(k * sizeof (int));
  239. if (a == NULL)
  240. stop("malloc failure");
  241. push(zero);
  242. multinomial_sum(k, n, a, 0, n);
  243. free(a);
  244. pop_frame(k * (n + 1));
  245. }
  246. //-----------------------------------------------------------------------------
  247. //
  248. // Compute multinomial sum
  249. //
  250. // Input: k number of factors
  251. //
  252. // n overall exponent
  253. //
  254. // a partition array
  255. //
  256. // i partition array index
  257. //
  258. // m partition remainder
  259. //
  260. // p1 n!
  261. //
  262. // A factor array
  263. //
  264. // Output: Result on stack
  265. //
  266. // Note:
  267. //
  268. // Uses recursive descent to fill the partition array.
  269. //
  270. //-----------------------------------------------------------------------------
  271. void
  272. multinomial_sum(int k, int n, int *a, int i, int m)
  273. {
  274. int j;
  275. if (i < k - 1) {
  276. for (j = 0; j <= m; j++) {
  277. a[i] = j;
  278. multinomial_sum(k, n, a, i + 1, m - j);
  279. }
  280. return;
  281. }
  282. a[i] = m;
  283. // coefficient
  284. push(p1);
  285. for (j = 0; j < k; j++) {
  286. push_integer(a[j]);
  287. factorial();
  288. divide();
  289. }
  290. // factors
  291. for (j = 0; j < k; j++) {
  292. push(A(j, a[j]));
  293. multiply();
  294. }
  295. add();
  296. }
  297. // exp(n/2 i pi) ?
  298. // p2 is the exponent expression
  299. // clobbers p3
  300. int
  301. simplify_polar(void)
  302. {
  303. int n;
  304. n = isquarterturn(p2);
  305. switch(n) {
  306. case 0:
  307. break;
  308. case 1:
  309. push_integer(1);
  310. return 1;
  311. case 2:
  312. push_integer(-1);
  313. return 1;
  314. case 3:
  315. push(imaginaryunit);
  316. return 1;
  317. case 4:
  318. push(imaginaryunit);
  319. negate();
  320. return 1;
  321. }
  322. if (car(p2) == symbol(ADD)) {
  323. p3 = cdr(p2);
  324. while (iscons(p3)) {
  325. n = isquarterturn(car(p3));
  326. if (n)
  327. break;
  328. p3 = cdr(p3);
  329. }
  330. switch (n) {
  331. case 0:
  332. return 0;
  333. case 1:
  334. push_integer(1);
  335. break;
  336. case 2:
  337. push_integer(-1);
  338. break;
  339. case 3:
  340. push(imaginaryunit);
  341. break;
  342. case 4:
  343. push(imaginaryunit);
  344. negate();
  345. break;
  346. }
  347. push(p2);
  348. push(car(p3));
  349. subtract();
  350. exponential();
  351. multiply();
  352. return 1;
  353. }
  354. return 0;
  355. }
  356. #if SELFTEST
  357. static char *s[] = {
  358. "2^(1/2)",
  359. "2^(1/2)",
  360. "2^(3/2)",
  361. "2*2^(1/2)",
  362. "(-2)^(1/2)",
  363. "i*2^(1/2)",
  364. "3^(4/3)",
  365. "3*3^(1/3)",
  366. "3^(-4/3)",
  367. "1/(3*3^(1/3))",
  368. "3^(5/3)",
  369. "3*3^(2/3)",
  370. "3^(2/3)-9^(1/3)",
  371. "0",
  372. "3^(10/3)",
  373. "27*3^(1/3)",
  374. "3^(-10/3)",
  375. "1/(27*3^(1/3))",
  376. "(1/3)^(10/3)",
  377. "1/(27*3^(1/3))",
  378. "(1/3)^(-10/3)",
  379. "27*3^(1/3)",
  380. "27^(2/3)",
  381. "9",
  382. "27^(-2/3)",
  383. "1/9",
  384. "102^(1/2)",
  385. "2^(1/2)*3^(1/2)*17^(1/2)",
  386. "32^(1/3)",
  387. "2*2^(2/3)",
  388. "9999^(1/2)",
  389. "3*11^(1/2)*101^(1/2)",
  390. "10000^(1/3)",
  391. "10*2^(1/3)*5^(1/3)",
  392. "sqrt(1000000)",
  393. "1000",
  394. "sqrt(-1000000)",
  395. "1000*i",
  396. "sqrt(2^60)",
  397. "1073741824",
  398. // this is why we factor irrationals
  399. "6^(1/3) 3^(2/3)",
  400. "3*2^(1/3)",
  401. // inverse of complex numbers
  402. "1/(2+3*i)",
  403. "2/13-3/13*i",
  404. "1/(2+3*i)^2",
  405. "-5/169-12/169*i",
  406. "(-1+3i)/(2-i)",
  407. "-1+i",
  408. // other
  409. "(0.0)^(0.0)",
  410. "1",
  411. "(-4.0)^(1.5)",
  412. "-8*i",
  413. "(-4.0)^(0.5)",
  414. "2*i",
  415. "(-4.0)^(-0.5)",
  416. "-0.5*i",
  417. "(-4.0)^(-1.5)",
  418. "0.125*i",
  419. // more complex number cases
  420. "(1+i)^2",
  421. "2*i",
  422. "(1+i)^(-2)",
  423. "-1/2*i",
  424. "(1+i)^(1/2)",
  425. "(-1)^(1/8)*2^(1/4)",
  426. "(1+i)^(-1/2)",
  427. "-(-1)^(7/8)/(2^(1/4))",
  428. "(1+i)^(0.5)",
  429. "1.09868+0.45509*i",
  430. "(1+i)^(-0.5)",
  431. "0.776887-0.321797*i",
  432. // test cases for simplification of polar forms, counterclockwise
  433. "exp(i*pi/2)",
  434. "i",
  435. "exp(i*pi)",
  436. "-1",
  437. "exp(i*3*pi/2)",
  438. "-i",
  439. "exp(i*2*pi)",
  440. "1",
  441. "exp(i*5*pi/2)",
  442. "i",
  443. "exp(i*3*pi)",
  444. "-1",
  445. "exp(i*7*pi/2)",
  446. "-i",
  447. "exp(i*4*pi)",
  448. "1",
  449. "exp(A+i*pi/2)",
  450. "i*exp(A)",
  451. "exp(A+i*pi)",
  452. "-exp(A)",
  453. "exp(A+i*3*pi/2)",
  454. "-i*exp(A)",
  455. "exp(A+i*2*pi)",
  456. "exp(A)",
  457. "exp(A+i*5*pi/2)",
  458. "i*exp(A)",
  459. "exp(A+i*3*pi)",
  460. "-exp(A)",
  461. "exp(A+i*7*pi/2)",
  462. "-i*exp(A)",
  463. "exp(A+i*4*pi)",
  464. "exp(A)",
  465. // test cases for simplification of polar forms, clockwise
  466. "exp(-i*pi/2)",
  467. "-i",
  468. "exp(-i*pi)",
  469. "-1",
  470. "exp(-i*3*pi/2)",
  471. "i",
  472. "exp(-i*2*pi)",
  473. "1",
  474. "exp(-i*5*pi/2)",
  475. "-i",
  476. "exp(-i*3*pi)",
  477. "-1",
  478. "exp(-i*7*pi/2)",
  479. "i",
  480. "exp(-i*4*pi)",
  481. "1",
  482. "exp(A-i*pi/2)",
  483. "-i*exp(A)",
  484. "exp(A-i*pi)",
  485. "-exp(A)",
  486. "exp(A-i*3*pi/2)",
  487. "i*exp(A)",
  488. "exp(A-i*2*pi)",
  489. "exp(A)",
  490. "exp(A-i*5*pi/2)",
  491. "-i*exp(A)",
  492. "exp(A-i*3*pi)",
  493. "-exp(A)",
  494. "exp(A-i*7*pi/2)",
  495. "i*exp(A)",
  496. "exp(A-i*4*pi)",
  497. "exp(A)",
  498. };
  499. void
  500. test_power(void)
  501. {
  502. test(__FILE__, s, sizeof s / sizeof (char *));
  503. }
  504. #endif