NaiveIRGenerator.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "NaiveIRGenerator.h"
  2. #include <omp.h>
  3. using mnd::NaiveIRGenerator;
  4. namespace mnd
  5. {
  6. template class NaiveIRGenerator<float>;
  7. template class NaiveIRGenerator<double>;
  8. template class NaiveIRGenerator<mnd::DoubleDouble>;
  9. template class NaiveIRGenerator<mnd::QuadDouble>;
  10. }
  11. template<typename T>
  12. NaiveIRGenerator<T>::NaiveIRGenerator(const mnd::ir::Formula& irf,
  13. mnd::Precision prec) :
  14. mnd::MandelGenerator{ prec },
  15. form{ irf }
  16. {
  17. }
  18. template<typename T>
  19. struct EvalRes
  20. {
  21. size_t incVal;
  22. T result;
  23. };
  24. using namespace mnd;
  25. template<typename T>
  26. struct TVisitor
  27. {
  28. T a, b, x, y;
  29. size_t incrementValue;
  30. T visitNode(ir::Node* n) {
  31. EvalRes<T>* nodeData = getNodeData(n);
  32. if (nodeData) {
  33. if (nodeData->incVal == incrementValue)
  34. return nodeData->result;
  35. }
  36. T res = std::visit(*this, *n);
  37. if (nodeData) {
  38. nodeData->incVal = incrementValue;
  39. nodeData->result = res;
  40. }
  41. return res;
  42. }
  43. EvalRes<T>* getNodeData(ir::Node* n) {
  44. assert(n != nullptr);
  45. std::any& x = std::visit([](auto& n) -> std::any& {
  46. return n.nodeData;
  47. }, *n);
  48. if (auto* v = std::any_cast<EvalRes<T>>(&x))
  49. return v;
  50. else
  51. return nullptr;
  52. }
  53. T operator()(const ir::Constant& c) {
  54. return mnd::convert<double>(c.value);
  55. }
  56. T operator()(const ir::Variable& v) {
  57. if (v.name == "z_re")
  58. return a;
  59. else if (v.name == "z_im")
  60. return b;
  61. else if (v.name == "c_re")
  62. return x;
  63. else if (v.name == "c_im")
  64. return y;
  65. else
  66. return 0.0;
  67. }
  68. T operator()(const ir::Negation& n) {
  69. return -visitNode(n.value);
  70. }
  71. T operator()(const ir::Addition& n) {
  72. return visitNode(n.left) + visitNode(n.right);
  73. }
  74. T operator()(const ir::Subtraction& n) {
  75. return visitNode(n.left) - visitNode(n.right);
  76. }
  77. T operator()(const ir::Multiplication& n) {
  78. return visitNode(n.left) * visitNode(n.right);
  79. }
  80. T operator()(const ir::Division& n) {
  81. return visitNode(n.left) / visitNode(n.right);
  82. }
  83. T operator()(const ir::Atan2& n) {
  84. return ::atan2(visitNode(n.left), visitNode(n.right));
  85. }
  86. T operator()(const ir::Pow& n) {
  87. return ::pow(visitNode(n.left), visitNode(n.right));
  88. }
  89. T operator()(const ir::Cos& n) {
  90. return ::cos(visitNode(n.value));
  91. }
  92. T operator()(const ir::Sin& n) {
  93. return ::sin(visitNode(n.value));
  94. }
  95. T operator()(const ir::Exp& n) {
  96. return ::exp(visitNode(n.value));
  97. }
  98. T operator()(const ir::Ln& n) {
  99. return ::log(visitNode(n.value));
  100. }
  101. };
  102. template<typename T>
  103. void NaiveIRGenerator<T>::generate(const mnd::MandelInfo& info, float* data)
  104. {
  105. const MandelViewport& view = info.view;
  106. const bool parallel = true;
  107. T viewx = mnd::convert<T>(view.x);
  108. T viewy = mnd::convert<T>(view.y);
  109. T wpp = mnd::convert<T>(view.width / info.bWidth);
  110. T hpp = mnd::convert<T>(view.height / info.bHeight);
  111. #if defined(_OPENMP)
  112. if constexpr (parallel)
  113. omp_set_num_threads(omp_get_num_procs());
  114. # pragma omp parallel for schedule(static, 1) if (parallel)
  115. #endif
  116. for (long j = 0; j < info.bHeight; j++) {
  117. T y = viewy + T(double(j)) * hpp;
  118. long i = 0;
  119. for (i; i < info.bWidth; i++) {
  120. T x = viewx + T(double(i)) * wpp;
  121. TVisitor<T> beforeVisitor{ 0, 0, x, y, 0 };
  122. T a = beforeVisitor.visitNode(form.startA);
  123. T b = beforeVisitor.visitNode(form.startB);
  124. TVisitor<T> visitor{ a, b, x, y, 0 };
  125. int k = 0;
  126. for (k = 0; k < info.maxIter; k++) {
  127. T newA = visitor.visitNode(form.newA);
  128. T newB = visitor.visitNode(form.newB);
  129. a = newA;
  130. b = newB;
  131. if (a * a + b * b >= 16.0)
  132. break;
  133. visitor.incrementValue++;
  134. }
  135. data[i + j * info.bWidth] = float(k);
  136. }
  137. }
  138. }