<commit_before>#pragma once

#include <stack>
#include <memory>

#include "acmacs-base/fmt.hh"

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

namespace in_json
{
    inline namespace v1
    {
        class error : public std::runtime_error
        {
          public:
            template <typename S> error(size_t line_no, ssize_t column_no, S&& message) : std::runtime_error(fmt::format("in_json error at {}:{}: {}", line_no, column_no, message)) {}
        };

        class parse_error : public std::runtime_error
        {
          public:
            parse_error(std::string_view m1) : std::runtime_error{fmt::format("in_json parsing error: {}", m1)} {}
            parse_error(std::string_view m1, std::string_view m2) : parse_error(fmt::format("{}{}", m1, m2)) {}
        };

        namespace detail
        {
            template <typename Iter> Iter read_string(Iter first, Iter last, Iter& line_start, size_t& line_no)
            {
                bool esc = false;
                for (; first != last; ++first) {
                    switch (*first) {
                        case '"':
                            if (!esc)
                                return first;
                            esc = false;
                            break;
                        case '\\':
                            esc = !esc;
                            break;
                        case '\n':
                            esc = false;
                            ++line_no;
                            line_start = first + 1;
                            break;
                        default:
                            esc = false;
                            break;
                    }
                }
                throw error(line_no, first - line_start, "unexpected EOF");
            }

            enum class number_is { integer, real };
            template <typename Iter> std::pair<Iter, number_is> read_number(Iter first, Iter last)
            {
                number_is nis = number_is::integer;
                for (; first != last; ++first) {
                    switch (*first) {
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                            break;
                        case '.':
                        case '-':
                        case 'e':
                        case 'E':
                            nis = number_is::real;
                            break;
                        default:
                            return {first, nis};
                    }
                }
                throw error(0, 0, "read_number internal");
            }
        } // namespace detail

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

        template <typename Sink, typename Iter> void parse(Sink& sink, Iter first, Iter last)
        {
            using namespace fmt::literals;

            auto line_start = first;
            size_t line_no = 1;
            while (first != last) {
                switch (*first) {
                    case ' ':
                    case ',':
                    case ':':
                        break;
                    case '\n':
                        line_start = first + 1;
                        ++line_no;
                        break;
                    case '{':
                        sink.injson_object_start();
                        break;
                    case '}':
                        sink.injson_object_end();
                        break;
                    case '[':
                        sink.injson_array_start();
                        break;
                    case ']':
                        sink.injson_array_end();
                        break;
                    case '"': {
                        const auto end = detail::read_string(first + 1, last, line_start, line_no); // may throw error on EOF
                        sink.injson_string(first + 1, end);
                        first = end; // end points to terminating double-quotes
                    } break;
                    case '+':
                    case '-':
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': {
                        const auto [end, nis] = detail::read_number(first + 1, last);
                        switch (nis) {
                            case detail::number_is::integer:
                                sink.injson_integer(first, end);
                                break;
                            case detail::number_is::real:
                                sink.injson_real(first, end);
                                break;
                        }
                        first = end - 1; // incremented after switch
                    } break;
                    default:
                        throw error(line_no, first - line_start, "unexpected '{}'"_format(*first));
                }
                ++first;
            }
        }

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

        class stack_entry
        {
          public:
            stack_entry() = default;
            stack_entry(const stack_entry&) = default;
            virtual ~stack_entry() = default;
            virtual const char* injson_name() = 0;
            virtual std::unique_ptr<stack_entry> injson_put_object() { throw in_json::parse_error(fmt::format("{}: unexpected subobject for key \"{}\"", injson_name(), key_)); }
            virtual void injson_put_key(std::string_view data) { key_ = data; }
            virtual void injson_put_string(std::string_view data) { throw parse_error(fmt::format("{}: unexpected string \"{}\" for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_integer(std::string_view data) { throw parse_error(fmt::format("{}: unexpected integer {} for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_real(std::string_view data) { throw parse_error(fmt::format("{}: unexpected real {} for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_array() { throw parse_error(fmt::format("{}: unexpected array for key \"{}\"", injson_name(), key_)); }
            virtual void injson_pop_array() {} //  throw parse_error("stack_entry::injson_pop_array");
            bool key_empty() const { return key_.empty(); }

          protected:
            std::string_view key_{};

            void reset_key() { key_ = std::string_view{}; }
        };

        template <typename TargetContainer, typename ToplevelStackEntry> class object_sink
        {
          public:
            object_sink(TargetContainer& target) : target_{target} {}

            void injson_object_start()
            {
                if (stack_.empty())
                    stack_.push(std::make_unique<ToplevelStackEntry>(target_));
                else
                    stack_.push(stack_.top()->injson_put_object());
            }

            void injson_object_end() { stack_.pop(); }
            void injson_array_start() { stack_.top()->injson_put_array(); }
            void injson_array_end() { stack_.top()->injson_pop_array(); }
            template <typename Iter> void injson_string(Iter first, Iter last)
            {
                const std::string_view data{&*first, static_cast<size_t>(last - first)};
                if (auto& tar = *stack_.top(); tar.key_empty())
                    tar.injson_put_key(data);
                else
                    tar.injson_put_string(data);
            }
            template <typename Iter> void injson_integer(Iter first, Iter last) { stack_.top()->injson_put_integer({&*first, static_cast<size_t>(last - first)}); }
            template <typename Iter> void injson_real(Iter first, Iter last) { stack_.top()->injson_put_real({&*first, static_cast<size_t>(last - first)}); }

          private:
            TargetContainer& target_;
            std::stack<std::unique_ptr<stack_entry>> stack_;
        };

    } // namespace v1
} // namespace in_json

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>in_json::error keeps line, column, message<commit_after>#pragma once

#include <stack>
#include <memory>

#include "acmacs-base/fmt.hh"

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

namespace in_json
{
    inline namespace v1
    {
        class error : public std::runtime_error
        {
          public:
            template <typename S> error(size_t a_line_no, ssize_t a_column_no, S&& a_message) : std::runtime_error(fmt::format("in_json error at {}:{}: {}", a_line_no, a_column_no, a_message)), line_no{a_line_no}, column_no{a_column_no}, message{a_message} {}

            size_t line_no;
            ssize_t column_no;
            std::string message;
        };

        class parse_error : public std::runtime_error
        {
          public:
            parse_error(std::string_view m1) : std::runtime_error{fmt::format("in_json parsing error: {}", m1)} {}
            parse_error(std::string_view m1, std::string_view m2) : parse_error(fmt::format("{}{}", m1, m2)) {}
        };

        namespace detail
        {
            template <typename Iter> Iter read_string(Iter first, Iter last, Iter& line_start, size_t& line_no)
            {
                bool esc = false;
                for (; first != last; ++first) {
                    switch (*first) {
                        case '"':
                            if (!esc)
                                return first;
                            esc = false;
                            break;
                        case '\\':
                            esc = !esc;
                            break;
                        case '\n':
                            esc = false;
                            ++line_no;
                            line_start = first + 1;
                            break;
                        default:
                            esc = false;
                            break;
                    }
                }
                throw error(line_no, first - line_start, "unexpected EOF");
            }

            enum class number_is { integer, real };
            template <typename Iter> std::pair<Iter, number_is> read_number(Iter first, Iter last)
            {
                number_is nis = number_is::integer;
                for (; first != last; ++first) {
                    switch (*first) {
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                            break;
                        case '.':
                        case '-':
                        case 'e':
                        case 'E':
                            nis = number_is::real;
                            break;
                        default:
                            return {first, nis};
                    }
                }
                throw error(0, 0, "read_number internal");
            }
        } // namespace detail

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

        template <typename Sink, typename Iter> void parse(Sink& sink, Iter first, Iter last)
        {
            using namespace fmt::literals;

            auto line_start = first;
            size_t line_no = 1;
            while (first != last) {
                switch (*first) {
                    case ' ':
                    case ',':
                    case ':':
                        break;
                    case '\n':
                        line_start = first + 1;
                        ++line_no;
                        break;
                    case '{':
                        sink.injson_object_start();
                        break;
                    case '}':
                        sink.injson_object_end();
                        break;
                    case '[':
                        sink.injson_array_start();
                        break;
                    case ']':
                        sink.injson_array_end();
                        break;
                    case '"': {
                        const auto end = detail::read_string(first + 1, last, line_start, line_no); // may throw error on EOF
                        sink.injson_string(first + 1, end);
                        first = end; // end points to terminating double-quotes
                    } break;
                    case '+':
                    case '-':
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9': {
                        const auto [end, nis] = detail::read_number(first + 1, last);
                        switch (nis) {
                            case detail::number_is::integer:
                                sink.injson_integer(first, end);
                                break;
                            case detail::number_is::real:
                                sink.injson_real(first, end);
                                break;
                        }
                        first = end - 1; // incremented after switch
                    } break;
                    default:
                        throw error(line_no, first - line_start, "unexpected '{}'"_format(*first));
                }
                ++first;
            }
        }

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

        class stack_entry
        {
          public:
            stack_entry() = default;
            stack_entry(const stack_entry&) = default;
            virtual ~stack_entry() = default;
            virtual const char* injson_name() = 0;
            virtual std::unique_ptr<stack_entry> injson_put_object() { throw in_json::parse_error(fmt::format("{}: unexpected subobject for key \"{}\"", injson_name(), key_)); }
            virtual void injson_put_key(std::string_view data) { key_ = data; }
            virtual void injson_put_string(std::string_view data) { throw parse_error(fmt::format("{}: unexpected string \"{}\" for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_integer(std::string_view data) { throw parse_error(fmt::format("{}: unexpected integer {} for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_real(std::string_view data) { throw parse_error(fmt::format("{}: unexpected real {} for key \"{}\"", injson_name(), data, key_)); }
            virtual void injson_put_array() { throw parse_error(fmt::format("{}: unexpected array for key \"{}\"", injson_name(), key_)); }
            virtual void injson_pop_array() {} //  throw parse_error("stack_entry::injson_pop_array");
            bool key_empty() const { return key_.empty(); }

          protected:
            std::string_view key_{};

            void reset_key() { key_ = std::string_view{}; }
        };

        template <typename TargetContainer, typename ToplevelStackEntry> class object_sink
        {
          public:
            object_sink(TargetContainer& target) : target_{target} {}

            void injson_object_start()
            {
                if (stack_.empty())
                    stack_.push(std::make_unique<ToplevelStackEntry>(target_));
                else
                    stack_.push(stack_.top()->injson_put_object());
            }

            void injson_object_end() { stack_.pop(); }
            void injson_array_start() { stack_.top()->injson_put_array(); }
            void injson_array_end() { stack_.top()->injson_pop_array(); }
            template <typename Iter> void injson_string(Iter first, Iter last)
            {
                const std::string_view data{&*first, static_cast<size_t>(last - first)};
                if (auto& tar = *stack_.top(); tar.key_empty())
                    tar.injson_put_key(data);
                else
                    tar.injson_put_string(data);
            }
            template <typename Iter> void injson_integer(Iter first, Iter last) { stack_.top()->injson_put_integer({&*first, static_cast<size_t>(last - first)}); }
            template <typename Iter> void injson_real(Iter first, Iter last) { stack_.top()->injson_put_real({&*first, static_cast<size_t>(last - first)}); }

          private:
            TargetContainer& target_;
            std::stack<std::unique_ptr<stack_entry>> stack_;
        };

    } // namespace v1
} // namespace in_json

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "serialworker.h"

#include <QSerialPort>
#include <QDebug>

SerialWorker::SerialWorker(QObject *parent) : QObject(parent)
{
    serial = NULL;
    rx_state = IDLE;
    rx_step = 0;
    buildFrame = new CANFrame;
}

SerialWorker::~SerialWorker()
{
    if (serial != NULL) delete serial;
}

void SerialWorker::setSerialPort(QSerialPortInfo *port)
{
    if (!(serial == NULL))
    {
        if (serial->isOpen())
        {
            serial->close();
        }
        delete serial;
    }

    serial = new QSerialPort(*port);

    qDebug() << "Serial port name is " << port->portName();
    serial->open(QIODevice::ReadWrite);
    QByteArray output;
    output.append(0xE7);
    output.append(0xE7);
    serial->write(output);
    ///isConnected = true;
    connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
}

void SerialWorker::readSerialData()
{
    QByteArray data = serial->readAll();
    unsigned char c;
    qDebug() << (tr("Got data from serial. Len = %0").arg(data.length()));
    for (int i = 0; i < data.length(); i++)
    {
        c = data.at(i);
        procRXChar(c);
    }
}

void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
{
    QByteArray buffer;
    int c;
    int ID;

    qDebug() << "Sending out frame with id " << frame->ID;

    ID = frame->ID;
    if (frame->extended) ID |= 1 << 31;

    buffer[0] = 0xF1; //start of a command over serial
    buffer[1] = 0; //command ID for sending a CANBUS frame
    buffer[2] = (unsigned char)(ID & 0xFF); //four bytes of ID LSB first
    buffer[3] = (unsigned char)(ID >> 8);
    buffer[4] = (unsigned char)(ID >> 16);
    buffer[5] = (unsigned char)(ID >> 24);
    buffer[6] = (unsigned char)(bus & 1);
    buffer[7] = (unsigned char)frame->len;
    for (c = 0; c < frame->len; c++)
    {
        buffer[8 + c] = frame->data[c];
    }
    buffer[8 + frame->len] = 0;

    if (serial == NULL) return;
    if (!serial->isOpen()) return;
    qDebug() << "writing " << buffer.length() << " bytes to serial port";
    serial->write(buffer);
}

void SerialWorker::updateBaudRates(int Speed1, int Speed2)
{
    QByteArray buffer;
    qDebug() << "Got signal to update bauds. 1: " << Speed1 <<" 2: " << Speed2;
    buffer[0] = 0xF1; //start of a command over serial
    buffer[1] = 5; //setup canbus
    buffer[2] = (unsigned char)(Speed1 & 0xFF); //four bytes of ID LSB first
    buffer[3] = (unsigned char)(Speed1 >> 8);
    buffer[4] = (unsigned char)(Speed1 >> 16);
    buffer[5] = (unsigned char)(Speed1 >> 24);
    buffer[6] = (unsigned char)(Speed2 & 0xFF); //four bytes of ID LSB first
    buffer[7] = (unsigned char)(Speed2 >> 8);
    buffer[8] = (unsigned char)(Speed2 >> 16);
    buffer[9] = (unsigned char)(Speed2 >> 24);
    buffer[10] = 0;
    if (serial == NULL) return;
    if (!serial->isOpen()) return;
    serial->write(buffer);
}

void SerialWorker::procRXChar(unsigned char c)
{
    switch (rx_state)
    {
    case IDLE:
        if (c == 0xF1) rx_state = GET_COMMAND;
        break;
    case GET_COMMAND:
        switch (c)
        {
        case 0: //receiving a can frame
            rx_state = BUILD_CAN_FRAME;
            rx_step = 0;
            break;
        case 1: //we don't accept time sync commands from the firmware
            rx_state = IDLE;
            break;
        case 2: //process a return reply for digital input states.
            rx_state = GET_DIG_INPUTS;
            rx_step = 0;
            break;
        case 3: //process a return reply for analog inputs
            rx_state = GET_ANALOG_INPUTS;
            break;
        case 4: //we set digital outputs we don't accept replies so nothing here.
            rx_state = IDLE;
            break;
        case 5: //we set canbus specs we don't accept replies.
            rx_state = IDLE;
            break;
        }
        break;
    case BUILD_CAN_FRAME:
        switch (rx_step)
        {
        case 0:
            buildFrame->timestamp = c;
            break;
        case 1:
            buildFrame->timestamp |= (uint)(c << 8);
            break;
        case 2:
            buildFrame->timestamp |= (uint)c << 16;
            break;
        case 3:
            buildFrame->timestamp |= (uint)c << 24;
            break;
        case 4:
            buildFrame->ID = c;
            break;
        case 5:
            buildFrame->ID |= c << 8;
            break;
        case 6:
            buildFrame->ID |= c << 16;
            break;
        case 7:
            buildFrame->ID |= c << 24;
            if ((buildFrame->ID & 1 << 31) == 1 << 31)
            {
                buildFrame->ID &= 0x7FFFFFFF;
                buildFrame->extended = true;
            }
            else buildFrame->extended = false;
            break;
        case 8:
            buildFrame->len = c & 0xF;
            if (buildFrame->len > 8) buildFrame->len = 8;
            buildFrame->bus = (c & 0xF0) >> 4;
            break;
        default:
            if (rx_step < buildFrame->len + 9)
            {
                buildFrame->data[rx_step - 9] = c;
            }
            else
            {
                rx_state = IDLE;
                rx_step = 0;
                qDebug() << "emit from serial handler to main form id: " << buildFrame->ID;
                emit receivedFrame(buildFrame);
                buildFrame = new CANFrame;
            }
            break;
        }
        rx_step++;
        break;
    case GET_ANALOG_INPUTS: //get 9 bytes - 2 per analog input plus checksum
        switch (rx_step)
        {
        case 0:
            break;
        }
        rx_step++;
        break;
    case GET_DIG_INPUTS: //get two bytes. One for digital in status and one for checksum.
        switch (rx_step)
        {
        case 0:
            break;
        case 1:
            rx_state = IDLE;
            break;
        }
        rx_step++;
        break;
    }
}
<commit_msg>Fix to make serial work much better with the candue boards.<commit_after>#include "serialworker.h"

#include <QSerialPort>
#include <QDebug>

SerialWorker::SerialWorker(QObject *parent) : QObject(parent)
{
    serial = NULL;
    rx_state = IDLE;
    rx_step = 0;
    buildFrame = new CANFrame;
}

SerialWorker::~SerialWorker()
{
    if (serial != NULL) delete serial;
}

void SerialWorker::setSerialPort(QSerialPortInfo *port)
{
    if (!(serial == NULL))
    {
        if (serial->isOpen())
        {
            serial->close();
        }
        delete serial;
    }

    serial = new QSerialPort(*port);

    qDebug() << "Serial port name is " << port->portName();
    serial->setBaudRate(serial->Baud115200);
    serial->setDataBits(serial->Data8);
    serial->setFlowControl(serial->HardwareControl);
    serial->open(QIODevice::ReadWrite);
    serial->setDataTerminalReady(true);
    serial->setRequestToSend(true);
    QByteArray output;
    output.append(0xE7);
    output.append(0xE7);
    serial->write(output);
    ///isConnected = true;
    connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
}

void SerialWorker::readSerialData()
{
    QByteArray data = serial->readAll();
    unsigned char c;
    qDebug() << (tr("Got data from serial. Len = %0").arg(data.length()));
    for (int i = 0; i < data.length(); i++)
    {
        c = data.at(i);
        procRXChar(c);
    }
}

void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
{
    QByteArray buffer;
    int c;
    int ID;

    qDebug() << "Sending out frame with id " << frame->ID;

    ID = frame->ID;
    if (frame->extended) ID |= 1 << 31;

    buffer[0] = 0xF1; //start of a command over serial
    buffer[1] = 0; //command ID for sending a CANBUS frame
    buffer[2] = (unsigned char)(ID & 0xFF); //four bytes of ID LSB first
    buffer[3] = (unsigned char)(ID >> 8);
    buffer[4] = (unsigned char)(ID >> 16);
    buffer[5] = (unsigned char)(ID >> 24);
    buffer[6] = (unsigned char)(bus & 1);
    buffer[7] = (unsigned char)frame->len;
    for (c = 0; c < frame->len; c++)
    {
        buffer[8 + c] = frame->data[c];
    }
    buffer[8 + frame->len] = 0;

    if (serial == NULL) return;
    if (!serial->isOpen()) return;
    qDebug() << "writing " << buffer.length() << " bytes to serial port";
    serial->write(buffer);
}

void SerialWorker::updateBaudRates(int Speed1, int Speed2)
{
    QByteArray buffer;
    qDebug() << "Got signal to update bauds. 1: " << Speed1 <<" 2: " << Speed2;
    buffer[0] = 0xF1; //start of a command over serial
    buffer[1] = 5; //setup canbus
    buffer[2] = (unsigned char)(Speed1 & 0xFF); //four bytes of ID LSB first
    buffer[3] = (unsigned char)(Speed1 >> 8);
    buffer[4] = (unsigned char)(Speed1 >> 16);
    buffer[5] = (unsigned char)(Speed1 >> 24);
    buffer[6] = (unsigned char)(Speed2 & 0xFF); //four bytes of ID LSB first
    buffer[7] = (unsigned char)(Speed2 >> 8);
    buffer[8] = (unsigned char)(Speed2 >> 16);
    buffer[9] = (unsigned char)(Speed2 >> 24);
    buffer[10] = 0;
    if (serial == NULL) return;
    if (!serial->isOpen()) return;
    serial->write(buffer);
}

void SerialWorker::procRXChar(unsigned char c)
{
    switch (rx_state)
    {
    case IDLE:
        if (c == 0xF1) rx_state = GET_COMMAND;
        break;
    case GET_COMMAND:
        switch (c)
        {
        case 0: //receiving a can frame
            rx_state = BUILD_CAN_FRAME;
            rx_step = 0;
            break;
        case 1: //we don't accept time sync commands from the firmware
            rx_state = IDLE;
            break;
        case 2: //process a return reply for digital input states.
            rx_state = GET_DIG_INPUTS;
            rx_step = 0;
            break;
        case 3: //process a return reply for analog inputs
            rx_state = GET_ANALOG_INPUTS;
            break;
        case 4: //we set digital outputs we don't accept replies so nothing here.
            rx_state = IDLE;
            break;
        case 5: //we set canbus specs we don't accept replies.
            rx_state = IDLE;
            break;
        }
        break;
    case BUILD_CAN_FRAME:
        switch (rx_step)
        {
        case 0:
            buildFrame->timestamp = c;
            break;
        case 1:
            buildFrame->timestamp |= (uint)(c << 8);
            break;
        case 2:
            buildFrame->timestamp |= (uint)c << 16;
            break;
        case 3:
            buildFrame->timestamp |= (uint)c << 24;
            break;
        case 4:
            buildFrame->ID = c;
            break;
        case 5:
            buildFrame->ID |= c << 8;
            break;
        case 6:
            buildFrame->ID |= c << 16;
            break;
        case 7:
            buildFrame->ID |= c << 24;
            if ((buildFrame->ID & 1 << 31) == 1 << 31)
            {
                buildFrame->ID &= 0x7FFFFFFF;
                buildFrame->extended = true;
            }
            else buildFrame->extended = false;
            break;
        case 8:
            buildFrame->len = c & 0xF;
            if (buildFrame->len > 8) buildFrame->len = 8;
            buildFrame->bus = (c & 0xF0) >> 4;
            break;
        default:
            if (rx_step < buildFrame->len + 9)
            {
                buildFrame->data[rx_step - 9] = c;
            }
            else
            {
                rx_state = IDLE;
                rx_step = 0;
                qDebug() << "emit from serial handler to main form id: " << buildFrame->ID;
                emit receivedFrame(buildFrame);
                buildFrame = new CANFrame;
            }
            break;
        }
        rx_step++;
        break;
    case GET_ANALOG_INPUTS: //get 9 bytes - 2 per analog input plus checksum
        switch (rx_step)
        {
        case 0:
            break;
        }
        rx_step++;
        break;
    case GET_DIG_INPUTS: //get two bytes. One for digital in status and one for checksum.
        switch (rx_step)
        {
        case 0:
            break;
        case 1:
            rx_state = IDLE;
            break;
        }
        rx_step++;
        break;
    }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * c7a/api/sort.hpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Alexander Noe <aleexnoe@gmail.com>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_SORT_HEADER
#define C7A_API_SORT_HEADER

#include <c7a/api/function_stack.hpp>
#include <c7a/api/dia.hpp>
#include <c7a/api/context.hpp>
#include <c7a/net/group.hpp>
#include <c7a/net/collective_communication.hpp>
#include <c7a/net/flow_control_channel.hpp>
#include <c7a/net/flow_control_manager.hpp>
#include <c7a/common/logger.hpp>

#include <cmath>

namespace c7a {
namespace api {

template <typename ValueType, typename ParentStack, typename CompareFunction>
class SortNode : public DOpNode<ValueType>
{
    static const bool debug = true;

    using Super = DOpNode<ValueType>;
    using Super::context_;
    using Super::data_id_;

    using ParentInput = typename ParentStack::Input;

public:
    SortNode(Context& ctx,
	     std::shared_ptr<DIANode<ParentInput> > parent,
	     const ParentStack& parent_stack,
	     CompareFunction compare_function)
        : DOpNode<ValueType>(ctx, { parent }),
          compare_function_(compare_function),
	  channel_id_samples_(ctx.data_manager().AllocateNetworkChannel()),
	  emitters_samples_(ctx.data_manager().
			    template GetNetworkEmitters<ValueType>(channel_id_samples_)),
	  channel_id_data_(ctx.data_manager().AllocateNetworkChannel()),
	  emitters_data_(ctx.data_manager().
			 template GetNetworkEmitters<ValueType>(channel_id_data_))
    {
        // Hook PreOp(s)
        auto pre_op_fn = [=](const ValueType& input) {
                             PreOp(input);
                         };

        auto lop_chain = parent_stack.push(pre_op_fn).emit();

        parent->RegisterChild(lop_chain);
    }

    virtual ~SortNode() { }

    //! Executes the sum operation.
    void Execute() override {
        MainOp();
    }

    /*!
     * Produces an 'empty' function stack, which only contains the identity
     * emitter function.
     *
     * \return Empty function stack
     */
    auto ProduceStack() {
        // Hook Identity
        auto id_fn = [=](ValueType t, auto emit_func) {
                         return emit_func(t);
                     };

        return MakeFunctionStack<ValueType>(id_fn);
    }

    /*!
     * Returns "[SortNode]" as a string.
     * \return "[SortNode]"
     */
    std::string ToString() override {
        return "[PrefixSumNode] Id:" + data_id_.ToString();
    }

private:
    //! The sum function which is applied to two elements.
    CompareFunction compare_function_;
    //! Local data
    std::vector<ValueType> data_;

    //!Emitter to send samples to process 0
    data::ChannelId channel_id_samples_;
    std::vector<data::Emitter<ValueType> > emitters_samples_;

    //!Emitters to send data to other workers specified by splitters.
    data::ChannelId channel_id_data_;
    std::vector<data::Emitter<ValueType> > emitters_data_;

    //epsilon
    double desired_imbalance = 0.25;

    void PreOp(ValueType input) {
        //LOG << "Input: " << input;
        data_.push_back(input);
    }

    void MainOp() {
        //LOG << "MainOp processing";

	size_t samplesize = std::ceil(log2((double) data_.size()) *
				      (1 / (desired_imbalance * desired_imbalance)));

	std::random_device random_device;
	std::default_random_engine generator(random_device());
	std::uniform_int_distribution<int> distribution(0, data_.size() - 1);

	//Send samples to worker 0
	for (size_t i = 0; i < samplesize; i++) {
	    size_t sample = distribution(generator);
	    emitters_samples_[0](data_[sample]);
	}
	emitters_samples_[0].Close();

	std::vector<ValueType> splitters;
	splitters.reserve(context_.number_worker() - 1);

	if (context_.rank() == 0) {
	    //Get samples
	    std::vector<ValueType> samples;
	    samples.reserve(samplesize * context_.number_worker());
	    auto it = context_.data_manager().
		template GetIterator<ValueType>(channel_id_samples_);
	    do {
		it.WaitForMore();
		while (it.HasNext()) {
		    samples.push_back(it.Next());
		}
	    } while (!it.IsFinished());

	    //Find splitters
	    std::sort(samples.begin(), samples.end(), compare_function_);

	    size_t splitting_size = samples.size() / context_.number_worker();

	    //Send splitters to other workers
	    for (size_t i = 1; i < context_.number_worker(); i++) {
		splitters.push_back(samples[i * splitting_size]);
		for (size_t j = 1; j < context_.number_worker(); j++) {
		    emitters_samples_[j](samples[i * splitting_size]);
		}
	    }

	    for (size_t j = 1; j < context_.number_worker(); j++) {
		emitters_samples_[j].Close();
	    }
	} else {
	    //Close unused emitters
	    for (size_t j = 1; j < context_.number_worker(); j++) {
		emitters_samples_[j].Close();
	    }
	    auto it = context_.data_manager().
		template GetIterator<ValueType>(channel_id_samples_);
	    do {
		it.WaitForMore();
		while (it.HasNext()) {
		    splitters.push_back(it.Next());
		}
	    } while (!it.IsFinished());
	}

        for (ValueType ele : data_) {
            bool sent = false;
            for (size_t i = 0; i < splitters.size() && !sent; i++) {
                if (compare_function_(ele, splitters[i])) {
                    emitters_data_[i](ele);
                    sent = true;
                    break;
                }
            }
            if (!sent) {
                emitters_data_[splitters.size()](ele);
            }
        }

        for (size_t i = 0; i < emitters_data_.size(); i++) {
            emitters_data_[i].Close();
        }

        data_.clear();

        auto it = context_.data_manager().
            template GetIterator<ValueType>(channel_id_data_);

        do {
            it.WaitForMore();
            while (it.HasNext()) {
                data_.push_back(it.Next());
            }
        } while (!it.IsFinished());

        std::sort(data_.begin(), data_.end(), compare_function_);

        for (size_t i = 0; i < data_.size(); i++) {
            for (auto func : DIANode<ValueType>::callbacks_) {
                func(data_[i]);
            }
        }
        std::vector<ValueType>().swap(data_);
    }

    void PostOp() { }
};

template <typename ValueType, typename Stack>
template <typename CompareFunction>
auto DIARef<ValueType, Stack>::Sort(const CompareFunction & compare_function) const {

    using SortResultNode
              = SortNode<ValueType, Stack, CompareFunction>;

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::template arg<0>,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::template arg<1>,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::result_type,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    auto shared_node
        = std::make_shared<SortResultNode>(node_->context(),
                                          node_,
                                          stack_,
                                          compare_function);

    auto sort_stack = shared_node->ProduceStack();

    return DIARef<ValueType, decltype(sort_stack)>(
        std::move(shared_node), sort_stack);
}

} // namespace api
} // namespace c7a

#endif // !C7A_API_SORT_NODE_HEADER

/******************************************************************************/
<commit_msg>Uncrustify.<commit_after>/*******************************************************************************
 * c7a/api/sort.hpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Alexander Noe <aleexnoe@gmail.com>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_API_SORT_HEADER
#define C7A_API_SORT_HEADER

#include <c7a/api/function_stack.hpp>
#include <c7a/api/dia.hpp>
#include <c7a/api/context.hpp>
#include <c7a/net/group.hpp>
#include <c7a/net/collective_communication.hpp>
#include <c7a/net/flow_control_channel.hpp>
#include <c7a/net/flow_control_manager.hpp>
#include <c7a/common/logger.hpp>

#include <cmath>

namespace c7a {
namespace api {

template <typename ValueType, typename ParentStack, typename CompareFunction>
class SortNode : public DOpNode<ValueType>
{
    static const bool debug = true;

    using Super = DOpNode<ValueType>;
    using Super::context_;
    using Super::data_id_;

    using ParentInput = typename ParentStack::Input;

public:
    SortNode(Context& ctx,
             std::shared_ptr<DIANode<ParentInput> > parent,
             const ParentStack& parent_stack,
             CompareFunction compare_function)
        : DOpNode<ValueType>(ctx, { parent }),
          compare_function_(compare_function),
          channel_id_samples_(ctx.data_manager().AllocateNetworkChannel()),
          emitters_samples_(ctx.data_manager().
                            template GetNetworkEmitters<ValueType>(channel_id_samples_)),
          channel_id_data_(ctx.data_manager().AllocateNetworkChannel()),
          emitters_data_(ctx.data_manager().
                         template GetNetworkEmitters<ValueType>(channel_id_data_))
    {
        // Hook PreOp(s)
        auto pre_op_fn = [ = ](const ValueType& input) {
                             PreOp(input);
                         };

        auto lop_chain = parent_stack.push(pre_op_fn).emit();

        parent->RegisterChild(lop_chain);
    }

    virtual ~SortNode() { }

    //! Executes the sum operation.
    void Execute() override {
        MainOp();
    }

    /*!
     * Produces an 'empty' function stack, which only contains the identity
     * emitter function.
     *
     * \return Empty function stack
     */
    auto ProduceStack() {
        // Hook Identity
        auto id_fn = [ = ](ValueType t, auto emit_func) {
                         return emit_func(t);
                     };

        return MakeFunctionStack<ValueType>(id_fn);
    }

    /*!
     * Returns "[SortNode]" as a string.
     * \return "[SortNode]"
     */
    std::string ToString() override {
        return "[PrefixSumNode] Id:" + data_id_.ToString();
    }

private:
    //! The sum function which is applied to two elements.
    CompareFunction compare_function_;
    //! Local data
    std::vector<ValueType> data_;

    //!Emitter to send samples to process 0
    data::ChannelId channel_id_samples_;
    std::vector<data::Emitter<ValueType> > emitters_samples_;

    //!Emitters to send data to other workers specified by splitters.
    data::ChannelId channel_id_data_;
    std::vector<data::Emitter<ValueType> > emitters_data_;

    //epsilon
    double desired_imbalance = 0.25;

    void PreOp(ValueType input) {
        //LOG << "Input: " << input;
        data_.push_back(input);
    }

    void MainOp() {
        //LOG << "MainOp processing";

        size_t samplesize = std::ceil(log2((double)data_.size()) *
                                      (1 / (desired_imbalance * desired_imbalance)));

        std::random_device random_device;
        std::default_random_engine generator(random_device());
        std::uniform_int_distribution<int> distribution(0, data_.size() - 1);

        //Send samples to worker 0
        for (size_t i = 0; i < samplesize; i++) {
            size_t sample = distribution(generator);
            emitters_samples_[0](data_[sample]);
        }
        emitters_samples_[0].Close();

        std::vector<ValueType> splitters;
        splitters.reserve(context_.number_worker() - 1);

        if (context_.rank() == 0) {
            //Get samples
            std::vector<ValueType> samples;
            samples.reserve(samplesize * context_.number_worker());
            auto it = context_.data_manager().
                      template GetIterator<ValueType>(channel_id_samples_);
            do {
                it.WaitForMore();
                while (it.HasNext()) {
                    samples.push_back(it.Next());
                }
            } while (!it.IsFinished());

            //Find splitters
            std::sort(samples.begin(), samples.end(), compare_function_);

            size_t splitting_size = samples.size() / context_.number_worker();

            //Send splitters to other workers
            for (size_t i = 1; i < context_.number_worker(); i++) {
                splitters.push_back(samples[i * splitting_size]);
                for (size_t j = 1; j < context_.number_worker(); j++) {
                    emitters_samples_[j](samples[i * splitting_size]);
                }
            }

            for (size_t j = 1; j < context_.number_worker(); j++) {
                emitters_samples_[j].Close();
            }
        }
        else {
            //Close unused emitters
            for (size_t j = 1; j < context_.number_worker(); j++) {
                emitters_samples_[j].Close();
            }
            auto it = context_.data_manager().
                      template GetIterator<ValueType>(channel_id_samples_);
            do {
                it.WaitForMore();
                while (it.HasNext()) {
                    splitters.push_back(it.Next());
                }
            } while (!it.IsFinished());
        }

        for (ValueType ele : data_) {
            bool sent = false;
            for (size_t i = 0; i < splitters.size() && !sent; i++) {
                if (compare_function_(ele, splitters[i])) {
                    emitters_data_[i](ele);
                    sent = true;
                    break;
                }
            }
            if (!sent) {
                emitters_data_[splitters.size()](ele);
            }
        }

        for (size_t i = 0; i < emitters_data_.size(); i++) {
            emitters_data_[i].Close();
        }

        data_.clear();

        auto it = context_.data_manager().
                  template GetIterator<ValueType>(channel_id_data_);

        do {
            it.WaitForMore();
            while (it.HasNext()) {
                data_.push_back(it.Next());
            }
        } while (!it.IsFinished());

        std::sort(data_.begin(), data_.end(), compare_function_);

        for (size_t i = 0; i < data_.size(); i++) {
            for (auto func : DIANode<ValueType>::callbacks_) {
                func(data_[i]);
            }
        }
        std::vector<ValueType>().swap(data_);
    }

    void PostOp() { }
};

template <typename ValueType, typename Stack>
template <typename CompareFunction>
auto DIARef<ValueType, Stack>::Sort(const CompareFunction &compare_function) const {

    using SortResultNode
              = SortNode<ValueType, Stack, CompareFunction>;

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::template arg<0>,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::template arg<1>,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    static_assert(
        std::is_same<
            typename common::FunctionTraits<CompareFunction>::result_type,
            ValueType>::value ||
        std::is_same<CompareFunction, common::LessThan<ValueType> >::value,
        "CompareFunction has the wrong input type");

    auto shared_node
        = std::make_shared<SortResultNode>(node_->context(),
                                           node_,
                                           stack_,
                                           compare_function);

    auto sort_stack = shared_node->ProduceStack();

    return DIARef<ValueType, decltype(sort_stack)>(
        std::move(shared_node), sort_stack);
}
} // namespace api
} // namespace c7a

#endif // !C7A_API_SORT_NODE_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "bi/io/bih_ostream.hpp"

#include <list>

namespace bi {
/**
 * Output stream for Markdown files.
 *
 * @ingroup compiler_io
 */
class md_ostream: public bih_ostream {
public:
  md_ostream(std::ostream& base);

  using bih_ostream::visit;

  virtual void visit(const Package* o);
  virtual void visit(const Name* o);

  virtual void visit(const Parameter* o);
  virtual void visit(const GlobalVariable* o);
  virtual void visit(const MemberVariable* o);
  virtual void visit(const Function* o);
  virtual void visit(const Fiber* o);
  virtual void visit(const Program* o);
  virtual void visit(const MemberFunction* o);
  virtual void visit(const MemberFiber* o);
  virtual void visit(const BinaryOperator* o);
  virtual void visit(const UnaryOperator* o);
  virtual void visit(const AssignmentOperator* o);
  virtual void visit(const ConversionOperator* o);
  virtual void visit(const Class* o);

  virtual void visit(const ListType* o);
  virtual void visit(const ClassType* o);
  virtual void visit(const BasicType* o);
  virtual void visit(const AliasType* o);
  virtual void visit(const IdentifierType* o);
  virtual void visit(const ArrayType* o);
  virtual void visit(const ParenthesesType* o);
  virtual void visit(const FunctionType* o);
  virtual void visit(const FiberType* o);
  virtual void visit(const OptionalType* o);

private:
  void genHead(const std::string& name);

  template<class ObjectType, class RootType>
  void genBrief(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genOneLine(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genDetailed(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genSections(const std::string& name, const RootType* root);

  /**
   * Current section depth.
   */
  int depth;
};
}

#include "bi/visitor/Gatherer.hpp"
#include "bi/primitive/encode.hpp"

template<class ObjectType, class RootType>
void bi::md_ostream::genBrief(const std::string& name, const RootType* root) {
  Gatherer<ObjectType> gatherer;
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    line("| --- | --- |");
    ++depth;
    for (auto o : gatherer) {
      line("| *" << o << "* | " << brief(o->loc->doc) << " |");
    }
    line("");
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genOneLine(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer;
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    line("| --- | --- |");
    ++depth;
    for (auto o : gatherer) {
      line("| *" << o << "* | " << one_line(o->loc->doc) << " |");
    }
    line("");
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genDetailed(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer([](const ObjectType* o) {
        return !detailed(o->loc->doc).empty();
      });
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    ++depth;
    for (auto o : gatherer) {
      std::string desc = detailed(o->loc->doc);
      line("*" << o << "*\n");
      line(desc << "\n");
    }
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genSections(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer([](const ObjectType* o) {
        return !detailed(o->loc->doc).empty();
      });
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    ++depth;
    for (auto o : gatherer) {
      genHead(o->name->str());
      *this << o;
    }
    --depth;
  }
}
<commit_msg>Added alphabetical sorting of function details.<commit_after>/**
 * @file
 */
#pragma once

#include "bi/io/bih_ostream.hpp"

#include <list>
#include <vector>
#include <algorithm>

namespace bi {
/**
 * Output stream for Markdown files.
 *
 * @ingroup compiler_io
 */
class md_ostream: public bih_ostream {
public:
  md_ostream(std::ostream& base);

  using bih_ostream::visit;

  virtual void visit(const Package* o);
  virtual void visit(const Name* o);

  virtual void visit(const Parameter* o);
  virtual void visit(const GlobalVariable* o);
  virtual void visit(const MemberVariable* o);
  virtual void visit(const Function* o);
  virtual void visit(const Fiber* o);
  virtual void visit(const Program* o);
  virtual void visit(const MemberFunction* o);
  virtual void visit(const MemberFiber* o);
  virtual void visit(const BinaryOperator* o);
  virtual void visit(const UnaryOperator* o);
  virtual void visit(const AssignmentOperator* o);
  virtual void visit(const ConversionOperator* o);
  virtual void visit(const Class* o);

  virtual void visit(const ListType* o);
  virtual void visit(const ClassType* o);
  virtual void visit(const BasicType* o);
  virtual void visit(const AliasType* o);
  virtual void visit(const IdentifierType* o);
  virtual void visit(const ArrayType* o);
  virtual void visit(const ParenthesesType* o);
  virtual void visit(const FunctionType* o);
  virtual void visit(const FiberType* o);
  virtual void visit(const OptionalType* o);

private:
  void genHead(const std::string& name);

  template<class ObjectType, class RootType>
  void genBrief(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genOneLine(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genDetailed(const std::string& name, const RootType* root);

  template<class ObjectType, class RootType>
  void genSections(const std::string& name, const RootType* root);

  /**
   * Current section depth.
   */
  int depth;
};
}

#include "bi/visitor/Gatherer.hpp"
#include "bi/primitive/encode.hpp"

template<class ObjectType, class RootType>
void bi::md_ostream::genBrief(const std::string& name, const RootType* root) {
  Gatherer<ObjectType> gatherer;
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    line("| --- | --- |");
    ++depth;
    for (auto o : gatherer) {
      line("| *" << o << "* | " << brief(o->loc->doc) << " |");
    }
    line("");
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genOneLine(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer;
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    line("| --- | --- |");
    ++depth;
    for (auto o : gatherer) {
      line("| *" << o << "* | " << one_line(o->loc->doc) << " |");
    }
    line("");
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genDetailed(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer([](const ObjectType* o) {
    return !detailed(o->loc->doc).empty();
  });
  root->accept(&gatherer);

  std::vector<ObjectType*> sorted(gatherer.size());
  std::copy(gatherer.begin(), gatherer.end(), sorted.begin());
  std::stable_sort(sorted.begin(), sorted.end(),
      [](const ObjectType* o1, const ObjectType* o2) {
        return o1->name->str() < o2->name->str();
      });

  if (sorted.size() > 0) {
    genHead(name);
    ++depth;
    for (auto o : sorted) {
      std::string desc = detailed(o->loc->doc);
      line("*" << o << "*\n");
      line(desc << "\n");
    }
    --depth;
  }
}

template<class ObjectType, class RootType>
void bi::md_ostream::genSections(const std::string& name,
    const RootType* root) {
  Gatherer<ObjectType> gatherer([](const ObjectType* o) {
    return !detailed(o->loc->doc).empty();
  });
  root->accept(&gatherer);
  if (gatherer.size() > 0) {
    genHead(name);
    ++depth;
    for (auto o : gatherer) {
      genHead(o->name->str());
      *this << o;
    }
    --depth;
  }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <sstream>
#include <cstring>
#include <cassert>
#include <set>
#include <string>
#include <queue>
#include <iostream>
#include "CallGraph.h"
#include "CodeGen_Bash.h"
#include "Parser.h"
#include "IRVisitor.h"

const std::string BISH_VERSION = "0.1";
const std::string BISH_URL = "https://github.com/tdenniston/bish";
const std::string STDLIB_PATH = "src/StdLib.bish";

class FindFunctionCalls : public Bish::IRVisitor {
public:
    FindFunctionCalls(const std::set<std::string> &n) {
        to_find.insert(n.begin(), n.end());
    }

    std::set<std::string> names() { return names_; }

    virtual void visit(Bish::FunctionCall *call) {
        for (std::vector<Bish::IRNode *>::const_iterator I = call->args.begin(),
                 E = call->args.end(); I != E; ++I) {
            (*I)->accept(this);
        }
        if (to_find.count(call->function->name)) {
            names_.insert(call->function->name);
        }
    }
private:
    std::set<std::string> to_find;
    std::set<std::string> names_;
};

// Add necessary stdlib functions to the given module.
void link_stdlib(Bish::Module *m) {
    Bish::Parser p;
    Bish::Module *stdlib = p.parse(STDLIB_PATH);
    std::set<std::string> stdlib_functions;
    for (std::vector<Bish::Function *>::iterator I = stdlib->functions.begin(),
             E = stdlib->functions.end(); I != E; ++I) {
        Bish::Function *f = *I;
        if (f->name.compare("main") == 0) continue;
        stdlib_functions.insert(f->name);
    }
    FindFunctionCalls find(stdlib_functions);
    m->accept(&find);
    Bish::CallGraphBuilder cgb;
    Bish::CallGraph cg = cgb.build(stdlib);

    std::set<std::string> to_link = find.names();
    for (std::set<std::string>::iterator I = to_link.begin(), E = to_link.end(); I != E; ++I) {
        Bish::Function *f = stdlib->get_function(*I);
        assert(f);
        if (f->name.compare("main") == 0) continue;
        m->add_function(f);
        std::vector<Bish::Function *> calls = cg.transitive_calls(f);
        for (std::vector<Bish::Function *>::iterator II = calls.begin(), EE = calls.end(); II != EE; ++II) {
            m->add_function(stdlib->get_function((*II)->name));
        }
    }
}

void compile_to_bash(std::ostream &os, Bish::Module *m) {
    link_stdlib(m);
    os << "#!/bin/bash\n";
    os << "# Autogenerated script, compiled from the Bish language.\n";
    os << "# Bish version " << BISH_VERSION << "\n";
    os << "# Please see " << BISH_URL << " for more information about Bish.\n\n";
    Bish::CodeGen_Bash compile(os);
    m->accept(&compile);
}

void run_on_bash(std::istream &is) {
    FILE *bash = popen("bash", "w");
    char buf[4096];
    while (is.read(buf, sizeof(buf))) {
        fwrite(buf, 1, is.gcount(), bash);
    }
    fwrite(buf, 1, is.gcount(), bash);

    fflush(bash);
    pclose(bash);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        std::cerr << "USAGE: " << argv[0] << " [-r] <INPUT>\n";
        std::cerr << "  Compiles Bish file <INPUT> to bash.\n";
        std::cerr << "\nOPTIONS:\n";
        std::cerr << "  -r  compiles and runs the file.\n";
        return 1;
    }

    if (strcmp(argv[1], "-r") == 0) {
        if (argc != 3) {
            std::cerr << "-r needs a filename\n";
            return 1;
        }

        std::string path(argv[2]);
        Bish::Parser p;
        Bish::Module *m = p.parse(path);

        std::stringstream s;
        compile_to_bash(s, m);
        run_on_bash(s);
    } else {
        std::string path(argv[1]);
        Bish::Parser p;
        Bish::Module *m = p.parse(path);

        compile_to_bash(std::cout, m);
    }

    return 0;
}
<commit_msg>Use a do-while loop to DRY up the stream reading<commit_after>#include <stdio.h>
#include <sstream>
#include <cstring>
#include <cassert>
#include <set>
#include <string>
#include <queue>
#include <iostream>
#include "CallGraph.h"
#include "CodeGen_Bash.h"
#include "Parser.h"
#include "IRVisitor.h"

const std::string BISH_VERSION = "0.1";
const std::string BISH_URL = "https://github.com/tdenniston/bish";
const std::string STDLIB_PATH = "src/StdLib.bish";

class FindFunctionCalls : public Bish::IRVisitor {
public:
    FindFunctionCalls(const std::set<std::string> &n) {
        to_find.insert(n.begin(), n.end());
    }

    std::set<std::string> names() { return names_; }

    virtual void visit(Bish::FunctionCall *call) {
        for (std::vector<Bish::IRNode *>::const_iterator I = call->args.begin(),
                 E = call->args.end(); I != E; ++I) {
            (*I)->accept(this);
        }
        if (to_find.count(call->function->name)) {
            names_.insert(call->function->name);
        }
    }
private:
    std::set<std::string> to_find;
    std::set<std::string> names_;
};

// Add necessary stdlib functions to the given module.
void link_stdlib(Bish::Module *m) {
    Bish::Parser p;
    Bish::Module *stdlib = p.parse(STDLIB_PATH);
    std::set<std::string> stdlib_functions;
    for (std::vector<Bish::Function *>::iterator I = stdlib->functions.begin(),
             E = stdlib->functions.end(); I != E; ++I) {
        Bish::Function *f = *I;
        if (f->name.compare("main") == 0) continue;
        stdlib_functions.insert(f->name);
    }
    FindFunctionCalls find(stdlib_functions);
    m->accept(&find);
    Bish::CallGraphBuilder cgb;
    Bish::CallGraph cg = cgb.build(stdlib);

    std::set<std::string> to_link = find.names();
    for (std::set<std::string>::iterator I = to_link.begin(), E = to_link.end(); I != E; ++I) {
        Bish::Function *f = stdlib->get_function(*I);
        assert(f);
        if (f->name.compare("main") == 0) continue;
        m->add_function(f);
        std::vector<Bish::Function *> calls = cg.transitive_calls(f);
        for (std::vector<Bish::Function *>::iterator II = calls.begin(), EE = calls.end(); II != EE; ++II) {
            m->add_function(stdlib->get_function((*II)->name));
        }
    }
}

void compile_to_bash(std::ostream &os, Bish::Module *m) {
    link_stdlib(m);
    os << "#!/bin/bash\n";
    os << "# Autogenerated script, compiled from the Bish language.\n";
    os << "# Bish version " << BISH_VERSION << "\n";
    os << "# Please see " << BISH_URL << " for more information about Bish.\n\n";
    Bish::CodeGen_Bash compile(os);
    m->accept(&compile);
}

void run_on_bash(std::istream &is) {
    FILE *bash = popen("bash", "w");
    char buf[4096];

    do {
        is.read(buf, sizeof(buf));
        fwrite(buf, 1, is.gcount(), bash);
    } while (is.gcount() > 0);

    fflush(bash);
    pclose(bash);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        std::cerr << "USAGE: " << argv[0] << " [-r] <INPUT>\n";
        std::cerr << "  Compiles Bish file <INPUT> to bash.\n";
        std::cerr << "\nOPTIONS:\n";
        std::cerr << "  -r  compiles and runs the file.\n";
        return 1;
    }

    if (strcmp(argv[1], "-r") == 0) {
        if (argc != 3) {
            std::cerr << "-r needs a filename\n";
            return 1;
        }

        std::string path(argv[2]);
        Bish::Parser p;
        Bish::Module *m = p.parse(path);

        std::stringstream s;
        compile_to_bash(s, m);
        run_on_bash(s);
    } else {
        std::string path(argv[1]);
        Bish::Parser p;
        Bish::Module *m = p.parse(path);

        compile_to_bash(std::cout, m);
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>

using namespace std;

#define uint unsigned int

int main(int argc, char* argv[])
{
	return 0;
}

<commit_msg>Update c++ template to print a newline<commit_after>#include <stdio.h>
#include <stdlib.h>

using namespace std;

#define uint unsigned int

int main(int argc, char* argv[])
{
	printf("\n");
	return 0;
}

<|endoftext|>


<commit_before>#include <vector>
#include <ostream>
#include "BST.h"
/*
namespace Graph
{
	template <typename Key, typename Value> class BST
	{//A Binary Search Tree.
		private:
			Node<Key, Value> root;
			Value get( Node subtreeNode, Key getKey );//Returns the value of the node with a specified key that is within the subtree rooted at subtreeNode. Returns null if the node isn't found.
			Node put( Node rootNode, Key newKey, Value newValue );
			Node min( Node minNode );
			Key floor( Node rootNode, Key key );

		public:
			int size() const;//Returns the size of the tree.
			int size(Node node) const;//Returns the size at node node.
			Value get( Key getKey );//Returns the value of the node with a specified key.
			void put( Key newKey, Value newValue );
			Key min();
			Key floor( Key key );
	};
}
*/

namespace Graph
{
	template <typename Key, typename Value> int BST<Key, Value>::size() const
	{//Returns the size of the tree.
		return size( root );
	}

	template <typename Key, typename Value> int size(Node node) const
	{//Returns the size at node node.
		if( node == null )
		{
			return 0;
		}
		else
		{
			return node.N;
		}
	}

	template <typename Key, typename Value> Value BST<Key, Value>::get( Key getKey )
	{//Returns the value of the node with a specified key.
		return get( root, key );
	}

	template <typename Key, typename Value> Value Node<Key, Value>::get( Node subtreeNode, Key getKey )
	{//Returns the value of the node with a specified key that is within the subtree rooted at subtreeNode. Returns null if the node isn't found.
		if( subtreeNode == null )
		{
			return null;
		}

		int compare = getKey.compareTo( subtreeNode.key );
		if( compare < 0 )
		{
			return get( subtreeNode.left, getKey );
		}
		else if( compare > 0 )
		{
			return get( subtreeNode.right, getKey );
		}
		else
		{
			return subtreeNode.value;
		}
	}

	template <typename Key, typename Value> void BST<Key, Value>::put( Key newKey, Value newValue )
	{//Search for the key. If there is a node with the key, update the value. If not, add it to the tree.
		root = put(root, newKey, newValue);
	}

	template <typename Key, typename Value> Node BST<Key, Value>::put( Node rootNode, Key newKey, Value newValue )
	{//If a node with newKey exists in the tree rooted at rootNode, change the value of the node. If not, add it to the tree.
		if( newKey == null )
		{
			return new Node( newKey, newValue, 1 );
		}

		int compare = newKey.compareTo( rootNode.key );
		if( compare < 0 )
		{
			rootNode.left = put( rootNode.left, newKey, newValue );
		}
		else if( compare > 0 )
		{
			rootNode.right = put( rootNode.right, newKey, newValue );
		}
		else
		{
			rootNode.value = newValue;
		}

		rootNode.N = size(rootNode.left) + size(rootNode.right) + 1;

		return rootNode;
	}

	template <typename Key, typename Value> Key BST<Key, Value>::min()
	{
		return min(root).key;
	}

	template <typename Key, typename Value> void BST<Key, Value>::min( Node rootNode )
	{
		if( rootNode.left == null )
		{
			return rootNode;
		}
		else
		{
			return min( rootNode.left );
		}
	}

	template <typename Key, typename Value> Key BST<Key, Value>::floor( Node rootNode, Key key )
	{
		if( rootNode == null )
		{
			return null;
		}
		int compare = key.compareTo( rootNode.key );
		if( compare == 0 )
		{
			return rootNode;
		}
		else if( compare < 0 )
		{
			return floor( rootNode.left, key );
		}

		Node t = floor( rootNode.right, key );
		if( t != null )
		{
			return t;
		}
		else
		{
			return rootNode;
		}
	}

	template <typename Key, typename Value> BST<Key, Value>::Key floor( Key key )
	{
		Node rootNode = floor( root, key );
		if( rootNode == null )
		{
			return null;
		}
		else
		{
			return rootNode.key;
		}
	}

	template <typename Key, typename Value> BST<Key, Value>::Key select( int n )
	{
	}
}
<commit_msg>Added a comment.<commit_after>#include <vector>
#include <ostream>
#include "BST.h"
/*
namespace Graph
{
	template <typename Key, typename Value> class BST
	{//A Binary Search Tree.
		private:
			Node<Key, Value> root;
			Value get( Node subtreeNode, Key getKey );//Returns the value of the node with a specified key that is within the subtree rooted at subtreeNode. Returns null if the node isn't found.
			Node put( Node rootNode, Key newKey, Value newValue );
			Node min( Node minNode );
			Key floor( Node rootNode, Key key );
			Key select( int n );

		public:
			int size() const;//Returns the size of the tree.
			int size(Node node) const;//Returns the size at node node.
			Value get( Key getKey );//Returns the value of the node with a specified key.
			void put( Key newKey, Value newValue );
			Key min();
			Key floor( Key key );
	};
}
*/

namespace Graph
{
	template <typename Key, typename Value> int BST<Key, Value>::size() const
	{//Returns the size of the tree.
		return size( root );
	}

	template <typename Key, typename Value> int size(Node node) const
	{//Returns the size at node node.
		if( node == null )
		{
			return 0;
		}
		else
		{
			return node.N;
		}
	}

	template <typename Key, typename Value> Value BST<Key, Value>::get( Key getKey )
	{//Returns the value of the node with a specified key.
		return get( root, key );
	}

	template <typename Key, typename Value> Value Node<Key, Value>::get( Node subtreeNode, Key getKey )
	{//Returns the value of the node with a specified key that is within the subtree rooted at subtreeNode. Returns null if the node isn't found.
		if( subtreeNode == null )
		{
			return null;
		}

		int compare = getKey.compareTo( subtreeNode.key );
		if( compare < 0 )
		{
			return get( subtreeNode.left, getKey );
		}
		else if( compare > 0 )
		{
			return get( subtreeNode.right, getKey );
		}
		else
		{
			return subtreeNode.value;
		}
	}

	template <typename Key, typename Value> void BST<Key, Value>::put( Key newKey, Value newValue )
	{//Search for the key. If there is a node with the key, update the value. If not, add it to the tree.
		root = put(root, newKey, newValue);
	}

	template <typename Key, typename Value> Node BST<Key, Value>::put( Node rootNode, Key newKey, Value newValue )
	{//If a node with newKey exists in the tree rooted at rootNode, change the value of the node. If not, add it to the tree.
		if( newKey == null )
		{
			return new Node( newKey, newValue, 1 );
		}

		int compare = newKey.compareTo( rootNode.key );
		if( compare < 0 )
		{
			rootNode.left = put( rootNode.left, newKey, newValue );
		}
		else if( compare > 0 )
		{
			rootNode.right = put( rootNode.right, newKey, newValue );
		}
		else
		{
			rootNode.value = newValue;
		}

		rootNode.N = size(rootNode.left) + size(rootNode.right) + 1;

		return rootNode;
	}

	template <typename Key, typename Value> Key BST<Key, Value>::min()
	{
		return min(root).key;
	}

	template <typename Key, typename Value> void BST<Key, Value>::min( Node rootNode )
	{
		if( rootNode.left == null )
		{
			return rootNode;
		}
		else
		{
			return min( rootNode.left );
		}
	}

	template <typename Key, typename Value> Key BST<Key, Value>::floor( Node rootNode, Key key )
	{
		if( rootNode == null )
		{
			return null;
		}
		int compare = key.compareTo( rootNode.key );
		if( compare == 0 )
		{
			return rootNode;
		}
		else if( compare < 0 )
		{
			return floor( rootNode.left, key );
		}

		Node t = floor( rootNode.right, key );
		if( t != null )
		{
			return t;
		}
		else
		{
			return rootNode;
		}
	}

	template <typename Key, typename Value> BST<Key, Value>::Key floor( Key key )
	{
		Node rootNode = floor( root, key );
		if( rootNode == null )
		{
			return null;
		}
		else
		{
			return rootNode.key;
		}
	}

	template <typename Key, typename Value> BST<Key, Value>::Key select( int n )
	{
	}
}
<|endoftext|>


<commit_before>#pragma once

#include "imgui.h"

void drawIGSLogo(
    const ImVec2& pos,
    const double time );

/** Show an info about window with animated IGS logo.
	Usage example:
	if( about_window_visible &&
        aboutWindow(
			ICON_FA_INFO_CIRCLE " About",
			"My fancy tools\n"
			"Abla bli blub ....\n",
			ImVec2( 400, 155 ),
			time ) )
			about_window_visible = false;
*/
bool aboutWindow(
    const char* title,
    const char* text,
    const ImVec2& size,
    double time );
<commit_msg>adjust comment<commit_after>#pragma once

#include "imgui.h"

void drawIGSLogo(
    const ImVec2& pos,
    const double time );

/** Show an info about window with animated IGS logo.
* \param time in secs.
*/
bool aboutWindow(
    const char* title,
    const char* text,
    const ImVec2& size,
    double time );
<|endoftext|>


<commit_before>#include "NMEAParser.cpp"
#include "gtest/gtest.h"

#include <cmath>

namespace NMEA {
TEST(ParseFloat, Valid_Float) {
  const std::string String = "3.0";
  const float Expected = 3.0f;

  EXPECT_EQ(Expected, ParseFloat(String));
}

TEST(ParseFloat, Invalid_Float) {
  const std::string String = "ASDF";

  EXPECT_TRUE(isnan(ParseFloat(String)));
}

TEST(ParseFloat, Invalid_Empty_Float) {
  const std::string String = "";
  const float Expected = NAN;

  EXPECT_TRUE(isnan(ParseFloat(String)));
}
}
<commit_msg>Add ParseFloat_Test file comment<commit_after>/**
 * File: ParseFloat_Test.cpp
 * Description: Unit tests for
 * Parse(const std::string &String)
 */
#include "NMEAParser.cpp"
#include "gtest/gtest.h"

#include <cmath>

namespace NMEA {
TEST(ParseFloat, Valid_Float) {
  const std::string String = "3.0";
  const float Expected = 3.0f;

  EXPECT_EQ(Expected, ParseFloat(String));
}

TEST(ParseFloat, Invalid_Float) {
  const std::string String = "ASDF";

  EXPECT_TRUE(isnan(ParseFloat(String)));
}

TEST(ParseFloat, Invalid_Empty_Float) {
  const std::string String = "";
  const float Expected = NAN;

  EXPECT_TRUE(isnan(ParseFloat(String)));
}
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkOnePlusOneEvolutionaryOptimizerv4_hxx
#define itkOnePlusOneEvolutionaryOptimizerv4_hxx

#include "itkMath.h"
#include "itkOnePlusOneEvolutionaryOptimizerv4.h"
#include "vnl/vnl_matrix.h"
namespace itk
{
template<typename TInternalComputationValueType>
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::OnePlusOneEvolutionaryOptimizerv4()
{
  m_CatchGetValueException = false;
  m_MetricWorstPossibleValue = 0;

  m_Epsilon = (double)1.5e-4;
  m_RandomGenerator = ITK_NULLPTR;

  m_Initialized = false;
  m_GrowthFactor = 1.05;
  m_ShrinkFactor = std::pow(m_GrowthFactor, -0.25);
  m_InitialRadius = 1.01;
  m_MaximumIteration = 100;
  m_Stop = false;
  m_StopConditionDescription.str("");
  m_CurrentCost = 0;
  m_FrobeniusNorm = 0.0;
}

template<typename TInternalComputationValueType>
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::~OnePlusOneEvolutionaryOptimizerv4()
{}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::SetNormalVariateGenerator(NormalVariateGeneratorType *generator)
{
  if ( m_RandomGenerator != generator )
    {
    m_RandomGenerator = generator;
    this->Modified();
    }
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::Initialize(double initialRadius, double grow, double shrink)
{
  m_InitialRadius = initialRadius;

  if ( Math::AlmostEquals( grow, -1 ) )
    {
    m_GrowthFactor = 1.05;
    }
  else
    {
    m_GrowthFactor = grow;
    }
  if ( Math::AlmostEquals( shrink, -1 ) )
    {
    m_ShrinkFactor = std::pow(m_GrowthFactor, -0.25);
    }
  else
    {
    m_ShrinkFactor = shrink;
    }
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::StartOptimization(bool /* doOnlyInitialization */)
{
  if ( this->m_Metric.IsNull() )
    {
    return;
    }

  Superclass::StartOptimization();

  this->InvokeEvent( StartEvent() );
  m_Stop = false;

  unsigned int         spaceDimension = this->m_Metric->GetNumberOfParameters();
  vnl_matrix< double > A(spaceDimension, spaceDimension);
  vnl_vector< double > parent( this->m_Metric->GetParameters() );
  vnl_vector< double > f_norm(spaceDimension);
  vnl_vector< double > child(spaceDimension);
  vnl_vector< double > delta(spaceDimension);

  ParametersType parentPosition(spaceDimension);
  ParametersType childPosition(spaceDimension);

  for ( unsigned int i = 0; i < spaceDimension; i++ )
    {
    parentPosition[i] = parent[i];
    }
  this->m_Metric->SetParameters( parentPosition );

  double pvalue = m_MetricWorstPossibleValue;
  try
    {
    pvalue = this->m_Metric->GetValue();
    }
  catch ( ... )
    {
    if ( m_CatchGetValueException )
      {
      pvalue = m_MetricWorstPossibleValue;
      }
    else
      {
      throw;
      }
    }

  itkDebugMacro(<< ": initial position: " << parentPosition);
  itkDebugMacro(<< ": initial fitness: " << pvalue);

  this->m_Metric->SetParameters(parentPosition);
  const ScalesType & scales = this->GetScales();

  // Make sure the scales have been set properly
  if ( scales.size() != spaceDimension )
    {
    itkExceptionMacro(<< "The size of Scales is "
                      << scales.size()
                      << ", but the NumberOfParameters for the CostFunction is "
                      << spaceDimension
                      << ".");
    }

  A.set_identity();
  for ( unsigned int i = 0; i < spaceDimension; i++ )
    {
    A(i, i) = m_InitialRadius / scales[i];
    }
  this->m_CurrentIteration = 0;

  for ( unsigned int iter = 0; iter < m_MaximumIteration; iter++ )
    {
    if ( m_Stop )
      {
      m_StopConditionDescription.str("");
      m_StopConditionDescription << this->GetNameOfClass() << ": ";
      m_StopConditionDescription << "StopOptimization() called";
      break;
      }

    ++this->m_CurrentIteration;

    for ( unsigned int i = 0; i < spaceDimension; i++ )
      {
      if ( !m_RandomGenerator )
        {
        itkExceptionMacro(<< "Random Generator is not set!");
        }
      f_norm[i] = m_RandomGenerator->GetVariate();
      }

    delta  = A * f_norm;
    child  = parent + delta;

    for ( unsigned int i = 0; i < spaceDimension; i++ )
      {
      childPosition[i] = child[i];
      }
    // Update the metric so we can check the metric value in childPosition
    this->m_Metric->SetParameters( childPosition );

    double cvalue = m_MetricWorstPossibleValue;
    try
      {
      cvalue = this->m_Metric->GetValue();
      // While we got the metric value in childPosition,
      // the metric paramteres are set back to parentPosition
      this->m_Metric->SetParameters( parentPosition );
      }
    catch ( ... )
      {
      if ( m_CatchGetValueException )
        {
        cvalue = m_MetricWorstPossibleValue;
        }
      else
        {
        throw;
        }
      }

    itkDebugMacro(<< "iter: " << iter << ": parent position: "
                  << parentPosition);
    itkDebugMacro(<< "iter: " << iter << ": parent fitness: "
                  << pvalue);
    itkDebugMacro(<< "iter: " << iter << ": random vector: " << f_norm);
    itkDebugMacro(<< "iter: " << iter << ": A: " << std::endl << A);
    itkDebugMacro(<< "iter: " << iter << ": delta: " << delta);
    itkDebugMacro(<< "iter: " << iter << ": child position: "
                  << childPosition);
    itkDebugMacro(<< "iter: " << iter << ": child fitness: "
                  << cvalue);

    double adjust = m_ShrinkFactor;

    if ( cvalue < pvalue )
      {
      itkDebugMacro(<< "iter: " << iter << ": increasing search radius");
      pvalue = cvalue;
      parent.swap(child);
      adjust = m_GrowthFactor;
      for ( unsigned int i = 0; i < spaceDimension; i++ )
        {
        parentPosition[i] = parent[i];
        }
      this->m_Metric->SetParameters(parentPosition);
      }
    else
      {
      itkDebugMacro(<< "iter: " << iter << ": decreasing search radius");
      }

    m_CurrentCost = pvalue;
    // convergence criterion: f-norm of A < epsilon_A
    // Compute double precision sum of absolute values of
    // a single precision vector
    m_FrobeniusNorm = A.fro_norm();
    itkDebugMacro(<< "A f-norm:" << m_FrobeniusNorm);
    if ( m_FrobeniusNorm <= m_Epsilon )
      {
      itkDebugMacro(<< "converges at iteration = " << iter);
      m_StopConditionDescription.str("");
      m_StopConditionDescription << this->GetNameOfClass() << ": ";
      m_StopConditionDescription << "Fnorm (" << m_FrobeniusNorm
                                 << ") is less than Epsilon (" << m_Epsilon
                                 << " at iteration #" << iter;
      this->InvokeEvent( EndEvent() );
      return;
      }

    // A += (adjust - 1)/ (f_norm * f_norm) * A * f_norm * f_norm;
    // Blas_R1_Update(A, A * f_norm, f_norm,
    //             ((adjust - 1) / Blas_Dot_Prod(f_norm, f_norm)));
    // = DGER(Fortran)
    //   performs the rank 1 operation
    // A := alpha*x*y' + A,
    // where y' = transpose(y)
    // where alpha is a scalar, x is an m element vector, y is an n element
    // vector and A is an m by n matrix.
    // x = A * f_norm , y = f_norm, alpha = (adjust - 1) / Blas_Dot_Prod(
    // f_norm, f_norm)

    //A = A + (adjust - 1.0) * A;
    double alpha = ( ( adjust - 1.0 ) / dot_product(f_norm, f_norm) );
    for ( unsigned int c = 0; c < spaceDimension; c++ )
      {
      for ( unsigned int r = 0; r < spaceDimension; r++ )
        {
        A(r, c) += alpha * delta[r] * f_norm[c];
        }
      }

    this->InvokeEvent( IterationEvent() );
    itkDebugMacro( << "Current position: " << this->GetCurrentPosition() );
    }
  m_StopConditionDescription.str("");
  m_StopConditionDescription << this->GetNameOfClass() << ": ";
  m_StopConditionDescription << "Maximum number of iterations ("
                             << m_MaximumIteration
                             << ") exceeded. ";
  this->InvokeEvent( EndEvent() );
}

template<typename TInternalComputationValueType>
const std::string
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::GetStopConditionDescription() const
{
  return m_StopConditionDescription.str();
}

template<typename TInternalComputationValueType>
const typename OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>::MeasureType &
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::GetValue() const
{
  return this->GetCurrentCost();
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  if ( m_RandomGenerator )
    {
    os << indent << "Random Generator  " << m_RandomGenerator.GetPointer()  << std::endl;
    }
  else
    {
    os << indent << "Random Generator  " << "(none)" << std::endl;
    }
  os << indent << "Maximum Iteration " << GetMaximumIteration() << std::endl;
  os << indent << "Epsilon           " << GetEpsilon()          << std::endl;
  os << indent << "Initial Radius    " << GetInitialRadius()    << std::endl;
  os << indent << "Growth Fractor    " << GetGrowthFactor()     << std::endl;
  os << indent << "Shrink Fractor    " << GetShrinkFactor()     << std::endl;
  os << indent << "Initialized       " << GetInitialized()      << std::endl;
  os << indent << "Current Cost      " << GetCurrentCost()      << std::endl;
  os << indent << "Frobenius Norm    " << GetFrobeniusNorm()    << std::endl;
  os << indent << "CatchGetValueException   " << GetCatchGetValueException()
     << std::endl;
  os << indent << "MetricWorstPossibleValue " << GetMetricWorstPossibleValue()
     << std::endl;
}
} // end of namespace itk
#endif
<commit_msg>BUG: First IterationEvent is at CurrentIteration==0<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkOnePlusOneEvolutionaryOptimizerv4_hxx
#define itkOnePlusOneEvolutionaryOptimizerv4_hxx

#include "itkMath.h"
#include "itkOnePlusOneEvolutionaryOptimizerv4.h"
#include "vnl/vnl_matrix.h"
namespace itk
{
template<typename TInternalComputationValueType>
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::OnePlusOneEvolutionaryOptimizerv4()
{
  m_CatchGetValueException = false;
  m_MetricWorstPossibleValue = 0;

  m_Epsilon = (double)1.5e-4;
  m_RandomGenerator = ITK_NULLPTR;

  m_Initialized = false;
  m_GrowthFactor = 1.05;
  m_ShrinkFactor = std::pow(m_GrowthFactor, -0.25);
  m_InitialRadius = 1.01;
  m_MaximumIteration = 100;
  m_Stop = false;
  m_StopConditionDescription.str("");
  m_CurrentCost = 0;
  m_FrobeniusNorm = 0.0;
}

template<typename TInternalComputationValueType>
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::~OnePlusOneEvolutionaryOptimizerv4()
{}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::SetNormalVariateGenerator(NormalVariateGeneratorType *generator)
{
  if ( m_RandomGenerator != generator )
    {
    m_RandomGenerator = generator;
    this->Modified();
    }
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::Initialize(double initialRadius, double grow, double shrink)
{
  m_InitialRadius = initialRadius;

  if ( Math::AlmostEquals( grow, -1 ) )
    {
    m_GrowthFactor = 1.05;
    }
  else
    {
    m_GrowthFactor = grow;
    }
  if ( Math::AlmostEquals( shrink, -1 ) )
    {
    m_ShrinkFactor = std::pow(m_GrowthFactor, -0.25);
    }
  else
    {
    m_ShrinkFactor = shrink;
    }
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::StartOptimization(bool /* doOnlyInitialization */)
{
  if ( this->m_Metric.IsNull() )
    {
    return;
    }

  Superclass::StartOptimization();

  this->InvokeEvent( StartEvent() );
  m_Stop = false;

  unsigned int         spaceDimension = this->m_Metric->GetNumberOfParameters();
  vnl_matrix< double > A(spaceDimension, spaceDimension);
  vnl_vector< double > parent( this->m_Metric->GetParameters() );
  vnl_vector< double > f_norm(spaceDimension);
  vnl_vector< double > child(spaceDimension);
  vnl_vector< double > delta(spaceDimension);

  ParametersType parentPosition(spaceDimension);
  ParametersType childPosition(spaceDimension);

  for ( unsigned int i = 0; i < spaceDimension; i++ )
    {
    parentPosition[i] = parent[i];
    }
  this->m_Metric->SetParameters( parentPosition );

  double pvalue = m_MetricWorstPossibleValue;
  try
    {
    pvalue = this->m_Metric->GetValue();
    }
  catch ( ... )
    {
    if ( m_CatchGetValueException )
      {
      pvalue = m_MetricWorstPossibleValue;
      }
    else
      {
      throw;
      }
    }

  itkDebugMacro(<< ": initial position: " << parentPosition);
  itkDebugMacro(<< ": initial fitness: " << pvalue);

  this->m_Metric->SetParameters(parentPosition);
  const ScalesType & scales = this->GetScales();

  // Make sure the scales have been set properly
  if ( scales.size() != spaceDimension )
    {
    itkExceptionMacro(<< "The size of Scales is "
                      << scales.size()
                      << ", but the NumberOfParameters for the CostFunction is "
                      << spaceDimension
                      << ".");
    }

  A.set_identity();
  for ( unsigned int i = 0; i < spaceDimension; i++ )
    {
    A(i, i) = m_InitialRadius / scales[i];
    }

  for ( this->m_CurrentIteration = 0;
        this->m_CurrentIteration < m_MaximumIteration;
        this->m_CurrentIteration++ )
    {
    if ( m_Stop )
      {
      m_StopConditionDescription.str("");
      m_StopConditionDescription << this->GetNameOfClass() << ": ";
      m_StopConditionDescription << "StopOptimization() called";
      break;
      }

    for ( unsigned int i = 0; i < spaceDimension; i++ )
      {
      if ( !m_RandomGenerator )
        {
        itkExceptionMacro(<< "Random Generator is not set!");
        }
      f_norm[i] = m_RandomGenerator->GetVariate();
      }

    delta  = A * f_norm;
    child  = parent + delta;

    for ( unsigned int i = 0; i < spaceDimension; i++ )
      {
      childPosition[i] = child[i];
      }
    // Update the metric so we can check the metric value in childPosition
    this->m_Metric->SetParameters( childPosition );

    double cvalue = m_MetricWorstPossibleValue;
    try
      {
      cvalue = this->m_Metric->GetValue();
      // While we got the metric value in childPosition,
      // the metric paramteres are set back to parentPosition
      this->m_Metric->SetParameters( parentPosition );
      }
    catch ( ... )
      {
      if ( m_CatchGetValueException )
        {
        cvalue = m_MetricWorstPossibleValue;
        }
      else
        {
        throw;
        }
      }

    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": parent position: "
                  << parentPosition);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": parent fitness: "
                  << pvalue);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": random vector: " << f_norm);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": A: " << std::endl << A);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": delta: " << delta);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": child position: "
                  << childPosition);
    itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": child fitness: "
                  << cvalue);

    double adjust = m_ShrinkFactor;

    if ( cvalue < pvalue )
      {
      itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": increasing search radius");
      pvalue = cvalue;
      parent.swap(child);
      adjust = m_GrowthFactor;
      for ( unsigned int i = 0; i < spaceDimension; i++ )
        {
        parentPosition[i] = parent[i];
        }
      this->m_Metric->SetParameters(parentPosition);
      }
    else
      {
      itkDebugMacro(<< "iter: " << this->m_CurrentIteration << ": decreasing search radius");
      }

    m_CurrentCost = pvalue;
    // convergence criterion: f-norm of A < epsilon_A
    // Compute double precision sum of absolute values of
    // a single precision vector
    m_FrobeniusNorm = A.fro_norm();
    itkDebugMacro(<< "A f-norm:" << m_FrobeniusNorm);
    if ( m_FrobeniusNorm <= m_Epsilon )
      {
      itkDebugMacro(<< "converges at iteration = " << this->m_CurrentIteration);
      m_StopConditionDescription.str("");
      m_StopConditionDescription << this->GetNameOfClass() << ": ";
      m_StopConditionDescription << "Fnorm (" << m_FrobeniusNorm
                                 << ") is less than Epsilon (" << m_Epsilon
                                 << " at iteration #" << this->m_CurrentIteration;
      this->InvokeEvent( EndEvent() );
      return;
      }

    // A += (adjust - 1)/ (f_norm * f_norm) * A * f_norm * f_norm;
    // Blas_R1_Update(A, A * f_norm, f_norm,
    //             ((adjust - 1) / Blas_Dot_Prod(f_norm, f_norm)));
    // = DGER(Fortran)
    //   performs the rank 1 operation
    // A := alpha*x*y' + A,
    // where y' = transpose(y)
    // where alpha is a scalar, x is an m element vector, y is an n element
    // vector and A is an m by n matrix.
    // x = A * f_norm , y = f_norm, alpha = (adjust - 1) / Blas_Dot_Prod(
    // f_norm, f_norm)

    //A = A + (adjust - 1.0) * A;
    double alpha = ( ( adjust - 1.0 ) / dot_product(f_norm, f_norm) );
    for ( unsigned int c = 0; c < spaceDimension; c++ )
      {
      for ( unsigned int r = 0; r < spaceDimension; r++ )
        {
        A(r, c) += alpha * delta[r] * f_norm[c];
        }
      }

    this->InvokeEvent( IterationEvent() );
    itkDebugMacro( << "Current position: " << this->GetCurrentPosition() );
    }
  m_StopConditionDescription.str("");
  m_StopConditionDescription << this->GetNameOfClass() << ": ";
  m_StopConditionDescription << "Maximum number of iterations ("
                             << m_MaximumIteration
                             << ") exceeded. ";
  this->InvokeEvent( EndEvent() );
}

template<typename TInternalComputationValueType>
const std::string
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::GetStopConditionDescription() const
{
  return m_StopConditionDescription.str();
}

template<typename TInternalComputationValueType>
const typename OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>::MeasureType &
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::GetValue() const
{
  return this->GetCurrentCost();
}

template<typename TInternalComputationValueType>
void
OnePlusOneEvolutionaryOptimizerv4<TInternalComputationValueType>
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  if ( m_RandomGenerator )
    {
    os << indent << "Random Generator  " << m_RandomGenerator.GetPointer()  << std::endl;
    }
  else
    {
    os << indent << "Random Generator  " << "(none)" << std::endl;
    }
  os << indent << "Maximum Iteration " << GetMaximumIteration() << std::endl;
  os << indent << "Epsilon           " << GetEpsilon()          << std::endl;
  os << indent << "Initial Radius    " << GetInitialRadius()    << std::endl;
  os << indent << "Growth Fractor    " << GetGrowthFactor()     << std::endl;
  os << indent << "Shrink Fractor    " << GetShrinkFactor()     << std::endl;
  os << indent << "Initialized       " << GetInitialized()      << std::endl;
  os << indent << "Current Cost      " << GetCurrentCost()      << std::endl;
  os << indent << "Frobenius Norm    " << GetFrobeniusNorm()    << std::endl;
  os << indent << "CatchGetValueException   " << GetCatchGetValueException()
     << std::endl;
  os << indent << "MetricWorstPossibleValue " << GetMetricWorstPossibleValue()
     << std::endl;
}
} // end of namespace itk
#endif
<|endoftext|>