CpuGenerators.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "CpuGenerators.h"
  2. #include "Types.h"
  3. #ifdef WITH_MPFR
  4. #include "MpfrWrapper.h"
  5. #endif // WITH_MPFR
  6. #include <omp.h>
  7. #include <cmath>
  8. #include <memory>
  9. using mnd::CpuGenerator;
  10. namespace mnd
  11. {
  12. template class CpuGenerator<float, mnd::NONE, false, false>;
  13. template class CpuGenerator<float, mnd::NONE, false, true>;
  14. template class CpuGenerator<float, mnd::NONE, true, false>;
  15. template class CpuGenerator<float, mnd::NONE, true, true>;
  16. template class CpuGenerator<double, mnd::NONE, false, false>;
  17. template class CpuGenerator<double, mnd::NONE, false, true>;
  18. template class CpuGenerator<double, mnd::NONE, true, false>;
  19. template class CpuGenerator<double, mnd::NONE, true, true>;
  20. //template class CpuGenerator<Fixed128, mnd::NONE, false, false>;
  21. //template class CpuGenerator<Fixed128, mnd::NONE, false, true>;
  22. //template class CpuGenerator<Fixed128, mnd::NONE, true, false>;
  23. //template class CpuGenerator<Fixed128, mnd::NONE, true, true>;
  24. #ifdef WITH_BOOST
  25. #include <boost/multiprecision/cpp_bin_float.hpp>
  26. template class CpuGenerator<mnd::Float128, mnd::NONE, false, false>;
  27. template class CpuGenerator<mnd::Float128, mnd::NONE, false, true>;
  28. template class CpuGenerator<mnd::Float128, mnd::NONE, true, false>;
  29. template class CpuGenerator<mnd::Float128, mnd::NONE, true, true>;
  30. template class CpuGenerator<mnd::Float256, mnd::NONE, false, false>;
  31. template class CpuGenerator<mnd::Float256, mnd::NONE, false, true>;
  32. template class CpuGenerator<mnd::Float256, mnd::NONE, true, false>;
  33. template class CpuGenerator<mnd::Float256, mnd::NONE, true, true>;
  34. #endif
  35. #ifdef WITH_QD
  36. template class CpuGenerator<mnd::DoubleDouble, mnd::NONE, false, false>;
  37. template class CpuGenerator<mnd::DoubleDouble, mnd::NONE, false, true>;
  38. template class CpuGenerator<mnd::DoubleDouble, mnd::NONE, true, false>;
  39. template class CpuGenerator<mnd::DoubleDouble, mnd::NONE, true, true>;
  40. template class CpuGenerator<mnd::QuadDouble, mnd::NONE, false, false>;
  41. template class CpuGenerator<mnd::QuadDouble, mnd::NONE, false, true>;
  42. template class CpuGenerator<mnd::QuadDouble, mnd::NONE, true, false>;
  43. template class CpuGenerator<mnd::QuadDouble, mnd::NONE, true, true>;
  44. #endif
  45. }
  46. template<typename T, bool parallel, bool smooth>
  47. void CpuGenerator<T, mnd::NONE, parallel, smooth>::generate(const mnd::MandelInfo& info, float* data)
  48. {
  49. const MandelViewport& view = info.view;
  50. T viewx = mnd::convert<T>(view.x);
  51. T viewy = mnd::convert<T>(view.y);
  52. T wpp = mnd::convert<T>(view.width / info.bWidth);
  53. T hpp = mnd::convert<T>(view.height / info.bHeight);
  54. if constexpr (parallel)
  55. omp_set_num_threads(2 * omp_get_num_procs());
  56. #pragma omp parallel for if (parallel)
  57. for (long j = 0; j < info.bHeight; j++) {
  58. T y = viewy + T(double(j)) * hpp;
  59. long i = 0;
  60. for (i; i < info.bWidth; i++) {
  61. T x = viewx + T(double(i)) * wpp;
  62. T a = x;
  63. T b = y;
  64. int k = 0;
  65. for (k = 0; k < info.maxIter; k++) {
  66. T aa = a * a;
  67. T bb = b * b;
  68. T ab = a * b;
  69. a = aa - bb + x;
  70. b = ab + ab + y;
  71. if (aa + bb > T(16)) {
  72. break;
  73. }
  74. }
  75. if constexpr (smooth) {
  76. if (k >= info.maxIter)
  77. data[i + j * info.bWidth] = info.maxIter;
  78. else
  79. data[i + j * info.bWidth] = ((float) k) + 1 - ::logf(::logf(mnd::convert<float>(a * a + b * b)) / 2) / ::logf(2.0f);
  80. }
  81. else
  82. data[i + j * info.bWidth] = k;
  83. }
  84. }
  85. }
  86. /*
  87. #if defined(WITH_BOOST) || 1
  88. template<bool parallel, bool smooth>
  89. void CpuGenerator<Fixed128, mnd::NONE, parallel, smooth>::generate(const mnd::MandelInfo& info, float* data)
  90. {
  91. using T = Fixed128;
  92. const MandelViewport& view = info.view;
  93. const auto fixedFromFloat = [] (const mnd::Float128& f) {
  94. boost::multiprecision::int128_t frac = boost::multiprecision::int128_t(f * 4294967296.0 * 4294967296.0 * 4294967296.0);
  95. std::vector<uint32_t> bits;
  96. export_bits(frac, std::back_inserter(bits), 32);
  97. bits.clear();
  98. while (bits.size() < 4) bits.push_back(0);
  99. return Fixed128{ bits[0], bits[1], bits[2], bits[3] };
  100. };
  101. if constexpr (parallel)
  102. omp_set_num_threads(2 * omp_get_num_procs());
  103. #pragma omp parallel for if (parallel)
  104. for (long j = 0; j < info.bHeight; j++) {
  105. T y = fixedFromFloat(view.y + mnd::Real(j) * view.height / info.bHeight);
  106. long i = 0;
  107. for (i; i < info.bWidth; i++) {
  108. T x = fixedFromFloat(view.x + mnd::Real(i) * view.width / info.bWidth);
  109. T a = x;
  110. T b = y;
  111. int k = 0;
  112. for (k = 0; k < info.maxIter; k++) {
  113. T aa = a * a;
  114. T bb = b * b;
  115. T ab = a * b;
  116. a = aa - bb + x;
  117. b = ab + ab + y;
  118. if (aa + bb > T(16)) {
  119. break;
  120. }
  121. }
  122. if constexpr (smooth) {
  123. if (k >= info.maxIter)
  124. data[i + j * info.bWidth] = info.maxIter;
  125. else
  126. data[i + j * info.bWidth] = ((float) k) + 1 - ::logf(::logf(float(a * a + b * b)) / 2) / ::logf(2.0f);
  127. }
  128. else
  129. data[i + j * info.bWidth] = k;
  130. }
  131. }
  132. }
  133. #endif // WITH_BOOST
  134. */
  135. #ifdef WITH_MPFR
  136. template<unsigned int bits, bool parallel, bool smooth>
  137. void CpuGenerator<mnd::MpfrFloat<bits>, mnd::NONE, parallel, smooth>::generate(const mnd::MandelInfo& info, float* data)
  138. {
  139. const MandelViewport& view = info.view;
  140. using T = mnd::MpfrFloat<bits>;
  141. if constexpr (parallel)
  142. omp_set_num_threads(2 * omp_get_num_procs());
  143. #pragma omp parallel for if (parallel)
  144. for (long j = 0; j < info.bHeight; j++) {
  145. T y = T(view.y) + T(j) * T(view.height / info.bHeight);
  146. long i = 0;
  147. for (i; i < info.bWidth; i++) {
  148. T x = T(view.x + T(i) * T(view.width / info.bWidth));
  149. T a = x;
  150. T b = y;
  151. int k = 0;
  152. for (k = 0; k < info.maxIter; k++) {
  153. T aa = a * a;
  154. T bb = b * b;
  155. T ab = a * b;
  156. a = aa - bb + x;
  157. b = ab + ab + y;
  158. if (aa + bb > T(16)) {
  159. break;
  160. }
  161. }
  162. if constexpr (smooth) {
  163. if (k >= info.maxIter)
  164. data[i + j * info.bWidth] = info.maxIter;
  165. else
  166. data[i + j * info.bWidth] = ((float) k) + 1 - ::log(::log(a * a + b * b) / 2) / ::log(2.0f);
  167. }
  168. else
  169. data[i + j * info.bWidth] = k;
  170. }
  171. }
  172. }
  173. #endif // WITH_MPFR
  174. /*
  175. void CpuGeneratorDouble::generate(const mnd::MandelInfo& info, float* data)
  176. {
  177. const MandelViewport& view = info.view;
  178. omp_set_num_threads(2 * omp_get_num_procs());
  179. #pragma omp parallel for
  180. for (long j = 0; j < info.bHeight; j++) {
  181. double y = double(view.y) + double(j) * double(view.height / info.bHeight);
  182. long i = 0;
  183. for (i; i < info.bWidth; i++) {
  184. double x = view.x + double(i) * view.width / info.bWidth;
  185. double a = x;
  186. double b = y;
  187. int k = 0;
  188. for (k = 0; k < info.maxIter; k++) {
  189. double aa = a * a;
  190. double bb = b * b;
  191. double ab = a * b;
  192. a = aa - bb + x;
  193. b = ab + ab + y;
  194. if (aa + bb > 16) {
  195. break;
  196. }
  197. }
  198. data[i + j * info.bWidth] = k;
  199. }
  200. }
  201. }
  202. void CpuGenerator128::generate(const mnd::MandelInfo& info, float* data)
  203. {
  204. const MandelViewport& view = info.view;
  205. omp_set_num_threads(2 * omp_get_num_procs());
  206. #pragma omp parallel for
  207. for (long j = 0; j < info.bHeight; j++) {
  208. Fixed128 y = Fixed128(view.y) + Fixed128(j) * Fixed128(view.height / info.bHeight);
  209. long i = 0;
  210. for (i; i < info.bWidth; i++) {
  211. Fixed128 x = view.x + Fixed128(i) * Fixed128(view.width / info.bWidth);
  212. Fixed128 a = x;
  213. Fixed128 b = y;
  214. int k = 0;
  215. for (k = 0; k < info.maxIter; k++) {
  216. Fixed128 aa = a * a;
  217. Fixed128 bb = b * b;
  218. Fixed128 ab = a * b;
  219. a = aa - bb + x;
  220. b = ab + ab + y;
  221. if (aa + bb > Fixed128(16)) {
  222. break;
  223. }
  224. }
  225. data[i + j * info.bWidth] = k;
  226. }
  227. }
  228. }
  229. */