JuliaGenerators.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "Generators.h"
  2. #include "JuliaGenerators.h"
  3. #include <immintrin.h>
  4. #include <omp.h>
  5. mnd::JuliaGeneratorFloat::JuliaGeneratorFloat(const mnd::Real& precision) :
  6. JuliaGenerator{ precision },
  7. a{ a },
  8. b{ b }
  9. {
  10. }
  11. mnd::JuliaGeneratorFloat::~JuliaGeneratorFloat(void)
  12. {
  13. }
  14. void mnd::JuliaGeneratorFloat::generate(const MandelInfo& info, float * data)
  15. {
  16. const MandelViewport& view = info.view;
  17. using T = double;
  18. const float dppf = float(view.width / info.bWidth);
  19. const float viewxf = float(view.x);
  20. __m256 viewx = { viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf };
  21. __m256 dpp = { dppf, dppf, dppf, dppf, dppf, dppf, dppf, dppf };
  22. T juliaa = mnd::convert<T>(info.juliaX);
  23. T juliab = mnd::convert<T>(info.juliaY);
  24. __m256 constA = { juliaa, juliaa, juliaa, juliaa, juliaa, juliaa, juliaa,juliaa };
  25. __m256 constB = { juliab, juliab, juliab, juliab, juliab, juliab, juliab, juliab};
  26. omp_set_num_threads(omp_get_num_procs());
  27. #pragma omp parallel for schedule(static, 1)
  28. for (long j = 0; j < info.bHeight; j++) {
  29. T y = T(view.y) + T(j) * T(view.height / info.bHeight);
  30. __m256 ys = {y, y, y, y, y, y, y, y};
  31. long i = 0;
  32. for (i; i < info.bWidth; i += 8) {
  33. __m256 pixc = { float(i), float(i + 1), float(i + 2), float(i + 3), float(i + 4), float(i + 5), float(i + 6), float(i + 7) };
  34. __m256 xs = _mm256_add_ps(_mm256_mul_ps(dpp, pixc), viewx);
  35. __m256 counter = { 0, 0, 0, 0, 0, 0, 0, 0 };
  36. __m256 adder = { 1, 1, 1, 1, 1, 1, 1, 1 };
  37. __m256 resultsa = { 0, 0, 0, 0, 0, 0, 0, 0 };
  38. __m256 resultsb = { 0, 0, 0, 0, 0, 0, 0, 0 };
  39. __m256 threshold = { 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f };
  40. __m256 a = xs;
  41. __m256 b = ys;
  42. if (info.smooth) {
  43. for (int k = 0; k < info.maxIter; k++) {
  44. __m256 aa = _mm256_mul_ps(a, a);
  45. __m256 bb = _mm256_mul_ps(b, b);
  46. __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
  47. a = _mm256_add_ps(_mm256_sub_ps(aa, bb), constA);
  48. b = _mm256_add_ps(abab, constB);
  49. __m256 cmp = _mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ);
  50. resultsa = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsa), _mm256_and_ps(cmp, a));
  51. resultsb = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsb), _mm256_and_ps(cmp, b));
  52. adder = _mm256_and_ps(adder, cmp);
  53. counter = _mm256_add_ps(counter, adder);
  54. if ((k & 0x7) == 0 && _mm256_testz_ps(cmp, cmp) != 0) {
  55. break;
  56. }
  57. }
  58. }
  59. else {
  60. for (int k = 0; k < info.maxIter; k++) {
  61. __m256 aa = _mm256_mul_ps(a, a);
  62. __m256 bb = _mm256_mul_ps(b, b);
  63. __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
  64. a = _mm256_add_ps(_mm256_sub_ps(aa, bb), constA);
  65. b = _mm256_add_ps(abab, constB);
  66. __m256 cmp = _mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ);
  67. adder = _mm256_and_ps(adder, cmp);
  68. counter = _mm256_add_ps(counter, adder);
  69. if ((k & 0x7) == 0 && _mm256_testz_ps(cmp, cmp) != 0) {
  70. break;
  71. }
  72. }
  73. }
  74. auto alignVec = [](float* data) -> float* {
  75. void* aligned = data;
  76. ::size_t length = 64;
  77. std::align(32, 8 * sizeof(float), aligned, length);
  78. return static_cast<float*>(aligned);
  79. };
  80. float resData[16];
  81. float* ftRes = alignVec(resData);
  82. float* resa = (float*) &resultsa;
  83. float* resb = (float*) &resultsb;
  84. _mm256_store_ps(ftRes, counter);
  85. for (int k = 0; k < 8 && i + k < info.bWidth; k++) {
  86. if (info.smooth) {
  87. data[i + k + j * info.bWidth] = ftRes[k] <= 0 ? info.maxIter :
  88. ftRes[k] >= info.maxIter ? info.maxIter :
  89. ((float)ftRes[k]) + 1 - ::log(::log(resa[k] * resa[k] + resb[k] * resb[k]) / 2) / ::log(2.0f);
  90. }
  91. else {
  92. data[i + k + j * info.bWidth] = ftRes[k] <= 0 ? info.maxIter : ftRes[k];
  93. }
  94. }
  95. }
  96. }
  97. }