<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef DISPATCHER_HH
#define DISPATCHER_HH

#include <stdexcept>
#include <queue>

#include "common.hh"
#include "locks.hh"

class Dispatcher;

enum task_state {
    task_dead,
    task_running,
    task_sleeping
};

enum dispatcher_state {
    dispatcher_running,
    dispatcher_stopping,
    dispatcher_stopped
};

class Task;

typedef shared_ptr<Task> TaskId;

class DispatcherCallback {
public:
    virtual ~DispatcherCallback() {}
    virtual bool callback(Dispatcher &d, TaskId t) = 0;
};

class CompareTasks;

class Task {
friend class CompareTasks;
public:
    ~Task() { }
private:
    Task(shared_ptr<DispatcherCallback> cb, int p=0, double sleeptime=0) :
         callback(cb), priority(p) {
        if (sleeptime > 0) {
            snooze(sleeptime);
        } else {
            state = task_running;
        }
    }

    Task(const Task &task) {
        priority = task.priority;
        state = task_running;
        callback = task.callback;
    }

    void snooze(const double secs) {
        LockHolder lh(mutex);
        gettimeofday(&waketime, NULL);
        advance_tv(waketime, secs);
        state = task_sleeping;
    }

    bool run(Dispatcher &d, TaskId t) {
        return callback->callback(d, t);
    }

    void cancel() {
        LockHolder lh(mutex);
        state = task_dead;
    }

    friend class Dispatcher;
    std::string name;
    struct timeval waketime;
    shared_ptr<DispatcherCallback> callback;
    int priority;
    enum task_state state;
    Mutex mutex;
};

class CompareTasks {
public:
    bool operator()(TaskId t1, TaskId t2) {
        if (t1->state == task_running) {
            if (t2->state == task_running) {
                return t1->priority > t2->priority;
            } else if (t2->state == task_sleeping) {
                return false;
            }
        } else if (t1->state == task_sleeping && t2->state == task_sleeping) {
            return less_tv(t2->waketime, t1->waketime);
        }
        return true;
    }
};

class Dispatcher {
public:
    Dispatcher() : state(dispatcher_running) { }

    ~Dispatcher() {
        stop();
    }

    TaskId schedule(shared_ptr<DispatcherCallback> callback, int priority=0,
                    double sleeptime=0) {
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Scheduling a new task\n");
        LockHolder lh(mutex);
        TaskId task(new Task(callback, priority, sleeptime));
        queue.push(task);
        mutex.notify();
        return TaskId(task);
    }

    TaskId wake(TaskId task) {
        cancel(task);
        TaskId oldTask(task);
        TaskId newTask(new Task(*oldTask));
        queue.push(newTask);
        mutex.notify();
        return TaskId(newTask);
    }

    void start();

    void run() {
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher starting\n");
        while (state == dispatcher_running) {
            LockHolder lh(mutex);
            if (queue.empty()) {
                // Wait forever
                mutex.wait();
            } else {
                TaskId task = queue.top();
                assert(task);
                LockHolder tlh(task->mutex);
                switch (task->state) {
                case task_sleeping:
                    {
                        struct timeval tv;
                        gettimeofday(&tv, NULL);
                        if (less_tv(tv, task->waketime)) {
                            tlh.unlock();
                            mutex.wait(task->waketime);
                        } else {
                            task->state = task_running;
                        }
                    }
                    break;
                case task_running:
                    queue.pop();
                    lh.unlock();
                    tlh.unlock();
                    try {
                        if(task->run(*this, TaskId(task))) {
                            reschedule(task);
                        }
                    } catch (std::exception& e) {
                        std::cerr << "exception caught in task " << task->name << ": " << e.what() << std::endl;
                    } catch(...) {
                        std::cerr << "Caught a fatal exception in task" << task->name <<std::endl;
                    }
                    break;
                case task_dead:
                    queue.pop();
                    break;
                default:
                    throw std::runtime_error("Unexpected state for task");
                }
            }
        }

        state = dispatcher_stopped;
        mutex.notify();
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher exited\n");
    }

    void stop() {
        LockHolder lh(mutex);
        if (state == dispatcher_stopped) {
            return;
        }
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Stopping dispatcher\n");
        state = dispatcher_stopping;
        mutex.notify();
        lh.unlock();
        pthread_join(thread, NULL);
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher stopped\n");
    }

    void snooze(TaskId t, double sleeptime) {
        t->snooze(sleeptime);
    }

    void cancel(TaskId t) {
        t->cancel();
    }

private:
    void reschedule(TaskId task) {
        // If the task is already in the queue it'll get run twice
        LockHolder lh(mutex);
        queue.push(task);
    }

    pthread_t thread;
    SyncObject mutex;
    std::priority_queue<TaskId, std::deque<TaskId >,
                        CompareTasks> queue;
    enum dispatcher_state state;
};

#endif
<commit_msg>Don't try to stop a stopping dispatcher.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef DISPATCHER_HH
#define DISPATCHER_HH

#include <stdexcept>
#include <queue>

#include "common.hh"
#include "locks.hh"

class Dispatcher;

enum task_state {
    task_dead,
    task_running,
    task_sleeping
};

enum dispatcher_state {
    dispatcher_running,
    dispatcher_stopping,
    dispatcher_stopped
};

class Task;

typedef shared_ptr<Task> TaskId;

class DispatcherCallback {
public:
    virtual ~DispatcherCallback() {}
    virtual bool callback(Dispatcher &d, TaskId t) = 0;
};

class CompareTasks;

class Task {
friend class CompareTasks;
public:
    ~Task() { }
private:
    Task(shared_ptr<DispatcherCallback> cb, int p=0, double sleeptime=0) :
         callback(cb), priority(p) {
        if (sleeptime > 0) {
            snooze(sleeptime);
        } else {
            state = task_running;
        }
    }

    Task(const Task &task) {
        priority = task.priority;
        state = task_running;
        callback = task.callback;
    }

    void snooze(const double secs) {
        LockHolder lh(mutex);
        gettimeofday(&waketime, NULL);
        advance_tv(waketime, secs);
        state = task_sleeping;
    }

    bool run(Dispatcher &d, TaskId t) {
        return callback->callback(d, t);
    }

    void cancel() {
        LockHolder lh(mutex);
        state = task_dead;
    }

    friend class Dispatcher;
    std::string name;
    struct timeval waketime;
    shared_ptr<DispatcherCallback> callback;
    int priority;
    enum task_state state;
    Mutex mutex;
};

class CompareTasks {
public:
    bool operator()(TaskId t1, TaskId t2) {
        if (t1->state == task_running) {
            if (t2->state == task_running) {
                return t1->priority > t2->priority;
            } else if (t2->state == task_sleeping) {
                return false;
            }
        } else if (t1->state == task_sleeping && t2->state == task_sleeping) {
            return less_tv(t2->waketime, t1->waketime);
        }
        return true;
    }
};

class Dispatcher {
public:
    Dispatcher() : state(dispatcher_running) { }

    ~Dispatcher() {
        stop();
    }

    TaskId schedule(shared_ptr<DispatcherCallback> callback, int priority=0,
                    double sleeptime=0) {
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Scheduling a new task\n");
        LockHolder lh(mutex);
        TaskId task(new Task(callback, priority, sleeptime));
        queue.push(task);
        mutex.notify();
        return TaskId(task);
    }

    TaskId wake(TaskId task) {
        cancel(task);
        TaskId oldTask(task);
        TaskId newTask(new Task(*oldTask));
        queue.push(newTask);
        mutex.notify();
        return TaskId(newTask);
    }

    void start();

    void run() {
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher starting\n");
        while (state == dispatcher_running) {
            LockHolder lh(mutex);
            if (queue.empty()) {
                // Wait forever
                mutex.wait();
            } else {
                TaskId task = queue.top();
                assert(task);
                LockHolder tlh(task->mutex);
                switch (task->state) {
                case task_sleeping:
                    {
                        struct timeval tv;
                        gettimeofday(&tv, NULL);
                        if (less_tv(tv, task->waketime)) {
                            tlh.unlock();
                            mutex.wait(task->waketime);
                        } else {
                            task->state = task_running;
                        }
                    }
                    break;
                case task_running:
                    queue.pop();
                    lh.unlock();
                    tlh.unlock();
                    try {
                        if(task->run(*this, TaskId(task))) {
                            reschedule(task);
                        }
                    } catch (std::exception& e) {
                        std::cerr << "exception caught in task " << task->name << ": " << e.what() << std::endl;
                    } catch(...) {
                        std::cerr << "Caught a fatal exception in task" << task->name <<std::endl;
                    }
                    break;
                case task_dead:
                    queue.pop();
                    break;
                default:
                    throw std::runtime_error("Unexpected state for task");
                }
            }
        }

        state = dispatcher_stopped;
        mutex.notify();
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher exited\n");
    }

    void stop() {
        LockHolder lh(mutex);
        if (state == dispatcher_stopped || state == dispatcher_stopping) {
            return;
        }
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Stopping dispatcher\n");
        state = dispatcher_stopping;
        mutex.notify();
        lh.unlock();
        pthread_join(thread, NULL);
        getLogger()->log(EXTENSION_LOG_DEBUG, NULL, "Dispatcher stopped\n");
    }

    void snooze(TaskId t, double sleeptime) {
        t->snooze(sleeptime);
    }

    void cancel(TaskId t) {
        t->cancel();
    }

private:
    void reschedule(TaskId task) {
        // If the task is already in the queue it'll get run twice
        LockHolder lh(mutex);
        queue.push(task);
    }

    pthread_t thread;
    SyncObject mutex;
    std::priority_queue<TaskId, std::deque<TaskId >,
                        CompareTasks> queue;
    enum dispatcher_state state;
};

#endif
<|endoftext|>


<commit_before>/*
 * opencog/learning/moses/moses/select_bscore.cc
 *
 * Copyright (C) 2002-2008 Novamente LLC
 * Copyright (C) 2012,2013 Poulin Holdings LLC
 * Copyright (C) 2014 Aidyia Limited
 * All Rights Reserved
 *
 * Written by Moshe Looks, Nil Geisweiller, Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "select_bscore.h"

namespace opencog { namespace moses {

using namespace combo;

/**
 * Return the highest-weighted value (and its weight) in a given CTable row.
 *
 * CTable rows may have multiple, weighted output values. Several of
 * these output values may have the same weight, and only one of these
 * will be the largest. Find and return that.
 */
std::pair<double, double>
select_bscore::get_weightiest(const Counter<vertex, count_t>& orow) const
{
    score_t weightiest_val = very_worst_score;
    score_t weightiest = 0.0;
    for (const CTable::counter_t::value_type& tcv : orow) {
        score_t val = get_contin(tcv.first);
        if (not _positive) val = -val;
        // The weight for a given value is in tcv.second.
        // We look for weightiest, or, if tied, then for the
        // largest value. This gives a unique sort order, even
        // for randomly re-ordereed tables.
        if (weightiest < tcv.second or
            (weightiest == tcv.second and weightiest_val < val))
        {
            weightiest = tcv.second;
            weightiest_val = val;
        }
    }
    return std::pair<double, double>(weightiest_val, weightiest);
}

/**
 * The selection scorer will learn a window that selects a target range
 * of values in a continuous-valued dataset.
 *
 * The dataset is assumed to have a contin-valued output column. The
 * highest and lowest values are found in the output column, and the
 * window is then framed relative to these two boundaries.  That is,
 * if 'low_val' and 'hi_val' are the smallest and largest values in the
 * table, then the bottom of the selected window is located at
 *
 *    window_bottom = low_val + lower_percentile * (hi_val - low_val)
 *
 * and the top is located at
 *
 *    window_top = low_val + upper_percentile * (hi_val - low_val)
 *
 * If the rows are weighted, then the weighted equivalent of the above
 * boundaries is used.
 */
select_bscore::select_bscore(const CTable& ctable,
                             double lower_percentile,
                             double upper_percentile,
                             double hardness,
                             bool positive) :
    bscore_ctable_base(ctable), _positive(positive)
{
    OC_ASSERT(id::contin_type == _wrk_ctable.get_output_type(),
        "The selection scorer can only be used with contin-valued tables!");

    // Verify that the bounds are sane
    OC_ASSERT((0.0 <= lower_percentile) and
              (lower_percentile < 1.0) and
              (0.0 < upper_percentile) and
              (upper_percentile <= 1.0) and
              (0.0 <= hardness) and
              (hardness <= 1.0),
        "Selection scorer, invalid bounds.");

    // Maps are implicitly ordered, so the below has the effect of
    // putting the rows into sorted order, by output score.
    std::map<score_t, const CTable::value_type&> ranked_out;

    score_t total_weight = 0.0;
    for (const CTable::value_type& io_row : ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        ranked_out.insert(std::pair<score_t, const CTable::value_type&>(weightiest_val, io_row));
        total_weight += weightiest;
    }

    logger().info() << "select_bscore: lower_percentile = " << lower_percentile
                    << " upper percentile = " << upper_percentile
                    << " total wieght = " << total_weight;

    // Now, carve out the selected range.
    upper_percentile *= total_weight;
    lower_percentile *= total_weight;
    score_t running_weight = 0.0;
    bool found_lower = false;
    bool found_upper = false;
    for (auto score_row : ranked_out) {
        score_t weightiest_val = score_row.first;

        auto w = get_weightiest(score_row.second.second);
        score_t weightiest = w.second;
        running_weight += weightiest;

        if (not found_lower and lower_percentile < running_weight) {
            _lower_bound = weightiest_val;
            found_lower = true;
        }
        if (not found_upper and upper_percentile < running_weight) {
            _upper_bound = weightiest_val;
            found_upper = true;
        }
    }

    logger().info() << "select_bscore: lower_bound = " << _lower_bound
                    << " upper bound = " << _upper_bound;
}

/// scorer, as described in the constructor, above.
behavioral_score select_bscore::operator()(const combo_tree& tr) const
{
    behavioral_score bs;

    interpreter_visitor iv(tr);
    auto interpret_tr = boost::apply_visitor(iv);

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (interpret_tr(io_row.first.get_variant()) == id::logical_true) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(0.0);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(0.0);
        }
    }

    return bs;
}

/// scorer, suitable for use with boosting.
behavioral_score select_bscore::operator()(const scored_combo_tree_set& ensemble) const
{
    // Step 1: accumulate the weighted prediction of each tree in
    // the ensemble.
    behavioral_score hypoth (_size);
    for (const scored_combo_tree& sct: ensemble) {
        const combo_tree& tr = sct.get_tree();
        score_t trweight = sct.get_weight();

        interpreter_visitor iv(tr);
        auto interpret_tr = boost::apply_visitor(iv);

        size_t i=0;
        for (const CTable::value_type& io_row : _wrk_ctable) {
            // io_row.first = input vector
            bool select = (interpret_tr(io_row.first.get_variant()) == id::logical_true);
            hypoth[i] += trweight * (2.0 * ((score_t) select) - 1.0);
            i++;
        }
    }

    // Step 2: compare the prediction of the ensemble to the desired
    // result. The array "hypoth" is positive to predict true, and
    // negative to predict false.  The resulting score is 0 if correct,
    // and -1 if incorrect.
    behavioral_score bs;
    size_t i = 0;
    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (0 < hypoth[i]) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(0.0);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(0.0);
        }
        i++;
    }

    return bs;
}

behavioral_score select_bscore::best_possible_bscore() const
{
    behavioral_score bs;

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // It should always be possible to correctly predict one
        // entry of the ctable; so best score is zero.
        bs.push_back(0.0);
    }
    return bs;
}

score_t select_bscore::min_improv() const
{
    return 1.0 / _ctable_usize;
}

} // ~namespace moses
} // ~namespace opencog
<commit_msg>moses: fix compiler warning in new code.<commit_after>/*
 * opencog/learning/moses/moses/select_bscore.cc
 *
 * Copyright (C) 2002-2008 Novamente LLC
 * Copyright (C) 2012,2013 Poulin Holdings LLC
 * Copyright (C) 2014 Aidyia Limited
 * All Rights Reserved
 *
 * Written by Moshe Looks, Nil Geisweiller, Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "select_bscore.h"

namespace opencog { namespace moses {

using namespace combo;

/**
 * Return the highest-weighted value (and its weight) in a given CTable row.
 *
 * CTable rows may have multiple, weighted output values. Several of
 * these output values may have the same weight, and only one of these
 * will be the largest. Find and return that.
 */
std::pair<double, double>
select_bscore::get_weightiest(const Counter<vertex, count_t>& orow) const
{
    score_t weightiest_val = very_worst_score;
    score_t weightiest = 0.0;
    for (const CTable::counter_t::value_type& tcv : orow) {
        score_t val = get_contin(tcv.first);
        if (not _positive) val = -val;
        // The weight for a given value is in tcv.second.
        // We look for weightiest, or, if tied, then for the
        // largest value. This gives a unique sort order, even
        // for randomly re-ordereed tables.
        if (weightiest < tcv.second or
            (weightiest == tcv.second and weightiest_val < val))
        {
            weightiest = tcv.second;
            weightiest_val = val;
        }
    }
    return std::pair<double, double>(weightiest_val, weightiest);
}

/**
 * The selection scorer will learn a window that selects a target range
 * of values in a continuous-valued dataset.
 *
 * The dataset is assumed to have a contin-valued output column. The
 * highest and lowest values are found in the output column, and the
 * window is then framed relative to these two boundaries.  That is,
 * if 'low_val' and 'hi_val' are the smallest and largest values in the
 * table, then the bottom of the selected window is located at
 *
 *    window_bottom = low_val + lower_percentile * (hi_val - low_val)
 *
 * and the top is located at
 *
 *    window_top = low_val + upper_percentile * (hi_val - low_val)
 *
 * If the rows are weighted, then the weighted equivalent of the above
 * boundaries is used.
 */
select_bscore::select_bscore(const CTable& ctable,
                             double lower_percentile,
                             double upper_percentile,
                             double hardness,
                             bool positive) :
    bscore_ctable_base(ctable), _positive(positive)
{
    OC_ASSERT(id::contin_type == _wrk_ctable.get_output_type(),
        "The selection scorer can only be used with contin-valued tables!");

    // Verify that the bounds are sane
    OC_ASSERT((0.0 <= lower_percentile) and
              (lower_percentile < 1.0) and
              (0.0 < upper_percentile) and
              (upper_percentile <= 1.0) and
              (0.0 <= hardness) and
              (hardness <= 1.0),
        "Selection scorer, invalid bounds.");

    // Maps are implicitly ordered, so the below has the effect of
    // putting the rows into sorted order, by output score.
    std::map<score_t, const CTable::value_type&> ranked_out;

    score_t total_weight = 0.0;
    for (const CTable::value_type& io_row : ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        ranked_out.insert(std::pair<score_t, const CTable::value_type&>(weightiest_val, io_row));
        total_weight += weightiest;
    }

    logger().info() << "select_bscore: lower_percentile = " << lower_percentile
                    << " upper percentile = " << upper_percentile
                    << " total wieght = " << total_weight;

    // Now, carve out the selected range.
    upper_percentile *= total_weight;
    lower_percentile *= total_weight;
    score_t running_weight = 0.0;
    bool found_lower = false;
    bool found_upper = false;
    for (auto score_row : ranked_out) {
        score_t weightiest_val = score_row.first;

        auto w = get_weightiest(score_row.second.second);
        score_t weightiest = w.second;
        running_weight += weightiest;

        if (not found_lower and lower_percentile < running_weight) {
            _lower_bound = weightiest_val;
            found_lower = true;
        }
        if (not found_upper and upper_percentile < running_weight) {
            _upper_bound = weightiest_val;
            found_upper = true;
        }
    }

    logger().info() << "select_bscore: lower_bound = " << _lower_bound
                    << " upper bound = " << _upper_bound;
}

/// scorer, as described in the constructor, above.
behavioral_score select_bscore::operator()(const combo_tree& tr) const
{
    behavioral_score bs;

    interpreter_visitor iv(tr);
    auto interpret_tr = boost::apply_visitor(iv);

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (interpret_tr(io_row.first.get_variant()) == id::logical_true) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(0.0);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(0.0);
        }
    }

    return bs;
}

/// scorer, suitable for use with boosting.
behavioral_score select_bscore::operator()(const scored_combo_tree_set& ensemble) const
{
    // Step 1: accumulate the weighted prediction of each tree in
    // the ensemble.
    behavioral_score hypoth (_size);
    for (const scored_combo_tree& sct: ensemble) {
        const combo_tree& tr = sct.get_tree();
        score_t trweight = sct.get_weight();

        interpreter_visitor iv(tr);
        auto interpret_tr = boost::apply_visitor(iv);

        size_t i=0;
        for (const CTable::value_type& io_row : _wrk_ctable) {
            // io_row.first = input vector
            bool select = (interpret_tr(io_row.first.get_variant()) == id::logical_true);
            hypoth[i] += trweight * (2.0 * ((score_t) select) - 1.0);
            i++;
        }
    }

    // Step 2: compare the prediction of the ensemble to the desired
    // result. The array "hypoth" is positive to predict true, and
    // negative to predict false.  The resulting score is 0 if correct,
    // and -1 if incorrect.
    behavioral_score bs;
    size_t i = 0;
    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (0 < hypoth[i]) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(0.0);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(0.0);
        }
        i++;
    }

    return bs;
}

behavioral_score select_bscore::best_possible_bscore() const
{
    // It should always be possible to correctly predict one entry
    // of the ctable; and so the  best score is zero for each row.
    return behavioral_score(_wrk_ctable.size(), 0.0);
}

score_t select_bscore::min_improv() const
{
    return 1.0 / _ctable_usize;
}

} // ~namespace moses
} // ~namespace opencog
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#ifndef MFEM_ROCM_HPP
#define MFEM_ROCM_HPP

#include "../config/config.hpp"
#include "error.hpp"

#ifdef MFEM_USE_ROCM
#include <hip/hip_runtime.h>
#endif

// ROCM block size used by MFEM.
#define MFEM_ROCM_BLOCKS 256

#ifdef MFEM_USE_ROCM
// Define a ROCM error check macro, MFEM_GPU_CHECK(x), where x returns/is of
// type 'rocmError_t'. This macro evaluates 'x' and raises an error if the
// result is not hipSuccess.
#define MFEM_GPU_CHECK(x) \
   do \
   { \
      hipError_t err = (x); \
      if (err != hipSuccess) \
      { \
         mfem_rocm_error(err, #x, _MFEM_FUNC_NAME, __FILE__, __LINE__); \
      } \
   } \
   while (0)
#endif // MFEM_USE_ROCM

// Define the MFEM inner threading macros
#if defined(MFEM_USE_ROCM) && defined(__ROCM_ARCH__)
#define MFEM_SHARED __shared__
#define MFEM_SYNC_THREAD __syncthreads()
#define MFEM_THREAD_ID(k) hipThreadIdx_ ##k
#define MFEM_THREAD_SIZE(k) hipBlockDim_ ##k
#define MFEM_FOREACH_THREAD(i,k,N) for(int i=hipThreadIdx_ ##k; i<N; i+=hipBlockDim_ ##k)
#else
#define MFEM_SHARED
#define MFEM_SYNC_THREAD
#define MFEM_THREAD_ID(k) 0
#define MFEM_THREAD_SIZE(k) 1
#define MFEM_FOREACH_THREAD(i,k,N) for(int i=0; i<N; i++)
#endif

namespace mfem
{

#ifdef MFEM_USE_ROCM
// Function used by the macro MFEM_GPU_CHECK.
void mfem_rocm_error(hipError_t err, const char *expr, const char *func,
                     const char *file, int line);
#endif

/// Allocates device memory
void* RocMemAlloc(void **d_ptr, size_t bytes);

/// Frees device memory
void* RocMemFree(void *d_ptr);

/// Copies memory from Host to Device
void* RocMemcpyHtoD(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Host to Device
void* RocMemcpyHtoDAsync(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Device to Device
void* RocMemcpyDtoD(void *d_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Device
void* RocMemcpyDtoDAsync(void *d_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* RocMemcpyDtoH(void *h_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* RocMemcpyDtoHAsync(void *h_dst, const void *d_src, size_t bytes);

} // namespace mfem

#endif // MFEM_ROCM_HPP
<commit_msg>general/rocm.hpp double defines fix<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#ifndef MFEM_ROCM_HPP
#define MFEM_ROCM_HPP

#include "../config/config.hpp"
#include "error.hpp"

#ifdef MFEM_USE_ROCM
#include <hip/hip_runtime.h>
#endif

// ROCM block size used by MFEM.
#define MFEM_ROCM_BLOCKS 256

#ifdef MFEM_USE_ROCM
// Define a ROCM error check macro, MFEM_GPU_CHECK(x), where x returns/is of
// type 'rocmError_t'. This macro evaluates 'x' and raises an error if the
// result is not hipSuccess.
#define MFEM_GPU_CHECK(x) \
   do \
   { \
      hipError_t err = (x); \
      if (err != hipSuccess) \
      { \
         mfem_rocm_error(err, #x, _MFEM_FUNC_NAME, __FILE__, __LINE__); \
      } \
   } \
   while (0)
#endif // MFEM_USE_ROCM

// Define the MFEM inner threading macros
#if defined(MFEM_USE_ROCM) && defined(__ROCM_ARCH__)
#define MFEM_SHARED __shared__
#define MFEM_SYNC_THREAD __syncthreads()
#define MFEM_THREAD_ID(k) hipThreadIdx_ ##k
#define MFEM_THREAD_SIZE(k) hipBlockDim_ ##k
#define MFEM_FOREACH_THREAD(i,k,N) for(int i=hipThreadIdx_ ##k; i<N; i+=hipBlockDim_ ##k)
#endif

namespace mfem
{

#ifdef MFEM_USE_ROCM
// Function used by the macro MFEM_GPU_CHECK.
void mfem_rocm_error(hipError_t err, const char *expr, const char *func,
                     const char *file, int line);
#endif

/// Allocates device memory
void* RocMemAlloc(void **d_ptr, size_t bytes);

/// Frees device memory
void* RocMemFree(void *d_ptr);

/// Copies memory from Host to Device
void* RocMemcpyHtoD(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Host to Device
void* RocMemcpyHtoDAsync(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Device to Device
void* RocMemcpyDtoD(void *d_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Device
void* RocMemcpyDtoDAsync(void *d_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* RocMemcpyDtoH(void *h_dst, const void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* RocMemcpyDtoHAsync(void *h_dst, const void *d_src, size_t bytes);

} // namespace mfem

#endif // MFEM_ROCM_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: cclass_unicode.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: khong $ $Date: 2002-11-05 23:41:29 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _I18N_CCLASS_UNICODE_HXX_
#define _I18N_CCLASS_UNICODE_HXX_

#include <drafts/com/sun/star/i18n/XNativeNumberSupplier.hpp>
#include <com/sun/star/i18n/XCharacterClassification.hpp>
#include <com/sun/star/i18n/XLocaleData.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hdl>
#include <cppuhelper/implbase1.hxx> // helper for implementations
#include <com/sun/star/lang/XServiceInfo.hpp>

#define TRANSLITERATION_casemapping
#include <transliteration_body.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

typedef sal_uInt32 UPT_FLAG_TYPE;

class cclass_Unicode : public cppu::WeakImplHelper1 < XCharacterClassification >
{
public:
    cclass_Unicode(com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xSMgr );
    ~cclass_Unicode();

    virtual rtl::OUString SAL_CALL toUpper( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual rtl::OUString SAL_CALL toLower( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual rtl::OUString SAL_CALL toTitle( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getType( const rtl::OUString& Text, sal_Int32 nPos )  throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getCharacterDirection( const rtl::OUString& Text, sal_Int32 nPos )
        throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getScript( const rtl::OUString& Text, sal_Int32 nPos ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getCharacterType( const rtl::OUString& text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getStringType( const rtl::OUString& text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual ParseResult SAL_CALL parseAnyToken( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& rLocale, sal_Int32 nStartCharFlags, const rtl::OUString& userDefinedCharactersStart,
        sal_Int32 nContCharFlags, const rtl::OUString& userDefinedCharactersCont ) throw(com::sun::star::uno::RuntimeException);
    virtual ParseResult SAL_CALL parsePredefinedToken( sal_Int32 nTokenType, const rtl::OUString& Text,
        sal_Int32 nPos, const com::sun::star::lang::Locale& rLocale, sal_Int32 nStartCharFlags,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 nContCharFlags,
        const rtl::OUString& userDefinedCharactersCont ) throw(com::sun::star::uno::RuntimeException);

    //XServiceInfo
    virtual rtl::OUString SAL_CALL getImplementationName() throw( com::sun::star::uno::RuntimeException );
    virtual sal_Bool SAL_CALL supportsService(const rtl::OUString& ServiceName) throw( com::sun::star::uno::RuntimeException );
    virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( com::sun::star::uno::RuntimeException );

protected:
    sal_Char *cClass;

private:
    Transliteration_casemapping *trans;

// --- parser specific (implemented in cclass_unicode_parser.cxx) ---

    enum ScanState
    {
        ssGetChar,
        ssGetValue,
        ssGetWord,
        ssGetWordFirstChar,
        ssGetString,
        ssGetBool,
        ssRewindFromValue,
        ssStopBack,
        ssBounce,
        ssStop
    };

    static const sal_uInt8      nDefCnt;
    static const UPT_FLAG_TYPE  pDefaultParserTable[];
    static const sal_Int32      pParseTokensType[];

    /// Flag values of table.
    static const UPT_FLAG_TYPE  TOKEN_ILLEGAL;
    static const UPT_FLAG_TYPE  TOKEN_CHAR;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_BOOL;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_WORD;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_STRING;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_DONTCARE;
    static const UPT_FLAG_TYPE  TOKEN_BOOL;
    static const UPT_FLAG_TYPE  TOKEN_WORD;
    static const UPT_FLAG_TYPE  TOKEN_WORD_SEP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_SEP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_EXP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_SIGN;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_EXP_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_DIGIT;
    static const UPT_FLAG_TYPE  TOKEN_NAME_SEP;
    static const UPT_FLAG_TYPE  TOKEN_STRING_SEP;
    static const UPT_FLAG_TYPE  TOKEN_EXCLUDED;

    /// If and where c occurs in pStr
    static  const sal_Unicode*  StrChr( const sal_Unicode* pStr, sal_Unicode c );

    com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xMSF;

    /// used for parser only
    com::sun::star::lang::Locale    aParserLocale;
    com::sun::star::uno::Reference < XLocaleData > xLocaleData;
    com::sun::star::uno::Reference < drafts::com::sun::star::i18n::XNativeNumberSupplier > xNatNumSup;
    rtl::OUString             aStartChars;
    rtl::OUString             aContChars;
    UPT_FLAG_TYPE*              pTable;
    UPT_FLAG_TYPE*              pStart;
    UPT_FLAG_TYPE*              pCont;
    sal_Int32                   nStartTypes;
    sal_Int32                   nContTypes;
    ScanState                   eState;
    sal_Unicode                 cGroupSep;
    sal_Unicode                 cDecimalSep;

    /// Get corresponding KParseTokens flag for a character
    sal_Int32 getParseTokensType( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser table flags.
    UPT_FLAG_TYPE getFlags( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser flags via International and special definitions.
    UPT_FLAG_TYPE getFlagsExtended( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser table flags for user defined start characters.
    UPT_FLAG_TYPE getStartCharsFlags( sal_Unicode c );

    /// Access parser table flags for user defined continuation characters.
    UPT_FLAG_TYPE getContCharsFlags( sal_Unicode c );

    /// Setup parser table. Calls initParserTable() only if needed.
    void setupParserTable( const com::sun::star::lang::Locale& rLocale, sal_Int32 startCharTokenType,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
        const rtl::OUString& userDefinedCharactersCont );

    /// Init parser table.
    void initParserTable( const com::sun::star::lang::Locale& rLocale, sal_Int32 startCharTokenType,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
        const rtl::OUString& userDefinedCharactersCont );

    /// Destroy parser table.
    void destroyParserTable();

    /// Parse a text.
    void parseText( ParseResult& r, const rtl::OUString& rText, sal_Int32 nPos,
        sal_Int32 nTokenType = 0xffffffff );

    /// Setup International class, new'ed only if different from existing.
    sal_Bool setupInternational( const com::sun::star::lang::Locale& rLocale );

    /// Implementation of getCharacterType() for one single character
    sal_Int32 getCharType( sal_Unicode c );

};

} } } }

#endif
<commit_msg>INTEGRATION: CWS tune01 (1.5.30); FILE MERGED 2003/03/12 16:20:47 er 1.5.30.1: #i11962# include .hpp files, not .hdl<commit_after>/*************************************************************************
 *
 *  $RCSfile: cclass_unicode.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-15 14:24:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _I18N_CCLASS_UNICODE_HXX_
#define _I18N_CCLASS_UNICODE_HXX_

#include <drafts/com/sun/star/i18n/XNativeNumberSupplier.hpp>
#include <com/sun/star/i18n/XCharacterClassification.hpp>
#include <com/sun/star/i18n/XLocaleData.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <cppuhelper/implbase1.hxx> // helper for implementations
#include <com/sun/star/lang/XServiceInfo.hpp>

#define TRANSLITERATION_casemapping
#include <transliteration_body.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

typedef sal_uInt32 UPT_FLAG_TYPE;

class cclass_Unicode : public cppu::WeakImplHelper1 < XCharacterClassification >
{
public:
    cclass_Unicode(com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xSMgr );
    ~cclass_Unicode();

    virtual rtl::OUString SAL_CALL toUpper( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual rtl::OUString SAL_CALL toLower( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual rtl::OUString SAL_CALL toTitle( const rtl::OUString& Text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getType( const rtl::OUString& Text, sal_Int32 nPos )  throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getCharacterDirection( const rtl::OUString& Text, sal_Int32 nPos )
        throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getScript( const rtl::OUString& Text, sal_Int32 nPos ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getCharacterType( const rtl::OUString& text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL getStringType( const rtl::OUString& text, sal_Int32 nPos, sal_Int32 nCount,
        const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual ParseResult SAL_CALL parseAnyToken( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& rLocale, sal_Int32 nStartCharFlags, const rtl::OUString& userDefinedCharactersStart,
        sal_Int32 nContCharFlags, const rtl::OUString& userDefinedCharactersCont ) throw(com::sun::star::uno::RuntimeException);
    virtual ParseResult SAL_CALL parsePredefinedToken( sal_Int32 nTokenType, const rtl::OUString& Text,
        sal_Int32 nPos, const com::sun::star::lang::Locale& rLocale, sal_Int32 nStartCharFlags,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 nContCharFlags,
        const rtl::OUString& userDefinedCharactersCont ) throw(com::sun::star::uno::RuntimeException);

    //XServiceInfo
    virtual rtl::OUString SAL_CALL getImplementationName() throw( com::sun::star::uno::RuntimeException );
    virtual sal_Bool SAL_CALL supportsService(const rtl::OUString& ServiceName) throw( com::sun::star::uno::RuntimeException );
    virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( com::sun::star::uno::RuntimeException );

protected:
    sal_Char *cClass;

private:
    Transliteration_casemapping *trans;

// --- parser specific (implemented in cclass_unicode_parser.cxx) ---

    enum ScanState
    {
        ssGetChar,
        ssGetValue,
        ssGetWord,
        ssGetWordFirstChar,
        ssGetString,
        ssGetBool,
        ssRewindFromValue,
        ssStopBack,
        ssBounce,
        ssStop
    };

    static const sal_uInt8      nDefCnt;
    static const UPT_FLAG_TYPE  pDefaultParserTable[];
    static const sal_Int32      pParseTokensType[];

    /// Flag values of table.
    static const UPT_FLAG_TYPE  TOKEN_ILLEGAL;
    static const UPT_FLAG_TYPE  TOKEN_CHAR;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_BOOL;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_WORD;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_STRING;
    static const UPT_FLAG_TYPE  TOKEN_CHAR_DONTCARE;
    static const UPT_FLAG_TYPE  TOKEN_BOOL;
    static const UPT_FLAG_TYPE  TOKEN_WORD;
    static const UPT_FLAG_TYPE  TOKEN_WORD_SEP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_SEP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_EXP;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_SIGN;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_EXP_VALUE;
    static const UPT_FLAG_TYPE  TOKEN_VALUE_DIGIT;
    static const UPT_FLAG_TYPE  TOKEN_NAME_SEP;
    static const UPT_FLAG_TYPE  TOKEN_STRING_SEP;
    static const UPT_FLAG_TYPE  TOKEN_EXCLUDED;

    /// If and where c occurs in pStr
    static  const sal_Unicode*  StrChr( const sal_Unicode* pStr, sal_Unicode c );

    com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xMSF;

    /// used for parser only
    com::sun::star::lang::Locale    aParserLocale;
    com::sun::star::uno::Reference < XLocaleData > xLocaleData;
    com::sun::star::uno::Reference < drafts::com::sun::star::i18n::XNativeNumberSupplier > xNatNumSup;
    rtl::OUString             aStartChars;
    rtl::OUString             aContChars;
    UPT_FLAG_TYPE*              pTable;
    UPT_FLAG_TYPE*              pStart;
    UPT_FLAG_TYPE*              pCont;
    sal_Int32                   nStartTypes;
    sal_Int32                   nContTypes;
    ScanState                   eState;
    sal_Unicode                 cGroupSep;
    sal_Unicode                 cDecimalSep;

    /// Get corresponding KParseTokens flag for a character
    sal_Int32 getParseTokensType( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser table flags.
    UPT_FLAG_TYPE getFlags( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser flags via International and special definitions.
    UPT_FLAG_TYPE getFlagsExtended( const sal_Unicode* aStr, sal_Int32 nPos );

    /// Access parser table flags for user defined start characters.
    UPT_FLAG_TYPE getStartCharsFlags( sal_Unicode c );

    /// Access parser table flags for user defined continuation characters.
    UPT_FLAG_TYPE getContCharsFlags( sal_Unicode c );

    /// Setup parser table. Calls initParserTable() only if needed.
    void setupParserTable( const com::sun::star::lang::Locale& rLocale, sal_Int32 startCharTokenType,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
        const rtl::OUString& userDefinedCharactersCont );

    /// Init parser table.
    void initParserTable( const com::sun::star::lang::Locale& rLocale, sal_Int32 startCharTokenType,
        const rtl::OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
        const rtl::OUString& userDefinedCharactersCont );

    /// Destroy parser table.
    void destroyParserTable();

    /// Parse a text.
    void parseText( ParseResult& r, const rtl::OUString& rText, sal_Int32 nPos,
        sal_Int32 nTokenType = 0xffffffff );

    /// Setup International class, new'ed only if different from existing.
    sal_Bool setupInternational( const com::sun::star::lang::Locale& rLocale );

    /// Implementation of getCharacterType() for one single character
    sal_Int32 getCharType( sal_Unicode c );

};

} } } }

#endif
<|endoftext|>


<commit_before>/*
 *
 * LedgerApiEthereumLikeBlockchainExplorer
 *
 * Created by El Khalil Bellakrid on 29/07/2018.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "LedgerApiEthereumLikeBlockchainExplorer.h"
#include "../../../../../cmake-build-debug/include/ledger/core/api/ErrorCode.hpp"
#include <api_impl/BigIntImpl.hpp>
namespace ledger {
    namespace core {

        LedgerApiEthereumLikeBlockchainExplorer::LedgerApiEthereumLikeBlockchainExplorer(const std::shared_ptr<api::ExecutionContext>& context,
                                                                                const std::shared_ptr<HttpClient>& http,
                                                                                const api::EthereumLikeNetworkParameters& parameters,
                                                                                const std::shared_ptr<api::DynamicObject>& configuration) :
                                        DedicatedContext(context), EthereumLikeBlockchainExplorer(configuration, {api::Configuration::BLOCKCHAIN_EXPLORER_API_ENDPOINT}) {
            _http = http;
            _parameters = parameters;
            _explorerVersion = configuration->getString(api::Configuration::BLOCKCHAIN_EXPLORER_VERSION).value_or("v3");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getNonce(const std::string &address) {
            return _http->GET(fmt::format("/blockchain/{}/{}/addresses/{}/nonce",_explorerVersion, _parameters.Identifier, address))
                    .json().mapPtr<BigInt>(getContext(), [address] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsArray() || json.Size() != 1 || !json[0].HasMember("nonce") || !json[0]["nonce"].IsUint64()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get nonce for {}", address);
                        }
                        auto nonce = json[0]["nonce"].GetUint64();
                        return std::make_shared<BigInt>((int64_t)nonce);
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getBalance(const std::vector<EthereumLikeKeychain::Address> &addresses) {

            std::string addressesStr;
            auto size = addresses.size();
            for (auto i = 0; i < size; i++) {
                auto address = addresses[i];
                addressesStr += address->toEIP55();
                if (i < addresses.size() - 1) {
                    addressesStr += ",";
                }
            }
            bool parseNumbersAsString = true;
            return _http->GET(fmt::format("/blockchain/{}/{}/addresses/{}/balance", _explorerVersion, _parameters.Identifier, addressesStr))
                    .json(parseNumbersAsString).mapPtr<BigInt>(getContext(), [addressesStr, size] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsArray() || json.Size() != size || !json[0].HasMember("balance") || !json[0]["balance"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get balance for {}", addressesStr);
                        }

                        BigInt balance(json[0]["balance"].GetString());
                        for (auto i = 1; i < size; i++) {
                            if (json[i].HasMember("balance") || json[i]["balance"].IsString()) {
                                balance = balance + BigInt(json[i]["balance"].GetString());
                            }
                        }

                        return std::make_shared<BigInt>(balance);
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getHelper(const std::string &url,
                                                                                const std::string &field) {
            bool parseNumbersAsString = true;
            auto networkId = getNetworkParameters().Identifier;
            return _http->GET(url, std::unordered_map<std::string, std::string>()).json(parseNumbersAsString).mapPtr<BigInt>(getContext(), [field, networkId] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsObject() || !json.GetObject().HasMember(field.c_str()) || !json.GetObject()[field.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, fmt::format("Failed to get {} for {}", field, networkId));
                        }
                        return std::make_shared<BigInt>(json.GetObject()[field.c_str()].GetString());
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getGasPrice() {
            return getHelper(fmt::format("/blockchain/{}/{}/fees", getExplorerVersion(), getNetworkParameters().Identifier), "gas_price");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getEstimatedGasLimit(const std::string &address) {
            return getHelper(fmt::format("/blockchain/{}/{}/addresses/{}/estimate-gas-limit", getExplorerVersion(), getNetworkParameters().Identifier, address), "estimated_gas_limit");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getERC20Balance(const std::string &address,
                                                                                const std::string &erc20Address) {
            return getERC20Balances(address, std::vector<std::string>{erc20Address})
                    .mapPtr<BigInt>(getContext(),
                                    [erc20Address](const std::vector<BigInt> &balances) {
                                        if (balances.empty()) {
                                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                                 fmt::format("Failed to get balance for token {}", erc20Address)
                                            );
                                        }
                                        return std::make_shared<BigInt>(balances[0]);
                                    }
                    );
        }

        Future<std::vector<BigInt>>
        LedgerApiEthereumLikeBlockchainExplorer::getERC20Balances(const std::string &address,
                                                                  const std::vector<std::string> &erc20Addresses) {
            rapidjson::Document docContainer;
            docContainer.SetArray();
            auto &allocator = docContainer.GetAllocator();
            for (auto &erc20Address : erc20Addresses) {
                rapidjson::Value o(rapidjson::kObjectType);
                rapidjson::Value vString(rapidjson::kStringType);
                // Set address of account to check balance of
                vString.SetString(address.c_str(), static_cast<rapidjson::SizeType>(address.length()), allocator);
                o.AddMember("address", vString, allocator);
                // Set address of contract (ERC20) to check balance on
                vString.SetString(erc20Address.c_str(), static_cast<rapidjson::SizeType>(erc20Address.length()), allocator);
                o.AddMember("contract", vString, allocator);
                docContainer.PushBack(o.GetObject(), allocator);
            }

            rapidjson::StringBuffer buffer;
            rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
            docContainer.Accept(writer);
            std::string requestBody(buffer.GetString());

            bool parseNumbersAsString = true;
            auto networkId = getNetworkParameters().Identifier;
            std::string field("balance");
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST(fmt::format("/blockchain/{}/{}/erc20/balances",
                                           getExplorerVersion(),
                                           getNetworkParameters().Identifier),
                               std::vector<uint8_t>(requestBody.begin(), requestBody.end()),
                               headers)
                    .json(parseNumbersAsString)
                    .map<std::vector<BigInt>>(getContext(), [field, networkId, erc20Addresses] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);

                        if (!json.IsArray() || json.Size() != erc20Addresses.size()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get balances for erc20 addresses.");
                        }

                        std::vector<BigInt> balances;
                        for (auto &b : json.GetArray()) {
                            if (!b.IsObject() || !b.GetObject().HasMember("balance")) {
                                throw make_exception(api::ErrorCode::HTTP_ERROR, "ERC20 balance: Malformed balance fields.");
                            }
                            balances.emplace_back(BigInt(b.GetObject()["balance"].GetString()));
                        }
                        return balances;
                    });
        }

        Future<String> LedgerApiEthereumLikeBlockchainExplorer::pushLedgerApiTransaction(const std::vector<uint8_t> &transaction) {
            std::stringstream body;
            auto hexTx = "0x" + hex::toString(transaction);
            body << "{" << "\"tx\":" << '"' << hexTx << '"' << "}";
            auto bodyString = body.str();
            return _http->POST(fmt::format("/blockchain/{}/{}/transactions/send", getExplorerVersion(), getNetworkParameters().Identifier),
                               std::vector<uint8_t>(bodyString.begin(), bodyString.end())
            ).json().template map<String>(getExplorerContext(), [] (const HttpRequest::JsonResult& result) -> String {
                auto& json = *std::get<1>(result);
                return json["result"].GetString();
            });
        }

        Future<void *> LedgerApiEthereumLikeBlockchainExplorer::startSession() {
            return startLedgerApiSession();
        }

        Future<Unit> LedgerApiEthereumLikeBlockchainExplorer::killSession(void *session) {
            return killLedgerApiSession(session);
        }

        Future<Bytes> LedgerApiEthereumLikeBlockchainExplorer::getRawTransaction(const String& transactionHash) {
            return getLedgerApiRawTransaction(transactionHash);
        }

        Future<String> LedgerApiEthereumLikeBlockchainExplorer::pushTransaction(const std::vector<uint8_t>& transaction) {
            return pushLedgerApiTransaction(transaction);
        }

        FuturePtr<EthereumLikeBlockchainExplorer::TransactionsBulk>
        LedgerApiEthereumLikeBlockchainExplorer::getTransactions(const std::vector<std::string> &addresses,
                                                        Option<std::string> fromBlockHash,
                                                        Option<void *> session) {
            bool isSnakeCase = true;
            return getLedgerApiTransactions(addresses, fromBlockHash, session, isSnakeCase);
        }

        FuturePtr<Block> LedgerApiEthereumLikeBlockchainExplorer::getCurrentBlock() const {
            return getLedgerApiCurrentBlock();
        }

        FuturePtr<EthereumLikeBlockchainExplorerTransaction>
        LedgerApiEthereumLikeBlockchainExplorer::getTransactionByHash(const String &transactionHash) const {
            return getLedgerApiTransactionByHash(transactionHash);
        }

        Future<int64_t > LedgerApiEthereumLikeBlockchainExplorer::getTimestamp() const {
            return getLedgerApiTimestamp();
        }

        std::shared_ptr<api::ExecutionContext> LedgerApiEthereumLikeBlockchainExplorer::getExplorerContext() const {
            return _executionContext;
        }

        api::EthereumLikeNetworkParameters LedgerApiEthereumLikeBlockchainExplorer::getNetworkParameters() const {
            return _parameters;
        }

        std::string LedgerApiEthereumLikeBlockchainExplorer::getExplorerVersion() const {
            return _explorerVersion;
        }
    }
}
<commit_msg>Take into consideration PR reviews<commit_after>/*
 *
 * LedgerApiEthereumLikeBlockchainExplorer
 *
 * Created by El Khalil Bellakrid on 29/07/2018.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "LedgerApiEthereumLikeBlockchainExplorer.h"
#include <api_impl/BigIntImpl.hpp>
namespace ledger {
    namespace core {

        LedgerApiEthereumLikeBlockchainExplorer::LedgerApiEthereumLikeBlockchainExplorer(const std::shared_ptr<api::ExecutionContext>& context,
                                                                                const std::shared_ptr<HttpClient>& http,
                                                                                const api::EthereumLikeNetworkParameters& parameters,
                                                                                const std::shared_ptr<api::DynamicObject>& configuration) :
                                        DedicatedContext(context), EthereumLikeBlockchainExplorer(configuration, {api::Configuration::BLOCKCHAIN_EXPLORER_API_ENDPOINT}) {
            _http = http;
            _parameters = parameters;
            _explorerVersion = configuration->getString(api::Configuration::BLOCKCHAIN_EXPLORER_VERSION).value_or("v3");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getNonce(const std::string &address) {
            return _http->GET(fmt::format("/blockchain/{}/{}/addresses/{}/nonce",_explorerVersion, _parameters.Identifier, address))
                    .json().mapPtr<BigInt>(getContext(), [address] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsArray() || json.Size() != 1 || !json[0].HasMember("nonce") || !json[0]["nonce"].IsUint64()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get nonce for {}", address);
                        }
                        auto nonce = json[0]["nonce"].GetUint64();
                        return std::make_shared<BigInt>((int64_t)nonce);
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getBalance(const std::vector<EthereumLikeKeychain::Address> &addresses) {

            std::string addressesStr;
            auto size = addresses.size();
            for (auto i = 0; i < size; i++) {
                auto address = addresses[i];
                addressesStr += address->toEIP55();
                if (i < addresses.size() - 1) {
                    addressesStr += ",";
                }
            }
            bool parseNumbersAsString = true;
            return _http->GET(fmt::format("/blockchain/{}/{}/addresses/{}/balance", _explorerVersion, _parameters.Identifier, addressesStr))
                    .json(parseNumbersAsString).mapPtr<BigInt>(getContext(), [addressesStr, size] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsArray() || json.Size() != size || !json[0].HasMember("balance") || !json[0]["balance"].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get balance for {}", addressesStr);
                        }

                        BigInt balance(json[0]["balance"].GetString());
                        for (auto i = 1; i < size; i++) {
                            if (json[i].HasMember("balance") || json[i]["balance"].IsString()) {
                                balance = balance + BigInt(json[i]["balance"].GetString());
                            }
                        }

                        return std::make_shared<BigInt>(balance);
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getHelper(const std::string &url,
                                                                                const std::string &field) {
            bool parseNumbersAsString = true;
            auto networkId = getNetworkParameters().Identifier;
            return _http->GET(url, std::unordered_map<std::string, std::string>()).json(parseNumbersAsString).mapPtr<BigInt>(getContext(), [field, networkId] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);
                        if (!json.IsObject() || !json.GetObject().HasMember(field.c_str()) || !json.GetObject()[field.c_str()].IsString()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, fmt::format("Failed to get {} for {}", field, networkId));
                        }
                        return std::make_shared<BigInt>(json.GetObject()[field.c_str()].GetString());
                    });
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getGasPrice() {
            return getHelper(fmt::format("/blockchain/{}/{}/fees", getExplorerVersion(), getNetworkParameters().Identifier), "gas_price");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getEstimatedGasLimit(const std::string &address) {
            return getHelper(fmt::format("/blockchain/{}/{}/addresses/{}/estimate-gas-limit", getExplorerVersion(), getNetworkParameters().Identifier, address), "estimated_gas_limit");
        }

        Future<std::shared_ptr<BigInt>> LedgerApiEthereumLikeBlockchainExplorer::getERC20Balance(const std::string &address,
                                                                                const std::string &erc20Address) {
            return getERC20Balances(address, std::vector<std::string>{erc20Address})
                    .mapPtr<BigInt>(getContext(),
                                    [erc20Address](const std::vector<BigInt> &balances) {
                                        if (balances.empty()) {
                                            throw make_exception(api::ErrorCode::HTTP_ERROR,
                                                                 fmt::format("Failed to get balance for token {}", erc20Address)
                                            );
                                        }
                                        return std::make_shared<BigInt>(balances[0]);
                                    }
                    );
        }

        Future<std::vector<BigInt>>
        LedgerApiEthereumLikeBlockchainExplorer::getERC20Balances(const std::string &address,
                                                                  const std::vector<std::string> &erc20Addresses) {
            rapidjson::Document docContainer;
            docContainer.SetArray();
            auto &allocator = docContainer.GetAllocator();
            for (auto &erc20Address : erc20Addresses) {
                rapidjson::Value o(rapidjson::kObjectType);
                rapidjson::Value vString(rapidjson::kStringType);
                // Set address of account to check balance of
                vString.SetString(address.c_str(), static_cast<rapidjson::SizeType>(address.length()), allocator);
                o.AddMember("address", vString, allocator);
                // Set address of contract (ERC20) to check balance on
                vString.SetString(erc20Address.c_str(), static_cast<rapidjson::SizeType>(erc20Address.length()), allocator);
                o.AddMember("contract", vString, allocator);
                docContainer.PushBack(o.GetObject(), allocator);
            }

            rapidjson::StringBuffer buffer;
            rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
            docContainer.Accept(writer);
            std::string requestBody(buffer.GetString());

            bool parseNumbersAsString = true;
            std::unordered_map<std::string, std::string> headers{{"Content-Type", "application/json"}};
            return _http->POST(fmt::format("/blockchain/{}/{}/erc20/balances",
                                           getExplorerVersion(),
                                           getNetworkParameters().Identifier),
                               std::vector<uint8_t>(requestBody.begin(), requestBody.end()),
                               headers)
                    .json(parseNumbersAsString)
                    .map<std::vector<BigInt>>(getContext(), [erc20Addresses] (const HttpRequest::JsonResult& result) {
                        auto& json = *std::get<1>(result);

                        if (!json.IsArray() || json.Size() != erc20Addresses.size()) {
                            throw make_exception(api::ErrorCode::HTTP_ERROR, "Failed to get balances for erc20 addresses.");
                        }

                        std::vector<BigInt> balances;
                        for (auto &b : json.GetArray()) {
                            if (!b.IsObject() || !b.GetObject().HasMember("balance")) {
                                throw make_exception(api::ErrorCode::HTTP_ERROR, "ERC20 balance: Malformed balance fields.");
                            }
                            balances.emplace_back(BigInt(b.GetObject()["balance"].GetString()));
                        }
                        return balances;
                    });
        }

        Future<String> LedgerApiEthereumLikeBlockchainExplorer::pushLedgerApiTransaction(const std::vector<uint8_t> &transaction) {
            std::stringstream body;
            auto hexTx = "0x" + hex::toString(transaction);
            body << "{" << "\"tx\":" << '"' << hexTx << '"' << "}";
            auto bodyString = body.str();
            return _http->POST(fmt::format("/blockchain/{}/{}/transactions/send", getExplorerVersion(), getNetworkParameters().Identifier),
                               std::vector<uint8_t>(bodyString.begin(), bodyString.end())
            ).json().template map<String>(getExplorerContext(), [] (const HttpRequest::JsonResult& result) -> String {
                auto& json = *std::get<1>(result);
                return json["result"].GetString();
            });
        }

        Future<void *> LedgerApiEthereumLikeBlockchainExplorer::startSession() {
            return startLedgerApiSession();
        }

        Future<Unit> LedgerApiEthereumLikeBlockchainExplorer::killSession(void *session) {
            return killLedgerApiSession(session);
        }

        Future<Bytes> LedgerApiEthereumLikeBlockchainExplorer::getRawTransaction(const String& transactionHash) {
            return getLedgerApiRawTransaction(transactionHash);
        }

        Future<String> LedgerApiEthereumLikeBlockchainExplorer::pushTransaction(const std::vector<uint8_t>& transaction) {
            return pushLedgerApiTransaction(transaction);
        }

        FuturePtr<EthereumLikeBlockchainExplorer::TransactionsBulk>
        LedgerApiEthereumLikeBlockchainExplorer::getTransactions(const std::vector<std::string> &addresses,
                                                        Option<std::string> fromBlockHash,
                                                        Option<void *> session) {
            bool isSnakeCase = true;
            return getLedgerApiTransactions(addresses, fromBlockHash, session, isSnakeCase);
        }

        FuturePtr<Block> LedgerApiEthereumLikeBlockchainExplorer::getCurrentBlock() const {
            return getLedgerApiCurrentBlock();
        }

        FuturePtr<EthereumLikeBlockchainExplorerTransaction>
        LedgerApiEthereumLikeBlockchainExplorer::getTransactionByHash(const String &transactionHash) const {
            return getLedgerApiTransactionByHash(transactionHash);
        }

        Future<int64_t > LedgerApiEthereumLikeBlockchainExplorer::getTimestamp() const {
            return getLedgerApiTimestamp();
        }

        std::shared_ptr<api::ExecutionContext> LedgerApiEthereumLikeBlockchainExplorer::getExplorerContext() const {
            return _executionContext;
        }

        api::EthereumLikeNetworkParameters LedgerApiEthereumLikeBlockchainExplorer::getNetworkParameters() const {
            return _parameters;
        }

        std::string LedgerApiEthereumLikeBlockchainExplorer::getExplorerVersion() const {
            return _explorerVersion;
        }
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 Northeastern University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// This file tests the CpuOperations::Transpose() function by checking to
// See if a matrix passed is transposed in the test IsTransposed
// A transposed Nice matrix is compared to a transposed Eigen Matrix in
// Transpose Eigen
// Behavior with oddly shaped matrices is also tested with test DifferentShapes
// And TransposeZeroRows
// All tests are made using a templated test fixture which attempts
// Integer, float, and double data types

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <memory>

#include "include/gpu_operations.h"
#include "include/cpu_operations.h"

#include "include/kernel_types.h"
#include "Eigen/SVD"
#include "include/svd_solver.h"
#include "include/util.h"

#include "Eigen/Dense"
#include "gtest/gtest.h"
#include "include/matrix.h"
#include "include/vector.h"
#include "include/gpu_util.h"
#include "include/cuda_matrix_vector_multiply.h"
#include "include/cuda_matrix_vector_multiply_shared_memory.h"

// This is a template test fixture class containing test matrices
template<typename T>  // Template
class CudaSharedMVMultiplyTest : public ::testing::Test {
 public:  // Members must be public to be accessed by tests
  Nice::Matrix<T> a_;
  Nice::Vector<T> b_;
  Nice::Vector<T> c_;

  int row_;
  int col_;

  // Constructor
  void CreateTestData(int m, int n) {
    // Check matrix
    if (a_.rows() != 0 && a_.cols() != 0)
      return;

    // Set up dimension
    row_ = m;
    col_ = n;

    // Create matrix
    a_ = Nice::Matrix<T>::Random(row_, col_);
    b_ = Nice::Vector<T>::Random(col_);
    //std::cout << a_ << std::endl;
    //std::cout << b_ << std::endl;

    Nice::CpuOperations<T> cpu_op;
    // Solve in CPU
    c_ = cpu_op.Multiply(a_, b_);
  }
};
// Establishes a test case with the given types, Char and short types will
// Throw compiler errors
typedef ::testing::Types<float, double> dataTypes;
TYPED_TEST_CASE(CudaSharedMVMultiplyTest, dataTypes);

TYPED_TEST(CudaSharedMVMultiplyTest, GlobalMemTest) {
  // Create test data
  int m = 1000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> global_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> global_op;
  global_c = global_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), global_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, SharedMemTest) {
  // Create test data
  int m = 10000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> shared_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> shared_op(32);
  shared_c = shared_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), shared_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, CublasTest) {
  // Create test data
  int m = 10000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> cublas_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::GpuOperations<TypeParam> cublas_op;
  cublas_c = cublas_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), cublas_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, GloVsSharedTest) {
  // Create test data
  int m = 1000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> shared_c(m);
  Nice::Vector<TypeParam> global_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> shared_op(32);
  Nice::CudaMatrixVectorMultiply<TypeParam> global_op;
  shared_c = shared_op.Multiply(this->a_, this->b_);
  global_c = global_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(global_c(i), shared_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, OnesTest) {
  int m = 16;
  int n = 16;
  srand(time(NULL));
  this->a_ = Nice::Matrix<TypeParam>::Constant(m, n, 1);
  this->b_ = Nice::Vector<TypeParam>::Constant(n, 1);
  Nice::Vector<TypeParam> gpu_c(m);
  Nice::CpuOperations<TypeParam> cpu_op;
  // Solve in CPU
  this->c_ = cpu_op.Multiply(this->a_, this->b_);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> gpu_op(32);
  gpu_c = gpu_op.Multiply(this->a_, this->b_);
  // Verify the result
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), gpu_c(i), 0.01);
  }
}
/**
TYPED_TEST(CudaMatrixVectorMultiplyTest, SizeTest) {
  // Create test data
  int m = 5;
  int n = 10;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, MatrixAndVectorEmptyTest) {
  // Create test data
  int m = 0;
  int n = 0;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, MatrixEmptyTest) {
  // Create test data
  int m = 10;
  int n = 5;
  srand(time(NULL));
  this->CreateTestData(m, n);
  this->a_ = Nice::Matrix<TypeParam>::Zero(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, VectorEmptyTest) {
  // Create test data
  int m = 0;
  int n = 0;
  srand(time(NULL));
  this->CreateTestData(m, n);
  this->b_ = Nice::Vector<TypeParam>::Zero(n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}**/
<commit_msg>Change test input size<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 Northeastern University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// This file tests the CpuOperations::Transpose() function by checking to
// See if a matrix passed is transposed in the test IsTransposed
// A transposed Nice matrix is compared to a transposed Eigen Matrix in
// Transpose Eigen
// Behavior with oddly shaped matrices is also tested with test DifferentShapes
// And TransposeZeroRows
// All tests are made using a templated test fixture which attempts
// Integer, float, and double data types

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <memory>

#include "include/gpu_operations.h"
#include "include/cpu_operations.h"

#include "include/kernel_types.h"
#include "Eigen/SVD"
#include "include/svd_solver.h"
#include "include/util.h"

#include "Eigen/Dense"
#include "gtest/gtest.h"
#include "include/matrix.h"
#include "include/vector.h"
#include "include/gpu_util.h"
#include "include/cuda_matrix_vector_multiply.h"
#include "include/cuda_matrix_vector_multiply_shared_memory.h"

// This is a template test fixture class containing test matrices
template<typename T>  // Template
class CudaSharedMVMultiplyTest : public ::testing::Test {
 public:  // Members must be public to be accessed by tests
  Nice::Matrix<T> a_;
  Nice::Vector<T> b_;
  Nice::Vector<T> c_;

  int row_;
  int col_;

  // Constructor
  void CreateTestData(int m, int n) {
    // Check matrix
    if (a_.rows() != 0 && a_.cols() != 0)
      return;

    // Set up dimension
    row_ = m;
    col_ = n;

    // Create matrix
    a_ = Nice::Matrix<T>::Random(row_, col_);
    b_ = Nice::Vector<T>::Random(col_);
    //std::cout << a_ << std::endl;
    //std::cout << b_ << std::endl;

    Nice::CpuOperations<T> cpu_op;
    // Solve in CPU
    c_ = cpu_op.Multiply(a_, b_);
  }
};
// Establishes a test case with the given types, Char and short types will
// Throw compiler errors
typedef ::testing::Types<float, double> dataTypes;
TYPED_TEST_CASE(CudaSharedMVMultiplyTest, dataTypes);

TYPED_TEST(CudaSharedMVMultiplyTest, GlobalMemTest) {
  // Create test data
  int m = 1000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> global_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> global_op;
  global_c = global_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), global_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, SharedMemTest) {
  // Create test data
  int m = 60000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> shared_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> shared_op(32);
  shared_c = shared_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), shared_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, CublasTest) {
  // Create test data
  int m = 60000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> cublas_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::GpuOperations<TypeParam> cublas_op;
  cublas_c = cublas_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), cublas_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, GloVsSharedTest) {
  // Create test data
  int m = 1000;
  int n = 1000;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> shared_c(m);
  Nice::Vector<TypeParam> global_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> shared_op(32);
  Nice::CudaMatrixVectorMultiply<TypeParam> global_op;
  shared_c = shared_op.Multiply(this->a_, this->b_);
  global_c = global_op.Multiply(this->a_, this->b_);
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(global_c(i), shared_c(i), 1e-5) << "Differ at index " << i;
  }
}

TYPED_TEST(CudaSharedMVMultiplyTest, OnesTest) {
  int m = 16;
  int n = 16;
  srand(time(NULL));
  this->a_ = Nice::Matrix<TypeParam>::Constant(m, n, 1);
  this->b_ = Nice::Vector<TypeParam>::Constant(n, 1);
  Nice::Vector<TypeParam> gpu_c(m);
  Nice::CpuOperations<TypeParam> cpu_op;
  // Solve in CPU
  this->c_ = cpu_op.Multiply(this->a_, this->b_);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaSharedMVMultiply<TypeParam> gpu_op(32);
  gpu_c = gpu_op.Multiply(this->a_, this->b_);
  // Verify the result
  for (int i = 0; i < m; i++) {
    EXPECT_NEAR(this->c_(i), gpu_c(i), 0.01);
  }
}
/**
TYPED_TEST(CudaMatrixVectorMultiplyTest, SizeTest) {
  // Create test data
  int m = 5;
  int n = 10;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, MatrixAndVectorEmptyTest) {
  // Create test data
  int m = 0;
  int n = 0;
  srand(time(NULL));
  this->CreateTestData(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, MatrixEmptyTest) {
  // Create test data
  int m = 10;
  int n = 5;
  srand(time(NULL));
  this->CreateTestData(m, n);
  this->a_ = Nice::Matrix<TypeParam>::Zero(m, n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}

TYPED_TEST(CudaMatrixVectorMultiplyTest, VectorEmptyTest) {
  // Create test data
  int m = 0;
  int n = 0;
  srand(time(NULL));
  this->CreateTestData(m, n);
  this->b_ = Nice::Vector<TypeParam>::Zero(n);
  Nice::Vector<TypeParam> gpu_c(m);
  // Test gpu matrix matrix multiply in Nice
  Nice::CudaMatrixVectorMultiply<TypeParam> gpu_op;
  ASSERT_DEATH(gpu_op.Multiply(this->a_, this->b_), ".*");
}**/
<|endoftext|>