Create a gist now

Instantly share code, notes, and snippets.

@usagi /Makefile
Last active Dec 10, 2015

What would you like to do?
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} {} \;
#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