text:
#include "by_edges_sssp.hpp"
#include "thread_local_allocator.hpp"
#include <boost/heap/fibonacci_heap.hpp>
#include <iostream>

#if defined(CRAUSER_IN) && defined(CRAUSER_INDYN)
#error CRAUSER_IN and CRAUSER_INDYN cannot be combined
#endif

#if defined(CRAUSER_OUT) && defined(CRAUSER_OUTDYN)
#error CRAUSER_OUT and CRAUSER_OUTDYN cannot be combined
#endif

using namespace boost::heap;

namespace {
enum class state : unsigned char { unexplored, fringe, settled };
}

void sssp::by_edges_sssp::run_collective(thread_group& threads,
                                         int thread_rank,
                                         int group_count,
                                         int group_rank,
                                         thread_group& group_threads,
                                         int group_thread_rank,
                                         size_t node_count,
                                         size_t edge_count,
                                         array_slice<const array_slice<const edge>> thread_edges_by_node,
                                         array_slice<double> out_thread_distances,
                                         array_slice<size_t> out_thread_predecessors) {
    BOOST_ASSERT(node_count == thread_edges_by_node.size());
    BOOST_ASSERT(node_count == out_thread_distances.size());
    BOOST_ASSERT(node_count == out_thread_predecessors.size());
    perf_counter perf;

    perf.first_timeblock("init");
    double time = 0;
    auto distances = out_thread_distances;
    auto predecessors = out_thread_predecessors;
    std::vector<state> states(node_count, state::unexplored);
    std::vector<int> last_updated(node_count, INT_MIN);
    std::vector<size_t, thread_local_allocator<size_t>> updated;
    std::vector<size_t, thread_local_allocator<size_t>> todo;

    auto cmp_distance = [&](size_t a, size_t b) { return distances[a] > distances[b]; };
    using distance_queue_t =
        fibonacci_heap<size_t, compare<decltype(cmp_distance)>, allocator<thread_local_allocator<size_t>>>;
    distance_queue_t distance_queue(cmp_distance);
    carray<distance_queue_t::handle_type> distance_queue_handles(node_count);

    threads.single_collective(
        [&] {
            m_global_distances = carray<std::atomic<double>>(node_count);
            m_global_updated = carray<size_t>(node_count * threads.thread_count());
            m_global_updated_at.store(0, std::memory_order_relaxed);
        },
        true);
    for (size_t i = threads.chunk_start(thread_rank, node_count), end = i + threads.chunk_size(thread_rank, node_count);
         i < end;
         ++i) {
        new (&m_global_distances[i]) std::atomic<double>(INFINITY);
    }
    threads.barrier_collective(true);

#if defined(CRAUSER_OUT)
    carray<double> min_outgoing(node_count);
    auto min_outgoing_value = [&](size_t n) { return min_outgoing[n]; };
    auto cmp_crauser_out = [&](size_t a, size_t b) {
        return distances[a] + min_outgoing_value(a) > distances[b] + min_outgoing_value(b);
    };

    using crauser_out_queue_t =
        fibonacci_heap<size_t, compare<decltype(cmp_crauser_out)>, allocator<thread_local_allocator<size_t>>>;
    crauser_out_queue_t crauser_out_queue(cmp_crauser_out);
    carray<crauser_out_queue_t::handle_type> crauser_out_queue_handles(node_count);

    for (size_t i = threads.chunk_start(thread_rank, node_count), end = i + threads.chunk_size(thread_rank, node_count);
         i < end;
         ++i) {
        m_global_distances[i].store(INFINITY, std::memory_order_relaxed);
    }
    threads.barrier_collective(true);

    for (size_t node = 0; node < node_count; ++node) {
        double min_outgoing = INFINITY;
        for (const edge& edge : thread_edges_by_node[node]) {
            if (edge.cost < min_outgoing) {
                min_outgoing = edge.cost;
            }
        }
        if (min_outgoing != INFINITY) {
            atomic_min(m_global_distances[node], min_outgoing);
        }
    }
    threads.barrier_collective(true);

    for (size_t node = 0; node < node_count; ++node) {
        min_outgoing[node] = m_global_distances[node].load(std::memory_order_relaxed);
    }
    threads.barrier_collective(true);
#endif

    for (size_t i = threads.chunk_start(thread_rank, node_count), end = i + threads.chunk_size(thread_rank, node_count);
         i < end;
         ++i) {
        m_global_distances[i].store(INFINITY, std::memory_order_relaxed);
    }
    threads.barrier_collective(true);

    distances[0] = 0.0;
    predecessors[0] = -1;
    states[0] = state::fringe;
    distance_queue_handles[0] = distance_queue.push(0);
#if defined(CRAUSER_OUT)
    crauser_out_queue_handles[0] = crauser_out_queue.push(0);
#endif
    m_global_distances[0].store(0.0, std::memory_order_relaxed);
    threads.barrier_collective(true);

    // Phase has to start at 1 not at 0, because I utilize +phase and -phase to
    // distinguish the two subphases.
    for (int phase = 1;; ++phase) {
        perf.next_timeblock("find_thresholds");
        m_global_updated_at.store(0, std::memory_order_relaxed);
        updated.clear();
        todo.clear();

#if defined(CRAUSER_OUT)
        if (crauser_out_queue.empty()) {
            break;
        }
        const double out_threshold = distances[crauser_out_queue.top()] + min_outgoing_value(crauser_out_queue.top());
        perf.next_timeblock("fill_todo");
        while (!distance_queue.empty() && distances[distance_queue.top()] <= out_threshold) {
            size_t node = distance_queue.top();
            todo.push_back(node);
            distance_queue.pop();
            crauser_out_queue.erase(crauser_out_queue_handles[node]);
        }
#endif

        perf.counter_add("phases", 1);
        perf.next_timeblock("relax");
        for (size_t node : todo) {
            BOOST_ASSERT(states[node] == state::fringe);
            states[node] = state::settled;
            for (const edge& e : thread_edges_by_node[node]) {
                if (states[e.destination] != state::settled && distances[node] + e.cost < distances[e.destination]) {
                    distances[e.destination] = distances[node] + e.cost;
                    predecessors[e.destination] = node;
                    if (states[e.destination] != state::fringe) {
                        states[e.destination] = state::fringe;
                        distance_queue_handles[e.destination] = distance_queue.push(e.destination);
#if defined(CRAUSER_OUT)
                        crauser_out_queue_handles[e.destination] = crauser_out_queue.push(e.destination);
#endif
                    } else {
                        distance_queue.update(distance_queue_handles[e.destination]);
#if defined(CRAUSER_OUT)
                        crauser_out_queue.update(crauser_out_queue_handles[e.destination]);
#endif
                    }
                    if (last_updated[e.destination] != phase) {
                        last_updated[e.destination] = phase;
                        updated.push_back(e.destination);
                    }
                }
            }
        }

        perf.next_timeblock("relax_barrier");
        threads.barrier_collective(true);

        perf.next_timeblock("announce_updated");
        for (size_t node : updated) {
            BOOST_ASSERT(states[node] == state::fringe);
            atomic_min(m_global_distances[node], distances[node]);
            m_global_updated[m_global_updated_at.fetch_add(1, std::memory_order_relaxed)] = node;
        }

        perf.next_timeblock("announce_updated_barrier");
        threads.barrier_collective(true);

        perf.next_timeblock("merge_updated");
        for (size_t i = 0, end = m_global_updated_at.load(std::memory_order_relaxed); i < end; ++i) {
            size_t node = m_global_updated[i];
            BOOST_ASSERT(states[node] != state::settled);
            if (last_updated[node] != -phase) {
                last_updated[node] = -phase;
                double global_distance = m_global_distances[node].load(std::memory_order_relaxed);
                if (global_distance < distances[node]) {
                    distances[node] = global_distance;
                    predecessors[node] = -2;
                    if (states[node] != state::fringe) {
                        states[node] = state::fringe;
                        distance_queue_handles[node] = distance_queue.push(node);
#if defined(CRAUSER_OUT)
                        crauser_out_queue_handles[node] = crauser_out_queue.push(node);
#endif
                    } else {
                        distance_queue.update(distance_queue_handles[node]);
#if defined(CRAUSER_OUT)
                        crauser_out_queue.update(crauser_out_queue_handles[node]);
#endif
                    }
                }
            }
        }

        perf.next_timeblock("merge_updated_barrier");
        threads.barrier_collective(true);
    }

    perf.end_timeblock();
    threads.single_collective([&] { m_perf.resize(threads.thread_count()); }, true);
    m_perf[thread_rank] = std::move(perf);
}

max_stars_repo_name: kaini/sssp-shm

max_issues_repo_name: kaini/sssp-shm

max_forks_repo_name: kaini/sssp-shm


text:
/*
 * OpenGL texture header
 *
 * This file is part of the "SoftPixel Engine" (Copyright (c) 2008 by Lukas Hermanns)
 * See "SoftPixelEngine.hpp" for license information.
 */

#include "RenderSystem/OpenGL/spOpenGLTexture.hpp"

#if defined(SP_COMPILE_WITH_OPENGL)

#include "Base/spImageManagement.hpp"
#include "Platform/spSoftPixelDeviceOS.hpp"
#include "RenderSystem/OpenGL/spOpenGLFunctionsARB.hpp"
#include "RenderSystem/OpenGL/spOpenGLRenderSystem.hpp"

#include <boost/shared_array.hpp>
#include <boost/foreach.hpp>

namespace sp
{

extern video::RenderSystem* GlbRenderSys;

namespace video
{

/*
 * Internal members
 */

// -> Don't use GL_DEPTH_COMPONENT16 here!
const GLenum GLTexFormatList[] = {
    GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT
};

const GLenum GLTexInternalFormatListFloat16[] = {
    GL_R16F, GL_LUMINANCE16F_ARB, GL_LUMINANCE_ALPHA16F_ARB, GL_RGB16F_ARB, GL_RGB16F_ARB, GL_RGBA16F_ARB, GL_RGBA16F_ARB, GL_DEPTH_COMPONENT24
};

const GLenum GLTexInternalFormatListFloat32[] = {
    GL_R32F, GL_LUMINANCE32F_ARB, GL_LUMINANCE_ALPHA32F_ARB, GL_RGB32F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_RGBA32F_ARB, GL_DEPTH_COMPONENT32F
};

extern GLenum GLTexInternalFormatListUByte8[];

/*
 * OpenGLTexture class
 */

OpenGLTexture::OpenGLTexture() :
    GLTextureBase       (),
    GLFrameBufferObject ()
{
}
OpenGLTexture::OpenGLTexture(const STextureCreationFlags &CreationFlags) :
    GLTextureBase       (CreationFlags  ),
    GLFrameBufferObject (               )
{
    updateFormatAndDimension();
    updateImageBuffer();
}
OpenGLTexture::~OpenGLTexture()
{
    deleteFramebuffer();
}

void OpenGLTexture::setCubeMapFace(const ECubeMapDirections Face)
{
    Texture::setCubeMapFace(Face);
    if (isRenderTarget_ && Type_ == TEXTURE_CUBEMAP)
    {
        setupCubeMapFace(
            getTexID(), CubeMapFace_, ImageBuffer_->getFormat() == PIXELFORMAT_DEPTH, MRTList_
        );
    }
}

void OpenGLTexture::setArrayLayer(u32 Layer)
{
    if ( ( Type_ == TEXTURE_1D_ARRAY && Layer < static_cast<u32>(ImageBuffer_->getSize().Height) ) ||
         Layer < ImageBuffer_->getDepth() )
    {
        Texture::setArrayLayer(Layer);
        if (isRenderTarget_ && Type_ >= TEXTURE_1D_ARRAY)
        {
            setupArrayLayer(
                getTexID(), ArrayLayer_, ImageBuffer_->getFormat() == PIXELFORMAT_DEPTH, MRTList_
            );
        }
    }
    #ifdef SP_DEBUGMODE
    else if (Type_ == TEXTURE_1D_ARRAY && Layer < static_cast<u32>(ImageBuffer_->getSize().Height))
        io::Log::debug("OpenGLTexture::setArrayLayer", "'Layer' index out of range for 1D texture array");
    else
        io::Log::debug("OpenGLTexture::setArrayLayer", "'Layer' index out of range");
    #endif
}

/* === Image buffer === */

bool OpenGLTexture::shareImageBuffer()
{
    if (!ImageBuffer_->getBuffer())
        return false;

    /* Bind this texture */
    glBindTexture(GLDimension_, getTexID());

    /* Get the dimensions */
    GLint GLInternalFormat;
    s32 Width, Height;
    EPixelFormats Format = PIXELFORMAT_RGB;

    glGetTexLevelParameteriv(GLDimension_, 0, GL_TEXTURE_WIDTH, &Width);
    glGetTexLevelParameteriv(GLDimension_, 0, GL_TEXTURE_HEIGHT, &Height);
    glGetTexLevelParameteriv(GLDimension_, 0, GL_TEXTURE_INTERNAL_FORMAT, &GLInternalFormat);

    /* Determine texture format */
    switch (GLInternalFormat)
    {
        case GL_LUMINANCE8:
            GLFormat_   = GL_LUMINANCE;
            Format      = PIXELFORMAT_GRAY;
            break;

        case GL_LUMINANCE8_ALPHA8:
            GLFormat_   = GL_LUMINANCE_ALPHA;
            Format      = PIXELFORMAT_GRAYALPHA;
            break;

        case GL_RGB:
        case GL_RGB8:
        case GL_RGB16F_ARB:
        case GL_RGB32F_ARB:
            GLFormat_   = GL_RGB;
            Format      = PIXELFORMAT_RGB;
            break;

        case GL_RGBA:
        case GL_RGBA8:
        case GL_RGBA16F_ARB:
        case GL_RGBA32F_ARB:
            GLFormat_   = GL_RGBA;
            Format      = PIXELFORMAT_RGBA;
            break;

        default:
            io::Log::error("Unexpected internal texture format");
            return false;
    }

    /* Check if the dimensions has changed */
    ImageBuffer_->setSize(dim::size2di(Width, Height));
    ImageBuffer_->setFormat(Format);

    /* Update renderer texture format */
    updateFormatAndDimension();

    /* Get the image data */
    if (Type_ == TEXTURE_CUBEMAP)
    {
        const u32 OffsetSize = ImageBuffer_->getSize().getArea() * ImageBuffer_->getPixelSize();

        glGetTexImage(
            GL_TEXTURE_CUBE_MAP_POSITIVE_X + CubeMapFace_, 0, GLFormat_,
            GLType_, static_cast<s8*>(ImageBuffer_->getBuffer()) + OffsetSize * static_cast<s32>(CubeMapFace_)
        );
    }
    else
        glGetTexImage(GLDimension_, 0, GLFormat_, GLType_, ImageBuffer_->getBuffer());

    return true;
}

bool OpenGLTexture::updateImageBuffer()
{
    /* Update dimension and format */
    const bool ReCreateTexture = (GLDimension_ != GLBasePipeline::getGlTexDimension(Type_));

    updateFormatAndDimension();

    if (ReCreateTexture)
        createHWTexture();

    /* Bind texture */
    glBindTexture(GLDimension_, getTexID());

    /* Update hardware texture settings */
    updateTextureAttributes();
    updateTextureImage();

    /* Update render target (create/delete) */
    if (GlbRenderSys->RenderQuery_[RenderSystem::RENDERQUERY_RENDERTARGET])
        updateRenderTarget();

    /* Unbind texture */
    glBindTexture(GLDimension_, 0);

    return true;
}

bool OpenGLTexture::updateImageBuffer(const dim::point2di &Pos, const dim::size2di &Size)
{
    if ( !ImageBuffer_->getBuffer() ||
         Size.Width <= 0 || Size.Height <= 0 ||
         Pos.X < 0 || Pos.Y < 0 ||
         Pos.X > getSize().Width - Size.Width ||
         Pos.Y > getSize().Height * static_cast<s32>(ImageBuffer_->getDepth()) - Size.Height )
    {
        #ifdef SP_DEBUGMODE
        io::Log::debug("OpenGLTexture::updateImageBuffer");
        #endif
        return false;
    }

    /* Get image buffer area */
    const u32 BufferSize = Size.getArea() * ImageBuffer_->getPixelSize();
    boost::shared_array<c8> Buffer = boost::shared_array<c8>(new c8[BufferSize]);

    ImageBuffer_->getBuffer(Buffer.get(), Pos, Size);

    /* Update hardware texture for specified area */
    glBindTexture(GLDimension_, getTexID());

    updateHardwareTextureArea(
        dim::vector3di(Pos.X, Pos.Y / ImageBuffer_->getDepth(), Pos.Y % ImageBuffer_->getDepth()),
        dim::vector3di(Size.Width, Size.Height, 1),
        Buffer.get()
    );

    glBindTexture(GLDimension_, 0);

    return true;
}

/*
 * ======= Private: =======
 */

void OpenGLTexture::updateFormatAndDimension()
{
    /* Update OpenGL texture formats */
    updateHardwareFormats();

    /* Determine which dimension is used */
    GLDimension_ = GLBasePipeline::getGlTexDimension(Type_);
}

void OpenGLTexture::updateMultiRenderTargets()
{
    updateImageBuffer();
    updateMultiFramebuffer(ImageBuffer_->getSize(), ImageBuffer_->getFormat(), MRTList_);
}
void OpenGLTexture::updateFramebufferMultisample()
{
    blitFramebufferMultisample(ImageBuffer_->getSize(), MRTList_.size());
}

void OpenGLTexture::updateHardwareFormats()
{
    /* Get GL format */
    const EPixelFormats Format = ImageBuffer_->getFormat();

    GLFormat_ = GLTexFormatList[Format];

    /* Get GL internal format */
    switch (HWFormat_)
    {
        case HWTEXFORMAT_UBYTE8:
            GLInternalFormat_ = GLTexInternalFormatListUByte8[Format];
            break;
        case HWTEXFORMAT_FLOAT16:
            GLInternalFormat_ = GLTexInternalFormatListFloat16[Format];
            break;
        case HWTEXFORMAT_FLOAT32:
            GLInternalFormat_ = GLTexInternalFormatListFloat32[Format];
            break;
        default:
            GLInternalFormat_ = GLFormat_;
            break;
    }

    /* Get GL image data type */
    switch (ImageBuffer_->getType())
    {
        case IMAGEBUFFER_UBYTE:
            GLType_ = GL_UNSIGNED_BYTE;
            break;
        case IMAGEBUFFER_FLOAT:
            GLType_ = GL_FLOAT;
            break;
    }
}

void OpenGLTexture::updateHardwareTexture(
    dim::vector3di Size, const u32 PixelSize, const void* ImageBuffer, s32 Level)
{
    if (Type_ != TEXTURE_BUFFER)
        TBO_.detachBuffer();

    switch (Type_)
    {
        case TEXTURE_1D:
        case TEXTURE_1D_RW:
        {
            /* Create 1D texture image */
            glTexImage1D(
                GL_TEXTURE_1D, Level, GLInternalFormat_, Size.X, 0, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_1D_ARRAY:
        case TEXTURE_2D:
        case TEXTURE_RECTANGLE:
        case TEXTURE_2D_RW:
        case TEXTURE_1D_ARRAY_RW:
        {
            /* Create 2D texture image */
            glTexImage2D(
                GLDimension_, Level, GLInternalFormat_, Size.X, Size.Y, 0, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_2D_ARRAY:
        case TEXTURE_CUBEMAP_ARRAY:
        case TEXTURE_3D:
        case TEXTURE_3D_RW:
        case TEXTURE_2D_ARRAY_RW:
        {
            /* Create 3D texture image */
            glTexImage3DEXT(
                GLDimension_, Level, GLInternalFormat_, Size.X, Size.Y, Size.Z, 0, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_CUBEMAP:
        {
            /* Get buffer offsets */
            const u32 OffsetSize = Size.X*Size.Y*PixelSize;
            const s8* Buffer = static_cast<const s8*>(ImageBuffer);

            for (s32 i = 0; i < 6; ++i)
            {
                /* Create 2D texture image for current cube-map face */
                glTexImage2D(
                    GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, Level, GLInternalFormat_,
                    Size.X, Size.Y, 0, GLFormat_, GLType_, Buffer
                );

                if (Buffer)
                    Buffer += OffsetSize;
            }
        }
        break;

        case TEXTURE_BUFFER:
        {
            /* Attach texture buffer to TBO */
            TBO_.attachBuffer(
                ImageBuffer, Size.X*Size.Y*Size.Z*PixelSize, getFormat(), getHardwareFormat()
            );
        }
        break;

        default:
            io::Log::error("Unsupported texture dimension type for the OpenGL render system");
            break;
    }

    /* Bind image texture for R/W access */
    if (hasRWAccess())
    {
        const GLenum GL3TexFormat = OpenGLRenderSystem::getGL3TexFormat(getHardwareFormat(), getFormat());

        if (GL3TexFormat)
        {
            glBindImageTexture(
                0, getTexID(), 0, GL_FALSE, 0, GL_WRITE_ONLY/*GL_READ_WRITE*/, GL3TexFormat
            );
        }
        else
            io::Log::error("Unsupported GL3 texture format for R/W texture");
    }
}

void OpenGLTexture::updateHardwareTextureArea(
    const dim::vector3di &Pos, const dim::vector3di &Size, const void* ImageBuffer, s32 Level)
{
    switch (Type_)
    {
        case TEXTURE_1D:
        {
            glTexSubImage1D(
                GL_TEXTURE_1D, Level, Pos.X, Size.X, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_1D_ARRAY:
        case TEXTURE_2D:
        case TEXTURE_RECTANGLE:
        {
            glTexSubImage2D(
                GLDimension_, Level, Pos.X, Pos.Y, Size.X, Size.Y, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_2D_ARRAY:
        case TEXTURE_CUBEMAP_ARRAY:
        case TEXTURE_3D:
        {
            glTexSubImage3DEXT(
                GLDimension_, Level, Pos.X, Pos.Y, Pos.Z, Size.X, Size.Y, Size.Z, GLFormat_, GLType_, ImageBuffer
            );
        }
        break;

        case TEXTURE_CUBEMAP:
        {
            for (s32 i = 0; i < 6; ++i)
            {
                glTexSubImage2D(
                    GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, Level,
                    Pos.X, Pos.Y, Size.X, Size.Y, GLFormat_, GLType_, ImageBuffer
                );
            }
        }
        break;

        case TEXTURE_BUFFER:
            // ignore that here
            break;

        default:
            io::Log::error("Unsupported texture dimension type for the OpenGL render system");
            break;
    }
}

void OpenGLTexture::updateRenderTarget()
{
    deleteFramebuffer();

    if (isRenderTarget_)
    {
        const GLuint DepthBufferSourceID = (DepthBufferSource_ ? static_cast<OpenGLTexture*>(DepthBufferSource_)->DepthBufferID_ : 0);

        /* Create GL frame buffer object */
        #ifdef SP_COMPILE_WITH_OPENGL
        if (MultiSamples_ > 0 && GlbRenderSys->RenderQuery_[RenderSystem::RENDERQUERY_MULTISAMPLE_RENDERTARGET])
        {
            createFramebufferMultisample(
                getTexID(), ImageBuffer_->getSize(), GLDimension_, GLInternalFormat_,
                MultiSamples_, MRTList_, ImageBuffer_->getFormat(),
                Type_, CubeMapFace_, ArrayLayer_, DepthBufferSourceID
            );
        }
        else
        #endif
        {
            createFramebuffer(
                getTexID(), ImageBuffer_->getSize(), GLDimension_, ImageBuffer_->getFormat(),
                Type_, CubeMapFace_, ArrayLayer_, DepthBufferSourceID
            );
        }
    }

    /* Refresh MRT view list for all referenced textures */
    refreshRefMRT();
}

void OpenGLTexture::refreshRefMRT()
{
    /* Refresh MRT view list for all affected textures */
    foreach (Texture* Tex, MRTRefList_)
        static_cast<OpenGLTexture*>(Tex)->updateMultiRenderTargets();
}

} // /namespace video

} // /namespace sp

#endif

// ================================================================================

ext: cpp

max_stars_repo_name: rontrek/softpixel

max_issues_repo_name: rontrek/softpixel

max_forks_repo_name: rontrek/softpixel


text:
#ifndef VMU931_SENSOR_HPP_LZK2XFWW
#define VMU931_SENSOR_HPP_LZK2XFWW

#include <array>
#include <functional>
#include <string>
#include <unordered_set>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/optional/optional.hpp>
#include "types.hpp"

namespace vmu931
{

class Sensor
{
public:
    using AccelerometersSink = std::function<void(vmu931::Accelerometers)>;
    using GyroscopesSink = std::function<void(vmu931::Gyroscopes)>;
    using MagnetometersSink = std::function<void(vmu931::Magnetometers)>;
    using EulerAnglesSink = std::function<void(vmu931::EulerAngles)>;
    using QuaternionsSink = std::function<void(vmu931::Quaternions)>;
    using HeadingSink = std::function<void(vmu931::Heading)>;
    using StatusSink = std::function<void(vmu931::Status)>;
    using StringSink = std::function<void(std::string)>;

    Sensor(boost::asio::serial_port&&);
    void send_command(char);
    void register_sink(AccelerometersSink);
    void register_sink(GyroscopesSink);
    void register_sink(MagnetometersSink);
    void register_sink(EulerAnglesSink);
    void register_sink(QuaternionsSink);
    void register_sink(HeadingSink);
    void register_sink(StatusSink);
    void register_sink(StringSink);
    void set_streams(const std::unordered_set<char>&);

private:
    void read_timeout();
    void read();
    void write();
    bool parse();
    void trim(const uint8_t*);
    void parse_data(char type, const uint8_t* begin, const uint8_t* end);
    void toggle_streams(const Status&);

    boost::asio::serial_port m_serial_port;
    boost::asio::deadline_timer m_timer;
    std::array<uint8_t, 256> m_buffer;
    std::size_t m_filled;
    std::string m_command;
    boost::optional<std::unordered_set<char>> m_pending_streams;

    AccelerometersSink m_accel;
    GyroscopesSink m_gyro;
    MagnetometersSink m_magneto;
    EulerAnglesSink m_euler;
    QuaternionsSink m_quat;
    HeadingSink m_heading;
    StatusSink m_status;
    StringSink m_string;
};

} // namespace vmu931

#endif /* VMU931_SENSOR_HPP_LZK2XFWW */

ext: hpp


text:
#ifndef __TVC_HH__
#define __TVC_HH__
/********************************* TRICK HEADER *******************************
PURPOSE:
      (Describe the TVC Module On Board)
LIBRARY DEPENDENCY:
      ((../src/Tvc.cpp))
*******************************************************************************/
#include <armadillo>
#include <functional>
#include <tuple>
#include <vector>
#include "component.hh"
#include "vehicle.hh"
#include "aux.hh"
#include "cadac_constants.hh"
#include "signal_process.hh"

class TVC : public FH_module {
  TRICK_INTERFACE(TVC);

 public:
  TVC();

  virtual void init(LaunchVehicle *VehicleIn);

  virtual void algorithm(LaunchVehicle *VehicleIn);

  std::function<double()> grab_theta_a_cmd;
  std::function<double()> grab_theta_b_cmd;
  std::function<double()> grab_theta_c_cmd;
  std::function<double()> grab_theta_d_cmd;

 private:
  /* Internal Initializers */
  void default_data();
};

#endif  // __TVC_HH__

ext: hh

max_stars_repo_name: mlouielu/mazu-sim

max_issues_repo_name: mlouielu/mazu-sim

max_forks_repo_name: mlouielu/mazu-sim


text:
#pragma once

#include "primitives.h"
#include "ant.h"
#include "world.h"
#include "utils/custom_console.h"

#include <boost/thread/thread.hpp>
#include <iostream>
#include <ostream>

namespace Ant
{
	Ant ant;
}

namespace World
{
	World world;
}

std::ostream &operator<<(std::ostream &os, World::World& world)
{
	for (char x = 0; x < world.trail.size(); ++x) {
		for (char y = 0; y < world.trail[x].size(); ++y) {
			os << world.trail[x][y] << " ";
		}

		os << "\n";
	}

	return os;
}

std::ostream &operator<<(std::ostream &os, Ant::Ant& ant)
{
	Console::SetCursorPosition(ant.x * 2, ant.y);
	os << ant.Draw();
	boost::this_thread::sleep(boost::posix_time::milliseconds(100));

	return os;
}

namespace Primitives
{
	Function tset[] = { Move, Right, Left }; // terminal set
	Function fset[] = { IfFoodAhead, Prog2, Prog3 }; // function set

	void SkipSubtree()
	{
		int not_end_of_subtree = 1;
		while (not_end_of_subtree > 0) {
			not_end_of_subtree += ArityMin1(*current_node++);
		}
	}

	int Primitives::IsFoodAhead()
	{
		char x = Ant::ant.x + Ant::ant.facing.first,
			 y = Ant::ant.y + Ant::ant.facing.second;

		if (x < 0)
			x = World::world.width - 1;
		else if (x > World::world.width - 1)
			x = 0;

		if (y < 0)
			y = World::world.height - 1;
		else if (y > World::world.height - 1)
			y = 0;

		return World::world.HasFood(x, y);
	}

	int IfFoodAhead()
	{
		if (IsFoodAhead()) {
			Next();
			++current_node;
		}
		else {
			SkipSubtree();
			Next();
		}

		return 0;
	}

	int Move()
	{
		if (display) {
			Console::SetCursorPosition(Ant::ant.x * 2, Ant::ant.y);
			std::cout << ".";
		}

		if (Ant::ant.steps_left-- > 0) {

			Ant::ant.x += Ant::ant.facing.first;
			Ant::ant.y += Ant::ant.facing.second;

			if (Ant::ant.x < 0)
				Ant::ant.x = World::world.width - 1;
			else if (Ant::ant.x > World::world.width - 1)
				Ant::ant.x = 0;

			if (Ant::ant.y < 0)
				Ant::ant.y = World::world.height - 1;
			else if (Ant::ant.y > World::world.height - 1)
				Ant::ant.y = 0;

			if (World::world.HasFood(Ant::ant.x, Ant::ant.y)) {
				World::world.RemovePiece(Ant::ant.x, Ant::ant.y);
				Ant::ant.food_eaten += 1;
			}

			if (display && Ant::ant.food_eaten < World::world.num_food_pieces)
				std::cout << Ant::ant;
		}

		return 0;
	}

	int Right()
	{
		if (Ant::ant.steps_left > 0)
			++Ant::ant;

		if (display && Ant::ant.food_eaten < World::world.num_food_pieces)
			std::cout << Ant::ant;

		return 0;
	}

	int Left()
	{
		if (Ant::ant.steps_left > 0)
			--Ant::ant;

		if (display && Ant::ant.food_eaten < World::world.num_food_pieces)
			std::cout << Ant::ant;

		return 0;
	}

	int Prog2()
	{
		Next();
		Next();

		return 0;
	}

	int Prog3()
	{
		Next();
		Next();
		Next();

		return 0;
	}

	float Evaluate(std::string program)
	{
		World::world.Refresh();
		Ant::ant.Spawn();

		int best_steps = Ant::ant.steps_left;
		int best_num_eaten = World::world.num_food_pieces;

		auto normalise_steps = [&best_steps](int steps_left)->float {return (float)steps_left / best_steps; };
		auto normalise_num_eaten = [&best_num_eaten](int num_pieces_eaten)->float {return (float)num_pieces_eaten / best_num_eaten; };

		while (Ant::ant.steps_left > 0) {
			current_node = program.begin();
			Next();
		}

		float food_weight = 0.7, steps_weight = 0.3;

		return 1 - food_weight * normalise_num_eaten(Ant::ant.food_eaten) - steps_weight * normalise_steps(Ant::ant.steps_left);
	}

	void Save(std::string program, std::string fullpath)
	{
		std::fstream program_file(fullpath, std::ios::out);

		std::unordered_map<char, std::string> tokens;
		tokens.emplace(MOVE, "MOVE");
		tokens.emplace(RIGHT, "RIGHT");
		tokens.emplace(LEFT, "LEFT");
		tokens.emplace(IF_FOOD_AHEAD, "IF-FOOD-AHEAD");
		tokens.emplace(PROG2, "PROG2");
		tokens.emplace(PROG3, "PROG3");

		for (int i = 0; i < program.size(); ++i)
			program_file << tokens[program[i]] << "\n";

		program_file.close();
	}

	std::string Load(std::string fullpath)
	{
		std::fstream program_file(fullpath);

		std::unordered_map<std::string, char> reverse_tokens;
		reverse_tokens.emplace("MOVE", MOVE);
		reverse_tokens.emplace("RIGHT", RIGHT);
		reverse_tokens.emplace("LEFT", LEFT);
		reverse_tokens.emplace("IF-FOOD-AHEAD", IF_FOOD_AHEAD);
		reverse_tokens.emplace("PROG2", PROG2);
		reverse_tokens.emplace("PROG3", PROG3);

		std::string line, program;
		while (true) {
			getline(program_file, line);
			if (program_file.eof())
				break;
			program += reverse_tokens[line];
		}

		program_file.close();

		return program;
	}

	void Test(std::string program_path, bool visualise)
	{
		display = visualise;

		Console::Maximise();
		Console::HideCursor();

		std::cout << World::world;

		Evaluate(Load(program_path));

		Console::SetCursorPosition(0, World::world.height);

		printf("\nNo. pieces available: %d", World::world.num_food_pieces);
		printf("\nNo. pieces eaten: %d", Ant::ant.food_eaten);
		printf("\nDone!");
		getchar();
	}

	int ArityMin1(char x, char dummy)
	{
		if (x < Primitives::FSET_START)
			return -1;

		if (x == PROG3)
			return 2;

		return 1;
	}

	std::unordered_map<char, Function> terminals;
	std::unordered_map<char, Function> jumptable;
	std::string::const_iterator current_node;

	int Next()
	{
		return jumptable[*current_node++]();
	}

	int Terminal()
	{
		return terminals[*(current_node - 1)]();
	}

	void SetUp()
	{
		char i = Primitives::TSET_START;

		for (; i <= Primitives::TSET_END; ++i) {
			terminals.emplace(i, Primitives::tset[i - Primitives::TSET_START]);
			jumptable.emplace(i, Terminal);
		}

		for (i = Primitives::FSET_START; i <= Primitives::FSET_END; ++i)
			jumptable.emplace(i, Primitives::fset[i - Primitives::FSET_START]);
	}

	bool display = false;
}

max_stars_repo_name: karolisjan/Genetic-Programming

max_issues_repo_name: karolisjan/Genetic-Programming

max_forks_repo_name: karolisjan/Genetic-Programming


text:
#include "qtsoftmatter.h"
#include "ui_qtsoftmatter.h"
#include <boost/format.hpp>

QtSoftMatter::QtSoftMatter(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QtSoftMatter)
{
    simLock = false;
    ui->setupUi(this);
    initModel();
    paintTimer.setInterval(50);
    simTimer.setInterval(50);
    connect(&paintTimer, SIGNAL(timeout()), this, SLOT(updatePaintWidgets()));
    connect(&simTimer, SIGNAL(timeout()), this, SLOT(computeRK4()));
    paintTimer.start();
    simTimer.start();

    connect(ui->nuDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(initModel()));
    connect(ui->nhSpinBox, SIGNAL(valueChanged(int)), this, SLOT(initModel()));
    connect(ui->dtDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateModel()));
    connect(ui->mSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateModel()));
    connect(ui->nSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateModel()));
}

QtSoftMatter::~QtSoftMatter()
{
    delete ui;
}

void QtSoftMatter::updatePaintWidgets()
{
    ui->paintWidget->setModel(model);
    ui->paintWidget->update();
}

void QtSoftMatter::initModel()
{
    model.init(ui->dtDoubleSpinBox->value(), ui->mSpinBox->value(), ui->nSpinBox->value(),
               ui->nhSpinBox->value(), 1/ui->nuDoubleSpinBox->value(),
               ui->sv0DoubleSpinBox->value());
    ui->paintWidget->setModel(model);
    ui->packingFractionLabel->setText(QString("%1 %").arg(100*model.packingFractionHCP));
    ui->cutoffLabel->setText(QString("%1 σ").arg(model.cutoff));
}

void QtSoftMatter::computeRK4()
{
    if (simLock)
        return;

    simLock = true;

    int steps = ui->spfSpinBox->value();

    for (int i=0; i<steps; ++i)
        model.rk4step();

    updatePaintWidgets();

    simLock = false;
}

void QtSoftMatter::updateModel()
{
    model.dt = pow(10, ui->dtDoubleSpinBox->value());
    model.m = ui->mSpinBox->value();
    model.n = ui->nSpinBox->value();
    model.update();
    ui->cutoffLabel->setText(QString("%1 σ").arg(model.cutoff));
}

max_stars_repo_name: macioosch/QtSoftMatter

max_issues_repo_name: macioosch/QtSoftMatter

max_forks_repo_name: macioosch/QtSoftMatter


text:
// Copyright (c) 2019 Graphcore Ltd. All rights reserved.
#ifndef POPLIBS_SUPPORT_MULTI_ARRAY_HPP
#define POPLIBS_SUPPORT_MULTI_ARRAY_HPP

#include <memory>
#include <sstream>

#include <boost/container/small_vector.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/numeric.hpp>

namespace poplibs_support {

using MultiArrayShape = boost::container::small_vector<std::size_t, 4>;
using MultiArrayShapeRange =
    boost::iterator_range<MultiArrayShape::const_iterator>;

// Similar to Boost.MultiArray except the dimensions are specified at runtime.
// Internally the data is stored in row-major order aka boost::c_storage_order.
template <typename T> class MultiArray {
  using Shape = MultiArrayShape;
  using ShapeRange = MultiArrayShapeRange;

public:
  class Reference {
  public:
    Reference(const ShapeRange shape, T *data) : shape(shape), data(data) {}

    // moveable, non-copyable, but support assignment from inner-most dim.
    Reference(Reference &&) = default;
    Reference(const Reference &) = delete;

    T &operator=(const Reference &o) {
      return *this = static_cast<const T &>(o);
    }

    T &operator=(const T &value) {
      T &d(*this);
      d = value;
      return d;
    }

    Reference operator[](const std::size_t idx) {
      return slice<Reference>(shape, data, idx);
    }

    operator const T &() const { return cast<const T &>(shape, data); }

    operator T &() { return cast<T &>(shape, data); }

  private:
    ShapeRange shape;
    T *data;
  };

  class ConstReference {
  public:
    ConstReference(const ShapeRange shape, const T *const data)
        : shape(shape), data(data) {}

    // moveable, but non-copyable. can enforce this at compile time as this is
    // a const reference and so cannot write to it's underlying data.
    ConstReference(ConstReference &&) = default;
    ConstReference &operator=(ConstReference &&) = default;
    ConstReference(const ConstReference &) = delete;
    ConstReference &operator=(const ConstReference &) = delete;

    ConstReference operator[](const std::size_t idx) const {
      return slice<ConstReference>(shape, data, idx);
    }

    operator const T &() const { return cast<const T &>(shape, data); }

  private:
    ShapeRange shape;
    const T *data;
  };

  MultiArray(std::initializer_list<std::size_t> shape)
      : shape_{shape}, data_{nullptr} {
    init();
  }

  MultiArray(const ShapeRange shape)
      : shape_{std::begin(shape), std::end(shape)}, data_{nullptr} {
    init();
  }

  T *data() const { return data_.get(); }

  ShapeRange shape() const { return shape_; }

  std::size_t size() const { return shape_[0]; }

  std::size_t numElements() const { return product(shape_); }

  std::size_t numDimensions() const { return shape_.size(); }

  Reference operator[](const std::size_t idx) {
    return slice<Reference>(shape_, data_.get(), idx);
  }

  Reference operator[](const ShapeRange indices) {
    return slice<Reference>(shape_, data_.get(), indices);
  }

  ConstReference operator[](const std::size_t idx) const {
    return slice<ConstReference>(shape_, data_.get(), idx);
  }

  ConstReference operator[](const ShapeRange indices) const {
    return slice<ConstReference>(shape_, data_.get(), indices);
  }

private:
  void init() {
    if (shape_.empty()) {
      throw std::runtime_error("Cannot create a MultiArray with a rank of 0.");
    }

    const auto size = numElements();
    data_.reset(new T[size]);
    std::fill_n(data_.get(), size, T{});
  }

  // get a view of the data at the next dimension in, offsetted by index.
  template <typename R, typename D>
  static R slice(const ShapeRange shape, D data, const std::size_t idx) {
    if (shape.empty()) {
      throw std::runtime_error(
          "Cannot slice MultiArray, already at inner-most dimension.");
    }

    if (idx >= shape[0]) {
      std::stringstream ss;
      ss << "MultiArray out of bounds error: " << idx << " >= " << shape[0]
         << ".";
      throw std::out_of_range(ss.str());
    }

    // remove the outer-most dimension from the shape.
    auto newShape = shape;
    newShape.advance_begin(1);

    // get the pointer to where this slice begins.
    auto offset = std::next(data, idx * product(newShape));

    return R{newShape, offset};
  }

  // get a view of the data at the next N-dimensions in, as described by the
  // range of indices.
  template <typename R, typename D>
  static R slice(const ShapeRange shape, D data, const ShapeRange indices) {
    if (shape.empty()) {
      throw std::runtime_error(
          "Cannot slice MultiArray, already at inner-most dimension.");
    }

    T *offset = data;
    auto newShape = shape;
    for (unsigned i = 0; i < shape.size(); ++i) {
      if (indices[i] >= shape[i]) {
        std::stringstream ss;
        ss << "MultiArray out of bounds error: " << indices[i]
           << " >= " << shape[i] << ".";
        throw std::out_of_range(ss.str());
      }

      // remove the outer-most dimension from the shape.
      newShape.advance_begin(1);

      // get the pointer to where this slice begins.
      offset = std::next(offset, indices[i] * product(newShape));
    }

    return R{newShape, offset};
  }

  // if this is a reference to a single element inside the multi-array (ie,
  // the shape is empty), then we can implicitly cast the reference to the
  // underlying value. same goes for assignment.
  template <typename R, typename D>
  static R cast(const ShapeRange shape, D data) {
    if (!shape.empty()) {
      throw std::runtime_error(
          "Cannot cast MultiArray slice to underlying data as this view is not "
          "of the inner-most dimension.");
    }

    return *data;
  }

  static std::size_t product(const ShapeRange shape) {
    return boost::accumulate(shape, 1ul, std::multiplies<std::size_t>{});
  }

  Shape shape_;
  std::unique_ptr<T[]> data_;
};

// given a MultiArray shape, call the functor with each value from the
// cartesian product of all the indices. this is basically a way of looping
// through as if you were to handwrite nested loops except the depth is decided
// at runtime. eg.
//  forEachIndex({3, 2, 1}, [](ShapeRange indices) { printf(indices); });
// will print:
//  0, 0, 0
//  0, 1, 0
//  1, 0, 0
//  1, 1, 0
//  2, 0, 0
//  2, 1, 0
// these shapes can be passed to a MultiArray via the subscript operator to get
// a slice/value at that point.
class ForEachIndex {
public:
  template <typename Fn>
  void operator()(const MultiArrayShapeRange shape, const Fn &fn) const {
    MultiArrayShape indices(shape.size(), 0ul);
    step(shape, fn, indices, 0);
  }

private:
  template <typename Fn>
  static void step(const MultiArrayShapeRange shape, const Fn &fn,
                   MultiArrayShape &indices, const std::size_t depth) {
    if (depth == shape.size()) {
      fn(MultiArrayShapeRange{indices});
    } else {
      for (unsigned i = 0; i < shape[depth]; ++i) {
        indices[depth] = i;
        step(shape, fn, indices, depth + 1);
      }
    }
  }
};

constexpr ForEachIndex forEachIndex{};

} // namespace poplibs_support

#endif // POPLIB_SUPPORT_MULTI_ARRAY_HPP

max_stars_repo_name: graphcore/poplibs