/sqrtvis/src/main.cpp
C++ | 221 lines | 168 code | 41 blank | 12 comment | 18 complexity | 51f3767143ea9b58e67db4891a34270d MD5 | raw file
- #include <string>
- #include <map>
- #include <algorithm>
- using std::string;
- using std::map;
- using std::for_each;
- using std::begin;
- using std::end;
-
- #include <SFML/Graphics.hpp>
- #include <SFML/Window.hpp>
-
- #include "rsqrt_carmack.h"
- #include "rsqrt_lomont.h"
- #include "rsqrt_walsh.h"
- #include "rsqrt_hulsman.h"
- #include "rsqrt_lee.h"
-
- #include "rsqrt_hsieh.h"
- #include "rsqrt_karvonen.h"
- #include "rsqrt_julery.h"
- #include "rsqrt_crowne.h"
- #include "rsqrt_juffa.h"
- #include "rsqrt_other.h"
-
- #define SHOW_STACKED
-
- #define GRADIENT_TYPE_RADIAL 1
- #define GRADIENT_TYPE_VERTICAL 2
-
- #ifdef SHOW_STACKED
- //#define GRADIENT_TYPE GRADIENT_TYPE_VERTICAL
- #define GRADIENT_TYPE GRADIENT_TYPE_RADIAL
- #else
- #define GRADIENT_TYPE GRADIENT_TYPE_RADIAL
- #endif
-
- static const int formulae = 17;
- static const int width = 1024;
-
- #ifdef SHOW_STACKED
- static const int sliceHeight = 80;//32;
- static const int height = (sliceHeight * formulae) + (formulae - 1);
- #else
- static const int sliceHeight = 1024;
- static const int height = 1024;
- #endif
-
- double lee_sqrt(double in) { return lee::sqrt(in); }
- double lee_fsqrt(double in) { return lee::fsqrt(in); }
- double hulsman_rsqrt(double in) { return 1.0 / hulsman::rsqrt(in); }
- double lomont_invsqrt(double in) { return 1.0 / lomont::InvSqrt(in); }
- double walsh_invsqrt(double in) { return 1.0 / walsh::invSqrt(in); }
- double carmack_q_rsqrt(double in) { return 1.0 / carmack::Q_rsqrt(in); }
- double carmack_q_frsqrt(double in) { return 1.0 / carmack::Q_frsqrt(in); }
- double carmack_d3rsqrt(double in) { return 1.0 / carmack::D3RSqrt(in); }
- double carmack_d3invsqrt(double in) { return 1.0 / carmack::D3InvSqrt(in); }
-
- double hsieh_fsqrt(double in) { return hsieh::fsqrt(in); }
- double karvonen_inv_sqrt(double in) { return 1.0 / karvonen::Inv_Sqrt(in); }
- // double hsieh_fred_sqrt(double in) { return static_cast<double>(hsieh::fred_sqrt(static_cast<unsigned long>(in * /*std::numeric_limits<unsigned long>::max() */ 65535))); } <<< this created the 'fractal' ;')
- double hsieh_fred_sqrt(double in) { return static_cast<double>(hsieh::fred_sqrt(static_cast<unsigned long>(in))); }
- double hsieh_isqrt(double in) { return static_cast<double>(hsieh::isqrt(static_cast<long>(in))); } // didn't work for me
- double julery_isqrt(double in) { return julery::julery_isqrt(static_cast<unsigned long>(in)); }
- double crowne_mcrowne_isqrt(double in) { return crowne::mcrowne_isqrt(static_cast<unsigned long>(in)); }
- double juffa_isqrt(double in) { return juffa::isqrt(static_cast<unsigned long>(in)); }
- double other_sqrt_approx(double in) { return other::sqrt_approx(in); }
-
- #define min(a, b) (a < b ? a : b)
- #define max(a, b) (a > b ? a : b)
- double dummy(double in) { return in ; }
-
- int main(int argc, char *argv[])
- {
- typedef double (*sqrtfunc)(double );
-
- map<string, sqrtfunc> funcs;
- funcs["sqrt"] = sqrt;
-
- if (true) {
- funcs["lee::sqrt"] = lee_sqrt;
- funcs["lee::fsqrt"] = lee_fsqrt;
- funcs["hulsman::rsqrt"] = hulsman_rsqrt;
- funcs["lomont::InvSqrt"] = lomont_invsqrt;
- funcs["walsh::invSqrt"] = walsh_invsqrt;
- funcs["carmack::Q_rsqrt"] = carmack_q_rsqrt;
- funcs["carmack::Q_frsqrt"] = carmack_q_frsqrt;
- funcs["carmack::D3RSqrt"] = carmack_d3rsqrt;
- funcs["carmack::D3InvSqrt"] = carmack_d3invsqrt;
- }
-
- funcs["hsieh_fsqrt"] = hsieh_fsqrt;
- funcs["hsieh_fred_sqrt"] = hsieh_fred_sqrt;
- funcs["julery_isqrt"] = julery_isqrt;
- funcs["crowne_mcrowne_isqrt"] = crowne_mcrowne_isqrt;
- funcs["juffa_isqrt"] = juffa_isqrt;
- funcs["other_sqrt_approx"] = other_sqrt_approx;
- //funcs["approx1"] = dummy; // Not really a good approximation for sqrt!
- //funcs["karvonen_inv_sqrt"] = karvonen_inv_sqrt; // didn't work on my VS2012 32bit
- //funcs["hsieh_isqrt"] = hsieh_isqrt; // idem.
-
- carmack::init();
-
- sf::RenderWindow window(sf::VideoMode(width, height, 32), "Test");
- sf::Image image;
-
- sf::Font font;
- if (!font.loadFromFile("test.otf"))
- return EXIT_FAILURE;
-
- const int centerX = static_cast<int>(static_cast<float>(width) / 2.0 + 0.5);
- const int centerY = static_cast<int>(static_cast<float>(sliceHeight) / 2.0 + 0.5);
-
- window.clear(sf::Color(0, 0, 0, 255));
-
- int offsetY = 0;
- for (auto i=funcs.begin(); i!=funcs.end() ; i++)
- {
- image.create(width, sliceHeight, sf::Color(0, 0, 0, 255));
-
- auto &a = *i;
- auto *pixels = const_cast<sf::Uint8 *>(image.getPixelsPtr());
- double maxdiff = 0.0;
- for(int x = 0; x < width; x++)
- {
- for(int y = 0; y < sliceHeight; y++)
- {
- #if GRADIENT_TYPE == GRADIENT_TYPE_RADIAL
- auto res = a.second((pow(x - centerX, 2) + pow(y - centerY, 2))); /// (-90 + sqrt(pow(width/2.0,2) + pow(height/2.0,2)));
- #endif
- #if GRADIENT_TYPE == GRADIENT_TYPE_VERTICAL
- auto res = a.second(pow(width - x , 2)) / width;
- #endif
-
- /**
- * Hardcoded clause for, because it's not really a good sqrt() replacement I couldn't fit it in the 'funcs' map, as it operates with x and y variables:
- * (source: http://www.azillionmonkeys.com/qed/sqroot.html#distance)
- *
- * (1 + 1/(4-2*√2))/2 * min((1 / √2)*(|x|+|y|), max (|x|, |y|))
- *
- */
- if (a.first == "approx1")
- {
- static const double sqrtOf2 = sqrt(2);
-
- #if GRADIENT_TYPE == GRADIENT_TYPE_RADIAL
- auto xAbs = abs(x - centerX);
- auto yAbs = abs(y - centerY);
- #endif
- #if GRADIENT_TYPE == GRADIENT_TYPE_VERTICAL
- auto xAbs = abs(width - x);
- auto yAbs = 0;
- #endif
-
- res = (1. + 1./(4.-2.*sqrtOf2))/2. * min((1. / sqrtOf2)*(xAbs + yAbs), max (xAbs, yAbs));
-
- #if GRADIENT_TYPE == GRADIENT_TYPE_VERTICAL
- res /= width;
- #endif
- }
-
- #if GRADIENT_TYPE == GRADIENT_TYPE_RADIAL
- res /= (-90 + sqrt(pow(width/2.0,2) + pow(height/2.0,2)));
- #endif
-
- if (a.first == "approx1")
- res = res;
-
- #if GRADIENT_TYPE == GRADIENT_TYPE_RADIAL
- res *= 4;
- #endif
- char color = 255.0 * res;
-
- #if GRADIENT_TYPE == GRADIENT_TYPE_RADIAL
- while (res > 1.0)
- res -= 1.0;
-
- color = (fabs(res - 0.5) * 2.0) * 255.0;
- #endif
-
- pixels[(x + y * width) * 4 + 0] = color; // R
- pixels[(x + y * width) * 4 + 1] = color; // G
- pixels[(x + y * width) * 4 + 2] = color; // B
- pixels[(x + y * width) * 4 + 3] = 255; // A
- }
- }
-
- sf::Texture texture;
- texture.loadFromImage(image);
-
- sf::Sprite sprite;
- sprite.setTexture(texture);
-
- sf::Text error;
- error.setString(a.first);
- error.setPosition(10, 3 + offsetY);
- error.setCharacterSize(18);
- error.setFont(font);
- error.setColor(sf::Color(255, 0, 0, 255));
-
- sprite.setPosition(0, offsetY);
- #ifdef SHOW_STACKED
- offsetY += sliceHeight + 1;
- #endif
- window.draw(sprite);
-
- window.draw(error);
-
- static int counter = 0;
- char filename[80+1] = {0x00};
- counter++;
- sprintf(filename, "%d %s.bmp", counter, a.first.c_str());
- std::replace(begin(filename), end(filename), ':', '_');
-
- window.display();
-
- window.capture().saveToFile(filename);
- };
-
- return 0;
- }