rationalize.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. #define DEBUG 0
  4. static void __rationalize_tensor(void);
  5. static void multiply_denominators(U *);
  6. static void multiply_denominators_term(U *);
  7. static void multiply_denominators_factor(U *);
  8. static void __lcm(void);
  9. void
  10. eval_rationalize(void)
  11. {
  12. push(cadr(p1));
  13. eval();
  14. rationalize();
  15. }
  16. void
  17. rationalize(void)
  18. {
  19. int x = expanding;
  20. save();
  21. yyrationalize();
  22. restore();
  23. expanding = x;
  24. }
  25. void
  26. yyrationalize(void)
  27. {
  28. p1 = pop();
  29. if (istensor(p1)) {
  30. __rationalize_tensor();
  31. return;
  32. }
  33. expanding = 0;
  34. if (car(p1) != symbol(ADD)) {
  35. push(p1);
  36. return;
  37. }
  38. // get common denominator
  39. push(one);
  40. multiply_denominators(p1);
  41. p2 = pop();
  42. // multiply each term by common denominator
  43. push(zero);
  44. p3 = cdr(p1);
  45. while (iscons(p3)) {
  46. push(p2);
  47. push(car(p3));
  48. multiply();
  49. add();
  50. p3 = cdr(p3);
  51. }
  52. // collect common factors
  53. Condense();
  54. // divide by common denominator
  55. push(p2);
  56. divide();
  57. }
  58. static void
  59. multiply_denominators(U *p)
  60. {
  61. if (car(p) == symbol(ADD)) {
  62. p = cdr(p);
  63. while (iscons(p)) {
  64. multiply_denominators_term(car(p));
  65. p = cdr(p);
  66. }
  67. } else
  68. multiply_denominators_term(p);
  69. }
  70. static void
  71. multiply_denominators_term(U *p)
  72. {
  73. if (car(p) == symbol(MULTIPLY)) {
  74. p = cdr(p);
  75. while (iscons(p)) {
  76. multiply_denominators_factor(car(p));
  77. p = cdr(p);
  78. }
  79. } else
  80. multiply_denominators_factor(p);
  81. }
  82. static void
  83. multiply_denominators_factor(U *p)
  84. {
  85. if (car(p) != symbol(POWER))
  86. return;
  87. push(p);
  88. p = caddr(p);
  89. // like x^(-2) ?
  90. if (isnegativenumber(p)) {
  91. inverse();
  92. __lcm();
  93. return;
  94. }
  95. // like x^(-a) ?
  96. if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p))) {
  97. inverse();
  98. __lcm();
  99. return;
  100. }
  101. // no match
  102. pop();
  103. }
  104. static void
  105. __rationalize_tensor(void)
  106. {
  107. int i, n;
  108. push(p1);
  109. eval(); // makes a copy
  110. p1 = pop();
  111. if (!istensor(p1)) { // might be zero
  112. push(p1);
  113. return;
  114. }
  115. n = p1->u.tensor->nelem;
  116. for (i = 0; i < n; i++) {
  117. push(p1->u.tensor->elem[i]);
  118. rationalize();
  119. p1->u.tensor->elem[i] = pop();
  120. }
  121. push(p1);
  122. }
  123. static void
  124. __lcm(void)
  125. {
  126. save();
  127. p1 = pop();
  128. p2 = pop();
  129. push(p1);
  130. push(p2);
  131. multiply();
  132. push(p1);
  133. push(p2);
  134. gcd();
  135. divide();
  136. restore();
  137. }