Last active
December 10, 2015 23:19
-
-
Save usagi/4508852 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CXX := g++ | |
OPT := -std=c++11 -O3 -Wall | |
#CORES := `grep processor /proc/cpuinfo | tail -n1 | sed "s/[^0-9]//g" | xargs expr 1 +` | |
#OPT += -floop-parallelize-all -ftree-parallelize-loops=${CORES} | |
OPT += -fopenmp | |
OPT_387 := -mfpmath=387 | |
OPT_SSE := -mfpmath=sse | |
OPT_SSE387 := -mfpmath=sse,387 | |
OPT_BINARY32 := -DADOPT_BINARY32 | |
OPT_BINARY64 := -DADOPT_BINARY64 | |
OPT_BINARY128 := -DADOPT_BINARY128 | |
LIB := -lpng | |
SRC := color.cxx | |
TIME1 := time | |
TIME2 := /usr/bin/time --verbose | |
all: binary32 binary64 binary128 | |
binary32: ${SRC} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY32} -o binary32 | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY32} -o binary32-387 ${OPT_387} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY32} -o binary32-SSE ${OPT_SSE} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY32} -o binary32-SSE387 ${OPT_SSE387} | |
binary64: ${SRC} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY64} -o binary64 | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY64} -o binary64-387 ${OPT_387} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY64} -o binary64-SSE ${OPT_SSE} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY64} -o binary64-SSE387 ${OPT_SSE387} | |
binary128: ${SRC} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY128} -lquadmath -o binary128 | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY128} -lquadmath -o binary128-387 ${OPT_387} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY128} -lquadmath -o binary128-SSE ${OPT_SSE} | |
${CXX} ${OPT} ${SRC} ${LIB} ${OPT_BINARY128} -lquadmath -o binary128-SSE387 ${OPT_SSE387} | |
clean: | |
-@rm -v binary* | |
execute: binary32 binary64 binary128 | |
find . -name "binary*" -print -exec {} \; | |
time1: binary32 binary64 binary128 | |
find . -name "binary*" -print -exec ${TIME1} {} \; | |
time2: binary32 binary64 binary128 | |
find . -name "binary*" -print -exec ${TIME2} {} \; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iomanip> | |
#include <stdexcept> | |
#include <limits> | |
#include <vector> | |
#include <array> | |
#include <cmath> | |
#include <algorithm> | |
#include <string> | |
#include <boost/gil/extension/io/png_io.hpp> // for only use to savea an image file | |
#include <mutex> | |
#if defined(_OPENMP) | |
#include <omp.h> | |
#endif | |
#if !defined(ADOPT_BINARY32) && !defined(ADOPT_BINARY64) && !defined(ADOPT_BINARY128) | |
#define ADOPT_BINARY32 | |
#endif | |
#if defined(ADOPT_BINARY128) | |
extern "C" { | |
#include <quadmath.h> | |
} | |
#define abs(a) fabsq(a) | |
#define fmod(a,b) fmodq(a,b) | |
using adopt_type = __float128; | |
namespace { const auto image_filename = "out_binary128.png"; } | |
#elif defined(ADOPT_BINARY64) | |
using adopt_type = double; | |
namespace { const auto image_filename = "out_binary64.png"; } | |
#elif defined(ADOPT_BINARY32) | |
using adopt_type = float; | |
namespace { const auto image_filename = "out_binary32.png"; } | |
#endif | |
using namespace std; | |
struct RGB24 { uint8_t r, g, b; }; | |
struct HSL24 { uint8_t h, s, l; }; | |
bool operator<(const RGB24& a,const RGB24& b) { | |
if ( a.b > b.b || a.g > b.g ) return false; | |
return a.r < b.r; | |
} | |
bool operator==(const RGB24& a,const RGB24& b) { | |
return a.r == b.r && a.g == b.g && a.b == b.b; | |
} | |
template<class INTERNAL_TYPE = double> | |
RGB24 rgb_from_hsl(HSL24&& i) { | |
using internal_type = INTERNAL_TYPE; | |
constexpr internal_type | |
zero = 0., one = 1., two = 2., six = 6., | |
senary_1 = 1. / six, senary_2 = 2. / six, | |
senary_3 = 3. / six, senary_4 = 4. / six, | |
senary_5 = 5. / six, | |
trinary_1 = 1. / 3., | |
max_factor = numeric_limits<decltype(i.h)>::max(), | |
unorm_factor = one / max_factor, | |
unorm_factor_loop = one / (max_factor + one); | |
const auto | |
h_ = internal_type( i.h ) * unorm_factor_loop, | |
s_ = internal_type( i.s ) * unorm_factor, | |
l_ = internal_type( i.l ) * unorm_factor; | |
const auto c = (one - abs( two * l_ - one ) ) * s_; | |
const auto x = c * ( one - abs( fmod( h_, trinary_1 ) * six - one ) ); | |
double r1, g1, b1; | |
if ( h_ >= senary_5 ) { r1 = c; g1 = zero; b1 = x;} | |
else if ( h_ >= senary_4 ) { r1 = x; g1 = zero; b1 = c;} | |
else if ( h_ >= senary_3 ) { r1 = zero; g1 = x; b1 = c;} | |
else if ( h_ >= senary_2 ) { r1 = zero; g1 = c; b1 = x;} | |
else if ( h_ >= senary_1 ) { r1 = x; g1 = c; b1 = zero;} | |
else if ( h_ >= zero ) { r1 = c; g1 = x; b1 = zero;} | |
else return { 0, 0, 0 }; | |
auto m = l_ - ( c / two ); | |
return { | |
uint8_t(max_factor * (r1 + m)), | |
uint8_t(max_factor * (g1 + m)), | |
uint8_t(max_factor * (b1 + m)) | |
}; | |
} | |
int main() try { | |
cout << hex << setfill('0'); | |
vector<RGB24> r(256 * 256 * 256); | |
array<uint8_t, 256> ns; | |
iota(ns.begin(), ns.end(), 0); | |
cout | |
<< "OpenMP: " | |
#if defined(_OPENMP) | |
"Enabled ( " | |
<< omp_get_num_procs() | |
<< " [processor-cores], " | |
<< omp_get_max_threads() | |
<< " [threads])" | |
#else | |
"Disabled" | |
#endif | |
<< endl; | |
#if defined(_OPENMP) | |
mutex m; | |
#pragma omp parallel | |
{ // omp scope - begin | |
{ | |
lock_guard<mutex> l(m); | |
cout | |
<< "OpenMP running thread: " | |
<< omp_get_thread_num() | |
<< endl; | |
} | |
#endif | |
#pragma omp for | |
for(uint_fast16_t h = 0; h < 256; ++h) | |
for(const auto& s : ns) | |
for(const auto& l : ns) { | |
auto rgb = rgb_from_hsl<adopt_type>({ | |
static_cast<uint8_t>(h), s, l | |
}); | |
#if defined(VERBOSE) | |
cout | |
<< "\033[41D" | |
"H8S8L8: " | |
<< setw(2) << unsigned(h) << ", " | |
<< setw(2) << unsigned(s) << ", " | |
<< setw(2) << unsigned(l) | |
<< " --> R8G8B8: " | |
<< setw(2) << unsigned(rgb.r) << ", " | |
<< setw(2) << unsigned(rgb.g) << ", " | |
<< setw(2) << unsigned(rgb.b) | |
<< flush | |
; | |
#endif | |
r[h*256*256+s*256+l] = move(rgb); | |
} | |
} // omp scope - end | |
#if defined(VERBOSE) | |
std::cout << endl; | |
#endif | |
{ | |
cout << "write result image: \"" << image_filename << "\" ... "; | |
using namespace boost::gil; | |
const size_t | |
width = 256 * 16, | |
height = 256 * 16, | |
stride = width * 3; | |
const rgb8_view_t v = interleaved_view( | |
width, | |
height, | |
reinterpret_cast<rgb8_pixel_t*>(r.data()), | |
stride | |
); | |
png_write_view( image_filename, v ); | |
cout << "done" << endl; | |
} | |
{ | |
sort(r.begin(), r.end()); | |
cout | |
<< dec | |
<< "total: " | |
<< r.size() | |
<< "\n" "duplicated: " | |
<< distance(unique(r.begin(), r.end()), r.end()) | |
<< endl | |
; | |
} | |
} catch (exception e) { | |
cerr << "oops! : " << e.what(); | |
} catch (...) { | |
cerr << "oops! : unknown exception"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment