MathFunctions.cxx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #include <cmath>
  2. #include <format>
  3. #include <MathLogger.h>
  4. // TODO3: If the TUTORIAL_USE_SSE2 definition is set, include
  5. // the <emmintrin.h> header
  6. namespace {
  7. mathlogger::Logger Logger;
  8. #if defined(TUTORIAL_USE_GNU_BUILTIN)
  9. typedef double v2df __attribute__((vector_size(16)));
  10. double gnu_mysqrt(double x)
  11. {
  12. v2df root = __builtin_ia32_sqrtsd(v2df{ x, 0.0 });
  13. double result = root[0];
  14. Logger.Log(std::format("Computed sqrt of {} to be {} with GNU-builtins\n", x,
  15. result));
  16. return result;
  17. }
  18. #elif defined(TUTORIAL_USE_SSE2)
  19. double sse2_mysqrt(double x)
  20. {
  21. __m128d root = _mm_sqrt_sd(_mm_setzero_pd(), _mm_set_sd(x));
  22. double result = _mm_cvtsd_f64(root);
  23. Logger.Log(
  24. std::format("Computed sqrt of {} to be {} with SSE2\n", x, result));
  25. return result;
  26. }
  27. #endif
  28. // a hack square root calculation using simple operations
  29. double fallback_mysqrt(double x)
  30. {
  31. if (x <= 0) {
  32. return 0;
  33. }
  34. double result = x;
  35. // do ten iterations
  36. for (int i = 0; i < 10; ++i) {
  37. if (result <= 0) {
  38. result = 0.1;
  39. }
  40. double delta = x - (result * result);
  41. result = result + 0.5 * delta / result;
  42. Logger.Log(std::format("Computing sqrt of {} to be {}\n", x, result));
  43. }
  44. return result;
  45. }
  46. double mysqrt(double x)
  47. {
  48. #if defined(TUTORIAL_USE_GNU_BUILTIN)
  49. return gnu_mysqrt(x);
  50. #elif defined(TUTORIAL_USE_SSE2)
  51. return sse2_mysqrt(x);
  52. #else
  53. return fallback_mysqrt(x);
  54. #endif
  55. }
  56. }
  57. namespace mathfunctions {
  58. double sqrt(double x)
  59. {
  60. #ifdef TUTORIAL_USE_STD_SQRT
  61. return std::sqrt(x);
  62. #else
  63. return mysqrt(x);
  64. #endif
  65. }
  66. }