<commit_before>#include "Simulation.h"

#include "Buffer.h"
#include "FrameBufferCache.h"
#include "Kernel.h"
#include "log.h"
#include "StopWatch.h"
#include "Vectors.h"
#include "VertexArray.h"

namespace ca {

Simulation::Simulation(const Size& world_size) : world_size_(world_size),
                                                 fft_(world_size) {
    sl_parameters_.inner_radius = 10.0/3.0;
    sl_parameters_.outer_radius = 10;
    sl_parameters_.border = 1;
    sl_parameters_.b1 = 0.257;
    sl_parameters_.b2 = 0.336;
    sl_parameters_.d1 = 0.365;
    sl_parameters_.d2 = 0.549;
    sl_parameters_.alphan = 0.028;
    sl_parameters_.alpham = 0.147;
    sl_parameters_.dt = 0.1;

    // Protoplasm
    /*
    sl_parameters_.inner_radius = 10.0/3.0;
    sl_parameters_.outer_radius = 10;
    sl_parameters_.border = 1;
    sl_parameters_.b1 = 0.305;
    sl_parameters_.b2 = 0.443;
    sl_parameters_.d1 = 0.556;
    sl_parameters_.d2 = 0.814;
    sl_parameters_.alphan = 0.028;
    sl_parameters_.alpham = 0.147;
    sl_parameters_.dt = 0.089;
*/
}

void Simulation::Init() {
    LoadShaders();
    // InitKernels depends on FFT init being called first.
    fft_.Init();
    InitKernels();
    InitState();
}

void Simulation::Step() {
    // StopWatch stop_watch("Simulation::Step");
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* read = state_ring_.read_buffer();
    FrameBuffer* write = state_ring_.write_buffer();
    // Step 1: take fourier transform of the state
    FrameBuffer* state_fft = fft_.Forward(read);
    // stop_watch.Mark("fft.Forward");
    // Step 2: convolution
    write->BindFrameBuffer();
    glViewport(0, 0, world_size_.w, world_size_.h);
    glUseProgram(convolve_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    // TODO: Premultiply kernels by scale factor
    glUniform2f(uniforms_.scale_location, 1./inner_sum_, 1./outer_sum_);
    CHECK_GL_ERROR("glUniform2f");
    glActiveTexture (GL_TEXTURE1);
    glBindTexture (GL_TEXTURE_2D, kernels_fft()->texture());
    glUniform1i(uniforms_.kernels_fft_tex_location, 1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, state_fft->texture());
    glUniform1i(uniforms_.state_fft_tex_location, 0);
    VertexArray::Default()->Bind();
    VertexArray::Default()->Draw();
    cache->RecycleBuffer(state_fft);
    // stop_watch.Mark("convolve shader");
    // 'write' now contains the products of state with kernels
    // in the frequency domain.
    // Step 3: Parallel inverse fourier transform
    FrameBuffer * nm = fft_.Inverse(write);
    // stop_watch.Mark("fft.Inverse");
    // Step 4: Compute derivative and apply
    write->BindFrameBuffer();
    glViewport(0, 0, world_size_.w, world_size_.h);
    glUseProgram(sigmoid_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    glActiveTexture (GL_TEXTURE1);
    glBindTexture (GL_TEXTURE_2D, read->texture());
    glUniform1i(uniforms_.state_tex_location, 1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, nm->texture());
    glUniform1i(uniforms_.integral_tex_location, 0);
    VertexArray::Default()->Bind();
    VertexArray::Default()->Draw();
    cache->RecycleBuffer(nm);
    // stop_watch.Mark("sigmoid shader");
    glUseProgram(0);
    // Done, new state at t+dt is in write buffer.
    state_ring_.Rotate();
    // std::cout << stop_watch.Report();
}

void Simulation::TestPerformance() {
    StopWatch stop_watch("Simulation::Step");
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* read = state_ring_.read_buffer();
    for (int i = 0; i < 100; i++) {
        FrameBuffer* state_fft = fft_.Forward(read);
        cache->RecycleBuffer(state_fft);
    }
    glFlush();
    stop_watch.Mark("fft.Forward x 100");
    std::cout << stop_watch.Report();
    std::cout << 100.0 / stop_watch.elapsed_time() << " DFTs/sec" << std::endl;
}

FrameBuffer* Simulation::LockRenderingBuffer() {
    return state_ring_.RemoveIdle();
}

void Simulation::UnlockRenderingBuffer(FrameBuffer* rendering_buffer) {
    state_ring_.Add(rendering_buffer);
}

FrameBuffer* Simulation::kernels_fft() const {
    return kernels_fft_.get();
}

void Simulation::LoadShaders() {
    Shader * convolve_shader = new Shader("minimal", "convolve_par");
    convolve_shader->Init(ShaderAttributes());
    convolve_shader_.reset(convolve_shader);
    uniforms_.scale_location = convolve_shader_->UniformLocation("scale");
    uniforms_.state_fft_tex_location = convolve_shader_->UniformLocation("stateFFT");
    uniforms_.kernels_fft_tex_location = convolve_shader_->UniformLocation("kernelsFFT");

    Shader * sigmoid_shader = new Shader("minimal", "sigmoid");
    sigmoid_shader->Init(ShaderAttributes());
    sigmoid_shader_.reset(sigmoid_shader);
    GLint integral_tex_location;
    GLint state_tex_location;
    uniforms_.integral_tex_location = sigmoid_shader_->UniformLocation("integralTexture");
    uniforms_.state_tex_location = sigmoid_shader_->UniformLocation("stateTexture");
    // TODO: make these parameters variable
    glUseProgram(sigmoid_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    glUniform1f(sigmoid_shader_->UniformLocation("b1"), sl_parameters_.b1);
    glUniform1f(sigmoid_shader_->UniformLocation("b2"), sl_parameters_.b2);
    glUniform1f(sigmoid_shader_->UniformLocation("d1"), sl_parameters_.d1);
    glUniform1f(sigmoid_shader_->UniformLocation("d2"), sl_parameters_.d2);
    glUniform1f(sigmoid_shader_->UniformLocation("sn"), sl_parameters_.alphan);
    glUniform1f(sigmoid_shader_->UniformLocation("sm"), sl_parameters_.alpham);
    glUniform1f(sigmoid_shader_->UniformLocation("dt"), sl_parameters_.dt);
    CHECK_GL_ERROR("glUniform1f");
    glUseProgram(0);
}

void Simulation::InitKernels() {
    // Set up kernels
    Buffer2D<float> inner_kernel(world_size_);
    inner_sum_ = CircularKernel(&inner_kernel,
                                sl_parameters_.inner_radius,
                                sl_parameters_.border);
    Buffer2D<float> outer_kernel(world_size_);
    outer_sum_ = RingKernel(&outer_kernel,
                             sl_parameters_.inner_radius,
                             sl_parameters_.outer_radius,
                            sl_parameters_.border);
    Buffer2D<Vec4<float>> kernels(world_size_);
    Size half_size = Size(world_size_.w / 2, world_size_.h / 2);
    for (int x = 0; x < world_size_.w; x++) {
        for (int y = 0; y < world_size_.h; y++) {
            // Perform FFT shift
            const int shift_x = (x + half_size.w) % world_size_.w;
            const int shift_y = (y + half_size.h) % world_size_.h;
            // Interleave both kernels using r and b channels of the same image
            kernels.set(x, y, Vec4<float>(inner_kernel.get(shift_x, shift_y), 0,
                                          outer_kernel.get(shift_x, shift_y), 0));
        }
    }
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* kernels_buffer = cache->ReserveBuffer();
    glBindTexture(GL_TEXTURE_2D, kernels_buffer->texture());
    CHECK_GL_ERROR("glBindTexture");
    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, world_size_.w, world_size_.h, GL_RGBA, GL_FLOAT, kernels.data());
    CHECK_GL_ERROR("glTexSubImage2D");
    // Compute the DFT of both kernels
    kernels_fft_.reset(fft_.Forward(kernels_buffer));
    cache->RecycleBuffer(kernels_buffer);
}

void Simulation::InitState() {
    // Set up state ring buffer
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    for (int i = 0; i < 3; i++) {
        FrameBuffer* buffer = cache->ReserveBuffer();
        state_ring_.Add(buffer);
    }
    // Configure initial state
    FrameBuffer * front_buffer = state_ring_.read_buffer();
    Buffer2D<Vec4<float>> state(world_size_);

    const float length = 40;
    const int iterations = 100;
    std::uniform_int_distribution<int> value_dist(0, 1);
    std::uniform_int_distribution<int> x_dist(0, world_size_.w);
    std::uniform_int_distribution<int> y_dist(0, world_size_.h);
    std::uniform_int_distribution<int> r_dist(length * .5, length * 1.5);
    for (int i = 0; i < iterations; i++) {
        float xo = x_dist(generator_);
        float yo = y_dist(generator_);
        float w = r_dist(generator_);
        float h = r_dist(generator_);
        float v = (float)value_dist(generator_);
        for (int x = xo; x < xo + w; x++) {
            for (int y = yo; y < yo + h; y++) {
                state.set(x % world_size_.w, y % world_size_.h, Vec4<float>(v, 0.0, 0.0, 0.0));
            }
        }
    }
    glBindTexture(GL_TEXTURE_2D, front_buffer->texture());
    CHECK_GL_ERROR("glBindTexture");
    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, world_size_.w, world_size_.h, GL_RGBA, GL_FLOAT, state.data());
    CHECK_GL_ERROR("glTexSubImage2D");
}

}  // namespace ca<commit_msg>Add more random material in initialization.<commit_after>#include "Simulation.h"

#include "Buffer.h"
#include "FrameBufferCache.h"
#include "Kernel.h"
#include "log.h"
#include "StopWatch.h"
#include "Vectors.h"
#include "VertexArray.h"

namespace ca {

Simulation::Simulation(const Size& world_size) : world_size_(world_size),
                                                 fft_(world_size) {
    sl_parameters_.inner_radius = 10.0/3.0;
    sl_parameters_.outer_radius = 10;
    sl_parameters_.border = 1;
    sl_parameters_.b1 = 0.257;
    sl_parameters_.b2 = 0.336;
    sl_parameters_.d1 = 0.365;
    sl_parameters_.d2 = 0.549;
    sl_parameters_.alphan = 0.028;
    sl_parameters_.alpham = 0.147;
    sl_parameters_.dt = 0.1;

    // Protoplasm
    /*
    sl_parameters_.inner_radius = 10.0/3.0;
    sl_parameters_.outer_radius = 10;
    sl_parameters_.border = 1;
    sl_parameters_.b1 = 0.305;
    sl_parameters_.b2 = 0.443;
    sl_parameters_.d1 = 0.556;
    sl_parameters_.d2 = 0.814;
    sl_parameters_.alphan = 0.028;
    sl_parameters_.alpham = 0.147;
    sl_parameters_.dt = 0.089;
*/
}

void Simulation::Init() {
    LoadShaders();
    // InitKernels depends on FFT init being called first.
    fft_.Init();
    InitKernels();
    InitState();
}

void Simulation::Step() {
    // StopWatch stop_watch("Simulation::Step");
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* read = state_ring_.read_buffer();
    FrameBuffer* write = state_ring_.write_buffer();
    // Step 1: take fourier transform of the state
    FrameBuffer* state_fft = fft_.Forward(read);
    // stop_watch.Mark("fft.Forward");
    // Step 2: convolution
    write->BindFrameBuffer();
    glViewport(0, 0, world_size_.w, world_size_.h);
    glUseProgram(convolve_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    // TODO: Premultiply kernels by scale factor
    glUniform2f(uniforms_.scale_location, 1./inner_sum_, 1./outer_sum_);
    CHECK_GL_ERROR("glUniform2f");
    glActiveTexture (GL_TEXTURE1);
    glBindTexture (GL_TEXTURE_2D, kernels_fft()->texture());
    glUniform1i(uniforms_.kernels_fft_tex_location, 1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, state_fft->texture());
    glUniform1i(uniforms_.state_fft_tex_location, 0);
    VertexArray::Default()->Bind();
    VertexArray::Default()->Draw();
    cache->RecycleBuffer(state_fft);
    // stop_watch.Mark("convolve shader");
    // 'write' now contains the products of state with kernels
    // in the frequency domain.
    // Step 3: Parallel inverse fourier transform
    FrameBuffer * nm = fft_.Inverse(write);
    // stop_watch.Mark("fft.Inverse");
    // Step 4: Compute derivative and apply
    write->BindFrameBuffer();
    glViewport(0, 0, world_size_.w, world_size_.h);
    glUseProgram(sigmoid_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    glActiveTexture (GL_TEXTURE1);
    glBindTexture (GL_TEXTURE_2D, read->texture());
    glUniform1i(uniforms_.state_tex_location, 1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, nm->texture());
    glUniform1i(uniforms_.integral_tex_location, 0);
    VertexArray::Default()->Bind();
    VertexArray::Default()->Draw();
    cache->RecycleBuffer(nm);
    // stop_watch.Mark("sigmoid shader");
    glUseProgram(0);
    // Done, new state at t+dt is in write buffer.
    state_ring_.Rotate();
    // std::cout << stop_watch.Report();
}

void Simulation::TestPerformance() {
    StopWatch stop_watch("Simulation::Step");
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* read = state_ring_.read_buffer();
    for (int i = 0; i < 100; i++) {
        FrameBuffer* state_fft = fft_.Forward(read);
        cache->RecycleBuffer(state_fft);
    }
    glFlush();
    stop_watch.Mark("fft.Forward x 100");
    std::cout << stop_watch.Report();
    std::cout << 100.0 / stop_watch.elapsed_time() << " DFTs/sec" << std::endl;
}

FrameBuffer* Simulation::LockRenderingBuffer() {
    return state_ring_.RemoveIdle();
}

void Simulation::UnlockRenderingBuffer(FrameBuffer* rendering_buffer) {
    state_ring_.Add(rendering_buffer);
}

FrameBuffer* Simulation::kernels_fft() const {
    return kernels_fft_.get();
}

void Simulation::LoadShaders() {
    Shader * convolve_shader = new Shader("minimal", "convolve_par");
    convolve_shader->Init(ShaderAttributes());
    convolve_shader_.reset(convolve_shader);
    uniforms_.scale_location = convolve_shader_->UniformLocation("scale");
    uniforms_.state_fft_tex_location = convolve_shader_->UniformLocation("stateFFT");
    uniforms_.kernels_fft_tex_location = convolve_shader_->UniformLocation("kernelsFFT");

    Shader * sigmoid_shader = new Shader("minimal", "sigmoid");
    sigmoid_shader->Init(ShaderAttributes());
    sigmoid_shader_.reset(sigmoid_shader);
    GLint integral_tex_location;
    GLint state_tex_location;
    uniforms_.integral_tex_location = sigmoid_shader_->UniformLocation("integralTexture");
    uniforms_.state_tex_location = sigmoid_shader_->UniformLocation("stateTexture");
    // TODO: make these parameters variable
    glUseProgram(sigmoid_shader_->program());
    CHECK_GL_ERROR("glUseProgram");
    glUniform1f(sigmoid_shader_->UniformLocation("b1"), sl_parameters_.b1);
    glUniform1f(sigmoid_shader_->UniformLocation("b2"), sl_parameters_.b2);
    glUniform1f(sigmoid_shader_->UniformLocation("d1"), sl_parameters_.d1);
    glUniform1f(sigmoid_shader_->UniformLocation("d2"), sl_parameters_.d2);
    glUniform1f(sigmoid_shader_->UniformLocation("sn"), sl_parameters_.alphan);
    glUniform1f(sigmoid_shader_->UniformLocation("sm"), sl_parameters_.alpham);
    glUniform1f(sigmoid_shader_->UniformLocation("dt"), sl_parameters_.dt);
    CHECK_GL_ERROR("glUniform1f");
    glUseProgram(0);
}

void Simulation::InitKernels() {
    // Set up kernels
    Buffer2D<float> inner_kernel(world_size_);
    inner_sum_ = CircularKernel(&inner_kernel,
                                sl_parameters_.inner_radius,
                                sl_parameters_.border);
    Buffer2D<float> outer_kernel(world_size_);
    outer_sum_ = RingKernel(&outer_kernel,
                             sl_parameters_.inner_radius,
                             sl_parameters_.outer_radius,
                            sl_parameters_.border);
    Buffer2D<Vec4<float>> kernels(world_size_);
    Size half_size = Size(world_size_.w / 2, world_size_.h / 2);
    for (int x = 0; x < world_size_.w; x++) {
        for (int y = 0; y < world_size_.h; y++) {
            // Perform FFT shift
            const int shift_x = (x + half_size.w) % world_size_.w;
            const int shift_y = (y + half_size.h) % world_size_.h;
            // Interleave both kernels using r and b channels of the same image
            kernels.set(x, y, Vec4<float>(inner_kernel.get(shift_x, shift_y), 0,
                                          outer_kernel.get(shift_x, shift_y), 0));
        }
    }
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    FrameBuffer* kernels_buffer = cache->ReserveBuffer();
    glBindTexture(GL_TEXTURE_2D, kernels_buffer->texture());
    CHECK_GL_ERROR("glBindTexture");
    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, world_size_.w, world_size_.h, GL_RGBA, GL_FLOAT, kernels.data());
    CHECK_GL_ERROR("glTexSubImage2D");
    // Compute the DFT of both kernels
    kernels_fft_.reset(fft_.Forward(kernels_buffer));
    cache->RecycleBuffer(kernels_buffer);
}

void Simulation::InitState() {
    // Set up state ring buffer
    FrameBufferCache* cache = FrameBufferCache::sharedCache(world_size_);
    for (int i = 0; i < 3; i++) {
        FrameBuffer* buffer = cache->ReserveBuffer();
        state_ring_.Add(buffer);
    }
    // Configure initial state
    FrameBuffer * front_buffer = state_ring_.read_buffer();
    Buffer2D<Vec4<float>> state(world_size_);

    const float length = 40;
    const int iterations = 400;
    std::uniform_int_distribution<int> value_dist(0, 1);
    std::uniform_int_distribution<int> x_dist(0, world_size_.w);
    std::uniform_int_distribution<int> y_dist(0, world_size_.h);
    std::uniform_int_distribution<int> r_dist(length * .5, length * 1.5);
    for (int i = 0; i < iterations; i++) {
        float xo = x_dist(generator_);
        float yo = y_dist(generator_);
        float w = r_dist(generator_);
        float h = r_dist(generator_);
        float v = (float)value_dist(generator_);
        for (int x = xo; x < xo + w; x++) {
            for (int y = yo; y < yo + h; y++) {
                state.set(x % world_size_.w, y % world_size_.h, Vec4<float>(v, 0.0, 0.0, 0.0));
            }
        }
    }
    glBindTexture(GL_TEXTURE_2D, front_buffer->texture());
    CHECK_GL_ERROR("glBindTexture");
    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, world_size_.w, world_size_.h, GL_RGBA, GL_FLOAT, state.data());
    CHECK_GL_ERROR("glTexSubImage2D");
}

}  // namespace ca<|endoftext|>


<commit_before>#ifndef SILICIUM_DELEGATOR_GENERATE_HPP
#define SILICIUM_DELEGATOR_GENERATE_HPP

// enclosing namespace struct:

#define DELEGATOR_TEMPLATE(...) template <__VA_ARGS__>
#define DELEGATOR_NAME(name)                                                                                \
	struct name                                                                                \
	{
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD

// abstract base class:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)                                                                                \
	struct abstract_base                                                                                \
	{                                                                                \
		virtual ~abstract_base()                                                                                \
		{                                                                                \
		}
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...) virtual auto name(__VA_ARGS__) constness->result = 0;

#include DELEGATOR_INCLUDE
}
;

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD

// eraser:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)                                                                                \
	template <class Impl>                                                                                \
	struct eraser : abstract_base                                                                                \
	{                                                                                \
		explicit eraser(Impl impl)                                                                                \
		    : m_impl(std::move(impl))                                                                                \
		{                                                                                \
		}                                                                                \
                                                                                \
	private:                                                                                \
		Impl m_impl;                                                                                \
                                                                                \
	public:
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	virtual auto name(                                                                                \
	    BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)))  \
	    constness->result SILICIUM_OVERRIDE                                                                            \
	{                                                                                \
		return m_impl.name(BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _,                          \
		                                            BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));                          \
	}

#include DELEGATOR_INCLUDE
}
;

template <class Impl>
static eraser<typename std::decay<Impl>::type> erase(Impl &&impl)
{
	return eraser<typename std::decay<Impl>::type>(std::forward<Impl>(impl));
}

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD

struct fat_ref
{
	template <class Impl>
	explicit fat_ref(Impl &impl)
	    : m_impl(&impl)
	{
		// initialize the vtable
		static vtable const instance = {
#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	[](void constness *impl, BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _,                      \
	                                                  BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))) -> result               \
	{                                                                                \
		return static_cast<Impl constness *>(impl)->name(BOOST_PP_LIST_FOR_EACH_I(                                     \
		    DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));                        \
	},

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD
		};
		m_virtuals = &instance;
	}

// methods:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	auto name(BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _,                                     \
	                                   BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))) constness->result                      \
	{                                                                                \
		return m_virtuals->name(m_impl, BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _,             \
		                                                         BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));             \
	}

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD

private:
	void *m_impl;

	struct vtable
	{
#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...) result (*name)(void constness *, __VA_ARGS__);

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD
	};
	vtable const *m_virtuals;
};

// end of enclosing namespace struct:
}
;

#endif
<commit_msg>avoid trailing return type for GCC 4.7<commit_after>#ifndef SILICIUM_DELEGATOR_GENERATE_HPP
#define SILICIUM_DELEGATOR_GENERATE_HPP

// enclosing namespace struct:

#define DELEGATOR_TEMPLATE(...) template <__VA_ARGS__>
#define DELEGATOR_NAME(name)                                                                                \
	struct name                                                                                \
	{
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD

// abstract base class:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)                                                                                \
	struct abstract_base                                                                                \
	{                                                                                \
		virtual ~abstract_base()                                                                                \
		{                                                                                \
		}
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...) virtual auto name(__VA_ARGS__) constness->result = 0;

#include DELEGATOR_INCLUDE
}
;

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD

// eraser:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)                                                                                \
	template <class Impl>                                                                                \
	struct eraser : abstract_base                                                                                \
	{                                                                                \
		explicit eraser(Impl impl)                                                                                \
		    : m_impl(std::move(impl))                                                                                \
		{                                                                                \
		}                                                                                \
                                                                                \
	private:                                                                                \
		Impl m_impl;                                                                                \
                                                                                \
	public:
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	virtual result name(BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _,                           \
	                                             BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))) constness SILICIUM_OVERRIDE  \
	{                                                                                \
		return m_impl.name(BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _,                          \
		                                            BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));                          \
	}

#include DELEGATOR_INCLUDE
}
;

template <class Impl>
static eraser<typename std::decay<Impl>::type> erase(Impl &&impl)
{
	return eraser<typename std::decay<Impl>::type>(std::forward<Impl>(impl));
}

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD

struct fat_ref
{
	template <class Impl>
	explicit fat_ref(Impl &impl)
	    : m_impl(&impl)
	{
		// initialize the vtable
		static vtable const instance = {
#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	[](void constness *impl, BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _,                      \
	                                                  BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))) -> result               \
	{                                                                                \
		return static_cast<Impl constness *>(impl)->name(BOOST_PP_LIST_FOR_EACH_I(                                     \
		    DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));                        \
	},

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD
		};
		m_virtuals = &instance;
	}

// methods:

#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...) __VA_ARGS__
#define DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER(r, data, i, elem) elem BOOST_PP_CAT(arg, i)
#define DELEGATOR_BASIC_METHOD_DETAIL_FORWARD(r, data, i, elem) std::forward<elem>(BOOST_PP_CAT(arg, i))
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...)                                                           \
	auto name(BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER, _,                                     \
	                                   BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))) constness->result                      \
	{                                                                                \
		return m_virtuals->name(m_impl, BOOST_PP_LIST_FOR_EACH_I(DELEGATOR_BASIC_METHOD_DETAIL_FORWARD, _,             \
		                                                         BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)));             \
	}

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD_DETAIL_PARAMETER
#undef DELEGATOR_BASIC_METHOD_DETAIL_FORWARD
#undef DELEGATOR_BASIC_METHOD

private:
	void *m_impl;

	struct vtable
	{
#define DELEGATOR_TEMPLATE(...)
#define DELEGATOR_NAME(name)
#define DELEGATOR_TYPEDEF(...)
#define DELEGATOR_BASIC_METHOD(name, constness, result, ...) result (*name)(void constness *, __VA_ARGS__);

#include DELEGATOR_INCLUDE

#undef DELEGATOR_TEMPLATE
#undef DELEGATOR_NAME
#undef DELEGATOR_TYPEDEF
#undef DELEGATOR_BASIC_METHOD
	};
	vtable const *m_virtuals;
};

// end of enclosing namespace struct:
}
;

#endif
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#ifndef IECORE_TRIANGLEALGO_INL
#define IECORE_TRIANGLEALGO_INL

#include "OpenEXR/ImathLimits.h"

#include "IECore/VectorOps.h"

namespace IECore
{

template<class Vec>
typename VectorTraits<Vec>::BaseType triangleArea( const Vec &v0, const Vec &v1, const Vec &v2 )
{
	return (v1-v0).cross(v2-v0).length() / 2;
}

template<class Vec>
Vec triangleNormal( const Vec &v0, const Vec &v1, const Vec &v2 )
{
	Vec n = (v2-v0).cross(v1-v0);
	vecNormalize( n );
	return n;
}

template<class Vec>
Vec trianglePoint( const Vec &v0, const Vec &v1, const Vec &v2, const Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	return vecAdd(
		vecAdd(
			vecMul( v0, barycentric[0] ),
			vecMul( v1, barycentric[1] )
		),
		vecMul( v2, barycentric[2] )
	);
}

/// Implementation derived from Wild Magic (Version 2) Software Library, available
/// from http://www.geometrictools.com/Downloads/WildMagic2p5.zip under free license
template<class Vec>
typename VectorTraits<Vec>::BaseType triangleClosestBarycentric( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p, Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	Vec triOrigin = v0;
	Vec triEdge0, triEdge1;

	vecSub( v1, v0, triEdge0 );
	vecSub( v2, v0, triEdge1 );

	Vec kDiff;
	vecSub( triOrigin, p, kDiff );

	Real a00 = vecDot( triEdge0, triEdge0 );
	Real a01 = vecDot( triEdge0, triEdge1 );
	Real a11 = vecDot( triEdge1, triEdge1 );
	Real b0 = vecDot( kDiff, triEdge0 );
	Real b1 = vecDot( kDiff, triEdge1 );
	Real c = vecDot( kDiff, kDiff );
	Real det = Real(fabs(a00*a11-a01*a01));
	Real s = a01*b1-a11*b0;
	Real t = a01*b0-a00*b1;
	Real distSqrd;

	if ( s + t <= det )
	{
		if ( s < Real(0.0) )
		{
			if ( t < Real(0.0) )  // region 4
			{
				if ( b0 < Real(0.0) )
				{
					t = Real(0.0);
					if ( -b0 >= a00 )
					{
						s = Real(1.0);
						distSqrd = a00+Real(2.0)*b0+c;
					}
					else
					{
						s = -b0/a00;
						distSqrd = b0*s+c;
					}
				}
				else
				{
					s = Real(0.0);
					if ( b1 >= Real(0.0) )
					{
						t = Real(0.0);
						distSqrd = c;
					}
					else if ( -b1 >= a11 )
					{
						t = Real(1.0);
						distSqrd = a11+Real(2.0)*b1+c;
					}
					else
					{
						t = -b1/a11;
						distSqrd = b1*t+c;
					}
				}
			}
			else  // region 3
			{
				s = Real(0.0);
				if ( b1 >= Real(0.0) )
				{
					t = Real(0.0);
					distSqrd = c;
				}
				else if ( -b1 >= a11 )
				{
					t = Real(1.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else
				{
					t = -b1/a11;
					distSqrd = b1*t+c;
				}
			}
		}
		else if ( t < Real(0.0) )  // region 5
		{
			t = Real(0.0);
			if ( b0 >= Real(0.0) )
			{
				s = Real(0.0);
				distSqrd = c;
			}
			else if ( -b0 >= a00 )
			{
				s = Real(1.0);
				distSqrd = a00+Real(2.0)*b0+c;
			}
			else
			{
				s = -b0/a00;
				distSqrd = b0*s+c;
			}
		}
		else  // region 0
		{
			// minimum at interior point
			if ( det == Real(0.0) )
			{
				s = Real(0.0);
				t = Real(0.0);
				distSqrd = Imath::limits<Real>::max();
			}
			else
			{
				Real invDet = Real(1.0)/det;
				s *= invDet;
				t *= invDet;
				distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
				           t*(a01*s+a11*t+Real(2.0)*b1)+c;
			}
		}
	}
	else
	{
		Real tmp0, tmp1, numer, denom;

		if ( s < Real(0.0) )  // region 2
		{
			tmp0 = a01 + b0;
			tmp1 = a11 + b1;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					s = Real(1.0);
					t = Real(0.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else
				{
					s = numer/denom;
					t = Real(1.0) - s;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
			else
			{
				s = Real(0.0);
				if ( tmp1 <= Real(0.0) )
				{
					t = Real(1.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else if ( b1 >= Real(0.0) )
				{
					t = Real(0.0);
					distSqrd = c;
				}
				else
				{
					t = -b1/a11;
					distSqrd = b1*t+c;
				}
			}
		}
		else if ( t < Real(0.0) )  // region 6
		{
			tmp0 = a01 + b1;
			tmp1 = a00 + b0;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					t = Real(1.0);
					s = Real(0.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else
				{
					t = numer/denom;
					s = Real(1.0) - t;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
			else
			{
				t = Real(0.0);
				if ( tmp1 <= Real(0.0) )
				{
					s = Real(1.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else if ( b0 >= Real(0.0) )
				{
					s = Real(0.0);
					distSqrd = c;
				}
				else
				{
					s = -b0/a00;
					distSqrd = b0*s+c;
				}
			}
		}
		else  // region 1
		{
			numer = a11 + b1 - a01 - b0;
			if ( numer <= Real(0.0) )
			{
				s = Real(0.0);
				t = Real(1.0);
				distSqrd = a11+Real(2.0)*b1+c;
			}
			else
			{
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					s = Real(1.0);
					t = Real(0.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else
				{
					s = numer/denom;
					t = Real(1.0) - s;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
		}
	}

	barycentric.y = s;
	barycentric.z = t;
	barycentric.x = 1 - s - t;

	return Real(fabs(distSqrd));
}

template<class Vec>
Vec triangleClosestPoint( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p, Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	triangleClosestBarycentric( v0, v1, v2, p, barycentric );
	return trianglePoint( v0, v1, v2, barycentric );
}

template<class Vec>
int triangleBarycentricFeature( const Vec &barycentric, typename VectorTraits<Vec>::BaseType tolerance )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	bool bx = VectorTraits<Vec>::get( barycentric, 0 ) > tolerance;
	bool by = VectorTraits<Vec>::get( barycentric, 1 ) > tolerance;
	bool bz = VectorTraits<Vec>::get( barycentric, 2 ) > tolerance;

	if (bx && by && bz)
	{
		return 0;
	}
	else if (bx && by)
	{
		return 5;
	}
	else if (bx && bz)
	{
		return 3;
	}
	else if (by && bz)
	{
		return 1;
	}
	else if (bx)
	{
		return 4;
	}
	else if (by)
	{
		return 6;
	}
	else
	{
		assert(bz);
		return 2;
	}
}

template<class Vec>
int triangleClosestFeature( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	Imath::Vec3<Real> barycentric;
	triangleClosestPoint( v0, v1, v2, p, barycentric);

	return triangleBarycentricFeature( barycentric );
}

} // namespace IECore

#endif // IECORE_TRIANGLEALGO_INL
<commit_msg>Added missing include<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#ifndef IECORE_TRIANGLEALGO_INL
#define IECORE_TRIANGLEALGO_INL

#include <cassert>

#include "OpenEXR/ImathLimits.h"

#include "IECore/VectorOps.h"

namespace IECore
{

template<class Vec>
typename VectorTraits<Vec>::BaseType triangleArea( const Vec &v0, const Vec &v1, const Vec &v2 )
{
	return (v1-v0).cross(v2-v0).length() / 2;
}

template<class Vec>
Vec triangleNormal( const Vec &v0, const Vec &v1, const Vec &v2 )
{
	Vec n = (v2-v0).cross(v1-v0);
	vecNormalize( n );
	return n;
}

template<class Vec>
Vec trianglePoint( const Vec &v0, const Vec &v1, const Vec &v2, const Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	return vecAdd(
		vecAdd(
			vecMul( v0, barycentric[0] ),
			vecMul( v1, barycentric[1] )
		),
		vecMul( v2, barycentric[2] )
	);
}

/// Implementation derived from Wild Magic (Version 2) Software Library, available
/// from http://www.geometrictools.com/Downloads/WildMagic2p5.zip under free license
template<class Vec>
typename VectorTraits<Vec>::BaseType triangleClosestBarycentric( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p, Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	Vec triOrigin = v0;
	Vec triEdge0, triEdge1;

	vecSub( v1, v0, triEdge0 );
	vecSub( v2, v0, triEdge1 );

	Vec kDiff;
	vecSub( triOrigin, p, kDiff );

	Real a00 = vecDot( triEdge0, triEdge0 );
	Real a01 = vecDot( triEdge0, triEdge1 );
	Real a11 = vecDot( triEdge1, triEdge1 );
	Real b0 = vecDot( kDiff, triEdge0 );
	Real b1 = vecDot( kDiff, triEdge1 );
	Real c = vecDot( kDiff, kDiff );
	Real det = Real(fabs(a00*a11-a01*a01));
	Real s = a01*b1-a11*b0;
	Real t = a01*b0-a00*b1;
	Real distSqrd;

	if ( s + t <= det )
	{
		if ( s < Real(0.0) )
		{
			if ( t < Real(0.0) )  // region 4
			{
				if ( b0 < Real(0.0) )
				{
					t = Real(0.0);
					if ( -b0 >= a00 )
					{
						s = Real(1.0);
						distSqrd = a00+Real(2.0)*b0+c;
					}
					else
					{
						s = -b0/a00;
						distSqrd = b0*s+c;
					}
				}
				else
				{
					s = Real(0.0);
					if ( b1 >= Real(0.0) )
					{
						t = Real(0.0);
						distSqrd = c;
					}
					else if ( -b1 >= a11 )
					{
						t = Real(1.0);
						distSqrd = a11+Real(2.0)*b1+c;
					}
					else
					{
						t = -b1/a11;
						distSqrd = b1*t+c;
					}
				}
			}
			else  // region 3
			{
				s = Real(0.0);
				if ( b1 >= Real(0.0) )
				{
					t = Real(0.0);
					distSqrd = c;
				}
				else if ( -b1 >= a11 )
				{
					t = Real(1.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else
				{
					t = -b1/a11;
					distSqrd = b1*t+c;
				}
			}
		}
		else if ( t < Real(0.0) )  // region 5
		{
			t = Real(0.0);
			if ( b0 >= Real(0.0) )
			{
				s = Real(0.0);
				distSqrd = c;
			}
			else if ( -b0 >= a00 )
			{
				s = Real(1.0);
				distSqrd = a00+Real(2.0)*b0+c;
			}
			else
			{
				s = -b0/a00;
				distSqrd = b0*s+c;
			}
		}
		else  // region 0
		{
			// minimum at interior point
			if ( det == Real(0.0) )
			{
				s = Real(0.0);
				t = Real(0.0);
				distSqrd = Imath::limits<Real>::max();
			}
			else
			{
				Real invDet = Real(1.0)/det;
				s *= invDet;
				t *= invDet;
				distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
				           t*(a01*s+a11*t+Real(2.0)*b1)+c;
			}
		}
	}
	else
	{
		Real tmp0, tmp1, numer, denom;

		if ( s < Real(0.0) )  // region 2
		{
			tmp0 = a01 + b0;
			tmp1 = a11 + b1;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					s = Real(1.0);
					t = Real(0.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else
				{
					s = numer/denom;
					t = Real(1.0) - s;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
			else
			{
				s = Real(0.0);
				if ( tmp1 <= Real(0.0) )
				{
					t = Real(1.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else if ( b1 >= Real(0.0) )
				{
					t = Real(0.0);
					distSqrd = c;
				}
				else
				{
					t = -b1/a11;
					distSqrd = b1*t+c;
				}
			}
		}
		else if ( t < Real(0.0) )  // region 6
		{
			tmp0 = a01 + b1;
			tmp1 = a00 + b0;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					t = Real(1.0);
					s = Real(0.0);
					distSqrd = a11+Real(2.0)*b1+c;
				}
				else
				{
					t = numer/denom;
					s = Real(1.0) - t;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
			else
			{
				t = Real(0.0);
				if ( tmp1 <= Real(0.0) )
				{
					s = Real(1.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else if ( b0 >= Real(0.0) )
				{
					s = Real(0.0);
					distSqrd = c;
				}
				else
				{
					s = -b0/a00;
					distSqrd = b0*s+c;
				}
			}
		}
		else  // region 1
		{
			numer = a11 + b1 - a01 - b0;
			if ( numer <= Real(0.0) )
			{
				s = Real(0.0);
				t = Real(1.0);
				distSqrd = a11+Real(2.0)*b1+c;
			}
			else
			{
				denom = a00-Real(2.0)*a01+a11;
				if ( numer >= denom )
				{
					s = Real(1.0);
					t = Real(0.0);
					distSqrd = a00+Real(2.0)*b0+c;
				}
				else
				{
					s = numer/denom;
					t = Real(1.0) - s;
					distSqrd = s*(a00*s+a01*t+Real(2.0)*b0) +
					           t*(a01*s+a11*t+Real(2.0)*b1)+c;
				}
			}
		}
	}

	barycentric.y = s;
	barycentric.z = t;
	barycentric.x = 1 - s - t;

	return Real(fabs(distSqrd));
}

template<class Vec>
Vec triangleClosestPoint( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p, Imath::Vec3<typename VectorTraits<Vec>::BaseType> &barycentric )
{
	triangleClosestBarycentric( v0, v1, v2, p, barycentric );
	return trianglePoint( v0, v1, v2, barycentric );
}

template<class Vec>
int triangleBarycentricFeature( const Vec &barycentric, typename VectorTraits<Vec>::BaseType tolerance )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	bool bx = VectorTraits<Vec>::get( barycentric, 0 ) > tolerance;
	bool by = VectorTraits<Vec>::get( barycentric, 1 ) > tolerance;
	bool bz = VectorTraits<Vec>::get( barycentric, 2 ) > tolerance;

	if (bx && by && bz)
	{
		return 0;
	}
	else if (bx && by)
	{
		return 5;
	}
	else if (bx && bz)
	{
		return 3;
	}
	else if (by && bz)
	{
		return 1;
	}
	else if (bx)
	{
		return 4;
	}
	else if (by)
	{
		return 6;
	}
	else
	{
		assert(bz);
		return 2;
	}
}

template<class Vec>
int triangleClosestFeature( const Vec &v0, const Vec &v1, const Vec &v2, const Vec &p )
{
	typedef typename VectorTraits<Vec>::BaseType Real;

	Imath::Vec3<Real> barycentric;
	triangleClosestPoint( v0, v1, v2, p, barycentric);

	return triangleBarycentricFeature( barycentric );
}

} // namespace IECore

#endif // IECORE_TRIANGLEALGO_INL
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_FRUSTUM_HPP
#define NAZARA_FRUSTUM_HPP

#include <Nazara/Core/String.hpp>
#include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Enums.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/OrientedBox.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Math/Sphere.hpp>
#include <Nazara/Math/Vector3.hpp>

namespace Nz
{
	struct SerializationContext;

	template<typename T>
	class Frustum
	{
		public:
			Frustum() = default;
			template<typename U> explicit Frustum(const Frustum<U>& frustum);
			Frustum(const Frustum& frustum) = default;
			~Frustum() = default;

			Frustum& Build(T angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());

			bool Contains(const BoundingVolume<T>& volume) const;
			bool Contains(const Box<T>& box) const;
			bool Contains(const OrientedBox<T>& orientedBox) const;
			bool Contains(const Sphere<T>& sphere) const;
			bool Contains(const Vector3<T>& point) const;
			bool Contains(const Vector3<T>* points, unsigned int pointCount) const;

			Frustum& Extract(const Matrix4<T>& clipMatrix);
			Frustum& Extract(const Matrix4<T>& view, const Matrix4<T>& projection);

			const Vector3<T>& GetCorner(BoxCorner corner) const;
			const Plane<T>& GetPlane(FrustumPlane plane) const;

			IntersectionSide Intersect(const BoundingVolume<T>& volume) const;
			IntersectionSide Intersect(const Box<T>& box) const;
			IntersectionSide Intersect(const OrientedBox<T>& orientedBox) const;
			IntersectionSide Intersect(const Sphere<T>& sphere) const;
			IntersectionSide Intersect(const Vector3<T>* points, unsigned int pointCount) const;

			Frustum& operator=(const Frustum& other) = default;

			Frustum& Set(const Frustum& frustum);
			template<typename U> Frustum& Set(const Frustum<U>& frustum);

			String ToString() const;

			template<typename U>
			friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum, TypeTag<Frustum<T>>);
			template<typename U>
			friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum, TypeTag<Frustum<T>>);

		private:
			Vector3<T> m_corners[BoxCorner_Max+1];
			Plane<T> m_planes[FrustumPlane_Max+1];
	};

	using Frustumd = Frustum<double>;
	using Frustumf = Frustum<float>;
}

template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Frustum<T>& frustum);

#include <Nazara/Math/Frustum.inl>

#endif // NAZARA_FRUSTUM_HPP
<commit_msg>And fix compilation again<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_FRUSTUM_HPP
#define NAZARA_FRUSTUM_HPP

#include <Nazara/Core/String.hpp>
#include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Enums.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/OrientedBox.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Math/Sphere.hpp>
#include <Nazara/Math/Vector3.hpp>

namespace Nz
{
	struct SerializationContext;

	template<typename T>
	class Frustum
	{
		public:
			Frustum() = default;
			template<typename U> explicit Frustum(const Frustum<U>& frustum);
			Frustum(const Frustum& frustum) = default;
			~Frustum() = default;

			Frustum& Build(T angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());

			bool Contains(const BoundingVolume<T>& volume) const;
			bool Contains(const Box<T>& box) const;
			bool Contains(const OrientedBox<T>& orientedBox) const;
			bool Contains(const Sphere<T>& sphere) const;
			bool Contains(const Vector3<T>& point) const;
			bool Contains(const Vector3<T>* points, unsigned int pointCount) const;

			Frustum& Extract(const Matrix4<T>& clipMatrix);
			Frustum& Extract(const Matrix4<T>& view, const Matrix4<T>& projection);

			const Vector3<T>& GetCorner(BoxCorner corner) const;
			const Plane<T>& GetPlane(FrustumPlane plane) const;

			IntersectionSide Intersect(const BoundingVolume<T>& volume) const;
			IntersectionSide Intersect(const Box<T>& box) const;
			IntersectionSide Intersect(const OrientedBox<T>& orientedBox) const;
			IntersectionSide Intersect(const Sphere<T>& sphere) const;
			IntersectionSide Intersect(const Vector3<T>* points, unsigned int pointCount) const;

			Frustum& operator=(const Frustum& other) = default;

			Frustum& Set(const Frustum& frustum);
			template<typename U> Frustum& Set(const Frustum<U>& frustum);

			String ToString() const;

			template<typename U>
			friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum, TypeTag<Frustum<U>>);

			template<typename U>
			friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum, TypeTag<Frustum<U>>);

		private:
			Vector3<T> m_corners[BoxCorner_Max+1];
			Plane<T> m_planes[FrustumPlane_Max+1];
	};

	using Frustumd = Frustum<double>;
	using Frustumf = Frustum<float>;
}

template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Frustum<T>& frustum);

#include <Nazara/Math/Frustum.inl>

#endif // NAZARA_FRUSTUM_HPP
<|endoftext|>


<commit_before>/**
 * \file
 * \brief Semaphore class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-10-27
 */

#ifndef INCLUDE_DISTORTOS_SEMAPHORE_HPP_
#define INCLUDE_DISTORTOS_SEMAPHORE_HPP_

#include "distortos/scheduler/ThreadControlBlockList.hpp"

namespace distortos
{

/**
 * \brief Semaphore is the basic synchronization primitive
 *
 * Similar to POSIX semaphores - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
 */

class Semaphore
{
public:

	/**
	 * \brief Semaphore constructor
	 *
	 * Similar to sem_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html#
	 *
	 * \param [in] value is the initial value of the semaphore
	 */

	Semaphore(int value);

	/**
	 * \brief Semaphore destructor
	 *
	 * Similar to sem_destroy() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html#
	 *
	 * It is safe to destroy a semaphore upon which no threads are currently blocked. The effect of destroying a
	 * semaphore upon which other threads are currently blocked is system error.
	 */

	~Semaphore();

	/**
	 * \brief Gets current value of semaphore.
	 *
	 * Similar to sem_getvalue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html#
	 *
	 * \return current value of semaphore, positive value if semaphore is not locked, negative value or zero otherwise;
	 * negative value represents the number of threads waiting on this semaphore
	 */

	int getValue() const { return value_; }

	/**
	 * \brief Unlocks the semaphore.
	 *
	 * Similar to sem_post() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html#
	 *
	 * This function shall unlock the semaphore by performing a semaphore unlock operation. If the semaphore value
	 * resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become
	 * unlocked; the semaphore value is simply incremented. Otherwise one of the threads blocked waiting for the
	 * semaphore shall be allowed to return successfully from its call to lock() - the highest priority waiting thread
	 * shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then
	 * the highest priority thread that has been waiting the longest shall be unblocked.
	 */

	void post();

	/**
	 * \brief Tries to lock the semaphore.
	 *
	 * Similar to sem_trywait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore only if the semaphore is currently not locked; that is, if the semaphore
	 * value is currently positive. Otherwise, it shall not lock the semaphore. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation,
	 * - EDEADLK - a deadlock condition was detected,
	 * - EINTR - a signal interrupted this function;
	 */

	int tryWait();

	/**
	 * \brief Locks the semaphore.
	 *
	 * Similar to sem_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore by performing a semaphore lock operation on that semaphore. If the
	 * semaphore value is currently zero, then the calling thread shall not return from the call to lock() until it
	 * either locks the semaphore or the call is interrupted by a signal. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EDEADLK - a deadlock condition was detected,
	 * - EINTR - a signal interrupted this function;
	 */

	int wait();

private:

	/// ThreadControlBlock objects blocked on this semaphore
	scheduler::ThreadControlBlockList blockedList_;

	/// internal value of the semaphore
	int value_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SEMAPHORE_HPP_
<commit_msg>Semaphore: fix formatting of Semaphore::getValue()<commit_after>/**
 * \file
 * \brief Semaphore class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-11-18
 */

#ifndef INCLUDE_DISTORTOS_SEMAPHORE_HPP_
#define INCLUDE_DISTORTOS_SEMAPHORE_HPP_

#include "distortos/scheduler/ThreadControlBlockList.hpp"

namespace distortos
{

/**
 * \brief Semaphore is the basic synchronization primitive
 *
 * Similar to POSIX semaphores - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
 */

class Semaphore
{
public:

	/**
	 * \brief Semaphore constructor
	 *
	 * Similar to sem_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html#
	 *
	 * \param [in] value is the initial value of the semaphore
	 */

	Semaphore(int value);

	/**
	 * \brief Semaphore destructor
	 *
	 * Similar to sem_destroy() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html#
	 *
	 * It is safe to destroy a semaphore upon which no threads are currently blocked. The effect of destroying a
	 * semaphore upon which other threads are currently blocked is system error.
	 */

	~Semaphore();

	/**
	 * \brief Gets current value of semaphore.
	 *
	 * Similar to sem_getvalue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html#
	 *
	 * \return current value of semaphore, positive value if semaphore is not locked, negative value or zero otherwise;
	 * negative value represents the number of threads waiting on this semaphore
	 */

	int getValue() const
	{
		return value_;
	}

	/**
	 * \brief Unlocks the semaphore.
	 *
	 * Similar to sem_post() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html#
	 *
	 * This function shall unlock the semaphore by performing a semaphore unlock operation. If the semaphore value
	 * resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become
	 * unlocked; the semaphore value is simply incremented. Otherwise one of the threads blocked waiting for the
	 * semaphore shall be allowed to return successfully from its call to lock() - the highest priority waiting thread
	 * shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then
	 * the highest priority thread that has been waiting the longest shall be unblocked.
	 */

	void post();

	/**
	 * \brief Tries to lock the semaphore.
	 *
	 * Similar to sem_trywait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore only if the semaphore is currently not locked; that is, if the semaphore
	 * value is currently positive. Otherwise, it shall not lock the semaphore. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation,
	 * - EDEADLK - a deadlock condition was detected,
	 * - EINTR - a signal interrupted this function;
	 */

	int tryWait();

	/**
	 * \brief Locks the semaphore.
	 *
	 * Similar to sem_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore by performing a semaphore lock operation on that semaphore. If the
	 * semaphore value is currently zero, then the calling thread shall not return from the call to lock() until it
	 * either locks the semaphore or the call is interrupted by a signal. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return zero if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EDEADLK - a deadlock condition was detected,
	 * - EINTR - a signal interrupted this function;
	 */

	int wait();

private:

	/// ThreadControlBlock objects blocked on this semaphore
	scheduler::ThreadControlBlockList blockedList_;

	/// internal value of the semaphore
	int value_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SEMAPHORE_HPP_
<|endoftext|>


<commit_before>#include "visitors.hpp"
#include "skeletons.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
#include <tuple>
#include <cmath>

using namespace std;

///////////////////////////////////////////////////////////////////////////////

template <typename Visitor, typename BinaryOp>
double compute(Visitor& v, skel_node& n, BinaryOp op) {
    double ts = 0;
    for (size_t i = 0; i < n.size() ; i++)
        ts = op(ts, v(*n.get(i)));
    return ts;
}

///////////////////////////////////////////////////////////////////////////////

servicetime::servicetime(rpl_environment& env)
    : env(env) {}

void servicetime::visit(seq_node& n) {
    res = n.servicetime;
}

void servicetime::visit(comp_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void servicetime::visit(pipe_node& n) {
    res = compute(*this, n, [](double a, double b){return std::max(a, b);});
}

void servicetime::visit(farm_node& n) {
    res = (*this)(*n.get(0)) / n.pardegree;
}

void servicetime::visit(map_node& n) {
    res = (*this)(*n.get(0)) / n.pardegree;
}

// TODO WRONG -> for reduce is important the dim of input
void servicetime::visit(reduce_node& n) {
    res = log2( (*this)(*n.get(0)) );
}

void servicetime::visit(id_node& n) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(*ptr);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string servicetime::print( skel_node& sk ){
    return std::to_string( (*this)( sk ) );
}

double servicetime::operator()(skel_node& sk){
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

latencytime::latencytime(rpl_environment& env)
    : env( env ) {}

void latencytime::visit(seq_node& n) {
    res = n.servicetime;
}

void latencytime::visit(comp_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void latencytime::visit(pipe_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void latencytime::visit(farm_node& n) {
    res = (*this)( *n.get(0) );
}

void latencytime::visit(map_node& n) {
    res = (*this)( *n.get(0) ) / n.pardegree;
}

// TODO WRONG -> for reduce is important the dim of input
void latencytime::visit(reduce_node& n) {
    res = log2( (*this)( *n.get(0) ) );
}

void latencytime::visit(id_node& n) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string latencytime::print( skel_node& sk ){
    return std::to_string( (*this)( sk ) );
}

double latencytime::operator()(skel_node& sk){
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

// TODO here the stream size is something "global"
// user should set it through some shell verbs
// like "set_dimension(_)" and get with "get_dimension"
// better ideas?

completiontime::completiontime( rpl_environment& env ) :
    lat( env ), ts( env ), env( env )
{}

void completiontime::visit( seq_node& n ) {
    res = n.servicetime;
}

void completiontime::visit( comp_node& n ) {
    res = compute(*this, n, std::plus<double>());
}

void completiontime::visit( pipe_node& n ) {
    /* latency of the first stage + ts*dimension */
    res = lat(*n.get(0)) + env.get_dim() * ts(n);
}

void completiontime::visit( farm_node& n ) {
    res = env.get_dim() / n.pardegree * lat(n);
}

void completiontime::visit( map_node& n ) {
    res = env.get_dim() / n.pardegree * ts(n);
}

void completiontime::visit( reduce_node& n ) {
    res = lat(n);
}

void completiontime::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string completiontime::print( skel_node& n ){
    return std::to_string( (*this)( n ));;
}

double completiontime::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

pardegree::pardegree( rpl_environment& env ) :
    env( env )
{}

void pardegree::visit( seq_node& n ) {
    res = 1;
}

void pardegree::visit( comp_node& n ) {
    res = compute(*this, n, [](double a, double b){return std::max(a, b);});
}

void pardegree::visit( pipe_node& n ) {
    res = compute(*this, n, std::plus<size_t>());
}

void pardegree::visit( farm_node& n ) {
    res = n.pardegree * (*this)(*n.get(0));
}

void pardegree::visit( map_node& n ) {
    res = n.pardegree * (*this)(*n.get(0));
}

// TODO also reduce should be have a configurable
// parallelism degree like farm and map!!
void pardegree::visit( reduce_node& n ) {
    res = 1;
}

void pardegree::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string pardegree::print( skel_node& n ){
    return std::to_string( (*this)( n ) );;
}

size_t pardegree::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

resources::resources( rpl_environment& env ) :
    env( env )
{}

void resources::visit( seq_node& n ) {
    res = 1;
}

void resources::visit( comp_node& n ) {
    res = compute(*this, n, [](size_t a, size_t b){return std::max(a, b);});
}

void resources::visit( pipe_node& n ) {
    res = compute(*this, n, std::plus<size_t>());
}

void resources::visit( farm_node& n ) {
    res = n.pardegree * (*this)(*n.get(0)) + 2;  //emitter + collector
}

void resources::visit( map_node& n ) {
    res = n.pardegree * (*this)(*n.get(0)) + 2;  //scatter + gather
}

// TODO also reduce should be have a configurable
// parallelism degree like farm and map!!
void resources::visit( reduce_node& n ) {
    res = 1;
}

void resources::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string resources::print( skel_node& n ){
    return std::to_string( (*this)( n ) );;
}

size_t resources::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

void printer::tostring(const string& name, const skel_node& n) {
    res += name + "(";
    for (size_t i = 0; i < n.size(); i++) {
        n.get(i)->accept(*this);
        res += (i != n.size()-1 ? "," : "");
    }
    res += ")";
}

void printer::visit(seq_node& n) {
    tostring("seq", n);
}

void printer::visit(comp_node& n) {
    tostring("comp", n);
}

void printer::visit(pipe_node& n) {
    tostring("pipe", n);
}

void printer::visit(farm_node& n) {
    tostring("farm", n);
}

void printer::visit(map_node& n) {
    tostring("map", n);
}

void printer::visit(reduce_node& n) {
    tostring("reduce", n);
}

void printer::visit(id_node& n) {
    res += n.id;
}

string printer::print( skel_node& sk ){
    return (*this)( sk );
}

string printer::operator()(skel_node& sk){
    res.clear();
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

void label_printer::visit( seq_node& n ) {
    str = "seq";
}

void label_printer::visit( comp_node& n ) {
    str = "comp";
}

void label_printer::visit( pipe_node& n ) {
    str = "pipe";
}

void label_printer::visit( farm_node& n ) {
    str = "farm";
}

void label_printer::visit( map_node& n ) {
    str = "map";
}

void label_printer::visit( reduce_node& n ) {
    str = "reduce";
}

void label_printer::visit( id_node& n ) {
    str = n.id;
}

string label_printer::operator()( skel_node& sk ) {
    sk.accept(*this);
    return str;
}

///////////////////////////////////////////////////////////////////////////////

void single_node_cloner::visit( seq_node& n ) {
    tmp = new seq_node(n);
}

void single_node_cloner::visit( comp_node& n ) {
    tmp = new comp_node{};
}

void single_node_cloner::visit( pipe_node& n ) {
    tmp = new pipe_node{};
}

void single_node_cloner::visit( farm_node& n ) {
    tmp = new farm_node{};
}

void single_node_cloner::visit( map_node& n ) {
    tmp = new map_node{};
}

void single_node_cloner::visit( reduce_node& n ) {
    tmp = new reduce_node{};
}

void single_node_cloner::visit( id_node& n ) {
    tmp = new id_node(n.id);
}

skel_node* single_node_cloner::operator()( skel_node& sk ) {
    sk.accept(*this);
    return tmp;
}

///////////////////////////////////////////////////////////////////////////////

reduce_resources::reduce_resources( rpl_environment& env ) :
    ts(env), getres(env)
{}

void reduce_resources::visit( seq_node& n ) {
    res = false;
}

typedef std::tuple<skel_node*, double, size_t> sds_t;

template < typename triples_container >
void fill_triples( triples_container& triples, skel_node& n, servicetime& ts, resources& res ) {
    for (size_t i = 0; i < n.size(); i++) {
        triples.push_back( make_tuple(
            n.get(i),
            ts ( *n.get(i) ),
            res( *n.get(i) )
        ) );
    }
}

void reduce_resources::visit( comp_node& n ) {

    std::vector<sds_t> triples;
    fill_triples( triples, n, ts, getres );

    sort (triples.begin(), triples.end(), [](const sds_t& a, const sds_t& b) {
        if (get<2>(a) == get<2>(b))
            return get<1>(b) < get<1>(a);
        return get<2>(a) > get<2>(b);
    });

    for ( auto it = triples.begin(); it != triples.end() && !res; it++ )
        (*this)( *get<0>(*it) );
}

void reduce_resources::visit( pipe_node& n ) {

    std::vector<sds_t> triples;
    fill_triples( triples, n, ts, getres );

    sort (triples.begin(), triples.end(), [](const sds_t& a, const sds_t& b) {
        if (get<1>(a) == get<1>(b))
            return get<2>(b) < get<2>(a);
        return get<1>(a) < get<1>(b);
    });

    for ( auto it = triples.begin(); it != triples.end() && !res; it++ )
        (*this)( *get<0>(*it) );
}

void reduce_resources::visit( farm_node& n ) {
    res = n.pardegree > 1;
    if ( res )
        n.pardegree--;
    else
        (*this)( *n.get(0) );
}

void reduce_resources::visit( map_node& n ) {
    res = n.pardegree > 1;
    if ( res )
        n.pardegree--;
    else
        (*this)( *n.get(0) );
}

void reduce_resources::visit( reduce_node& n ) {
    res = false;
}

void reduce_resources::visit( id_node& n ) {
    res = false;
}

bool reduce_resources::operator()(skel_node& n) {
    res = false;
    n.accept(*this);
    return res;
}
<commit_msg>fixed visit the id_node in resources<commit_after>#include "visitors.hpp"
#include "skeletons.hpp"
#include <iostream>
#include <functional>
#include <algorithm>
#include <tuple>
#include <cmath>

using namespace std;

///////////////////////////////////////////////////////////////////////////////

template <typename Visitor, typename BinaryOp>
double compute(Visitor& v, skel_node& n, BinaryOp op) {
    double ts = 0;
    for (size_t i = 0; i < n.size() ; i++)
        ts = op(ts, v(*n.get(i)));
    return ts;
}

///////////////////////////////////////////////////////////////////////////////

servicetime::servicetime(rpl_environment& env)
    : env(env) {}

void servicetime::visit(seq_node& n) {
    res = n.servicetime;
}

void servicetime::visit(comp_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void servicetime::visit(pipe_node& n) {
    res = compute(*this, n, [](double a, double b){return std::max(a, b);});
}

void servicetime::visit(farm_node& n) {
    res = (*this)(*n.get(0)) / n.pardegree;
}

void servicetime::visit(map_node& n) {
    res = (*this)(*n.get(0)) / n.pardegree;
}

// TODO WRONG -> for reduce is important the dim of input
void servicetime::visit(reduce_node& n) {
    res = log2( (*this)(*n.get(0)) );
}

void servicetime::visit(id_node& n) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(*ptr);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string servicetime::print( skel_node& sk ){
    return std::to_string( (*this)( sk ) );
}

double servicetime::operator()(skel_node& sk){
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

latencytime::latencytime(rpl_environment& env)
    : env( env ) {}

void latencytime::visit(seq_node& n) {
    res = n.servicetime;
}

void latencytime::visit(comp_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void latencytime::visit(pipe_node& n) {
    res = compute(*this, n, std::plus<double>());
}

void latencytime::visit(farm_node& n) {
    res = (*this)( *n.get(0) );
}

void latencytime::visit(map_node& n) {
    res = (*this)( *n.get(0) ) / n.pardegree;
}

// TODO WRONG -> for reduce is important the dim of input
void latencytime::visit(reduce_node& n) {
    res = log2( (*this)( *n.get(0) ) );
}

void latencytime::visit(id_node& n) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string latencytime::print( skel_node& sk ){
    return std::to_string( (*this)( sk ) );
}

double latencytime::operator()(skel_node& sk){
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

// TODO here the stream size is something "global"
// user should set it through some shell verbs
// like "set_dimension(_)" and get with "get_dimension"
// better ideas?

completiontime::completiontime( rpl_environment& env ) :
    lat( env ), ts( env ), env( env )
{}

void completiontime::visit( seq_node& n ) {
    res = n.servicetime;
}

void completiontime::visit( comp_node& n ) {
    res = compute(*this, n, std::plus<double>());
}

void completiontime::visit( pipe_node& n ) {
    /* latency of the first stage + ts*dimension */
    res = lat(*n.get(0)) + env.get_dim() * ts(n);
}

void completiontime::visit( farm_node& n ) {
    res = env.get_dim() / n.pardegree * lat(n);
}

void completiontime::visit( map_node& n ) {
    res = env.get_dim() / n.pardegree * ts(n);
}

void completiontime::visit( reduce_node& n ) {
    res = lat(n);
}

void completiontime::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string completiontime::print( skel_node& n ){
    return std::to_string( (*this)( n ));;
}

double completiontime::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

pardegree::pardegree( rpl_environment& env ) :
    env( env )
{}

void pardegree::visit( seq_node& n ) {
    res = 1;
}

void pardegree::visit( comp_node& n ) {
    res = compute(*this, n, [](double a, double b){return std::max(a, b);});
}

void pardegree::visit( pipe_node& n ) {
    res = compute(*this, n, std::plus<size_t>());
}

void pardegree::visit( farm_node& n ) {
    res = n.pardegree * (*this)(*n.get(0));
}

void pardegree::visit( map_node& n ) {
    res = n.pardegree * (*this)(*n.get(0));
}

// TODO also reduce should be have a configurable
// parallelism degree like farm and map!!
void pardegree::visit( reduce_node& n ) {
    res = 1;
}

void pardegree::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(n);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string pardegree::print( skel_node& n ){
    return std::to_string( (*this)( n ) );;
}

size_t pardegree::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

resources::resources( rpl_environment& env ) :
    env( env )
{}

void resources::visit( seq_node& n ) {
    res = 1;
}

void resources::visit( comp_node& n ) {
    res = compute(*this, n, [](size_t a, size_t b){return std::max(a, b);});
}

void resources::visit( pipe_node& n ) {
    res = compute(*this, n, std::plus<size_t>());
}

void resources::visit( farm_node& n ) {
    res = n.pardegree * (*this)(*n.get(0)) + 2;  //emitter + collector
}

void resources::visit( map_node& n ) {
    res = n.pardegree * (*this)(*n.get(0)) + 2;  //scatter + gather
}

// TODO also reduce should be have a configurable
// parallelism degree like farm and map!!
void resources::visit( reduce_node& n ) {
    res = 1;
}

void resources::visit( id_node& n ) {
    try {
        auto ptr = env.get(n.id);
        res = (*this)(*ptr);
    } catch (out_of_range& e) {
        //TODO handle in a better way
        cout << "error, not found: " << n.id << endl;
    }
}

string resources::print( skel_node& n ){
    return std::to_string( (*this)( n ) );;
}

size_t resources::operator()(skel_node& n){
    n.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

void printer::tostring(const string& name, const skel_node& n) {
    res += name + "(";
    for (size_t i = 0; i < n.size(); i++) {
        n.get(i)->accept(*this);
        res += (i != n.size()-1 ? "," : "");
    }
    res += ")";
}

void printer::visit(seq_node& n) {
    tostring("seq", n);
}

void printer::visit(comp_node& n) {
    tostring("comp", n);
}

void printer::visit(pipe_node& n) {
    tostring("pipe", n);
}

void printer::visit(farm_node& n) {
    tostring("farm", n);
}

void printer::visit(map_node& n) {
    tostring("map", n);
}

void printer::visit(reduce_node& n) {
    tostring("reduce", n);
}

void printer::visit(id_node& n) {
    res += n.id;
}

string printer::print( skel_node& sk ){
    return (*this)( sk );
}

string printer::operator()(skel_node& sk){
    res.clear();
    sk.accept(*this);
    return res;
}

///////////////////////////////////////////////////////////////////////////////

void label_printer::visit( seq_node& n ) {
    str = "seq";
}

void label_printer::visit( comp_node& n ) {
    str = "comp";
}

void label_printer::visit( pipe_node& n ) {
    str = "pipe";
}

void label_printer::visit( farm_node& n ) {
    str = "farm";
}

void label_printer::visit( map_node& n ) {
    str = "map";
}

void label_printer::visit( reduce_node& n ) {
    str = "reduce";
}

void label_printer::visit( id_node& n ) {
    str = n.id;
}

string label_printer::operator()( skel_node& sk ) {
    sk.accept(*this);
    return str;
}

///////////////////////////////////////////////////////////////////////////////

void single_node_cloner::visit( seq_node& n ) {
    tmp = new seq_node(n);
}

void single_node_cloner::visit( comp_node& n ) {
    tmp = new comp_node{};
}

void single_node_cloner::visit( pipe_node& n ) {
    tmp = new pipe_node{};
}

void single_node_cloner::visit( farm_node& n ) {
    tmp = new farm_node{};
}

void single_node_cloner::visit( map_node& n ) {
    tmp = new map_node{};
}

void single_node_cloner::visit( reduce_node& n ) {
    tmp = new reduce_node{};
}

void single_node_cloner::visit( id_node& n ) {
    tmp = new id_node(n.id);
}

skel_node* single_node_cloner::operator()( skel_node& sk ) {
    sk.accept(*this);
    return tmp;
}

///////////////////////////////////////////////////////////////////////////////

reduce_resources::reduce_resources( rpl_environment& env ) :
    ts(env), getres(env)
{}

void reduce_resources::visit( seq_node& n ) {
    res = false;
}

typedef std::tuple<skel_node*, double, size_t> sds_t;

template < typename triples_container >
void fill_triples( triples_container& triples, skel_node& n, servicetime& ts, resources& res ) {
    for (size_t i = 0; i < n.size(); i++) {
        triples.push_back( make_tuple(
            n.get(i),
            ts ( *n.get(i) ),
            res( *n.get(i) )
        ) );
    }
}

void reduce_resources::visit( comp_node& n ) {

    std::vector<sds_t> triples;
    fill_triples( triples, n, ts, getres );

    sort (triples.begin(), triples.end(), [](const sds_t& a, const sds_t& b) {
        if (get<2>(a) == get<2>(b))
            return get<1>(b) < get<1>(a);
        return get<2>(a) > get<2>(b);
    });

    for ( auto it = triples.begin(); it != triples.end() && !res; it++ )
        (*this)( *get<0>(*it) );
}

void reduce_resources::visit( pipe_node& n ) {

    std::vector<sds_t> triples;
    fill_triples( triples, n, ts, getres );

    sort (triples.begin(), triples.end(), [](const sds_t& a, const sds_t& b) {
        if (get<1>(a) == get<1>(b))
            return get<2>(b) < get<2>(a);
        return get<1>(a) < get<1>(b);
    });

    for ( auto it = triples.begin(); it != triples.end() && !res; it++ )
        (*this)( *get<0>(*it) );
}

void reduce_resources::visit( farm_node& n ) {
    res = n.pardegree > 1;
    if ( res )
        n.pardegree--;
    else
        (*this)( *n.get(0) );
}

void reduce_resources::visit( map_node& n ) {
    res = n.pardegree > 1;
    if ( res )
        n.pardegree--;
    else
        (*this)( *n.get(0) );
}

void reduce_resources::visit( reduce_node& n ) {
    res = false;
}

void reduce_resources::visit( id_node& n ) {
    res = false;
}

bool reduce_resources::operator()(skel_node& n) {
    res = false;
    n.accept(*this);
    return res;
}
<|endoftext|>


<commit_before>#include "player.hpp"

#include <SFML/System/Time.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window/Keyboard.hpp>

#include <fstream>
#include <sstream>

//#define NDEBUG
#include <assert.h>

namespace aw
{
	void Player::upate(const sf::Time &frameTime)
	{
		//let the gravitation do his work
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
		{
			m_speed.y -= 1.5f * (m_gravitation * frameTime.asSeconds());
		}
		else
		{
			m_speed.y += (m_gravitation * frameTime.asSeconds());
		}
		//update the position
		sf::Vector2f unitSpeed = m_speed / std::sqrt((m_speed.x * m_speed.x) + (m_speed.y * m_speed.y));
		m_position.x += (m_speed.x * frameTime.asSeconds() * unitSpeed.x);
		m_position.y += (m_speed.x * frameTime.asSeconds() * unitSpeed.y);
		//update the body
		updateBody();
	}

	void Player::render(sf::RenderWindow &window)
	{
		window.draw(&m_body[0], 3, sf::Triangles);
	}

	void Player::loadInformation(const std::string &path)
	{
		std::fstream file(path.c_str(), std::ios::in);

		std::string line;
		while (std::getline(file, line))
		{
			if (line == "[Start speed]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				float startSpeed;
				sstr >> startSpeed;
				m_speed.x = startSpeed;
				m_startXSpeed = m_speed.x;
			}
			else if (line == "[Start Gravitation]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				float startGravitation;
				sstr >> startGravitation;
				m_gravitation = startGravitation;
				m_startGravitation = startGravitation;
			}
			else if (line == "[Start Position]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				sf::Vector2f startPosition;
				sstr >> startPosition.x >> startPosition.y;
				m_position = startPosition * 25.f; // *25 because of the block size...
				m_startPosition = m_position;
			}
		}

		m_bodyColor = sf::Color::White;

		file.close();
	}

	void Player::resetToStartSettings()
	{
		m_position = m_startPosition;
		m_speed.x = m_startXSpeed;
		m_speed.y = 0;
		m_gravitation = m_startGravitation;

		updateBody();
	}

	void Player::setPosition(const sf::Vector2f &position)
	{
		m_position = position;
	}

	void Player::setSpeedX(float xSpeed)
	{
		m_speed.x = xSpeed;
	}

	void Player::setGravitation(float gravitation)
	{
		m_gravitation = gravitation;
	}

	void Player::setColor(const sf::Color &color)
	{
		m_bodyColor = color;
	}

	float Player::getXPosition() const
	{
		return m_position.x;
	}
	const sf::Vector2f &Player::getPosition() const
	{
		return m_position;
	}

	sf::Vector2f Player::getVertexPosition(std::size_t index) const
	{
		if (index < 3)
		{
			return m_body[index].position;
		}
		assert(index < 3);
		return sf::Vector2f(-1,-1);
	}

	void Player::updateBody()
	{
		//Size of the "ship"
		float sizeX = 20;
		float halfSizeY = 6;
		//Needed to calculate the rotation of the triangle
		sf::Vector2f unitSpeed = m_speed / std::sqrt((m_speed.x * m_speed.x) + (m_speed.y * m_speed.y));

		m_body[0] = sf::Vertex(sf::Vector2f(m_position.x + (sizeX * unitSpeed.x), m_position.y + (sizeX * unitSpeed.y)), m_bodyColor);
		m_body[1] = sf::Vertex(sf::Vector2f(m_position.x + (halfSizeY * unitSpeed.y), m_position.y + (halfSizeY * -unitSpeed.x)), m_bodyColor);
		m_body[2] = sf::Vertex(sf::Vector2f(m_position.x + -(halfSizeY * unitSpeed.y), m_position.y + -(halfSizeY * -unitSpeed.x)), m_bodyColor);
	}
}<commit_msg>Revert "Fixed a out of bounds vector bug"<commit_after>#include "player.hpp"

#include <SFML/System/Time.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window/Keyboard.hpp>

#include <fstream>
#include <sstream>

//#define NDEBUG
#include <assert.h>

namespace aw
{
	void Player::upate(const sf::Time &frameTime)
	{
		//let the gravitation do his work
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
		{
			m_speed.y -= 1.5f * (m_gravitation * frameTime.asSeconds());
		}
		else
		{
			m_speed.y += (m_gravitation * frameTime.asSeconds());
		}
		//update the position
		m_position += (m_speed * frameTime.asSeconds());
		//update the body
		updateBody();
	}

	void Player::render(sf::RenderWindow &window)
	{
		window.draw(&m_body[0], 3, sf::Triangles);
	}

	void Player::loadInformation(const std::string &path)
	{
		std::fstream file(path.c_str(), std::ios::in);

		std::string line;
		while (std::getline(file, line))
		{
			if (line == "[Start speed]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				float startSpeed;
				sstr >> startSpeed;
				m_speed.x = startSpeed;
				m_startXSpeed = m_speed.x;
			}
			else if (line == "[Start Gravitation]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				float startGravitation;
				sstr >> startGravitation;
				m_gravitation = startGravitation;
				m_startGravitation = startGravitation;
			}
			else if (line == "[Start Position]")
			{
				std::getline(file, line);
				std::stringstream sstr(line);
				sf::Vector2f startPosition;
				sstr >> startPosition.x >> startPosition.y;
				m_position = startPosition * 25.f; // *25 because of the block size...
				m_startPosition = m_position;
			}
		}

		m_bodyColor = sf::Color::White;

		file.close();
	}

	void Player::resetToStartSettings()
	{
		m_position = m_startPosition;
		m_speed.x = m_startXSpeed;
		m_speed.y = 0;
		m_gravitation = m_startGravitation;

		updateBody();
	}

	void Player::setPosition(const sf::Vector2f &position)
	{
		m_position = position;
	}

	void Player::setSpeedX(float xSpeed)
	{
		m_speed.x = xSpeed;
	}

	void Player::setGravitation(float gravitation)
	{
		m_gravitation = gravitation;
	}

	void Player::setColor(const sf::Color &color)
	{
		m_bodyColor = color;
	}

	float Player::getXPosition() const
	{
		return m_position.x;
	}
	const sf::Vector2f &Player::getPosition() const
	{
		return m_position;
	}

	sf::Vector2f Player::getVertexPosition(std::size_t index) const
	{
		if (index < 3)
		{
			return m_body[index].position;
		}
		assert(index < 3);
		return sf::Vector2f(-1,-1);
	}

	void Player::updateBody()
	{
		//Size of the "ship"
		float sizeX = 20;
		float halfSizeY = 6;
		//Needed to calculate the rotation of the triangle
		sf::Vector2f unitSpeed = m_speed / std::sqrt((m_speed.x * m_speed.x) + (m_speed.y * m_speed.y));

		m_body[0] = sf::Vertex(sf::Vector2f(m_position.x + (sizeX * unitSpeed.x), m_position.y + (sizeX * unitSpeed.y)), m_bodyColor);
		m_body[1] = sf::Vertex(sf::Vector2f(m_position.x + (halfSizeY * unitSpeed.y), m_position.y + (halfSizeY * -unitSpeed.x)), m_bodyColor);
		m_body[2] = sf::Vertex(sf::Vector2f(m_position.x + -(halfSizeY * unitSpeed.y), m_position.y + -(halfSizeY * -unitSpeed.x)), m_bodyColor);
	}
}<|endoftext|>


<commit_before>///
/// @file  primecount-internal.hpp
/// @brief primecount internal functions
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_INTERNAL_HPP
#define PRIMECOUNT_INTERNAL_HPP

#include <int128_t.hpp>

#include <stdint.h>
#include <algorithm>
#include <string>

namespace primecount {

template<class T>
void unused_param(const T&)
{ }

std::string pi(const std::string& x, int threads);

int64_t pi(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi(int128_t x);

int128_t pi(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x);

int128_t pi_deleglise_rivat(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat1(int64_t x);

int64_t pi_deleglise_rivat2(int64_t x);

int64_t pi_deleglise_rivat_parallel1(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat_parallel2(int128_t x, int threads);

#endif

int64_t pi_legendre(int64_t x, int threads);

int64_t pi_lehmer(int64_t x, int threads);

int64_t pi_lehmer2(int64_t x, int threads);

int64_t pi_lmo(int64_t x, int threads);

int64_t pi_lmo1(int64_t x);

int64_t pi_lmo2(int64_t x);

int64_t pi_lmo3(int64_t x);

int64_t pi_lmo4(int64_t x);

int64_t pi_lmo5(int64_t x);

int64_t pi_lmo_parallel(int64_t x, int threads);

int64_t pi_meissel(int64_t x, int threads);

int64_t phi(int64_t x, int64_t a, int threads);

int64_t Li(int64_t);

int64_t Li_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Li(int128_t);

int128_t Li_inverse(int128_t);

#endif

int64_t Ri(int64_t);

int64_t Ri_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Ri(int128_t);

int128_t Ri_inverse(int128_t);

#endif

int64_t nth_prime(int64_t n, int threads);

int64_t P2(int64_t x, int64_t y, int threads);

int64_t P3(int64_t x, int64_t a, int threads);

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads);

#endif

void set_status_precision(int precision);

int get_status_precision(maxint_t x);

void set_alpha(double alpha);

double get_alpha();

double get_alpha(maxint_t x, int64_t y);

double get_alpha_lmo(maxint_t x);

double get_alpha_deleglise_rivat(maxint_t x);

double get_alpha_y_gourdon(maxint_t x);

double get_alpha_z_gourdon(double alpha_y);

double get_time();

int ideal_num_threads(int threads, int64_t sieve_limit, int64_t thread_threshold = 100000);

maxint_t to_maxint(const std::string& expr);

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

template <typename T>
double get_percent(T low, T limit)
{
  double percent = (100.0 * low) / std::max<T>(1, limit);
  return in_between(0, percent, 100);
}

template <typename T>
T S2_approx(T x, int64_t pi_y, T P2, T S1)
{
  T pix = Ri(x);
  T S2 = pix - S1 - pi_y + 1 + P2;
  return S2;
}

#ifdef HAVE_MPI

class PiTable;

bool is_mpi_master_proc();
int mpi_num_procs();
int mpi_proc_id();
int mpi_master_proc_id();

int64_t P2_mpi(int64_t x, int64_t y, int threads);

#ifdef HAVE_INT128_T

int128_t P2_mpi(int128_t x, int64_t y, int threads);

#endif

#endif

} // namespace

#endif
<commit_msg>Improve in_between(min, x, max)<commit_after>///
/// @file  primecount-internal.hpp
/// @brief primecount internal functions
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_INTERNAL_HPP
#define PRIMECOUNT_INTERNAL_HPP

#include <int128_t.hpp>

#include <stdint.h>
#include <algorithm>
#include <string>

namespace primecount {

template<class T>
void unused_param(const T&)
{ }

std::string pi(const std::string& x, int threads);

int64_t pi(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi(int128_t x);

int128_t pi(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x);

int128_t pi_deleglise_rivat(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat1(int64_t x);

int64_t pi_deleglise_rivat2(int64_t x);

int64_t pi_deleglise_rivat_parallel1(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat_parallel2(int128_t x, int threads);

#endif

int64_t pi_legendre(int64_t x, int threads);

int64_t pi_lehmer(int64_t x, int threads);

int64_t pi_lehmer2(int64_t x, int threads);

int64_t pi_lmo(int64_t x, int threads);

int64_t pi_lmo1(int64_t x);

int64_t pi_lmo2(int64_t x);

int64_t pi_lmo3(int64_t x);

int64_t pi_lmo4(int64_t x);

int64_t pi_lmo5(int64_t x);

int64_t pi_lmo_parallel(int64_t x, int threads);

int64_t pi_meissel(int64_t x, int threads);

int64_t phi(int64_t x, int64_t a, int threads);

int64_t Li(int64_t);

int64_t Li_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Li(int128_t);

int128_t Li_inverse(int128_t);

#endif

int64_t Ri(int64_t);

int64_t Ri_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Ri(int128_t);

int128_t Ri_inverse(int128_t);

#endif

int64_t nth_prime(int64_t n, int threads);

int64_t P2(int64_t x, int64_t y, int threads);

int64_t P3(int64_t x, int64_t a, int threads);

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads);

#endif

void set_status_precision(int precision);

int get_status_precision(maxint_t x);

void set_alpha(double alpha);

double get_alpha();

double get_alpha(maxint_t x, int64_t y);

double get_alpha_lmo(maxint_t x);

double get_alpha_deleglise_rivat(maxint_t x);

double get_alpha_y_gourdon(maxint_t x);

double get_alpha_z_gourdon(double alpha_y);

double get_time();

int ideal_num_threads(int threads, int64_t sieve_limit, int64_t thread_threshold = 100000);

maxint_t to_maxint(const std::string& expr);

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min || max < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

template <typename T>
double get_percent(T low, T limit)
{
  double percent = (100.0 * low) / std::max<T>(1, limit);
  return in_between(0, percent, 100);
}

template <typename T>
T S2_approx(T x, int64_t pi_y, T P2, T S1)
{
  T pix = Ri(x);
  T S2 = pix - S1 - pi_y + 1 + P2;
  return S2;
}

#ifdef HAVE_MPI

class PiTable;

bool is_mpi_master_proc();
int mpi_num_procs();
int mpi_proc_id();
int mpi_master_proc_id();

int64_t P2_mpi(int64_t x, int64_t y, int threads);

#ifdef HAVE_INT128_T

int128_t P2_mpi(int128_t x, int64_t y, int threads);

#endif

#endif

} // namespace

#endif
<|endoftext|>