/* g++ test2.cpp -o test -O3 -lrt -ffast-math */ #include #include #include #include #if defined _WIN32 # include #endif static void version1(float h, float s, float v, float &r, float &g, float &b) { h *= 6.f; s *= v; float r2 = -2.f + fabs(h - 3.f); float g2 = 1.f - fabs(h - 2.f); float b2 = 1.f - fabs(h - 4.f); /* Minus 1 */ r2 = std::min(std::max(r2, -1.f), 0.f); g2 = std::min(std::max(g2, -1.f), 0.f); b2 = std::min(std::max(b2, -1.f), 0.f); r = r2 * s + v; g = g2 * s + v; b = b2 * s + v; } static void version2(float h, float s, float v, float &r, float &g, float &b) { h *= 3.f; s *= v; float x = fabs(1.5f - fabs(h - 2.5f)); float y = fabs(1.5f - fabs(h - 0.5f)); float z = -0.5f - fabs(1.5f - h); /* Minus 1 */ float r2 = x + y - 2.f; float g2 = y + z; float b2 = x + z; r = r2 * s + v; g = g2 * s + v; b = b2 * s + v; } static int const NCOLORS = 10000; static int const NITERS = 5000; static float data[NCOLORS * 2 * 3]; static void reset(int seed) { srand(seed); for (int i = 0; i < NCOLORS; i++) { data[i * 6 + 0] = rand() % 131072 / 131071.f; data[i * 6 + 1] = rand() % 131072 / 131071.f; data[i * 6 + 2] = rand() % 131072 / 131071.f; } } static volatile long double gettime() { #if defined _WIN32 static long double secs_per_cycle = 0.0L; LARGE_INTEGER cycles; if (!secs_per_cycle) { QueryPerformanceFrequency(&cycles); secs_per_cycle = 1.0L / cycles.QuadPart; } QueryPerformanceCounter(&cycles); return secs_per_cycle * cycles.QuadPart; #else timespec t1; clock_gettime(CLOCK_MONOTONIC, &t1); return 1.e-9L * t1.tv_nsec + t1.tv_sec; #endif } #define TEST(fn) \ { \ long double t = 0; \ for (int n = 0; n < NITERS; n++) \ { \ reset(n); \ t -= gettime(); \ for (int i = 0; i < NCOLORS; i++) \ fn(data[i * 6 + 0], data[i * 6 + 1], data[i * 6 + 2], \ data[i * 6 + 3], data[i * 6 + 4], data[i * 6 + 5]); \ t += gettime(); \ } \ \ for (int n = 0; n < 16; n++) \ fprintf(stderr, #fn ": %f nanoseconds [%f %f %f]\n", \ (double)t / NITERS / NCOLORS * 1e9, \ data[n * 6 + 3], data[n * 6 + 4], data[n * 6 + 5]); \ } int main(void) { TEST(version1); TEST(version2); }