IterationIR.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include "IterationIR.h"
  2. #include <utility>
  3. using namespace mnd;
  4. namespace mnd
  5. {
  6. using ir::Node;
  7. struct ConvertVisitor
  8. {
  9. using NodePair = std::pair<Node*, Node*>;
  10. util::Arena<Node>& arena;
  11. ConvertVisitor(util::Arena<Node>& arena) :
  12. arena{ arena }
  13. {
  14. }
  15. NodePair operator() (const Constant& c)
  16. {
  17. Node* cnst = arena.allocate(ir::Constant{ c.value });
  18. Node* zero = arena.allocate(ir::Constant{ 0.0 });
  19. return { cnst, zero };
  20. }
  21. NodePair operator() (const Variable& v)
  22. {
  23. //printf("var %s\n", v.name.c_str()); fflush(stdout);
  24. if (v.name == "z") {
  25. Node* a = arena.allocate(ir::Variable{ "a" });
  26. Node* b = arena.allocate(ir::Variable{ "b" });
  27. return { a, b };
  28. }
  29. else if (v.name == "c") {
  30. Node* x = arena.allocate(ir::Variable{ "x" });
  31. Node* y = arena.allocate(ir::Variable{ "y" });
  32. return { x, y };
  33. }
  34. else if (v.name == "i") {
  35. Node* x = arena.allocate(ir::Constant{ 0.0 });
  36. Node* y = arena.allocate(ir::Constant{ 1.0 });
  37. return { x, y };
  38. }
  39. else
  40. throw "unknown variable";
  41. }
  42. NodePair operator() (const UnaryOperation& v)
  43. {
  44. auto [opa, opb] = std::visit(*this, *v.operand);
  45. Node* a = arena.allocate(ir::Negation{ opa });
  46. Node* b = arena.allocate(ir::Negation{ opb });
  47. return { a, b };
  48. }
  49. NodePair operator() (const Addition& add)
  50. {
  51. auto [lefta, leftb] = std::visit(*this, *add.left);
  52. auto [righta, rightb] = std::visit(*this, *add.right);
  53. if (add.subtraction) {
  54. Node* a = arena.allocate(ir::Subtraction{ lefta, righta });
  55. Node* b = arena.allocate(ir::Subtraction{ leftb, rightb });
  56. return { a, b };
  57. }
  58. else {
  59. Node* a = arena.allocate(ir::Addition{ lefta, righta });
  60. Node* b = arena.allocate(ir::Addition{ leftb, rightb });
  61. return { a, b };
  62. }
  63. }
  64. NodePair operator() (const Multiplication& mul)
  65. {
  66. auto [a, b] = std::visit(*this, *mul.left);
  67. auto [c, d] = std::visit(*this, *mul.right);
  68. Node* ac = arena.allocate(ir::Multiplication{ a, c });
  69. Node* bd = arena.allocate(ir::Multiplication{ b, d });
  70. Node* ad = arena.allocate(ir::Multiplication{ a, d });
  71. Node* bc = arena.allocate(ir::Multiplication{ b, c });
  72. Node* newa = arena.allocate(ir::Subtraction{ ac, bd });
  73. Node* newb = arena.allocate(ir::Addition{ ad, bc });
  74. return { newa, newb };
  75. }
  76. NodePair operator() (const Division& mul)
  77. {
  78. // TODO implement
  79. throw "unimplemented";
  80. return { nullptr, nullptr };
  81. }
  82. NodePair operator() (const Pow& p)
  83. {
  84. auto [a, b] = std::visit(*this, *p.left);
  85. auto [c, d] = std::visit(*this, *p.right);
  86. auto half = arena.allocate(ir::Constant{ 0.5 });
  87. auto arg = arena.allocate(ir::Atan2{ b, a });
  88. auto aa = arena.allocate(ir::Multiplication{ a, a });
  89. auto bb = arena.allocate(ir::Multiplication{ b, b });
  90. auto absSq = arena.allocate(ir::Addition{ aa, bb });
  91. auto halfc = arena.allocate(ir::Multiplication{ c, half });
  92. auto darg = arena.allocate(ir::Multiplication{ d, arg });
  93. auto minusdarg = arena.allocate(ir::Negation{ darg });
  94. auto abspowc = arena.allocate(ir::Pow{ absSq, halfc });
  95. auto expdarg = arena.allocate(ir::Exp{ minusdarg });
  96. auto newAbs = arena.allocate(ir::Multiplication{ abspowc, expdarg });
  97. auto carg = arena.allocate(ir::Multiplication{ arg, c });
  98. auto halfd = arena.allocate(ir::Multiplication{ d, half });
  99. //absSq = arena.allocate(ir::Addition{ absSq, half });
  100. auto lnabsSq = arena.allocate(ir::Ln{ absSq });
  101. auto halfdlnabsSq = arena.allocate(ir::Multiplication{ halfd, lnabsSq });
  102. auto newArg = arena.allocate(ir::Addition{ halfdlnabsSq, carg });
  103. auto cosArg = arena.allocate(ir::Cos{ newArg });
  104. auto sinArg = arena.allocate(ir::Sin{ newArg });
  105. auto newA = arena.allocate(ir::Multiplication{ cosArg, newAbs });
  106. auto newB = arena.allocate(ir::Multiplication{ sinArg, newAbs });
  107. return { newA, newB };
  108. }
  109. };
  110. ir::Formula expand(const mnd::IterationFormula& fmla)
  111. {
  112. ir::Formula formula;
  113. ConvertVisitor cv{ formula.nodeArena };
  114. std::tie(formula.newA, formula.newB) = std::visit(cv, *fmla.expr);
  115. return formula;
  116. }
  117. }
  118. std::string mnd::ir::Formula::toString(void) const
  119. {
  120. struct ToStringVisitor
  121. {
  122. std::string operator()(const ir::Constant& c) {
  123. return mnd::toString(c.value);
  124. }
  125. std::string operator()(const ir::Variable& v) {
  126. return v.name;
  127. }
  128. std::string operator()(const ir::Negation& n) {
  129. return "-(" + std::visit(*this, *n.value) + ")";
  130. }
  131. std::string operator()(const ir::Addition& n) {
  132. return "(" + std::visit(*this, *n.left) + ") + (" + std::visit(*this, *n.right) + ")";
  133. }
  134. std::string operator()(const ir::Subtraction& n) {
  135. return "(" + std::visit(*this, *n.left) + ") - (" + std::visit(*this, *n.right) + ")";
  136. }
  137. std::string operator()(const ir::Multiplication& n) {
  138. return "(" + std::visit(*this, *n.left) + ") * (" + std::visit(*this, *n.right) + ")";
  139. }
  140. std::string operator()(const ir::Atan2& n) {
  141. return "atan2(" + std::visit(*this, *n.left) + ", " + std::visit(*this, *n.right) + ")";
  142. }
  143. std::string operator()(const ir::Pow& n) {
  144. return std::visit(*this, *n.left) + " ^ " + std::visit(*this, *n.right);
  145. }
  146. std::string operator()(const ir::Cos& n) {
  147. return "cos(" + std::visit(*this, *n.value) + ")";
  148. }
  149. std::string operator()(const ir::Sin& n) {
  150. return "sin(" + std::visit(*this, *n.value) + ")";
  151. }
  152. std::string operator()(const ir::Exp& n) {
  153. return "exp(" + std::visit(*this, *n.value) + ")";
  154. }
  155. std::string operator()(const ir::Ln& n) {
  156. return "ln(" + std::visit(*this, *n.value) + ")";
  157. }
  158. };
  159. return std::string("a = ") + std::visit(ToStringVisitor{}, *this->newA) +
  160. "\nb = " + std::visit(ToStringVisitor{}, *this->newB);
  161. }