<commit_before>#include <gtest/gtest.h>

#include <cstdlib>
#include <cmath>
#include <cassert>
#include <atomic>
#include <queue>
#include <pthread.h>

#include <libprecisegc/details/utils/make_unique.hpp>
#include <libprecisegc/details/utils/scoped_thread.hpp>
#include <libprecisegc/details/utils/scope_guard.hpp>
#include <libprecisegc/details/threads/managed_thread.hpp>
#include <libprecisegc/details/serial_garbage_collector.hpp>
#include <libprecisegc/details/incremental_garbage_collector.hpp>
#include <libprecisegc/gc_ptr.h>
#include <libprecisegc/gc_new.h>
#include <libprecisegc/gc.h>
#include <libprecisegc/details/gc_mark.h>
#include <libprecisegc/details/barrier.h>
#include <libprecisegc/details/utils/math.h>

using namespace precisegc;
using namespace precisegc::details;

#define DEBUG_PRINT_TREE

namespace {

const int TREE_DEPTH    = 2;
const int THREADS_COUNT = 4; // must be power of 2 and <= 2^(TREE_DEPTH)
const size_t LIVE_LEVEL = ::log2(THREADS_COUNT);

struct node
{
    gc_ptr<node> m_left;
    gc_ptr<node> m_right;
};

gc_ptr<node> create_gc_node()
{
    return gc_new<node>();
}

gc_ptr<node> create_tree(size_t depth)
{
    std::queue<gc_ptr<node>> q;
    const size_t LEAFS_CNT = pow(2, depth);
    for (int i = 0; i < LEAFS_CNT; ++i) {
        q.push(create_gc_node());
    }
    while (q.size() > 1) {
        auto parent = create_gc_node();
        parent->m_left = q.front();
        q.pop();
        parent->m_right = q.front();
        q.pop();
        q.push(parent);
    }
    return q.front();
}

void unmark_tree(const gc_ptr<node>& ptr)
{
    if (ptr) {
        gc_pin<node> pin(ptr);
        set_object_mark(pin.get(), false);
        unmark_tree(ptr->m_left);
        unmark_tree(ptr->m_right);
    }
}

void print_tree(const gc_ptr<node>& root, const std::string& offset = "")
{
#ifdef DEBUG_PRINT_TREE
    if (!root) {
        std::cout << offset << "nullptr" << std::endl;
        return;
    }
    gc_pin<node> pin(root);
    std::cout << offset << &root << " (" << pin.get() << ") [" << get_object_mark(pin.get()) << "]" << std::endl;
    auto new_offset = offset + "    ";
    print_tree(root->m_left, new_offset);
    print_tree(root->m_right, new_offset);
#endif
}

void print_tree(node* root, const std::string& offset = "")
{
#ifdef DEBUG_PRINT_TREE
    std::cout << offset << "nullptr" << " (" << root << ") [" << get_object_mark(root) << "]" << std::endl;
    auto new_offset = offset + "    ";
    print_tree(root->m_left, new_offset);
    print_tree(root->m_right, new_offset);
#endif
}

void generate_random_child(gc_ptr<node> ptr)
{
    while (true) {
        gc_ptr<node>& new_ptr = rand() % 2 ? ptr->m_left : ptr->m_right;
        if (!new_ptr || rand() % 4 == 0) {
            new_ptr = create_gc_node();
            return;
        } else {
            ptr = new_ptr;
        }
    }
}

void check_nodes(node* ptr, size_t depth)
{
    if (depth < LIVE_LEVEL) {
        EXPECT_FALSE(get_object_mark(ptr)) << "ptr=" << ptr;
    } else if (depth == LIVE_LEVEL) {
        EXPECT_TRUE(get_object_mark(ptr)) << "ptr=" << ptr;
    }
    if (ptr->m_left) {
        gc_pin<node> pin(ptr->m_left);
        check_nodes(pin.get(), depth + 1);
    }
    if (ptr->m_right) {
        gc_pin<node> pin(ptr->m_right);
        check_nodes(pin.get(), depth + 1);
    }
}

std::atomic<int> thread_num(0);
std::atomic<bool> gc_finished(false);

barrier threads_ready(THREADS_COUNT + 1);

static void* thread_routine(void* arg)
{
    gc_ptr<node>& root = *((gc_ptr<node>*) arg);
    int num = thread_num++;
    // assign to each thread a leaf in the tree
    gc_ptr<node> ptr = root;
    for (int i = 0; i < ::log2(THREADS_COUNT); ++i, num /= 2) {
        ptr = num % 2 ? ptr->m_left : ptr->m_right;
    }
    threads_ready.wait();
    while (!gc_finished) {
        generate_random_child(ptr);
//        sleep(1);
    }
}

}

/**
 * The following test fixture creates tree and starts several threads.
 * In each thread gc pointer to some node in the tree is saved.
 * Then the original root is saved in a raw pointer and gc_ptr to it is reset.
 * It is assumed that then test code will perform gc or one of it phases (marking, compacting),
 * and the top levels of tree, that are not reachable from thread's gc pointers, will be freed.
 *
 *          0 <--------------- root
 *         / \
 *        0   0
 *       / \  /\
 *      *  * *  *  <---------- pointers to these nodes are saved in thread's program stacks
 *     / \  /    \
 *    *  * *      * <--------- all nodes below are randomly generated in threads
 */

struct gc_test: public ::testing::Test
{
    gc_test(std::unique_ptr<gc_interface> new_gc)
    {
        old_gc = gc_reset(std::move(new_gc));
        auto guard = utils::make_scope_guard([this] {
            gc_set(std::move(old_gc));
        });

        srand(time(nullptr));

        gc_finished = false;
        thread_num = 0;

        std::cout << "Creating tree" << std::endl;
        root = create_tree(TREE_DEPTH);
        unmark_tree(root);
        print_tree(root);

        for (auto& thread: threads) {
            thread = threads::managed_thread::create(thread_routine, (void*) &root);
        }
        threads_ready.wait();

        // save root in raw pointer and then null gc_ptr to collect it during gc
        gc_pin<node> pin(root);
        root_raw = pin.get();
        root.reset();

        std::this_thread::sleep_for(std::chrono::milliseconds(10));

        guard.commit();
    }

    ~gc_test()
    {
        auto guard = utils::make_scope_guard([this] {
            gc_set(std::move(old_gc));
        });
        for (auto& thread: threads) {
            thread.join();
        }
    }

    gc_ptr<node> root;
    utils::scoped_thread threads[THREADS_COUNT];
    node* root_raw;
    std::unique_ptr<gc_interface> old_gc;
};

struct serial_gc_test : public gc_test
{
    serial_gc_test()
        : gc_test(utils::make_unique<serial_garbage_collector>(gc_compacting::DISABLED, utils::make_unique<empty_policy>()))
    {
        garbage_collector = static_cast<serial_garbage_collector*>(gc_get());
    }

    serial_garbage_collector* garbage_collector;
};

struct incremental_gc_test : public gc_test
{
    incremental_gc_test()
        : gc_test(utils::make_unique<incremental_garbage_collector>(gc_compacting::DISABLED, utils::make_unique<incremental_empty_policy>()))
    {
        garbage_collector = static_cast<incremental_garbage_collector*>(gc_get());
    }

    incremental_garbage_collector* garbage_collector;
};

// This test doesn't check anything.
// Consider it is passed if nothing will crash or hang.
TEST_F(serial_gc_test, test_serial_gc)
{
    garbage_collector->gc();
    gc_finished = true;
    print_tree(root_raw);
}

TEST_F(incremental_gc_test, test_marking)
{
    incremental_gc_ops ops;

    ops.phase           = gc_phase::MARKING;
    ops.concurrent_flag = true;
    ops.threads_num     = 1;

    garbage_collector->incremental_gc(ops);

    std::this_thread::sleep_for(std::chrono::milliseconds(10));

    ops.phase           = gc_phase::IDLING;
    ops.concurrent_flag = false;
    ops.threads_num     = 0;

    garbage_collector->incremental_gc(ops);

    gc_finished = true;
    print_tree(root_raw);
    check_nodes(root_raw, 0);
}

TEST_F(incremental_gc_test, test_sweeping)
{
    incremental_gc_ops ops;

    ops.phase           = gc_phase::SWEEPING;
    ops.concurrent_flag = false;
    ops.threads_num     = 1;

    garbage_collector->incremental_gc(ops);

    gc_finished = true;
    print_tree(root_raw);
}

//TEST_F(gc_test, test_marking)
//{
//    auto& collector = gc_garbage_collector::instance();
//    std::cout << "Start marking" << std::endl;
//    collector.start_marking();
//    std::this_thread::sleep_for(std::chrono::milliseconds(10));
//    std::cout << "Pause marking" << std::endl;
//
//    gc_finished = true;
//    collector.force_move_to_idle();
//
//    std::cout << std::endl;
//    print_tree(root_raw);
//    // travers tree and check marks of objects
//    check_nodes(root_raw, 0);
//
//    collector.force_move_to_idle();
//}
<commit_msg>fix gc_test<commit_after>#include <gtest/gtest.h>

#include <cstdlib>
#include <cmath>
#include <cassert>
#include <atomic>
#include <queue>
#include <pthread.h>

#include <libprecisegc/details/utils/make_unique.hpp>
#include <libprecisegc/details/utils/scoped_thread.hpp>
#include <libprecisegc/details/utils/scope_guard.hpp>
#include <libprecisegc/details/threads/managed_thread.hpp>
#include <libprecisegc/details/serial_garbage_collector.hpp>
#include <libprecisegc/details/incremental_garbage_collector.hpp>
#include <libprecisegc/gc_ptr.h>
#include <libprecisegc/gc_new.h>
#include <libprecisegc/gc.h>
#include <libprecisegc/details/gc_mark.h>
#include <libprecisegc/details/barrier.h>
#include <libprecisegc/details/utils/math.h>

using namespace precisegc;
using namespace precisegc::details;

#define DEBUG_PRINT_TREE

namespace {

const int TREE_DEPTH    = 2;
const int THREADS_COUNT = 4; // must be power of 2 and <= 2^(TREE_DEPTH)
const size_t LIVE_LEVEL = ::log2(THREADS_COUNT);

struct node
{
    gc_ptr<node> m_left;
    gc_ptr<node> m_right;
};

gc_ptr<node> create_gc_node()
{
    return gc_new<node>();
}

gc_ptr<node> create_tree(size_t depth)
{
    std::queue<gc_ptr<node>> q;
    const size_t LEAFS_CNT = pow(2, depth);
    for (int i = 0; i < LEAFS_CNT; ++i) {
        q.push(create_gc_node());
    }
    while (q.size() > 1) {
        auto parent = create_gc_node();
        parent->m_left = q.front();
        q.pop();
        parent->m_right = q.front();
        q.pop();
        q.push(parent);
    }
    return q.front();
}

void unmark_tree(const gc_ptr<node>& ptr)
{
    if (ptr) {
        gc_pin<node> pin(ptr);
        set_object_mark(pin.get(), false);
        unmark_tree(ptr->m_left);
        unmark_tree(ptr->m_right);
    }
}

void print_tree(const gc_ptr<node>& root, const std::string& offset = "")
{
#ifdef DEBUG_PRINT_TREE
    if (!root) {
        std::cout << offset << "nullptr" << std::endl;
        return;
    }
    gc_pin<node> pin(root);
    std::cout << offset << &root << " (" << pin.get() << ") [" << get_object_mark(pin.get()) << "]" << std::endl;
    auto new_offset = offset + "    ";
    print_tree(root->m_left, new_offset);
    print_tree(root->m_right, new_offset);
#endif
}

void print_tree(node* root, const std::string& offset = "")
{
#ifdef DEBUG_PRINT_TREE
    std::cout << offset << "nullptr" << " (" << root << ") [" << get_object_mark(root) << "]" << std::endl;
    auto new_offset = offset + "    ";
    print_tree(root->m_left, new_offset);
    print_tree(root->m_right, new_offset);
#endif
}

void generate_random_child(gc_ptr<node> ptr)
{
    while (true) {
        gc_pin<node> pin(ptr);
        gc_ptr<node> new_ptr = rand() % 2 ? pin->m_left : pin->m_right;
        if (!new_ptr || rand() % 4 == 0) {
            new_ptr = create_gc_node();
            return;
        } else {
            ptr = new_ptr;
        }
    }
}

void check_nodes(node* ptr, size_t depth)
{
    if (depth < LIVE_LEVEL) {
        EXPECT_FALSE(get_object_mark(ptr)) << "ptr=" << ptr;
    } else if (depth == LIVE_LEVEL) {
        EXPECT_TRUE(get_object_mark(ptr)) << "ptr=" << ptr;
    }
    if (ptr->m_left) {
        gc_pin<node> pin(ptr->m_left);
        check_nodes(pin.get(), depth + 1);
    }
    if (ptr->m_right) {
        gc_pin<node> pin(ptr->m_right);
        check_nodes(pin.get(), depth + 1);
    }
}

std::atomic<int> thread_num(0);
std::atomic<bool> gc_finished(false);

barrier threads_ready(THREADS_COUNT + 1);

static void* thread_routine(void* arg)
{
    gc_ptr<node>& root = *((gc_ptr<node>*) arg);
    int num = thread_num++;
    // assign to each thread a leaf in the tree
    gc_ptr<node> ptr = root;
    for (int i = 0; i < ::log2(THREADS_COUNT); ++i, num /= 2) {
        ptr = num % 2 ? ptr->m_left : ptr->m_right;
    }
    threads_ready.wait();
    while (!gc_finished) {
        generate_random_child(ptr);
//        sleep(1);
    }
}

}

/**
 * The following test fixture creates tree and starts several threads.
 * In each thread gc pointer to some node in the tree is saved.
 * Then the original root is saved in a raw pointer and gc_ptr to it is reset.
 * It is assumed that then test code will perform gc or one of it phases (marking, compacting),
 * and the top levels of tree, that are not reachable from thread's gc pointers, will be freed.
 *
 *          0 <--------------- root
 *         / \
 *        0   0
 *       / \  /\
 *      *  * *  *  <---------- pointers to these nodes are saved in thread's program stacks
 *     / \  /    \
 *    *  * *      * <--------- all nodes below are randomly generated in threads
 */

struct gc_test: public ::testing::Test
{
    gc_test(std::unique_ptr<gc_interface> new_gc)
    {
        old_gc = gc_reset(std::move(new_gc));
        auto guard = utils::make_scope_guard([this] {
            gc_set(std::move(old_gc));
        });

        srand(time(nullptr));

        gc_finished = false;
        thread_num = 0;

        std::cout << "Creating tree" << std::endl;
        root = create_tree(TREE_DEPTH);
        unmark_tree(root);
        print_tree(root);

        for (auto& thread: threads) {
            thread = threads::managed_thread::create(thread_routine, (void*) &root);
        }
        threads_ready.wait();

        // save root in raw pointer and then null gc_ptr to collect it during gc
        gc_pin<node> pin(root);
        root_raw = pin.get();
        root.reset();

        std::this_thread::sleep_for(std::chrono::milliseconds(10));

        guard.commit();
    }

    ~gc_test()
    {
        auto guard = utils::make_scope_guard([this] {
            gc_set(std::move(old_gc));
        });
        for (auto& thread: threads) {
            thread.join();
        }
    }

    gc_ptr<node> root;
    utils::scoped_thread threads[THREADS_COUNT];
    node* root_raw;
    std::unique_ptr<gc_interface> old_gc;
};

struct serial_gc_test : public gc_test
{
    serial_gc_test()
        : gc_test(utils::make_unique<serial_garbage_collector>(gc_compacting::DISABLED, utils::make_unique<empty_policy>()))
    {
        garbage_collector = static_cast<serial_garbage_collector*>(gc_get());
    }

    serial_garbage_collector* garbage_collector;
};

struct incremental_gc_test : public gc_test
{
    incremental_gc_test()
        : gc_test(utils::make_unique<incremental_garbage_collector>(gc_compacting::DISABLED, utils::make_unique<incremental_empty_policy>()))
    {
        garbage_collector = static_cast<incremental_garbage_collector*>(gc_get());
    }

    incremental_garbage_collector* garbage_collector;
};

// This test doesn't check anything.
// Consider it is passed if nothing will crash or hang.
TEST_F(serial_gc_test, test_serial_gc)
{
    garbage_collector->gc();
    gc_finished = true;
    print_tree(root_raw);
}

TEST_F(incremental_gc_test, test_marking)
{
    incremental_gc_ops ops;

    ops.phase           = gc_phase::MARKING;
    ops.concurrent_flag = true;
    ops.threads_num     = 1;

    garbage_collector->incremental_gc(ops);

    std::this_thread::sleep_for(std::chrono::milliseconds(10));

    ops.phase           = gc_phase::IDLING;
    ops.concurrent_flag = false;
    ops.threads_num     = 0;

    garbage_collector->incremental_gc(ops);

    gc_finished = true;
    print_tree(root_raw);
    check_nodes(root_raw, 0);
}

TEST_F(incremental_gc_test, test_sweeping)
{
    incremental_gc_ops ops;

    ops.phase           = gc_phase::SWEEPING;
    ops.concurrent_flag = false;
    ops.threads_num     = 1;

    garbage_collector->incremental_gc(ops);

    gc_finished = true;
    print_tree(root_raw);
}

//TEST_F(gc_test, test_marking)
//{
//    auto& collector = gc_garbage_collector::instance();
//    std::cout << "Start marking" << std::endl;
//    collector.start_marking();
//    std::this_thread::sleep_for(std::chrono::milliseconds(10));
//    std::cout << "Pause marking" << std::endl;
//
//    gc_finished = true;
//    collector.force_move_to_idle();
//
//    std::cout << std::endl;
//    print_tree(root_raw);
//    // travers tree and check marks of objects
//    check_nodes(root_raw, 0);
//
//    collector.force_move_to_idle();
//}
<|endoftext|>


<commit_before>#include "baseMesh.h"

baseMesh::baseMesh()
{
    lightShader.load("shaders/lightShader");
    shaderColorSource = 0;

    //if you need to load an image to pass in use this
    //
    //image.loadImage("stripes.jpg");
    //mesh.mapTexCoordsFromTexture(image.getTextureReference());
}

void baseMesh::update()
{

}

void baseMesh::draw(ofVec3f &_lightLocation, ofVec3f &_lightAttenuation, ofVec3f &_cameraLocation)
{
    lightLocation = _lightLocation;
    lightAttenuation = _lightAttenuation;
    cameraLocation = _cameraLocation;

    lightShader.begin();
    lightShader.setUniform3f("colorInput", unitColor.r, unitColor.g, unitColor.b);
    lightShader.setUniform1f("colorAlpha", alphaColor);
    lightShader.setUniform1i("shaderColorSource", shaderColorSource);
    lightShader.setUniform3f("lightLocation", lightLocation.x, lightLocation.y, lightLocation.z);
    lightShader.setUniform3f("cameraLocation", cameraLocation.x, cameraLocation.y, cameraLocation.z);

    lightShader.setUniform1f("constantAttenuation", lightAttenuation.x);//
    lightShader.setUniform1f("linearAttenuation", lightAttenuation.y);/////// XYZ used for easy data encapsulation
    lightShader.setUniform1f("quadraticAttenuation", lightAttenuation.z);//

    UnitRGB lightColor = mapToUnitRGB(231, 230, 220);
    lightShader.setUniform3f("lightColor", lightColor.r, lightColor.g, lightColor.b);

    UnitRGB specularColor = mapToUnitRGB(150, 150, 150);
    lightShader.setUniform3f("specularColor", specularColor.r, specularColor.g, specularColor.b);

    mesh.draw();
    lightShader.end();
}

void baseMesh::setupImportMesh(const char *fileName, bool loadMaterial)
{
    //determines where the color source comes from
    if (loadMaterial == true)
    {
        shaderColorSource = 1; //1 == true, 0 == false
    }

    //create mesh
    objLoader = new waveFrontLoader();
    objLoader->loadMaterial(loadMaterial);
    objLoader->loadFile(fileName);
    mesh = objLoader->generateMesh();
    delete objLoader;
}

void baseMesh::setupCubeMesh(float _length, float _width, float _height)
{
    ofBoxPrimitive box;
    box.set(_width, _height, _length);
    mesh = box.getMesh();
}

void baseMesh::setupSphereMesh(float _radius, int _resolution)
{
    ofSpherePrimitive sphere;
    sphere.set(_radius, _resolution);
    mesh = sphere.getMesh();
}

void baseMesh::setupPlaneMesh(float _width, float _height, int _rows, int _columns)
{
    ofPlanePrimitive plane;
    plane.set(_width, _height, _columns, _rows);
    mesh = plane.getMesh();
}

void baseMesh::scaleMesh(float scaleAmount)
{
    int numVerts = mesh.getNumVertices();
    std::vector<ofVec3f> meshVerts = mesh.getVertices();
    mesh.clearVertices();

    for (std::vector<ofVec3f>::iterator i = meshVerts.begin(); i != meshVerts.end(); ++i)
    {
        *i = scaleAmount * (*i);

        mesh.addVertex(*i);
    }
}

void baseMesh::addColors(float red, float green, float blue, float alpha)
{
    unitColor = mapToUnitRGB(red, green, blue);
    alphaColor = ofMap(alpha, 0.0, 255.0, 0.0, 1.0);
}

baseMesh::UnitRGB baseMesh::mapToUnitRGB(float red255, float green255, float blue255)
{
    UnitRGB unitOutColor;

    unitOutColor.r = ofMap(red255, 0.0, 255.0, 0.0, 1.0);
    unitOutColor.g = ofMap(green255, 0.0, 255.0, 0.0, 1.0);
    unitOutColor.b = ofMap(blue255, 0.0, 255.0, 0.0, 1.0);

    return unitOutColor;
}
<commit_msg>Update baseMesh.cpp<commit_after>#include "baseMesh.h"

baseMesh::baseMesh()
{
    lightShader.load("shaders/lightShader");

    //this defines where the color comes from
    //0 takes whatever RGB values you define
    //1 gets the data from a .mtl file
    //this is not accessed directly
    //
    shaderColorSource = 0;

    //if you need to load an image to pass in use this
    //
    //image.loadImage("stripes.jpg");
    //mesh.mapTexCoordsFromTexture(image.getTextureReference());
}

void baseMesh::update()
{

}

void baseMesh::draw(ofVec3f &_lightLocation, ofVec3f &_lightAttenuation, ofVec3f &_cameraLocation)
{
    lightLocation = _lightLocation;
    lightAttenuation = _lightAttenuation;
    cameraLocation = _cameraLocation;

    lightShader.begin();
    lightShader.setUniform3f("colorInput", unitColor.r, unitColor.g, unitColor.b);
    lightShader.setUniform1f("colorAlpha", alphaColor);
    lightShader.setUniform1i("shaderColorSource", shaderColorSource);
    lightShader.setUniform3f("lightLocation", lightLocation.x, lightLocation.y, lightLocation.z);
    lightShader.setUniform3f("cameraLocation", cameraLocation.x, cameraLocation.y, cameraLocation.z);

    lightShader.setUniform1f("constantAttenuation", lightAttenuation.x);//
    lightShader.setUniform1f("linearAttenuation", lightAttenuation.y);/////// XYZ used for easy data encapsulation
    lightShader.setUniform1f("quadraticAttenuation", lightAttenuation.z);//

    UnitRGB lightColor = mapToUnitRGB(231, 230, 220);
    lightShader.setUniform3f("lightColor", lightColor.r, lightColor.g, lightColor.b);

    UnitRGB specularColor = mapToUnitRGB(150, 150, 150);
    lightShader.setUniform3f("specularColor", specularColor.r, specularColor.g, specularColor.b);

    mesh.draw();
    lightShader.end();
}

void baseMesh::setupImportMesh(const char *fileName, bool loadMaterial)
{
    //determines where the color source comes from
    if (loadMaterial == true)
    {
        shaderColorSource = 1; //1 == true, 0 == false
    }

    //create mesh
    objLoader = new waveFrontLoader();
    objLoader->loadMaterial(loadMaterial);
    objLoader->loadFile(fileName);
    mesh = objLoader->generateMesh();
    delete objLoader;
}

void baseMesh::setupCubeMesh(float _length, float _width, float _height)
{
    ofBoxPrimitive box;
    box.set(_width, _height, _length);
    mesh = box.getMesh();
}

void baseMesh::setupSphereMesh(float _radius, int _resolution)
{
    ofSpherePrimitive sphere;
    sphere.set(_radius, _resolution);
    mesh = sphere.getMesh();
}

void baseMesh::setupPlaneMesh(float _width, float _height, int _rows, int _columns)
{
    ofPlanePrimitive plane;
    plane.set(_width, _height, _columns, _rows);
    mesh = plane.getMesh();
}

void baseMesh::scaleMesh(float scaleAmount)
{
    int numVerts = mesh.getNumVertices();
    std::vector<ofVec3f> meshVerts = mesh.getVertices();
    mesh.clearVertices();

    for (std::vector<ofVec3f>::iterator i = meshVerts.begin(); i != meshVerts.end(); ++i)
    {
        *i = scaleAmount * (*i);

        mesh.addVertex(*i);
    }
}

void baseMesh::addColors(float red, float green, float blue, float alpha)
{
    unitColor = mapToUnitRGB(red, green, blue);
    alphaColor = ofMap(alpha, 0.0, 255.0, 0.0, 1.0);
}

baseMesh::UnitRGB baseMesh::mapToUnitRGB(float red255, float green255, float blue255)
{
    UnitRGB unitOutColor;

    unitOutColor.r = ofMap(red255, 0.0, 255.0, 0.0, 1.0);
    unitOutColor.g = ofMap(green255, 0.0, 255.0, 0.0, 1.0);
    unitOutColor.b = ofMap(blue255, 0.0, 255.0, 0.0, 1.0);

    return unitOutColor;
}
<|endoftext|>


<commit_before>/*

PICCANTE Examples
The hottest examples of Piccante:
http://vcg.isti.cnr.it/piccante

Copyright (C) 2014
Visual Computing Laboratory - ISTI CNR
http://vcg.isti.cnr.it
First author: Francesco Banterle

This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3.0 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    See the GNU Lesser General Public License
    ( http://www.gnu.org/licenses/lgpl-3.0.html ) for more details.
*/

//This means that we disable Eigen; some functionalities cannot be used.
//For example, estimating the camera response function
#define PIC_DISABLE_EIGEN

//This means that OpenGL acceleration layer is disabled
#define PIC_DISABLE_OPENGL

//This means we do not use QT for I/O
#define PIC_DISABLE_QT

#include "piccante.hpp"

int main(int argc, char *argv[])
{
    std::string img_str;

    if(argc == 2) {
        img_str = argv[1];
    } else {
        img_str = "../data/input/bottles.hdr";
    }

    pic::JSONFile tmp;
    pic::JSONNumber ret;
    tmp.testParserNumbers();

    printf("Reading an HDR file...");

    pic::Image img;
    img.Read(img_str);

    printf("Ok\n");

    printf("Is it valid? ");
    if(img.isValid()) {
        printf("OK\n");

        //we estimate the best exposure for this HDR image
        float fstop = pic::findBestExposureHistogram(&img);

        printf("The best exposure value (histogram-based) is: %f f-stops\n", fstop);

        pic::FilterSimpleTMO fltSimpleTMO(2.2f, fstop);

        pic::Image *img_histo_tmo = fltSimpleTMO.Process(Single(&img), NULL);

        /*pic::LT_NOR implies that when we save the image
          we just convert it to 8-bit withou applying gamma.
          In this case, this is fine, because gamma was already applied
          in the pic::FilterSimpleTMO*/
        bool bWritten = img_histo_tmo->Write("../data/output/simple_exp_histo_tmo.bmp", pic::LT_NOR);

        if(bWritten) {
            printf("Ok\n");
        } else {
            printf("Writing had some issues!\n");
        }

        //
        //
        //

        //we estimate the best exposure for this HDR image
        fstop = pic::findBestExposureMean(&img);

        printf("The best exposure value (mean-based) is: %f f-stops\n", fstop);

        fltSimpleTMO.update(2.2f, fstop);

        pic::Image *img_mean_tmo = fltSimpleTMO.Process(Single(&img), NULL);

        /*pic::LT_NOR implies that when we save the image
          we just convert it to 8-bit withou applying gamma.
          In this case, this is fine, because gamma was already applied
          in the pic::FilterSimpleTMO*/
        bWritten = img_mean_tmo->Write("../data/output/simple_exp_mean_tmo.bmp", pic::LT_NOR);

        if(bWritten) {
            printf("Ok\n");
        } else {
            printf("Writing had some issues!\n");
        }

    } else {
        printf("No it is not a valid file!\n");
    }

    return 0;
}
<commit_msg>Update main.cpp<commit_after>/*

PICCANTE Examples
The hottest examples of Piccante:
http://vcg.isti.cnr.it/piccante

Copyright (C) 2014
Visual Computing Laboratory - ISTI CNR
http://vcg.isti.cnr.it
First author: Francesco Banterle

This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3.0 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    See the GNU Lesser General Public License
    ( http://www.gnu.org/licenses/lgpl-3.0.html ) for more details.
*/

//This means that we disable Eigen; some functionalities cannot be used.
//For example, estimating the camera response function
#define PIC_DISABLE_EIGEN

//This means that OpenGL acceleration layer is disabled
#define PIC_DISABLE_OPENGL

//This means we do not use QT for I/O
#define PIC_DISABLE_QT

#include "piccante.hpp"

int main(int argc, char *argv[])
{
    std::string img_str;

    if(argc == 2) {
        img_str = argv[1];
    } else {
        img_str = "../data/input/bottles.hdr";
    }

    printf("Reading an HDR file...");

    pic::Image img;
    img.Read(img_str);

    printf("Ok\n");

    printf("Is it valid? ");
    if(img.isValid()) {
        printf("OK\n");

        //we estimate the best exposure for this HDR image
        float fstop = pic::findBestExposureHistogram(&img);

        printf("The best exposure value (histogram-based) is: %f f-stops\n", fstop);

        pic::FilterSimpleTMO fltSimpleTMO(2.2f, fstop);

        pic::Image *img_histo_tmo = fltSimpleTMO.Process(Single(&img), NULL);

        /*pic::LT_NOR implies that when we save the image
          we just convert it to 8-bit withou applying gamma.
          In this case, this is fine, because gamma was already applied
          in the pic::FilterSimpleTMO*/
        bool bWritten = img_histo_tmo->Write("../data/output/simple_exp_histo_tmo.bmp", pic::LT_NOR);

        if(bWritten) {
            printf("Ok\n");
        } else {
            printf("Writing had some issues!\n");
        }

        //
        //
        //

        //we estimate the best exposure for this HDR image
        fstop = pic::findBestExposureMean(&img);

        printf("The best exposure value (mean-based) is: %f f-stops\n", fstop);

        fltSimpleTMO.update(2.2f, fstop);

        pic::Image *img_mean_tmo = fltSimpleTMO.Process(Single(&img), NULL);

        /*pic::LT_NOR implies that when we save the image
          we just convert it to 8-bit withou applying gamma.
          In this case, this is fine, because gamma was already applied
          in the pic::FilterSimpleTMO*/
        bWritten = img_mean_tmo->Write("../data/output/simple_exp_mean_tmo.bmp", pic::LT_NOR);

        if(bWritten) {
            printf("Ok\n");
        } else {
            printf("Writing had some issues!\n");
        }

    } else {
        printf("No it is not a valid file!\n");
    }

    return 0;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
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 the author nor the names of its
      contributors 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.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/utp_socket_manager.hpp"
#include <boost/shared_ptr.hpp>
#include <stdexcept>

namespace libtorrent
{
	TORRENT_EXPORT bool instantiate_connection(io_service& ios
		, proxy_settings const& ps, socket_type& s
		, void* ssl_context
		, utp_socket_manager* sm
		, bool peer_connection)
	{
		if (sm)
		{
			utp_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<utp_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<utp_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<utp_stream>(ios);
				str = s.get<utp_stream>();
			}
			str->set_impl(sm->new_utp_socket(str));
		}
#if TORRENT_USE_I2P
		else if (ps.type == proxy_settings::i2p_proxy)
		{
			// it doesn't make any sense to try ssl over i2p
			TORRENT_ASSERT(ssl_context == 0);
			s.instantiate<i2p_stream>(ios);
			s.get<i2p_stream>()->set_proxy(ps.hostname, ps.port);
		}
#endif
		else if (ps.type == proxy_settings::none
			|| (peer_connection && !ps.proxy_peer_connections))
		{
			stream_socket* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<stream_socket> >(ios, ssl_context);
				str = &s.get<ssl_stream<stream_socket> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<stream_socket>(ios);
				str = s.get<stream_socket>();
			}
		}
		else if (ps.type == proxy_settings::http
			|| ps.type == proxy_settings::http_pw)
		{
			http_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<http_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<http_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<http_stream>(ios);
				str = s.get<http_stream>();
			}

			str->set_proxy(ps.hostname, ps.port);
			if (ps.type == proxy_settings::http_pw)
				str->set_username(ps.username, ps.password);
		}
		else if (ps.type == proxy_settings::socks5
			|| ps.type == proxy_settings::socks5_pw
			|| ps.type == proxy_settings::socks4)
		{
			socks5_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<socks5_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<socks5_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<socks5_stream>(ios);
				str = s.get<socks5_stream>();
			}
			str->set_proxy(ps.hostname, ps.port);
			if (ps.type == proxy_settings::socks5_pw)
				str->set_username(ps.username, ps.password);
			if (ps.type == proxy_settings::socks4)
				str->set_version(4);
		}
		else
		{
			TORRENT_ASSERT_VAL(false, ps.type);
			return false;
		}
		return true;
	}

}

<commit_msg>remove unused variable<commit_after>/*

Copyright (c) 2007, Arvid Norberg
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 the author nor the names of its
      contributors 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.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/utp_socket_manager.hpp"
#include <boost/shared_ptr.hpp>
#include <stdexcept>

namespace libtorrent
{
	TORRENT_EXPORT bool instantiate_connection(io_service& ios
		, proxy_settings const& ps, socket_type& s
		, void* ssl_context
		, utp_socket_manager* sm
		, bool peer_connection)
	{
		if (sm)
		{
			utp_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<utp_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<utp_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<utp_stream>(ios);
				str = s.get<utp_stream>();
			}
			str->set_impl(sm->new_utp_socket(str));
		}
#if TORRENT_USE_I2P
		else if (ps.type == proxy_settings::i2p_proxy)
		{
			// it doesn't make any sense to try ssl over i2p
			TORRENT_ASSERT(ssl_context == 0);
			s.instantiate<i2p_stream>(ios);
			s.get<i2p_stream>()->set_proxy(ps.hostname, ps.port);
		}
#endif
		else if (ps.type == proxy_settings::none
			|| (peer_connection && !ps.proxy_peer_connections))
		{
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<stream_socket> >(ios, ssl_context);
			}
			else
#endif
			{
				s.instantiate<stream_socket>(ios);
			}
		}
		else if (ps.type == proxy_settings::http
			|| ps.type == proxy_settings::http_pw)
		{
			http_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<http_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<http_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<http_stream>(ios);
				str = s.get<http_stream>();
			}

			str->set_proxy(ps.hostname, ps.port);
			if (ps.type == proxy_settings::http_pw)
				str->set_username(ps.username, ps.password);
		}
		else if (ps.type == proxy_settings::socks5
			|| ps.type == proxy_settings::socks5_pw
			|| ps.type == proxy_settings::socks4)
		{
			socks5_stream* str;
#ifdef TORRENT_USE_OPENSSL
			if (ssl_context)
			{
				s.instantiate<ssl_stream<socks5_stream> >(ios, ssl_context);
				str = &s.get<ssl_stream<socks5_stream> >()->next_layer();
			}
			else
#endif
			{
				s.instantiate<socks5_stream>(ios);
				str = s.get<socks5_stream>();
			}
			str->set_proxy(ps.hostname, ps.port);
			if (ps.type == proxy_settings::socks5_pw)
				str->set_username(ps.username, ps.password);
			if (ps.type == proxy_settings::socks4)
				str->set_version(4);
		}
		else
		{
			TORRENT_ASSERT_VAL(false, ps.type);
			return false;
		}
		return true;
	}

}

<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include "../shared/util.h"
#include "../../include/ctf.hpp"

tCTF_ScheduleBase* global_schedule;

template<typename dtype>
void tCTF_Schedule<dtype>::record() {
  global_schedule = this;
}

template<typename dtype>
inline void tCTF_Schedule<dtype>::schedule_op_successors(tCTF_TensorOperation<dtype>* op) {
  assert(op->dependency_left == 0);

  typename std::vector<tCTF_TensorOperation<dtype>* >::iterator it;
  for (it=op->successors.begin(); it!=op->successors.end(); it++) {
    (*it)->dependency_left--;
    assert((*it)->dependency_left >= 0);
    if ((*it)->dependency_left == 0) {
      ready_tasks.push_back(*it);
    }
  }
}

template<typename dtype>
bool tensor_op_cost_greater(tCTF_TensorOperation<dtype>* A, tCTF_TensorOperation<dtype>* B) {
  return A->estimate_cost() > B->estimate_cost();
  //return A->successors.size() > B->successors.size();
}

/**
 * \brief Data structure containing what each partition is going to do.
 */
template<typename dtype>
struct tCTF_PartitionOps {
  int color;
  tCTF_World<dtype>* world;

  std::vector<tCTF_TensorOperation<dtype>*> ops;  // operations to execute
  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> local_tensors; // all local tensors used
  std::map<tCTF_Tensor<dtype>*, tCTF_Tensor<dtype>*> remap; // mapping from global tensor -> local tensor

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> global_tensors; // all referenced tensors stored as global tensors
  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> output_tensors; // tensors to be written back out, stored as global tensors
};

template<typename dtype>
tCTF_ScheduleTimer tCTF_Schedule<dtype>::partition_and_execute() {
  tCTF_ScheduleTimer schedule_timer;
  schedule_timer.total_time = MPI_Wtime();

  int rank, size;
  MPI_Comm_rank(world->comm, &rank);
  MPI_Comm_size(world->comm, &size);

  // Partition operations into worlds, and do split
  std::vector<tCTF_PartitionOps<dtype> > comm_ops; // operations for each subcomm
  int max_colors = size <= ready_tasks.size()? size : ready_tasks.size();
  if (partitions > 0 && max_colors > partitions) {
    max_colors = partitions;
  }

  // Sort tasks by descending runtime
  std::sort(ready_tasks.begin(), ready_tasks.end(), tensor_op_cost_greater<dtype>);

  // Maximum load imbalance algorithm:
  // Keep attempting to add the next available task until either reached max_colors
  // (user-specified parameter or number of nodes) or the next added node would
  // require less than one processor's worth of compute
  int starting_task;

  int max_starting_task = 0;
  int max_num_tasks = 0;
  int max_cost = 0;
  // Try to find the longest sequence of tasks that aren't too imbalanced
  for (int starting_task=0; starting_task<max_colors; starting_task++) {
    long_int sum_cost = 0;
    long_int min_cost = 0;
    int num_tasks = 0;
    for (int i=starting_task; i<max_colors; i++) {
      long_int this_cost = ready_tasks[i]->estimate_cost();
      if (min_cost == 0 || this_cost < min_cost) {
        min_cost = this_cost;
      }
      if (min_cost < (this_cost + sum_cost) / size) {
        break;
      } else {
        num_tasks = i - starting_task + 1;
        sum_cost += this_cost;
      }
    }

    if (num_tasks > max_num_tasks) {
      max_num_tasks = num_tasks;
      max_starting_task = starting_task;
      max_cost = sum_cost;
    }
  }

  // Do processor division according to estimated cost
  // Algorithm: divide sum_cost into size blocks, and each processor samples the
  // middle of its block to determine which task it works on
  int color_sample_point = (max_cost / size) * rank + (max_cost / size / 2);
  int my_color = 0;
  for (int i=0; i<max_num_tasks; i++) {
    my_color = i;
    if (color_sample_point < ready_tasks[max_starting_task+i]->estimate_cost()) {
      break;
    } else {
      color_sample_point -= ready_tasks[max_starting_task+i]->estimate_cost();
    }
  }

  MPI_Comm my_comm;
  MPI_Comm_split(world->comm, my_color, rank, &my_comm);

  if (rank == 0) {
    std::cout << "Maxparts " << max_colors << ", start " << max_starting_task <<
        ", tasks " << max_num_tasks << " // ";
    for (auto it : ready_tasks) {
      std::cout << it->name() << "(" << it->estimate_cost() << ") ";
    }
    std::cout << std::endl;
  }

  for (int color=0; color<max_num_tasks; color++) {
    comm_ops.push_back(tCTF_PartitionOps<dtype>());
    comm_ops[color].color = color;
    if (color == my_color) {
      comm_ops[color].world = new tCTF_World<dtype>(my_comm);
    } else {
      comm_ops[color].world = NULL;
    }
    comm_ops[color].ops.push_back(ready_tasks[max_starting_task + color]);
    ready_tasks.erase(ready_tasks.begin() + max_starting_task + color);
  }

  // Initialize local data structures
  for (auto &comm_op : comm_ops) {
    // gather required tensors
    for (auto &op : comm_op.ops) {
      assert(op != NULL);
      op->get_inputs(&comm_op.global_tensors);
      op->get_outputs(&comm_op.global_tensors);
      op->get_outputs(&comm_op.output_tensors);
    }
  }

  // Create and communicate tensors to subworlds
  schedule_timer.comm_down_time = MPI_Wtime();
  for (auto &comm_op : comm_ops) {
    for (auto &global_tensor : comm_op.global_tensors) {
      tCTF_Tensor<dtype>* local_clone;
      if (comm_op.world != NULL) {
        local_clone = new tCTF_Tensor<dtype>(*global_tensor, *comm_op.world);
      } else {
        local_clone = NULL;
      }
      comm_op.local_tensors.insert(local_clone);
      comm_op.remap[global_tensor] = local_clone;
      global_tensor->add_to_subworld(local_clone, 1, 0);
    }
    for (auto &output_tensor : comm_op.output_tensors) {
      assert(comm_op.remap.find(output_tensor) != comm_op.remap.end());
    }
  }
  schedule_timer.comm_down_time = MPI_Wtime() - schedule_timer.comm_down_time;

  // Run my tasks
  MPI_Barrier(world->comm);
  schedule_timer.exec_time = MPI_Wtime();
  if (comm_ops.size() > my_color) {
    for (auto &op : comm_ops[my_color].ops) {
      op->execute(&comm_ops[my_color].remap);
    }
  }

  MPI_Barrier(world->comm);
  schedule_timer.exec_time = MPI_Wtime() - schedule_timer.exec_time;

  // Communicate results back into global
  schedule_timer.comm_up_time = MPI_Wtime();
  for (auto &comm_op : comm_ops) {
    for (auto &output_tensor : comm_op.output_tensors) {
      output_tensor->add_from_subworld(comm_op.remap[output_tensor], 1, 0);
    }
  }
  schedule_timer.comm_up_time = MPI_Wtime() - schedule_timer.comm_up_time;

  // Clean up local tensors & world
  if (comm_ops.size() > my_color) {
    for (auto &local_tensor : comm_ops[my_color].local_tensors) {
      delete local_tensor;
    }
    delete comm_ops[my_color].world;
  }

  // Update ready tasks
  for (auto &comm_op : comm_ops) {
    for (auto &op : comm_op.ops) {
      schedule_op_successors(op);
    }
  }

  schedule_timer.total_time = MPI_Wtime() - schedule_timer.total_time;
  return schedule_timer;
}

/*
// The dead simple scheduler
template<typename dtype>
void tCTF_Schedule<dtype>::partition_and_execute() {
  while (ready_tasks.size() >= 1) {
    tCTF_TensorOperation<dtype>* op = ready_tasks.front();
    ready_tasks.pop_front();
    op->execute();
    schedule_op_successors(op);
  }
}
*/

template<typename dtype>
tCTF_ScheduleTimer tCTF_Schedule<dtype>::execute() {
  tCTF_ScheduleTimer schedule_timer;

  global_schedule = NULL;

  typename std::deque<tCTF_TensorOperation<dtype>*>::iterator it;

  // Initialize all tasks & initial ready queue
  for (it = steps_original.begin(); it != steps_original.end(); it++) {
    (*it)->dependency_left = (*it)->dependency_count;
  }
  ready_tasks = root_tasks;

  // Preprocess dummy operations
  while (!ready_tasks.empty()) {
    if (ready_tasks.front()->is_dummy()) {
      schedule_op_successors(ready_tasks.front());
      ready_tasks.pop_front();
    } else {
      break;
    }
  }

  while (!ready_tasks.empty()) {
    int rank;
    MPI_Comm_rank(world->comm, &rank);
    schedule_timer += partition_and_execute();
  }
  return schedule_timer;
}

template<typename dtype>
void tCTF_Schedule<dtype>::add_operation_typed(tCTF_TensorOperation<dtype>* op) {
  steps_original.push_back(op);

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> op_lhs_set;
  op->get_outputs(&op_lhs_set);
  assert(op_lhs_set.size() == 1); // limited case to make this a bit easier
  tCTF_Tensor<dtype>* op_lhs = *op_lhs_set.begin();

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> op_deps;
  op->get_inputs(&op_deps);

  typename std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>::iterator deps_iter;
  for (deps_iter = op_deps.begin(); deps_iter != op_deps.end(); deps_iter++) {
    tCTF_Tensor<dtype>* dep = *deps_iter;
    typename std::map<tCTF_Tensor<dtype>*, tCTF_TensorOperation<dtype>*>::iterator dep_loc = latest_write.find(dep);
    tCTF_TensorOperation<dtype>* dep_op;
    if (dep_loc != latest_write.end()) {
      dep_op = dep_loc->second;
    } else {
      // create dummy operation to serve as a root dependency
      // TODO: this can be optimized away
      dep_op = new tCTF_TensorOperation<dtype>(TENSOR_OP_NONE, NULL, NULL);
      latest_write[dep] = dep_op;
      root_tasks.push_back(dep_op);
      steps_original.push_back(dep_op);
    }

    dep_op->successors.push_back(op);
    dep_op->reads.push_back(op);
    op->dependency_count++;
  }
  typename std::map<tCTF_Tensor<dtype>*, tCTF_TensorOperation<dtype>*>::iterator prev_loc = latest_write.find(op_lhs);
  if (prev_loc != latest_write.end()) {
    // if there was a previous write, add its dependencies to my dependencies
    // to ensure that I don't clobber values that a ready dependency needs
    std::vector<tCTF_TensorOperation<dtype>*>* prev_reads = &(prev_loc->second->reads);
    typename std::vector<tCTF_TensorOperation<dtype>*>::iterator prev_iter;
    for (prev_iter = prev_reads->begin(); prev_iter != prev_reads->end(); prev_iter++) {
      if (*prev_iter != op) {
        (*prev_iter)->successors.push_back(op);
        op->dependency_count++;
      }
    }
  }

  latest_write[op_lhs] = op;
}

template<typename dtype>
void tCTF_Schedule<dtype>::add_operation(tCTF_TensorOperationBase* op) {
  tCTF_TensorOperation<dtype>* op_typed = dynamic_cast<tCTF_TensorOperation<dtype>* >(op);
  assert(op_typed != NULL);
  add_operation_typed(op_typed);
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::execute(std::map<tCTF_Tensor<dtype>*, tCTF_Tensor<dtype>*>* remap) {
  assert(global_schedule == NULL);  // ensure this isn't going into a record()

  tCTF_Idx_Tensor<dtype>* remapped_lhs = lhs;
  const tCTF_Term<dtype>* remapped_rhs = rhs;

  if (remap != NULL) {
    remapped_lhs = dynamic_cast<tCTF_Idx_Tensor<dtype>* >(remapped_lhs->clone(remap));
    assert(remapped_lhs != NULL);
    remapped_rhs = remapped_rhs->clone(remap);
  }

  switch (op) {
  case TENSOR_OP_NONE:
    break;
  case TENSOR_OP_SET:
    *remapped_lhs = *remapped_rhs;
    break;
  case TENSOR_OP_SUM:
    *remapped_lhs += *remapped_rhs;
    break;
  case TENSOR_OP_SUBTRACT:
    *remapped_lhs -= *remapped_rhs;
    break;
  case TENSOR_OP_MULTIPLY:
    *remapped_lhs *= *remapped_rhs;
    break;
  default:
    std::cerr << "tCTF_TensorOperation::execute(): unexpected op: " << op << std::endl;
    assert(false);
  }
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::get_outputs(std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>* outputs_set) const {
  assert(lhs->parent);
  assert(outputs_set != NULL);
  outputs_set->insert(lhs->parent);
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::get_inputs(std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>* inputs_set) const {
  assert(this != NULL);
  assert(rhs != NULL);
  assert(inputs_set != NULL);
  rhs->get_inputs(inputs_set);

  switch (op) {
  case TENSOR_OP_SET:
    break;
  case TENSOR_OP_SUM:
  case TENSOR_OP_SUBTRACT:
  case TENSOR_OP_MULTIPLY:
    assert(lhs != NULL && lhs->parent != NULL);
    inputs_set->insert(lhs->parent);
    break;
  default:
    std::cerr << "tCTF_TensorOperation::get_inputs(): unexpected op: " << op << std::endl;
    assert(false);
  }
}

template<typename dtype>
long_int tCTF_TensorOperation<dtype>::estimate_cost() {
  if (cached_estimated_cost == 0) {
    assert(rhs != NULL);
    assert(lhs != NULL);
    cached_estimated_cost = rhs->estimate_cost(*lhs);
    assert(cached_estimated_cost > 0);
  }
  return cached_estimated_cost;
}

template class tCTF_Schedule<double>;
#ifdef CTF_COMPLEX
template class tCTF_Schedule< std::complex<double> >;
#endif
<commit_msg>yet more asserts<commit_after>#include <algorithm>
#include <iostream>
#include "../shared/util.h"
#include "../../include/ctf.hpp"

tCTF_ScheduleBase* global_schedule;

template<typename dtype>
void tCTF_Schedule<dtype>::record() {
  global_schedule = this;
}

template<typename dtype>
inline void tCTF_Schedule<dtype>::schedule_op_successors(tCTF_TensorOperation<dtype>* op) {
  assert(op->dependency_left == 0);

  typename std::vector<tCTF_TensorOperation<dtype>* >::iterator it;
  for (it=op->successors.begin(); it!=op->successors.end(); it++) {
    (*it)->dependency_left--;
    assert((*it)->dependency_left >= 0);
    if ((*it)->dependency_left == 0) {
      ready_tasks.push_back(*it);
    }
  }
}

template<typename dtype>
bool tensor_op_cost_greater(tCTF_TensorOperation<dtype>* A, tCTF_TensorOperation<dtype>* B) {
  return A->estimate_cost() > B->estimate_cost();
  //return A->successors.size() > B->successors.size();
}

/**
 * \brief Data structure containing what each partition is going to do.
 */
template<typename dtype>
struct tCTF_PartitionOps {
  int color;
  tCTF_World<dtype>* world;

  std::vector<tCTF_TensorOperation<dtype>*> ops;  // operations to execute
  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> local_tensors; // all local tensors used
  std::map<tCTF_Tensor<dtype>*, tCTF_Tensor<dtype>*> remap; // mapping from global tensor -> local tensor

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> global_tensors; // all referenced tensors stored as global tensors
  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> output_tensors; // tensors to be written back out, stored as global tensors
};

template<typename dtype>
tCTF_ScheduleTimer tCTF_Schedule<dtype>::partition_and_execute() {
  tCTF_ScheduleTimer schedule_timer;
  schedule_timer.total_time = MPI_Wtime();

  int rank, size;
  MPI_Comm_rank(world->comm, &rank);
  MPI_Comm_size(world->comm, &size);

  // Partition operations into worlds, and do split
  std::vector<tCTF_PartitionOps<dtype> > comm_ops; // operations for each subcomm
  int max_colors = size <= ready_tasks.size()? size : ready_tasks.size();
  if (partitions > 0 && max_colors > partitions) {
    max_colors = partitions;
  }

  // Sort tasks by descending runtime
  std::sort(ready_tasks.begin(), ready_tasks.end(), tensor_op_cost_greater<dtype>);

  // Maximum load imbalance algorithm:
  // Keep attempting to add the next available task until either reached max_colors
  // (user-specified parameter or number of nodes) or the next added node would
  // require less than one processor's worth of compute
  int starting_task;

  int max_starting_task = 0;
  int max_num_tasks = 0;
  int max_cost = 0;
  // Try to find the longest sequence of tasks that aren't too imbalanced
  for (int starting_task=0; starting_task<max_colors; starting_task++) {
    long_int sum_cost = 0;
    long_int min_cost = 0;
    int num_tasks = 0;
    for (int i=starting_task; i<max_colors; i++) {
      long_int this_cost = ready_tasks[i]->estimate_cost();
      if (min_cost == 0 || this_cost < min_cost) {
        min_cost = this_cost;
      }
      if (min_cost < (this_cost + sum_cost) / size) {
        break;
      } else {
        num_tasks = i - starting_task + 1;
        sum_cost += this_cost;
      }
    }

    if (num_tasks > max_num_tasks) {
      max_num_tasks = num_tasks;
      max_starting_task = starting_task;
      max_cost = sum_cost;
    }
  }

  // Do processor division according to estimated cost
  // Algorithm: divide sum_cost into size blocks, and each processor samples the
  // middle of its block to determine which task it works on
  int color_sample_point = (max_cost / size) * rank + (max_cost / size / 2);
  int my_color = 0;
  for (int i=0; i<max_num_tasks; i++) {
    my_color = i;
    if (color_sample_point < ready_tasks[max_starting_task+i]->estimate_cost()) {
      break;
    } else {
      color_sample_point -= ready_tasks[max_starting_task+i]->estimate_cost();
    }
  }

  MPI_Comm my_comm;
  MPI_Comm_split(world->comm, my_color, rank, &my_comm);

  if (rank == 0) {
    std::cout << "Maxparts " << max_colors << ", start " << max_starting_task <<
        ", tasks " << max_num_tasks << " // ";
    for (auto it : ready_tasks) {
      std::cout << it->name() << "(" << it->estimate_cost() << ") ";
    }
    std::cout << std::endl;
  }

  for (int color=0; color<max_num_tasks; color++) {
    comm_ops.push_back(tCTF_PartitionOps<dtype>());
    comm_ops[color].color = color;
    if (color == my_color) {
      comm_ops[color].world = new tCTF_World<dtype>(my_comm);
    } else {
      comm_ops[color].world = NULL;
    }
    assert(max_starting_task + color < ready_tasks.size());
    comm_ops[color].ops.push_back(ready_tasks[max_starting_task + color]);
    ready_tasks.erase(ready_tasks.begin() + max_starting_task + color);
  }

  // Initialize local data structures
  for (auto &comm_op : comm_ops) {
    // gather required tensors
    for (auto &op : comm_op.ops) {
      assert(op != NULL);
      op->get_inputs(&comm_op.global_tensors);
      op->get_outputs(&comm_op.global_tensors);
      op->get_outputs(&comm_op.output_tensors);
    }
  }

  // Create and communicate tensors to subworlds
  schedule_timer.comm_down_time = MPI_Wtime();
  for (auto &comm_op : comm_ops) {
    for (auto &global_tensor : comm_op.global_tensors) {
      tCTF_Tensor<dtype>* local_clone;
      if (comm_op.world != NULL) {
        local_clone = new tCTF_Tensor<dtype>(*global_tensor, *comm_op.world);
      } else {
        local_clone = NULL;
      }
      comm_op.local_tensors.insert(local_clone);
      comm_op.remap[global_tensor] = local_clone;
      global_tensor->add_to_subworld(local_clone, 1, 0);
    }
    for (auto &output_tensor : comm_op.output_tensors) {
      assert(comm_op.remap.find(output_tensor) != comm_op.remap.end());
    }
  }
  schedule_timer.comm_down_time = MPI_Wtime() - schedule_timer.comm_down_time;

  // Run my tasks
  MPI_Barrier(world->comm);
  schedule_timer.exec_time = MPI_Wtime();
  if (comm_ops.size() > my_color) {
    for (auto &op : comm_ops[my_color].ops) {
      op->execute(&comm_ops[my_color].remap);
    }
  }

  MPI_Barrier(world->comm);
  schedule_timer.exec_time = MPI_Wtime() - schedule_timer.exec_time;

  // Communicate results back into global
  schedule_timer.comm_up_time = MPI_Wtime();
  for (auto &comm_op : comm_ops) {
    for (auto &output_tensor : comm_op.output_tensors) {
      output_tensor->add_from_subworld(comm_op.remap[output_tensor], 1, 0);
    }
  }
  schedule_timer.comm_up_time = MPI_Wtime() - schedule_timer.comm_up_time;

  // Clean up local tensors & world
  if (comm_ops.size() > my_color) {
    for (auto &local_tensor : comm_ops[my_color].local_tensors) {
      delete local_tensor;
    }
    delete comm_ops[my_color].world;
  }

  // Update ready tasks
  for (auto &comm_op : comm_ops) {
    for (auto &op : comm_op.ops) {
      schedule_op_successors(op);
    }
  }

  schedule_timer.total_time = MPI_Wtime() - schedule_timer.total_time;
  return schedule_timer;
}

/*
// The dead simple scheduler
template<typename dtype>
void tCTF_Schedule<dtype>::partition_and_execute() {
  while (ready_tasks.size() >= 1) {
    tCTF_TensorOperation<dtype>* op = ready_tasks.front();
    ready_tasks.pop_front();
    op->execute();
    schedule_op_successors(op);
  }
}
*/

template<typename dtype>
tCTF_ScheduleTimer tCTF_Schedule<dtype>::execute() {
  tCTF_ScheduleTimer schedule_timer;

  global_schedule = NULL;

  typename std::deque<tCTF_TensorOperation<dtype>*>::iterator it;

  // Initialize all tasks & initial ready queue
  for (it = steps_original.begin(); it != steps_original.end(); it++) {
    (*it)->dependency_left = (*it)->dependency_count;
  }
  ready_tasks = root_tasks;

  // Preprocess dummy operations
  while (!ready_tasks.empty()) {
    if (ready_tasks.front()->is_dummy()) {
      schedule_op_successors(ready_tasks.front());
      ready_tasks.pop_front();
    } else {
      break;
    }
  }

  while (!ready_tasks.empty()) {
    int rank;
    MPI_Comm_rank(world->comm, &rank);
    schedule_timer += partition_and_execute();
  }
  return schedule_timer;
}

template<typename dtype>
void tCTF_Schedule<dtype>::add_operation_typed(tCTF_TensorOperation<dtype>* op) {
  steps_original.push_back(op);

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> op_lhs_set;
  op->get_outputs(&op_lhs_set);
  assert(op_lhs_set.size() == 1); // limited case to make this a bit easier
  tCTF_Tensor<dtype>* op_lhs = *op_lhs_set.begin();

  std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>> op_deps;
  op->get_inputs(&op_deps);

  typename std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>::iterator deps_iter;
  for (deps_iter = op_deps.begin(); deps_iter != op_deps.end(); deps_iter++) {
    tCTF_Tensor<dtype>* dep = *deps_iter;
    typename std::map<tCTF_Tensor<dtype>*, tCTF_TensorOperation<dtype>*>::iterator dep_loc = latest_write.find(dep);
    tCTF_TensorOperation<dtype>* dep_op;
    if (dep_loc != latest_write.end()) {
      dep_op = dep_loc->second;
    } else {
      // create dummy operation to serve as a root dependency
      // TODO: this can be optimized away
      dep_op = new tCTF_TensorOperation<dtype>(TENSOR_OP_NONE, NULL, NULL);
      latest_write[dep] = dep_op;
      root_tasks.push_back(dep_op);
      steps_original.push_back(dep_op);
    }

    dep_op->successors.push_back(op);
    dep_op->reads.push_back(op);
    op->dependency_count++;
  }
  typename std::map<tCTF_Tensor<dtype>*, tCTF_TensorOperation<dtype>*>::iterator prev_loc = latest_write.find(op_lhs);
  if (prev_loc != latest_write.end()) {
    // if there was a previous write, add its dependencies to my dependencies
    // to ensure that I don't clobber values that a ready dependency needs
    std::vector<tCTF_TensorOperation<dtype>*>* prev_reads = &(prev_loc->second->reads);
    typename std::vector<tCTF_TensorOperation<dtype>*>::iterator prev_iter;
    for (prev_iter = prev_reads->begin(); prev_iter != prev_reads->end(); prev_iter++) {
      if (*prev_iter != op) {
        (*prev_iter)->successors.push_back(op);
        op->dependency_count++;
      }
    }
  }

  latest_write[op_lhs] = op;
}

template<typename dtype>
void tCTF_Schedule<dtype>::add_operation(tCTF_TensorOperationBase* op) {
  tCTF_TensorOperation<dtype>* op_typed = dynamic_cast<tCTF_TensorOperation<dtype>* >(op);
  assert(op_typed != NULL);
  add_operation_typed(op_typed);
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::execute(std::map<tCTF_Tensor<dtype>*, tCTF_Tensor<dtype>*>* remap) {
  assert(global_schedule == NULL);  // ensure this isn't going into a record()

  tCTF_Idx_Tensor<dtype>* remapped_lhs = lhs;
  const tCTF_Term<dtype>* remapped_rhs = rhs;

  if (remap != NULL) {
    remapped_lhs = dynamic_cast<tCTF_Idx_Tensor<dtype>* >(remapped_lhs->clone(remap));
    assert(remapped_lhs != NULL);
    remapped_rhs = remapped_rhs->clone(remap);
  }

  switch (op) {
  case TENSOR_OP_NONE:
    break;
  case TENSOR_OP_SET:
    *remapped_lhs = *remapped_rhs;
    break;
  case TENSOR_OP_SUM:
    *remapped_lhs += *remapped_rhs;
    break;
  case TENSOR_OP_SUBTRACT:
    *remapped_lhs -= *remapped_rhs;
    break;
  case TENSOR_OP_MULTIPLY:
    *remapped_lhs *= *remapped_rhs;
    break;
  default:
    std::cerr << "tCTF_TensorOperation::execute(): unexpected op: " << op << std::endl;
    assert(false);
  }
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::get_outputs(std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>* outputs_set) const {
  assert(lhs->parent);
  assert(outputs_set != NULL);
  outputs_set->insert(lhs->parent);
}

template<typename dtype>
void tCTF_TensorOperation<dtype>::get_inputs(std::set<tCTF_Tensor<dtype>*, tensor_tid_less<dtype>>* inputs_set) const {
  assert(this != NULL);
  assert(rhs != NULL);
  assert(inputs_set != NULL);
  rhs->get_inputs(inputs_set);

  switch (op) {
  case TENSOR_OP_SET:
    break;
  case TENSOR_OP_SUM:
  case TENSOR_OP_SUBTRACT:
  case TENSOR_OP_MULTIPLY:
    assert(lhs != NULL && lhs->parent != NULL);
    inputs_set->insert(lhs->parent);
    break;
  default:
    std::cerr << "tCTF_TensorOperation::get_inputs(): unexpected op: " << op << std::endl;
    assert(false);
  }
}

template<typename dtype>
long_int tCTF_TensorOperation<dtype>::estimate_cost() {
  if (cached_estimated_cost == 0) {
    assert(rhs != NULL);
    assert(lhs != NULL);
    cached_estimated_cost = rhs->estimate_cost(*lhs);
    assert(cached_estimated_cost > 0);
  }
  return cached_estimated_cost;
}

template class tCTF_Schedule<double>;
#ifdef CTF_COMPLEX
template class tCTF_Schedule< std::complex<double> >;
#endif
<|endoftext|>


<commit_before><commit_msg>Add version to window title if version.txt exists<commit_after><|endoftext|>


<commit_before><commit_msg>Updated version number and date.<commit_after><|endoftext|>


<commit_before><commit_msg>NEW removed MPI C++ binding and replaced them by C<commit_after><|endoftext|>


<commit_before><commit_msg>Remove a redundant test.<commit_after><|endoftext|>


<commit_before>// LAF Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/rw_lock.h"

// Uncomment this line in case that you want TRACE() lock/unlock
// operations.
//#define DEBUG_OBJECT_LOCKS

#include "base/scoped_lock.h"
#include "base/thread.h"

namespace base {

RWLock::RWLock()
  : m_write_lock(false)
  , m_read_locks(0)
  , m_weak_lock(nullptr)
{
}

RWLock::~RWLock()
{
  ASSERT(!m_write_lock);
  ASSERT(m_read_locks == 0);
  ASSERT(m_weak_lock == nullptr);
}

bool RWLock::lock(LockType lockType, int timeout)
{
  while (timeout >= 0) {
    {
      scoped_lock lock(m_mutex);

      // Check that there is no weak lock
      if (m_weak_lock) {
        if (*m_weak_lock == WeakLocked)
          *m_weak_lock = WeakUnlocking;

        // Wait some time
        if (*m_weak_lock == WeakUnlocking)
          goto go_wait;

        ASSERT(*m_weak_lock == WeakUnlocked);
      }

      switch (lockType) {

        case ReadLock:
          // If no body is writting the object...
          if (!m_write_lock) {
            // We can read it
            ++m_read_locks;
            return true;
          }
          break;

        case WriteLock:
          // If no body is reading and writting...
          if (m_read_locks == 0 && !m_write_lock) {
            // We can start writting the object...
            m_write_lock = true;

#ifdef DEBUG_OBJECT_LOCKS
            TRACE("LCK: lock: Locked <%p> to write\n", this);
#endif
            return true;
          }
          break;

      }

    go_wait:;
    }

    if (timeout > 0) {
      int delay = MIN(100, timeout);
      timeout -= delay;

#ifdef DEBUG_OBJECT_LOCKS
      TRACE("LCK: lock: wait 100 msecs for <%p>\n", this);
#endif

      base::this_thread::sleep_for(double(delay) / 1000.0);
    }
    else
      break;
  }

#ifdef DEBUG_OBJECT_LOCKS
  TRACE("LCK: lock: Cannot lock <%p> to %s (has %d read locks and %d write locks)\n",
    this, (lockType == ReadLock ? "read": "write"), m_read_locks, m_write_lock);
#endif

  return false;
}

void RWLock::downgradeToRead()
{
  scoped_lock lock(m_mutex);

  ASSERT(m_read_locks == 0);
  ASSERT(m_write_lock);

  m_write_lock = false;
  m_read_locks = 1;
}

void RWLock::unlock()
{
  scoped_lock lock(m_mutex);

  if (m_write_lock) {
    m_write_lock = false;
  }
  else if (m_read_locks > 0) {
    --m_read_locks;
  }
  else {
    ASSERT(false);
  }
}

bool RWLock::weakLock(WeakLock* weak_lock_flag)
{
  scoped_lock lock(m_mutex);

  if (m_weak_lock ||
      m_write_lock ||
      m_read_locks > 0)
    return false;

  m_weak_lock = weak_lock_flag;
  *m_weak_lock = WeakLocked;
  return true;
}

void RWLock::weakUnlock()
{
  ASSERT(m_weak_lock);
  ASSERT(*m_weak_lock != WeakLock::WeakUnlocked);
  ASSERT(!m_write_lock);
  ASSERT(m_read_locks == 0);

  if (m_weak_lock) {
    *m_weak_lock = WeakLock::WeakUnlocked;
    m_weak_lock = nullptr;
  }
}

bool RWLock::upgradeToWrite(int timeout)
{
  while (timeout >= 0) {
    {
      scoped_lock lock(m_mutex);

      // Check that there is no weak lock
      if (m_weak_lock) {
        if (*m_weak_lock == WeakLocked)
          *m_weak_lock = WeakUnlocking;

        // Wait some time
        if (*m_weak_lock == WeakUnlocking)
          goto go_wait;

        ASSERT(*m_weak_lock == WeakUnlocked);
      }

      // this only is possible if there are just one reader
      if (m_read_locks == 1) {
        ASSERT(!m_write_lock);
        m_read_locks = 0;
        m_write_lock = true;

#ifdef DEBUG_OBJECT_LOCKS
        TRACE("LCK: upgradeToWrite: Locked <%p> to write\n", this);
#endif

        return true;
      }

    go_wait:;
    }

    if (timeout > 0) {
      int delay = MIN(100, timeout);
      timeout -= delay;

#ifdef DEBUG_OBJECT_LOCKS
      TRACE("LCK: upgradeToWrite: wait 100 msecs for <%p>\n", this);
#endif

      base::this_thread::sleep_for(double(delay) / 1000.0);
    }
    else
      break;
  }

#ifdef DEBUG_OBJECT_LOCKS
  TRACE("LCK: upgradeToWrite: Cannot lock <%p> to write (has %d read locks and %d write locks)\n",
    this, m_read_locks, m_write_lock);
#endif

  return false;
}

} // namespace base
<commit_msg>Include base/debug.h to use ASSERT() in rw_lock.cpp<commit_after>// LAF Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/rw_lock.h"

// Uncomment this line in case that you want TRACE() lock/unlock
// operations.
//#define DEBUG_OBJECT_LOCKS

#include "base/debug.h"
#include "base/scoped_lock.h"
#include "base/thread.h"

namespace base {

RWLock::RWLock()
  : m_write_lock(false)
  , m_read_locks(0)
  , m_weak_lock(nullptr)
{
}

RWLock::~RWLock()
{
  ASSERT(!m_write_lock);
  ASSERT(m_read_locks == 0);
  ASSERT(m_weak_lock == nullptr);
}

bool RWLock::lock(LockType lockType, int timeout)
{
  while (timeout >= 0) {
    {
      scoped_lock lock(m_mutex);

      // Check that there is no weak lock
      if (m_weak_lock) {
        if (*m_weak_lock == WeakLocked)
          *m_weak_lock = WeakUnlocking;

        // Wait some time
        if (*m_weak_lock == WeakUnlocking)
          goto go_wait;

        ASSERT(*m_weak_lock == WeakUnlocked);
      }

      switch (lockType) {

        case ReadLock:
          // If no body is writting the object...
          if (!m_write_lock) {
            // We can read it
            ++m_read_locks;
            return true;
          }
          break;

        case WriteLock:
          // If no body is reading and writting...
          if (m_read_locks == 0 && !m_write_lock) {
            // We can start writting the object...
            m_write_lock = true;

#ifdef DEBUG_OBJECT_LOCKS
            TRACE("LCK: lock: Locked <%p> to write\n", this);
#endif
            return true;
          }
          break;

      }

    go_wait:;
    }

    if (timeout > 0) {
      int delay = MIN(100, timeout);
      timeout -= delay;

#ifdef DEBUG_OBJECT_LOCKS
      TRACE("LCK: lock: wait 100 msecs for <%p>\n", this);
#endif

      base::this_thread::sleep_for(double(delay) / 1000.0);
    }
    else
      break;
  }

#ifdef DEBUG_OBJECT_LOCKS
  TRACE("LCK: lock: Cannot lock <%p> to %s (has %d read locks and %d write locks)\n",
    this, (lockType == ReadLock ? "read": "write"), m_read_locks, m_write_lock);
#endif

  return false;
}

void RWLock::downgradeToRead()
{
  scoped_lock lock(m_mutex);

  ASSERT(m_read_locks == 0);
  ASSERT(m_write_lock);

  m_write_lock = false;
  m_read_locks = 1;
}

void RWLock::unlock()
{
  scoped_lock lock(m_mutex);

  if (m_write_lock) {
    m_write_lock = false;
  }
  else if (m_read_locks > 0) {
    --m_read_locks;
  }
  else {
    ASSERT(false);
  }
}

bool RWLock::weakLock(WeakLock* weak_lock_flag)
{
  scoped_lock lock(m_mutex);

  if (m_weak_lock ||
      m_write_lock ||
      m_read_locks > 0)
    return false;

  m_weak_lock = weak_lock_flag;
  *m_weak_lock = WeakLocked;
  return true;
}

void RWLock::weakUnlock()
{
  ASSERT(m_weak_lock);
  ASSERT(*m_weak_lock != WeakLock::WeakUnlocked);
  ASSERT(!m_write_lock);
  ASSERT(m_read_locks == 0);

  if (m_weak_lock) {
    *m_weak_lock = WeakLock::WeakUnlocked;
    m_weak_lock = nullptr;
  }
}

bool RWLock::upgradeToWrite(int timeout)
{
  while (timeout >= 0) {
    {
      scoped_lock lock(m_mutex);

      // Check that there is no weak lock
      if (m_weak_lock) {
        if (*m_weak_lock == WeakLocked)
          *m_weak_lock = WeakUnlocking;

        // Wait some time
        if (*m_weak_lock == WeakUnlocking)
          goto go_wait;

        ASSERT(*m_weak_lock == WeakUnlocked);
      }

      // this only is possible if there are just one reader
      if (m_read_locks == 1) {
        ASSERT(!m_write_lock);
        m_read_locks = 0;
        m_write_lock = true;

#ifdef DEBUG_OBJECT_LOCKS
        TRACE("LCK: upgradeToWrite: Locked <%p> to write\n", this);
#endif

        return true;
      }

    go_wait:;
    }

    if (timeout > 0) {
      int delay = MIN(100, timeout);
      timeout -= delay;

#ifdef DEBUG_OBJECT_LOCKS
      TRACE("LCK: upgradeToWrite: wait 100 msecs for <%p>\n", this);
#endif

      base::this_thread::sleep_for(double(delay) / 1000.0);
    }
    else
      break;
  }

#ifdef DEBUG_OBJECT_LOCKS
  TRACE("LCK: upgradeToWrite: Cannot lock <%p> to write (has %d read locks and %d write locks)\n",
    this, m_read_locks, m_write_lock);
#endif

  return false;
}

} // namespace base
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string16.h"

#if defined(WCHAR_T_IS_UTF16)

#error This file should not be used on 2-byte wchar_t systems
// If this winds up being needed on 2-byte wchar_t systems, either the
// definitions below can be used, or the host system's wide character
// functions like wmemcmp can be wrapped.

#elif defined(WCHAR_T_IS_UTF32)

#include "base/utf_string_conversions.h"

namespace base {

int c16memcmp(const char16* s1, const char16* s2, size_t n) {
  // We cannot call memcmp because that changes the semantics.
  while (n-- > 0) {
    if (*s1 != *s2) {
      // We cannot use (*s1 - *s2) because char16 is unsigned.
      return ((*s1 < *s2) ? -1 : 1);
    }
    ++s1;
    ++s2;
  }
  return 0;
}

size_t c16len(const char16* s) {
  const char16 *s_orig = s;
  while (*s) {
    ++s;
  }
  return s - s_orig;
}

const char16* c16memchr(const char16* s, char16 c, size_t n) {
  while (n-- > 0) {
    if (*s == c) {
      return s;
    }
    ++s;
  }
  return 0;
}

char16* c16memmove(char16* s1, const char16* s2, size_t n) {
  return reinterpret_cast<char16*>(memmove(s1, s2, n * sizeof(char16)));
}

char16* c16memcpy(char16* s1, const char16* s2, size_t n) {
  return reinterpret_cast<char16*>(memcpy(s1, s2, n * sizeof(char16)));
}

char16* c16memset(char16* s, char16 c, size_t n) {
  char16 *s_orig = s;
  while (n-- > 0) {
    *s = c;
    ++s;
  }
  return s_orig;
}

}  // namespace base

template class std::basic_string<char16, base::string16_char_traits>;

namespace base {
std::ostream& operator<<(std::ostream& out, const string16& str) {
  return out << UTF16ToUTF8(str);
}
}

#endif  // WCHAR_T_IS_UTF32
<commit_msg>#include <ostream> in base/string16.cc. This is required for the Mac OS X 10.6 SDK build. Otherwise, various bits of <ostream> that would be needed are declared but not defined.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string16.h"

#if defined(WCHAR_T_IS_UTF16)

#error This file should not be used on 2-byte wchar_t systems
// If this winds up being needed on 2-byte wchar_t systems, either the
// definitions below can be used, or the host system's wide character
// functions like wmemcmp can be wrapped.

#elif defined(WCHAR_T_IS_UTF32)

#include <ostream>

#include "base/utf_string_conversions.h"

namespace base {

int c16memcmp(const char16* s1, const char16* s2, size_t n) {
  // We cannot call memcmp because that changes the semantics.
  while (n-- > 0) {
    if (*s1 != *s2) {
      // We cannot use (*s1 - *s2) because char16 is unsigned.
      return ((*s1 < *s2) ? -1 : 1);
    }
    ++s1;
    ++s2;
  }
  return 0;
}

size_t c16len(const char16* s) {
  const char16 *s_orig = s;
  while (*s) {
    ++s;
  }
  return s - s_orig;
}

const char16* c16memchr(const char16* s, char16 c, size_t n) {
  while (n-- > 0) {
    if (*s == c) {
      return s;
    }
    ++s;
  }
  return 0;
}

char16* c16memmove(char16* s1, const char16* s2, size_t n) {
  return reinterpret_cast<char16*>(memmove(s1, s2, n * sizeof(char16)));
}

char16* c16memcpy(char16* s1, const char16* s2, size_t n) {
  return reinterpret_cast<char16*>(memcpy(s1, s2, n * sizeof(char16)));
}

char16* c16memset(char16* s, char16 c, size_t n) {
  char16 *s_orig = s;
  while (n-- > 0) {
    *s = c;
    ++s;
  }
  return s_orig;
}

}  // namespace base

template class std::basic_string<char16, base::string16_char_traits>;

namespace base {
std::ostream& operator<<(std::ostream& out, const string16& str) {
  return out << UTF16ToUTF8(str);
}
}

#endif  // WCHAR_T_IS_UTF32
<|endoftext|>


<commit_before>#ifndef LAYER_HPP_
#define LAYER_HPP_

#include "tensor.cu"
#include <vector>

// TODO: discuss and finalize interfaces: forward() & backward()

template <class Dtype>
class Layer {
public:
  virtual void Forward(Tensor<Dtype>* bottom, Tensor<Dtype>* top) = 0;
  // virtual std::vector<Tensor<Dtype>* > Forward(const std::vector<Tensor<Dtype> *> &bottom) = 0;
  // virtual void Backward(Packet& bottom, Packet& top) = 0;
};

#endif  // LAYER_HPP_
<commit_msg>layer.hpp<commit_after>#ifndef LAYER_HPP_
#define LAYER_HPP_

#include "tensor.cu"
#include <vector>

// TODO: discuss and finalize interfaces: forward() & backward()

template <class Dtype>
class Layer {
public:
  virtual void Forward(std::vector<Tensor<Dtype>*> &bottom, std::vector<Tensor<Dtype>*> &top) = 0;
  // virtual std::vector<Tensor<Dtype>* > Forward(const std::vector<Tensor<Dtype> *> &bottom) = 0;
  // virtual void Backward(Packet& bottom, Packet& top) = 0;
};

#endif  // LAYER_HPP_
<|endoftext|>


<commit_before>/*
        ##########    Copyright (C) 2015 Vincenzo Pacella
        ##      ##    Distributed under MIT license, see file LICENSE
        ##      ##    or <http://opensource.org/licenses/MIT>
        ##      ##
##########      ############################################################# shaduzlabs.com #####*/

#include <catch.hpp>
#include <unMIDIfy.hpp>

using namespace std::placeholders;

namespace sl
{
namespace midi
{
namespace test
{

class TestMidiListenerCallbacks : public Unmidifier
{
public:
  void onNoteOff(NoteOff msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::NoteOff);
    MidiNote note(MidiNote::Name::CSharp, 6);
    CHECK(note == msg_.getNote());
    CHECK(0x41 == msg_.getVelocity());
    CHECK(3 == msg_.data().size());
  }

  void onNoteOn(NoteOn msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::NoteOn);
    MidiNote note(MidiNote::Name::D, 6);
    CHECK(note == msg_.getNote());
    CHECK(0x42 == msg_.getVelocity());
    CHECK(3 == msg_.data().size());
  }

  void onPolyPressure(PolyPressure msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::PolyPressure);
    CHECK(0x63 == msg_.getNote());
    CHECK(0x43 == msg_.getPressure());
    CHECK(3 == msg_.data().size());
  }

  void onControlChange(ControlChange msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ControlChange);
    CHECK(0x64 == msg_.getControl());
    CHECK(0x44 == msg_.getValue());
    CHECK(3 == msg_.data().size());
  }

  void onProgramChange(ProgramChange msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ProgramChange);
    CHECK(0x65 == msg_.getProgram());
    CHECK(2 == msg_.data().size());
  }

  void onChannelPressure(ChannelPressure msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ChannelPressure);
    CHECK(0x66 == msg_.getPressure());
    CHECK(2 == msg_.data().size());
  }

  void onPitchBend(PitchBend msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::PitchBend);
    CHECK(0x8FF == msg_.getPitch());
    CHECK(3 == msg_.data().size());
  }
};

//--------------------------------------------------------------------------------------------------

TEST_CASE("Test MidiMessageListener callbacks", "[midi]")
{

  TestMidiListenerCallbacks midiListener;

  NoteOff msgNoteOff(MidiMessage::Channel::Ch1, 0x61, 0x41);
  midiListener.process(msgNoteOff.data());

  NoteOn msgNoteOn(MidiMessage::Channel::Ch2, 0x62, 0x42);
  midiListener.process(msgNoteOn.data());

  PolyPressure msgPolyPressure(MidiMessage::Channel::Ch3, 0x63, 0x43);
  midiListener.process(msgPolyPressure.data());

  ControlChange msgControlChange(MidiMessage::Channel::Ch4, 0x64, 0x44);
  midiListener.process(msgControlChange.data());

  ProgramChange msgProgramChange(MidiMessage::Channel::Ch5, 0x65);
  midiListener.process(msgProgramChange.data());

  ChannelPressure msgChannelPressure(MidiMessage::Channel::Ch6, 0x66);
  midiListener.process(msgChannelPressure.data());

  PitchBend msgPitchBend(MidiMessage::Channel::Ch7, 0x7F, 0x11);
  midiListener.process(msgPitchBend.data());
}

//--------------------------------------------------------------------------------------------------

TEST_CASE("Test SysEx messages", "[midi]")
{
  // 0x00 0x21 0x02 - Mutable Instruments
  SysEx msgSysEx_1(
    {0xF0, 0x00, 0x21, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xf7});
  SysEx msgSysEx_2(
    {0xF0, 0x00, 0x21, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09});

  CHECK(3 == msgSysEx_1.getHeader().size());
  CHECK(11 == msgSysEx_1.getPayload().size());

  CHECK(3 == msgSysEx_2.getHeader().size());
  CHECK(11 == msgSysEx_2.getPayload().size());

  CHECK(msgSysEx_1.getPayload().size() == msgSysEx_2.getPayload().size());

  // 0x41 - Roland Corporation
  SysEx msgSysEx_3(
    {0xF0, 0x41, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xf7});
  CHECK(1 == msgSysEx_3.getHeader().size());
  CHECK(11 == msgSysEx_3.getPayload().size());
}

//--------------------------------------------------------------------------------------------------

} // test
} // midi
} // sl
<commit_msg>fixed unit tests<commit_after>/*
        ##########    Copyright (C) 2015 Vincenzo Pacella
        ##      ##    Distributed under MIT license, see file LICENSE
        ##      ##    or <http://opensource.org/licenses/MIT>
        ##      ##
##########      ############################################################# shaduzlabs.com #####*/

#include <catch.hpp>
#include <unMIDIfy.hpp>

using namespace std::placeholders;

namespace sl
{
namespace midi
{
namespace test
{

class TestMidiListenerCallbacks : public Unmidifier
{
public:
  void onNoteOff(NoteOff msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::NoteOff);
    MidiNote note(MidiNote::Name::CSharp, 5);
    CHECK(note == msg_.getNote());
    CHECK(0x41 == msg_.getVelocity());
    CHECK(3 == msg_.data().size());
  }

  void onNoteOn(NoteOn msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::NoteOn);
    MidiNote note(MidiNote::Name::D, 5);
    CHECK(note == msg_.getNote());
    CHECK(0x42 == msg_.getVelocity());
    CHECK(3 == msg_.data().size());
  }

  void onPolyPressure(PolyPressure msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::PolyPressure);
    CHECK(0x63 == msg_.getNote());
    CHECK(0x43 == msg_.getPressure());
    CHECK(3 == msg_.data().size());
  }

  void onControlChange(ControlChange msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ControlChange);
    CHECK(0x64 == msg_.getControl());
    CHECK(0x44 == msg_.getValue());
    CHECK(3 == msg_.data().size());
  }

  void onProgramChange(ProgramChange msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ProgramChange);
    CHECK(0x65 == msg_.getProgram());
    CHECK(2 == msg_.data().size());
  }

  void onChannelPressure(ChannelPressure msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::ChannelPressure);
    CHECK(0x66 == msg_.getPressure());
    CHECK(2 == msg_.data().size());
  }

  void onPitchBend(PitchBend msg_) override
  {
    CHECK(msg_.getType() == MidiMessage::Type::PitchBend);
    CHECK(0x8FF == msg_.getPitch());
    CHECK(3 == msg_.data().size());
  }
};

//--------------------------------------------------------------------------------------------------

TEST_CASE("Test MidiMessageListener callbacks", "[midi]")
{

  TestMidiListenerCallbacks midiListener;

  NoteOff msgNoteOff(MidiMessage::Channel::Ch1, 0x61, 0x41);
  midiListener.process(msgNoteOff.data());

  NoteOn msgNoteOn(MidiMessage::Channel::Ch2, 0x62, 0x42);
  midiListener.process(msgNoteOn.data());

  PolyPressure msgPolyPressure(MidiMessage::Channel::Ch3, 0x63, 0x43);
  midiListener.process(msgPolyPressure.data());

  ControlChange msgControlChange(MidiMessage::Channel::Ch4, 0x64, 0x44);
  midiListener.process(msgControlChange.data());

  ProgramChange msgProgramChange(MidiMessage::Channel::Ch5, 0x65);
  midiListener.process(msgProgramChange.data());

  ChannelPressure msgChannelPressure(MidiMessage::Channel::Ch6, 0x66);
  midiListener.process(msgChannelPressure.data());

  PitchBend msgPitchBend(MidiMessage::Channel::Ch7, 0x7F, 0x11);
  midiListener.process(msgPitchBend.data());
}

//--------------------------------------------------------------------------------------------------

TEST_CASE("Test SysEx messages", "[midi]")
{
  // 0x00 0x21 0x02 - Mutable Instruments
  SysEx msgSysEx_1(
    {0xF0, 0x00, 0x21, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xf7});
  SysEx msgSysEx_2(
    {0xF0, 0x00, 0x21, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09});

  CHECK(3 == msgSysEx_1.getHeader().size());
  CHECK(11 == msgSysEx_1.getPayload().size());

  CHECK(3 == msgSysEx_2.getHeader().size());
  CHECK(11 == msgSysEx_2.getPayload().size());

  CHECK(msgSysEx_1.getPayload().size() == msgSysEx_2.getPayload().size());

  // 0x41 - Roland Corporation
  SysEx msgSysEx_3(
    {0xF0, 0x41, 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xf7});
  CHECK(1 == msgSysEx_3.getHeader().size());
  CHECK(11 == msgSysEx_3.getPayload().size());
}

//--------------------------------------------------------------------------------------------------

} // test
} // midi
} // sl
<|endoftext|>


<commit_before>#include <cmath>
#include "mbed.h"
#include "motor.h"
#include "encoder.h"
#include "irsensor.h"

Serial serial(PA_9, PA_10);

Motor left_motor(PB_6, PA_7, 3);
Motor right_motor(PC_7, PB_10);

Encoder left_encoder(PA_1, PC_4, Encoder::X2, 1.72);
Encoder right_encoder(PA_15, PB_3, Encoder::X0);

Ticker interrupts;

IRSensor left_irsensor(PC_0, PB_7);
IRSensor front_left_irsensor(PC_1, PB_0);
IRSensor front_right_irsensor(PA_4, PC_11);
IRSensor right_irsensor(PA_0, PC_10);

const float IR_READ_DELAY = 0.1;

void forward(int);
void right_turn(int);
void ir_update();

int main()
{
	interrupts.attach(&ir_update, IR_READ_DELAY);
    forward(100000);
}

void forward(int cells)
{
    const float P = 0.002;
    const float I = 0;
    const float D = 0;
    const int CELL_LENGTH = 500;
    const float SPEED = 0.1;
    const float DELAY = 0.005;
    const int LEFT_STOP = 950;
    const int RIGHT_STOP = 1140;
    // Divisor is to ignore small errors between left & right, multiplier is for error weighting
    const int IR_DIVISOR = 100;
    const int IR_MULTIPLIER = 2;

    int prev_error = 0;
    int integral = 0;
    left_encoder.reset();
    right_encoder.reset();
    while(left_encoder.count() < CELL_LENGTH * cells) {
        if (front_left_irsensor.getValue() >= LEFT_STOP ||
                front_right_irsensor.getValue() >= RIGHT_STOP) {
            left_motor.set_speed(0);
            right_motor.set_speed(0);
            continue;
        }
        int error = left_encoder.count() - right_encoder.count();
        error += IR_MULTIPLIER *
            ((right_irsensor.getValue() - left_irsensor.getValue()) / IR_DIVISOR);
        integral += error;
        float correction = P * error + I * integral + D * (error - prev_error);
        if(correction > SPEED) {
            correction = SPEED;
        } else if(correction < -1 * SPEED) {
            correction = -1 * SPEED;
        }
        prev_error = error;
        left_motor.set_speed(SPEED - correction);
        right_motor.set_speed(SPEED + correction);
        wait(DELAY);
    }
    left_motor.set_speed(0);
    right_motor.set_speed(0);
    wait(0.1);
}

void right_turn(int times)
{
    int dir = (times > 0) ? 1 : -1;
    left_encoder.reset();
    right_encoder.reset();
    left_motor.set_speed(dir * 0.05);
    right_motor.set_speed(dir * -0.05);
    while(abs(left_encoder.count() - right_encoder.count()) < 200 * abs(times));
    left_motor.set_speed(0);
    right_motor.set_speed(0);
    wait(0.5);
}

void ir_update()
{
	left_irsensor.read();
	front_left_irsensor.read();
	front_right_irsensor.read();
	right_irsensor.read();
}
<commit_msg>super sketch code that somehow got 1st place<commit_after>#include <cmath>
#include "mbed.h"
#include "motor.h"
#include "encoder.h"
#include "irsensor.h"

Serial serial(PA_9, PA_10);

Motor left_motor(PB_6, PA_7, 3);
Motor right_motor(PC_7, PB_10);

Encoder left_encoder(PA_1, PC_4, Encoder::X2, 1.72);
Encoder right_encoder(PA_15, PB_3, Encoder::X0);

Ticker interrupts;

IRSensor left_irsensor(PC_0, PB_7);
IRSensor front_left_irsensor(PC_1, PB_0);
IRSensor front_right_irsensor(PA_4, PC_11);
IRSensor right_irsensor(PA_0, PC_10);

const int SIDE_BIAS = 0;

enum Direction {
    LEFT,
    RIGHT
};

void forward();
void backward();
void turn(Direction);
void ir_update();

int main()
{
    const float IR_READ_DELAY = 0.1;
	interrupts.attach(&ir_update, IR_READ_DELAY);
    while(true) {
        forward();
        backward();
        if(left_irsensor.getValue() < right_irsensor.getValue()) {
            turn(LEFT);
        } else {
            turn(RIGHT);
        }
    }
}

inline bool is_wall()
{
    const int LEFT_STOP = 1050;
    const int RIGHT_STOP = 1250;
    return front_left_irsensor.getValue() >= LEFT_STOP || front_right_irsensor.getValue() >= RIGHT_STOP;
}

inline bool is_crashed()
{
    return front_left_irsensor.getValue() > 3800 || front_right_irsensor.getValue() > 3800;
}

void backward()
{
    const float BACKWARD_SPEED = 0.05;
    while(is_crashed()) {
        left_motor.set_speed(-1*BACKWARD_SPEED);
        right_motor.set_speed(-1*BACKWARD_SPEED);
    }
    left_motor.set_speed(0);
    right_motor.set_speed(0);
    wait(0.1);
}

void forward()
{
    const float P = 0.002;
    const float I = 0;
    const float D = 0;
    const float SPEED = 0.1;
    const int CELL_LENGTH = 500;
    const float DELAY = 0.005;
    const float IR_MULTIPLIER = 0.025;

    int prev_error = 0;
    int integral = 0;

    left_encoder.reset();
    right_encoder.reset();
    while(!is_wall()) {
        int error = left_encoder.count() - right_encoder.count();
        error += IR_MULTIPLIER * (right_irsensor.getValue() - left_irsensor.getValue() - SIDE_BIAS);
        integral += error;
        float correction = P * error + I * integral + D * (error - prev_error);
        if(correction > SPEED) {
            correction = SPEED;
        } else if(correction < -1 * SPEED) {
            correction = -1 * SPEED;
        }
        prev_error = error;
        left_motor.set_speed(SPEED - correction);
        right_motor.set_speed(SPEED + correction);
        wait(DELAY);
    }
    left_motor.set_speed(0);
    right_motor.set_speed(0);
    wait(0.1);
}

void turn(Direction d)
{
    const float TURN_SPEED = 0.03;
    const float RIGHT_SPEED = 0.05;
    const int TURN_COUNT = 134;
    int dir = (d == RIGHT) ? 1 : -1;
    left_encoder.reset();
    right_encoder.reset();
    left_motor.set_speed(dir * TURN_SPEED);
    right_motor.set_speed(dir * -1*RIGHT_SPEED);
    while(is_wall()) {
        if(is_crashed()) {
            break;
        }
    }
    left_motor.set_speed(0);
    right_motor.set_speed(0);
    wait(0.1);
}

void ir_update()
{
	left_irsensor.read();
	front_left_irsensor.read();
	front_right_irsensor.read();
	right_irsensor.read();
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2000, 2001, 2002, 2003 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------------------------------------------------------

#include <base/logstream.h>
#include <lac/vector.h>
#include <lac/block_vector.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <dofs/dof_renumbering.h>
#include <fe/fe_dgp.h>
#include <fe/fe_dgq.h>
#include <fe/fe_q.h>
#include <fe/fe_system.h>
#include <multigrid/mg_dof_handler.h>
#include <multigrid/mg_transfer.h>
#include <multigrid/mg_dof_tools.h>

#include <fstream>
#include <iostream>
#include <algorithm>

template <int dim>
void check_simple(const FiniteElement<dim>& fe)
{
  deallog << fe.get_name() << std::endl;

  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr);
  tr.refine_global(2);

  MGDoFHandler<dim> mgdof(tr);
  mgdof.distribute_dofs(fe);

  MGTransferPrebuilt<double> transfer;
  transfer.build_matrices(mgdof);

  Vector<double> u2(mgdof.n_dofs(2));
  Vector<double> u1(mgdof.n_dofs(1));
  Vector<double> u0(mgdof.n_dofs(0));

  u0 = 1;
  transfer.prolongate(1,u1,u0);
  transfer.prolongate(2,u2,u1);
  deallog << "u0 " << u0.l2_norm()
	  << "\tu1 " << u1.l2_norm()
	  << "\tu2 " << u2.l2_norm();
  u1 = 0.;
  u0 = 0.;
  transfer.restrict_and_add(2,u1,u2);
  transfer.restrict_and_add(1,u0,u1);
  deallog << "\tu1 " << u1.l2_norm()
	  << "\tu0 " << u0.l2_norm()
	  << std::endl;
}

template <int dim>
void check_select(const FiniteElement<dim>& fe,
		 std::vector<unsigned int> target_component)
{
  deallog << fe.get_name() << std::endl;

  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr);
  tr.refine_global(2);

  MGDoFHandler<dim> mgdof(tr);
  mgdof.distribute_dofs(fe);
  DoFRenumbering::component_wise(mgdof, target_component);
  for (unsigned int l=0;l<tr.n_levels();++l)
    DoFRenumbering::component_wise(mgdof, l, target_component);

  std::vector<std::vector<unsigned int> > ndofs(mgdof.get_tria().n_levels());
  MGTools::count_dofs_per_component(mgdof, ndofs, target_component);
  for (unsigned int l=0;l<ndofs.size();++l)
    {
      deallog << "Level " << l << " dofs:";
      for (unsigned int i=0;i<ndofs[l].size();++i)
	deallog << ' ' << ndofs[l][i];
      deallog << std::endl;
    }

  MGTransferSelect<double> transfer;
  transfer.build_matrices(mgdof, 0,
			  target_component);

  Vector<double> u2(ndofs[2][0]);
  Vector<double> u1(ndofs[1][0]);
  Vector<double> u0(ndofs[0][0]);

  u0 = 1;
  transfer.prolongate(1,u1,u0);
  transfer.prolongate(2,u2,u1);
  deallog << "u0 " << u0.l2_norm()
	  << "\tu1 " << u1.l2_norm()
	  << "\tu2 " << u2.l2_norm();
  u1 = 0.;
  u0 = 0.;
  transfer.restrict_and_add(2,u1,u2);
  transfer.restrict_and_add(1,u0,u1);
  deallog << "\tu1 " << u1.l2_norm()
	  << "\tu0 " << u0.l2_norm()
	  << std::endl;
}

int main()
{
//  check_simple (FE_DGP<2>(0));
//  check_simple (FE_DGP<2>(1));
  check_simple (FE_DGQ<2>(1));
//  check_simple (FE_DGQ<2>(2));
//  check_simple (FE_Q<2>(1));
//  check_simple (FE_Q<2>(2));

  std::vector<unsigned int> v1(4);
  std::vector<unsigned int> v2(4);
  std::vector<unsigned int> v3(4);
  for (unsigned int i=0;i<4;++i)
    {
      v1[i] = i;
      v2[i] = 0;
      v3[i] = i/2;
    }

  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v1);
  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v2);
  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v3);
}
<commit_msg>first multigrid test<commit_after>//----------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2000, 2001, 2002, 2003 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------------------------------------------------------

#include <base/logstream.h>
#include <lac/vector.h>
#include <lac/block_vector.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <dofs/dof_renumbering.h>
#include <fe/fe_dgp.h>
#include <fe/fe_dgq.h>
#include <fe/fe_q.h>
#include <fe/fe_system.h>
#include <multigrid/mg_dof_handler.h>
#include <multigrid/mg_transfer.h>
#include <multigrid/mg_dof_tools.h>

#include <fstream>
#include <iostream>
#include <algorithm>

template <int dim>
void check_simple(const FiniteElement<dim>& fe)
{
  deallog << fe.get_name() << std::endl;

  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr);
  tr.refine_global(2);

  MGDoFHandler<dim> mgdof(tr);
  mgdof.distribute_dofs(fe);

  MGTransferPrebuilt<double> transfer;
  transfer.build_matrices(mgdof);

  Vector<double> u2(mgdof.n_dofs(2));
  Vector<double> u1(mgdof.n_dofs(1));
  Vector<double> u0(mgdof.n_dofs(0));

  u0 = 1;
  transfer.prolongate(1,u1,u0);
  transfer.prolongate(2,u2,u1);
  deallog << "u0 " << u0.l2_norm()
	  << "\tu1 " << u1.l2_norm()
	  << "\tu2 " << u2.l2_norm();
  u1 = 0.;
  u0 = 0.;
  transfer.restrict_and_add(2,u1,u2);
  transfer.restrict_and_add(1,u0,u1);
  deallog << "\tu1 " << u1.l2_norm()
	  << "\tu0 " << u0.l2_norm()
	  << std::endl;
}

template <int dim>
void check_select(const FiniteElement<dim>& fe,
		  std::vector<unsigned int> target_component,
		  std::vector<unsigned int> mg_target_component)
{
  deallog << fe.get_name() << std::endl;

  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr);
  tr.refine_global(2);

  MGDoFHandler<dim> mgdof(tr);
  mgdof.distribute_dofs(fe);
  DoFRenumbering::component_wise(mgdof, target_component);
  for (unsigned int l=0;l<tr.n_levels();++l)
    DoFRenumbering::component_wise(mgdof, l, mg_target_component);

  std::vector<std::vector<unsigned int> > ndofs(mgdof.get_tria().n_levels());
  MGTools::count_dofs_per_component(mgdof, ndofs, mg_target_component);
  for (unsigned int l=0;l<ndofs.size();++l)
    {
      deallog << "Level " << l << " dofs:";
      for (unsigned int i=0;i<ndofs[l].size();++i)
	deallog << ' ' << ndofs[l][i];
      deallog << std::endl;
    }

  MGTransferSelect<double> transfer;
  transfer.build_matrices(mgdof, 0,
			  mg_target_component);

  Vector<double> u2(ndofs[2][0]);
  Vector<double> u1(ndofs[1][0]);
  Vector<double> u0(ndofs[0][0]);

  u0 = 1;
  transfer.prolongate(1,u1,u0);
  transfer.prolongate(2,u2,u1);
  deallog << "u0 " << u0.l2_norm()
	  << "\tu1 " << u1.l2_norm()
	  << "\tu2 " << u2.l2_norm();
  u1 = 0.;
  u0 = 0.;
  transfer.restrict_and_add(2,u1,u2);
  transfer.restrict_and_add(1,u0,u1);
  deallog << "\tu1 " << u1.l2_norm()
	  << "\tu0 " << u0.l2_norm()
	  << std::endl;
}

int main()
{
  std::ofstream logfile("transfer.output");
  logfile.precision(3);
  deallog.attach(logfile);
  deallog.depth_console(100);

//  check_simple (FE_DGP<2>(0));
//  check_simple (FE_DGP<2>(1));
  check_simple (FE_DGQ<2>(1));
//  check_simple (FE_DGQ<2>(2));
//  check_simple (FE_Q<2>(1));
//  check_simple (FE_Q<2>(2));

  std::vector<unsigned int> v1(4);
  std::vector<unsigned int> v2(4);
  std::vector<unsigned int> v3(4);
  for (unsigned int i=0;i<4;++i)
    {
      v1[i] = i;
      v2[i] = 0;
      v3[i] = i/2;
    }

  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v1, v1);
  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v2, v2);
  check_select (FESystem<2>(FE_DGQ<2>(1), 4), v3, v3);
}
<|endoftext|>