<commit_before>#include "evpp/inner_pre.h"

#include "sync_udp_client.h"
#include "evpp/libevent.h"
#include "evpp/sockets.h"

namespace evpp {
namespace udp {
namespace sync {
Client::Client() {
    sockfd_ = INVALID_SOCKET;
    memset(&remote_addr_, 0, sizeof(remote_addr_));
}

Client::~Client(void) {
    Close();
}

bool Client::Connect(const struct sockaddr_in& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect(const char* host, int port) {
    char buf[32] = {};
    snprintf(buf, sizeof buf, "%s:%d", host, port);
    return Connect(buf);
}

bool Client::Connect(const struct sockaddr_storage& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect(const char* addr/*host:port*/) {
    remote_addr_ = sock::ParseFromIPPort(addr);
    return Connect();
}

bool Client::Connect(const struct sockaddr& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect() {
    sockfd_ = ::socket(AF_INET, SOCK_DGRAM, 0);
    sock::SetReuseAddr(sockfd_);

    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&remote_addr_);
    socklen_t addrlen = sizeof(*addr);
    int ret = ::connect(sockfd_, addr, addrlen);

    if (ret != 0) {
        Close();
        LOG_ERROR << "Failed to connect to remote "
                  << sock::ToIPPort(&remote_addr_)
                  << ", errno=" << errno << " " << strerror(errno);
        return false;
    }

    connected_ = true;
    return true;
}

void Client::Close() {
    EVUTIL_CLOSESOCKET(sockfd_);
}

std::string Client::DoRequest(const std::string& data, uint32_t timeout_ms) {
    if (!Send(data)) {
        int eno = errno;
        LOG_ERROR << "sent failed, errno=" << eno << " " << strerror(eno) << " , dlen=" << data.size();
        return "";
    }

    sock::SetTimeout(sockfd_, timeout_ms);

    size_t buf_size = 1472; // The UDP max payload size
    MessagePtr msg(new Message(sockfd_, buf_size));
    socklen_t addrLen = sizeof(struct sockaddr);
    int readn = ::recvfrom(sockfd_, msg->WriteBegin(), buf_size, 0, msg->mutable_remote_addr(), &addrLen);
    int err = errno;
    if (readn >= 0) {
        msg->WriteBytes(readn);
        return std::string(msg->data(), msg->size());
    } else {
        LOG_ERROR << "errno=" << err << " " << strerror(err) << " recvfrom return -1";
    }

    return "";
}

std::string Client::DoRequest(const std::string& remote_ip, int port, const std::string& udp_package_data, uint32_t timeout_ms) {
    Client c;
    if (!c.Connect(remote_ip.data(), port)) {
        return "";
    }

    return c.DoRequest(udp_package_data, timeout_ms);
}

bool Client::Send(const char* msg, size_t len) {
    if (connected_) {
        int sentn = ::send(sockfd(), msg, len, 0);
        return sentn == len;
    }

    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&remote_addr_);
    socklen_t addrlen = sizeof(*addr);
    int sentn = ::sendto(sockfd(),
                         msg, len, 0,
                         addr,
                         addrlen);
    return sentn > 0;
}

bool Client::Send(const std::string& msg) {
    return Send(msg.data(), msg.size());
}

bool Client::Send(const std::string& msg, const struct sockaddr_in& addr) {
    return Client::Send(msg.data(), msg.size(), addr);
}

bool Client::Send(const char* msg, size_t len, const struct sockaddr_in& addr) {
    Client c;
    if (!c.Connect(addr)) {
        return false;
    }

    return c.Send(msg, len);
}

bool Client::Send(const MessagePtr& msg) {
    return Client::Send(msg->data(), msg->size(), *reinterpret_cast<const struct sockaddr_in*>(msg->remote_addr()));
}

bool Client::Send(const Message* msg) {
    return Client::Send(msg->data(), msg->size(), *reinterpret_cast<const struct sockaddr_in*>(msg->remote_addr()));
}

}
}
}

<commit_msg>fixed connect error code<commit_after>#include "evpp/inner_pre.h"

#include "sync_udp_client.h"
#include "evpp/libevent.h"
#include "evpp/sockets.h"

namespace evpp {
namespace udp {
namespace sync {
Client::Client() {
    sockfd_ = INVALID_SOCKET;
    memset(&remote_addr_, 0, sizeof(remote_addr_));
}

Client::~Client(void) {
    Close();
}

bool Client::Connect(const struct sockaddr_in& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect(const char* host, int port) {
    char buf[32] = {};
    snprintf(buf, sizeof buf, "%s:%d", host, port);
    return Connect(buf);
}

bool Client::Connect(const struct sockaddr_storage& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect(const char* addr/*host:port*/) {
    remote_addr_ = sock::ParseFromIPPort(addr);
    return Connect();
}

bool Client::Connect(const struct sockaddr& addr) {
    memcpy(&remote_addr_, &addr, sizeof(remote_addr_));
    return Connect();
}

bool Client::Connect() {
    sockfd_ = ::socket(AF_INET, SOCK_DGRAM, 0);
    sock::SetReuseAddr(sockfd_);

    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&remote_addr_);
    socklen_t addrlen = sizeof(*addr);
    int ret = ::connect(sockfd_, addr, addrlen);

    if (ret != 0) {
        LOG_ERROR << "Failed to connect to remote "
                  << sock::ToIPPort(&remote_addr_)
                  << ", errno=" << errno << " " << strerror(errno);
        Close();
        return false;
    }

    connected_ = true;
    return true;
}

void Client::Close() {
    EVUTIL_CLOSESOCKET(sockfd_);
}

std::string Client::DoRequest(const std::string& data, uint32_t timeout_ms) {
    if (!Send(data)) {
        int eno = errno;
        LOG_ERROR << "sent failed, errno=" << eno << " " << strerror(eno) << " , dlen=" << data.size();
        return "";
    }

    sock::SetTimeout(sockfd_, timeout_ms);

    size_t buf_size = 1472; // The UDP max payload size
    MessagePtr msg(new Message(sockfd_, buf_size));
    socklen_t addrLen = sizeof(struct sockaddr);
    int readn = ::recvfrom(sockfd_, msg->WriteBegin(), buf_size, 0, msg->mutable_remote_addr(), &addrLen);
    int err = errno;
    if (readn >= 0) {
        msg->WriteBytes(readn);
        return std::string(msg->data(), msg->size());
    } else {
        LOG_ERROR << "errno=" << err << " " << strerror(err) << " recvfrom return -1";
    }

    return "";
}

std::string Client::DoRequest(const std::string& remote_ip, int port, const std::string& udp_package_data, uint32_t timeout_ms) {
    Client c;
    if (!c.Connect(remote_ip.data(), port)) {
        return "";
    }

    return c.DoRequest(udp_package_data, timeout_ms);
}

bool Client::Send(const char* msg, size_t len) {
    if (connected_) {
        int sentn = ::send(sockfd(), msg, len, 0);
        return sentn == len;
    }

    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&remote_addr_);
    socklen_t addrlen = sizeof(*addr);
    int sentn = ::sendto(sockfd(),
                         msg, len, 0,
                         addr,
                         addrlen);
    return sentn > 0;
}

bool Client::Send(const std::string& msg) {
    return Send(msg.data(), msg.size());
}

bool Client::Send(const std::string& msg, const struct sockaddr_in& addr) {
    return Client::Send(msg.data(), msg.size(), addr);
}

bool Client::Send(const char* msg, size_t len, const struct sockaddr_in& addr) {
    Client c;
    if (!c.Connect(addr)) {
        return false;
    }

    return c.Send(msg, len);
}

bool Client::Send(const MessagePtr& msg) {
    return Client::Send(msg->data(), msg->size(), *reinterpret_cast<const struct sockaddr_in*>(msg->remote_addr()));
}

bool Client::Send(const Message* msg) {
    return Client::Send(msg->data(), msg->size(), *reinterpret_cast<const struct sockaddr_in*>(msg->remote_addr()));
}

}
}
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2020 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include "recurring.hpp"
#include "args.hpp"
#include "accounts.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"
#include "expenses.hpp"
#include "writer.hpp"

using namespace budget;

namespace {

static data_handler<recurring> recurrings { "recurrings", "recurrings.data" };

} //end of anonymous namespace

std::map<std::string, std::string> budget::recurring::get_params()  const {
    std::map<std::string, std::string> params;

    params["input_id"]      = budget::to_string(id);
    params["input_guid"]    = guid;
    params["input_name"]    = name;
    params["input_amount"]  = budget::to_string(amount);
    params["input_recurs"]  = recurs;
    params["input_account"] = account;

    return params;
}

void budget::check_for_recurrings(){
    // In random mode, we do not try to create recurrings
    if (config_contains("random")) {
        return;
    }

    auto now = budget::local_day();

    bool changed = false;

    for (auto& recurring : recurrings.data()) {
        auto l_year  = last_year(recurring);

        if (l_year == 1400) {
            budget::date recurring_date(now.year(), now.month(), 1);

            budget::expense recurring_expense;
            recurring_expense.guid    = generate_guid();
            recurring_expense.date    = recurring_date;
            recurring_expense.account = get_account(recurring.account, recurring_date.year(), recurring_date.month()).id;
            recurring_expense.amount  = recurring.amount;
            recurring_expense.name    = recurring.name;

            add_expense(std::move(recurring_expense));

            changed = true;
        } else {
            auto l_month = last_month(recurring, l_year);

            budget::date recurring_date(l_year, l_month, 1);

            while (!(recurring_date.year() == now.year() && recurring_date.month() == now.month())) {
                // Get to the next month
                recurring_date += budget::months(1);

                budget::expense recurring_expense;
                recurring_expense.guid    = generate_guid();
                recurring_expense.date    = recurring_date;
                recurring_expense.account = get_account(recurring.account, recurring_date.year(), recurring_date.month()).id;
                recurring_expense.amount  = recurring.amount;
                recurring_expense.name    = recurring.name;

                add_expense(std::move(recurring_expense));

                changed = true;
            }
        }
    }

    if (changed) {
        save_expenses();
    }

    internal_config_remove("recurring:last_checked");
}

void budget::recurring_module::preload() {
    // In server mode, there is no need to generate recurring expenses
    // the server will take charge of that
    if (is_server_mode()) {
        return;
    }

    load_recurrings();
    load_accounts();
    load_expenses();

    check_for_recurrings();
}

void budget::recurring_module::load() {
    // Only need to load in server mode
    if (is_server_mode()) {
        load_recurrings();
        load_accounts();
        load_expenses();
    }
}

void budget::recurring_module::unload() {
    save_recurrings();
}

void budget::recurring_module::handle(const std::vector<std::string>& args) {
    budget::console_writer w(std::cout);

    if (args.size() == 1) {
        show_recurrings(w);
    } else {
        auto& subcommand = args[1];

        if (subcommand == "show") {
            show_recurrings(w);
        } else if (subcommand == "add") {
            recurring recurring;
            recurring.guid   = generate_guid();
            recurring.recurs = "monthly";

            edit_string_complete(recurring.account, "Account", all_account_names(), not_empty_checker(), account_checker());
            edit_string(recurring.name, "Name", not_empty_checker());
            edit_money(recurring.amount, "Amount", not_negative_checker());

            // Create the equivalent expense

            auto date = budget::local_day();

            budget::expense recurring_expense;
            recurring_expense.guid    = generate_guid();
            recurring_expense.account = get_account(recurring.account, date.year(), date.month()).id;
            recurring_expense.date    = date;
            recurring_expense.amount  = recurring.amount;
            recurring_expense.name    = recurring.name;

            add_expense(std::move(recurring_expense));

            save_expenses();

            auto id = recurrings.add(std::move(recurring));
            std::cout << "Recurring expense " << id << " has been created" << std::endl;
        } else if (subcommand == "delete") {
            enough_args(args, 3);

            size_t id = to_number<size_t>(args[2]);

            if (recurrings.remove(id)) {
                std::cout << "Recurring expense " << id << " has been deleted" << std::endl;
                std::cout << "Note: The generated expenses have not been deleted" << std::endl;
            } else {
                throw budget_exception("There are no recurring expense with id " + args[2]);
            }
        } else if (subcommand == "edit") {
            enough_args(args, 3);

            size_t id = to_number<size_t>(args[2]);

            auto recurring          = recurrings[id];
            auto previous_recurring = recurring; // Temporary Copy

            auto now = budget::local_day();

            edit_string_complete(recurring.account, "Account", all_account_names(), not_empty_checker(), account_checker());
            edit_string(recurring.name, "Name", not_empty_checker());
            edit_money(recurring.amount, "Amount", not_negative_checker());

            // Update the corresponding expense

            for (auto& expense : all_expenses()) {
                if (expense.date.year() == now.year() && expense.date.month() == now.month() && expense.name == previous_recurring.name && expense.amount == previous_recurring.amount && get_account(expense.account).name == previous_recurring.account) {
                    expense.name    = recurring.name;
                    expense.amount  = recurring.amount;
                    expense.account = get_account(recurring.account, now.year(), now.month()).id;

                    edit_expense(expense);

                    break;
                }
            }

            save_expenses();

            if (recurrings.indirect_edit(recurring)) {
                std::cout << "Recurring expense " << id << " has been modified" << std::endl;
            }
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_recurrings() {
    recurrings.load();
}

void budget::save_recurrings() {
    recurrings.save();
}

void budget::recurring::save(data_writer & writer) {
    writer << id;
    writer << guid;
    writer << account;
    writer << name;
    writer << amount;
    writer << recurs;
}

void budget::recurring::load(data_reader & reader) {
    reader >> id;
    reader >> guid;
    reader >> account;
    reader >> name;
    reader >> amount;
    reader >> recurs;

    if (config_contains("random")) {
        amount = budget::random_money(100, 1000);
    }
}

budget::year budget::first_year(const budget::recurring& recurring) {
    budget::year year(1400);

    for (auto& expense : all_expenses()) {
        if (expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (year == 1400 || expense.date.year() < year) {
                year = expense.date.year();
            }
        }
    }

    return year;
}

budget::month budget::first_month(const budget::recurring& recurring, budget::year year) {
    budget::month month(13);

    for (auto& expense : all_expenses()) {
        if (expense.date.year() == year && expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (month == 13 || expense.date.month() < month) {
                month = expense.date.month();
            }
        }
    }

    return month;
}

budget::year budget::last_year(const budget::recurring& recurring) {
    budget::year year(1400);

    for (auto& expense : all_expenses()) {
        if (expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (year == 1400 || expense.date.year() > year) {
                year = expense.date.year();
            }
        }
    }

    return year;
}

budget::month budget::last_month(const budget::recurring& recurring, budget::year year) {
    budget::month month(13);

    for (auto& expense : all_expenses()) {
        if (expense.date.year() == year && expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (month == 13 || expense.date.month() > month) {
                month = expense.date.month();
            }
        }
    }

    return month;
}

std::vector<recurring> budget::all_recurrings() {
    return recurrings.data();
}

void budget::set_recurrings_changed() {
    recurrings.set_changed();
}

void budget::set_recurrings_next_id(size_t next_id) {
    recurrings.next_id = next_id;
}

void budget::show_recurrings(budget::writer& w) {
    w << title_begin << "Recurring expenses " << add_button("recurrings") << title_end;

    if (recurrings.empty()) {
        w << "No recurring expenses" << end_of_line;
    } else {
        std::vector<std::string> columns = {"ID", "Account", "Name", "Amount", "Recurs", "Edit"};
        std::vector<std::vector<std::string>> contents;

        money total;

        for (auto& recurring : recurrings.data()) {
            contents.push_back({to_string(recurring.id), recurring.account, recurring.name, to_string(recurring.amount), recurring.recurs, "::edit::recurrings::" + to_string(recurring.id)});

            total += recurring.amount;
        }

        contents.push_back({"", "", "", "", "", ""});
        contents.push_back({"", "", "Total", to_string(total), "", ""});

        w.display_table(columns, contents, 1, {}, 0, 2);
    }
}

bool budget::recurring_exists(size_t id) {
    return recurrings.exists(id);
}

void budget::recurring_delete(size_t id) {
    if (!recurrings.exists(id)) {
        throw budget_exception("There are no recurring with id ");
    }

    recurrings.remove(id);
}

recurring budget::recurring_get(size_t id) {
    return recurrings[id];
}

void budget::add_recurring(budget::recurring&& recurring) {
    recurrings.add(std::forward<budget::recurring>(recurring));
}

void budget::edit_recurring(const budget::recurring& recurring) {
    recurrings.indirect_edit(recurring);
}
<commit_msg>Refactor check_for_recurrings<commit_after>//=======================================================================
// Copyright (c) 2013-2020 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include "recurring.hpp"
#include "args.hpp"
#include "accounts.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"
#include "expenses.hpp"
#include "writer.hpp"

using namespace budget;

namespace {

static data_handler<recurring> recurrings { "recurrings", "recurrings.data" };

} //end of anonymous namespace

std::map<std::string, std::string> budget::recurring::get_params()  const {
    std::map<std::string, std::string> params;

    params["input_id"]      = budget::to_string(id);
    params["input_guid"]    = guid;
    params["input_name"]    = name;
    params["input_amount"]  = budget::to_string(amount);
    params["input_recurs"]  = recurs;
    params["input_account"] = account;

    return params;
}

void budget::check_for_recurrings(){
    // In random mode, we do not try to create recurrings
    if (config_contains("random")) {
        return;
    }

    auto now = budget::local_day();

    bool changed = false;

    for (auto& recurring : recurrings.data()) {
        if (recurring.recurs == "monthly") {
            auto l_year = last_year(recurring);

            if (l_year == 1400) {
                // If the recurring has never been created, we create it for
                // the first at the time of today

                budget::date recurring_date(now.year(), now.month(), 1);

                budget::expense recurring_expense;
                recurring_expense.guid    = generate_guid();
                recurring_expense.date    = recurring_date;
                recurring_expense.account = get_account(recurring.account, recurring_date.year(), recurring_date.month()).id;
                recurring_expense.amount  = recurring.amount;
                recurring_expense.name    = recurring.name;

                add_expense(std::move(recurring_expense));

                changed = true;
            } else {
                // If the recurring has already been triggered, we trigger again
                // for each of the missing months

                auto l_month = last_month(recurring, l_year);

                budget::date recurring_date(l_year, l_month, 1);

                while (!(recurring_date.year() == now.year() && recurring_date.month() == now.month())) {
                    // Get to the next month
                    recurring_date += budget::months(1);

                    budget::expense recurring_expense;
                    recurring_expense.guid    = generate_guid();
                    recurring_expense.date    = recurring_date;
                    recurring_expense.account = get_account(recurring.account, recurring_date.year(), recurring_date.month()).id;
                    recurring_expense.amount  = recurring.amount;
                    recurring_expense.name    = recurring.name;

                    add_expense(std::move(recurring_expense));

                    changed = true;
                }
            }
        } else {
            cpp_unreachable("Invalid recurrence");
        }
    }

    if (changed) {
        save_expenses();
    }

    internal_config_remove("recurring:last_checked");
}

void budget::recurring_module::preload() {
    // In server mode, there is no need to generate recurring expenses
    // the server will take charge of that
    if (is_server_mode()) {
        return;
    }

    load_recurrings();
    load_accounts();
    load_expenses();

    check_for_recurrings();
}

void budget::recurring_module::load() {
    // Only need to load in server mode
    if (is_server_mode()) {
        load_recurrings();
        load_accounts();
        load_expenses();
    }
}

void budget::recurring_module::unload() {
    save_recurrings();
}

void budget::recurring_module::handle(const std::vector<std::string>& args) {
    budget::console_writer w(std::cout);

    if (args.size() == 1) {
        show_recurrings(w);
    } else {
        auto& subcommand = args[1];

        if (subcommand == "show") {
            show_recurrings(w);
        } else if (subcommand == "add") {
            recurring recurring;
            recurring.guid   = generate_guid();
            recurring.recurs = "monthly";

            edit_string_complete(recurring.account, "Account", all_account_names(), not_empty_checker(), account_checker());
            edit_string(recurring.name, "Name", not_empty_checker());
            edit_money(recurring.amount, "Amount", not_negative_checker());

            // Create the equivalent expense

            auto date = budget::local_day();

            budget::expense recurring_expense;
            recurring_expense.guid    = generate_guid();
            recurring_expense.account = get_account(recurring.account, date.year(), date.month()).id;
            recurring_expense.date    = date;
            recurring_expense.amount  = recurring.amount;
            recurring_expense.name    = recurring.name;

            add_expense(std::move(recurring_expense));

            save_expenses();

            auto id = recurrings.add(std::move(recurring));
            std::cout << "Recurring expense " << id << " has been created" << std::endl;
        } else if (subcommand == "delete") {
            enough_args(args, 3);

            size_t id = to_number<size_t>(args[2]);

            if (recurrings.remove(id)) {
                std::cout << "Recurring expense " << id << " has been deleted" << std::endl;
                std::cout << "Note: The generated expenses have not been deleted" << std::endl;
            } else {
                throw budget_exception("There are no recurring expense with id " + args[2]);
            }
        } else if (subcommand == "edit") {
            enough_args(args, 3);

            size_t id = to_number<size_t>(args[2]);

            auto recurring          = recurrings[id];
            auto previous_recurring = recurring; // Temporary Copy

            auto now = budget::local_day();

            edit_string_complete(recurring.account, "Account", all_account_names(), not_empty_checker(), account_checker());
            edit_string(recurring.name, "Name", not_empty_checker());
            edit_money(recurring.amount, "Amount", not_negative_checker());

            // Update the corresponding expense

            for (auto& expense : all_expenses()) {
                if (expense.date.year() == now.year() && expense.date.month() == now.month() && expense.name == previous_recurring.name && expense.amount == previous_recurring.amount && get_account(expense.account).name == previous_recurring.account) {
                    expense.name    = recurring.name;
                    expense.amount  = recurring.amount;
                    expense.account = get_account(recurring.account, now.year(), now.month()).id;

                    edit_expense(expense);

                    break;
                }
            }

            save_expenses();

            if (recurrings.indirect_edit(recurring)) {
                std::cout << "Recurring expense " << id << " has been modified" << std::endl;
            }
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_recurrings() {
    recurrings.load();
}

void budget::save_recurrings() {
    recurrings.save();
}

void budget::recurring::save(data_writer & writer) {
    writer << id;
    writer << guid;
    writer << account;
    writer << name;
    writer << amount;
    writer << recurs;
}

void budget::recurring::load(data_reader & reader) {
    reader >> id;
    reader >> guid;
    reader >> account;
    reader >> name;
    reader >> amount;
    reader >> recurs;

    if (config_contains("random")) {
        amount = budget::random_money(100, 1000);
    }
}

budget::year budget::first_year(const budget::recurring& recurring) {
    budget::year year(1400);

    for (auto& expense : all_expenses()) {
        if (expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (year == 1400 || expense.date.year() < year) {
                year = expense.date.year();
            }
        }
    }

    return year;
}

budget::month budget::first_month(const budget::recurring& recurring, budget::year year) {
    budget::month month(13);

    for (auto& expense : all_expenses()) {
        if (expense.date.year() == year && expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (month == 13 || expense.date.month() < month) {
                month = expense.date.month();
            }
        }
    }

    return month;
}

budget::year budget::last_year(const budget::recurring& recurring) {
    budget::year year(1400);

    for (auto& expense : all_expenses()) {
        if (expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (year == 1400 || expense.date.year() > year) {
                year = expense.date.year();
            }
        }
    }

    return year;
}

budget::month budget::last_month(const budget::recurring& recurring, budget::year year) {
    budget::month month(13);

    for (auto& expense : all_expenses()) {
        if (expense.date.year() == year && expense.name == recurring.name && expense.amount == recurring.amount && get_account(expense.account).name == recurring.account) {
            if (month == 13 || expense.date.month() > month) {
                month = expense.date.month();
            }
        }
    }

    return month;
}

std::vector<recurring> budget::all_recurrings() {
    return recurrings.data();
}

void budget::set_recurrings_changed() {
    recurrings.set_changed();
}

void budget::set_recurrings_next_id(size_t next_id) {
    recurrings.next_id = next_id;
}

void budget::show_recurrings(budget::writer& w) {
    w << title_begin << "Recurring expenses " << add_button("recurrings") << title_end;

    if (recurrings.empty()) {
        w << "No recurring expenses" << end_of_line;
    } else {
        std::vector<std::string> columns = {"ID", "Account", "Name", "Amount", "Recurs", "Edit"};
        std::vector<std::vector<std::string>> contents;

        money total;

        for (auto& recurring : recurrings.data()) {
            contents.push_back({to_string(recurring.id), recurring.account, recurring.name, to_string(recurring.amount), recurring.recurs, "::edit::recurrings::" + to_string(recurring.id)});

            total += recurring.amount;
        }

        contents.push_back({"", "", "", "", "", ""});
        contents.push_back({"", "", "Total", to_string(total), "", ""});

        w.display_table(columns, contents, 1, {}, 0, 2);
    }
}

bool budget::recurring_exists(size_t id) {
    return recurrings.exists(id);
}

void budget::recurring_delete(size_t id) {
    if (!recurrings.exists(id)) {
        throw budget_exception("There are no recurring with id ");
    }

    recurrings.remove(id);
}

recurring budget::recurring_get(size_t id) {
    return recurrings[id];
}

void budget::add_recurring(budget::recurring&& recurring) {
    recurrings.add(std::forward<budget::recurring>(recurring));
}

void budget::edit_recurring(const budget::recurring& recurring) {
    recurrings.indirect_edit(recurring);
}
<|endoftext|>


<commit_before>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-09-05 16:04
 * Last modified : 2017-09-06 14:42
 * Filename	  : Layer.cpp
 * Description   : RNN network Layer
 **********************************************/
#include "rnn/Layer.h"

namespace abcdl{
namespace rnn{

void Layer::farward(const abcdl::algebra::Mat& train_seq_data,
					const abcdl::algebra::Mat& weight,
					const abcdl::algebra::Mat& pre_weight,
					const abcdl::algebra::Mat& act_weight,
					abcdl::algebra::Mat& state,
					abcdl::algebra::Mat& activation){

	size_t seq_rows = train_seq_data.rows();
	size_t seq_cols = train_seq_data.cols();
	state.reset(0, seq_rows, _hidden_dim);
	activation.reset(0, seq_rows, seq_cols);

	abcdl::algebra::Mat s_t;
	for(size_t t = 0; t != seq_rows; t++){
		//s[t] = tanh(U*x[t] + W*s[t-1])
		//o[t] = softmax(V* s[t])
		if(t > 0){
			s_t = (helper.dot(weight, train_seq_data.get_row(t).Ts()) + helper.dot(pre_weight, state.get_row(t - 1).Ts())).tanh();
		}else{
			s_t = helper.dot(weight, train_seq_data.get_row(t).Ts()).tanh();
		}

		state.set_row(t, s_t.Ts());
		activation.set_row(t, helper.dot(act_weight, s_t).softmax().Ts());
	}
}

void Layer::backward(const abcdl::algebra::Mat& train_seq_data,
					 const abcdl::algebra::Mat& train_seq_label,
					 abcdl::algebra::Mat& weight,
					 abcdl::algebra::Mat& pre_weight,
					 abcdl::algebra::Mat& act_weight,
					 const abcdl::algebra::Mat& state,
					 const abcdl::algebra::Mat& activation,
					 abcdl::algebra::Mat& derivate_weight,
					 abcdl::algebra::Mat& derivate_pre_weight,
					 abcdl::algebra::Mat& derivate_act_weight){

	//todo cost function
	abcdl::algebra::Mat derivate_output;
	_cost->delta(derivate_output, activation,train_seq_label);

	size_t seq_size = train_seq_data.rows();
    auto now = []{return std::chrono::system_clock::now();};
    auto start_time = now();

	for(long int t = seq_size - 1; t >= 0 ; t--){
		auto derivate_output_t = derivate_output.get_row(t).Ts();
		auto state_t = state.get_row(t).Ts();

        //update derivate_act_weight
		derivate_output_t.outer(state_t);
		derivate_act_weight += derivate_output_t;

        //calc derivate_t
		abcdl::algebra::Mat state_derivate;
		helper.sigmoid_derivative(state_derivate, state_t);
		auto derivate_t = helper.dot(act_weight.Ts(), derivate_output_t.Ts()) * state_derivate;

		//back_propagation steps
		for(size_t step = 0; step < _bptt_truncate && (int)step <= t; step++){
			size_t bptt_step = t - step;

    		printf("Backpropagation step t=%ld bptt step=%ld\n", t, bptt_step);

			abcdl::algebra::Mat derivate_state_t;
			if(bptt_step > 0){
				state.get_row(&derivate_state_t, bptt_step -1);
			}else{
				derivate_state_t.reset(0, state.cols(), 1);
			}

            //update derivate_pre_weight
			derivate_pre_weight += helper.outer(derivate_t, derivate_state_t.Ts());

            //update derivate_weight
			auto train_data_t = train_seq_data.get_row(bptt_step).Ts();
            auto derivate_weight_t = helper.dot(derivate_weight, train_data_t) + derivate_t;

            size_t idx = train_data_t.argmax(0, abcdl::algebra::Axis_type::ROW);
            derivate_weight.set_col(idx, derivate_weight.get_col(idx) + derivate_weight_t);

			//update delta
			if(bptt_step > 0){
				helper.sigmoid_derivative(derivate_state_t, derivate_state_t);
				derivate_t = pre_weight.Ts().dot(derivate_t) * derivate_state_t;
			}
		}
	}
    printf("thread[%lu][%ld-%ld][%ld].\n", std::this_thread::get_id(), start_time, now(), std::chrono::duration_cast<std::chrono::milliseconds>(now() - start_time).count());
}

}//namespace rnn
}//namespace abcdl
<commit_msg>initialize<commit_after>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-09-05 16:04
 * Last modified : 2017-09-06 14:42
 * Filename	  : Layer.cpp
 * Description   : RNN network Layer
 **********************************************/
#include "rnn/Layer.h"

namespace abcdl{
namespace rnn{

void Layer::farward(const abcdl::algebra::Mat& train_seq_data,
					const abcdl::algebra::Mat& weight,
					const abcdl::algebra::Mat& pre_weight,
					const abcdl::algebra::Mat& act_weight,
					abcdl::algebra::Mat& state,
					abcdl::algebra::Mat& activation){

	size_t seq_rows = train_seq_data.rows();
	size_t seq_cols = train_seq_data.cols();
	state.reset(0, seq_rows, _hidden_dim);
	activation.reset(0, seq_rows, seq_cols);

	abcdl::algebra::Mat s_t;
	for(size_t t = 0; t != seq_rows; t++){
		//s[t] = tanh(U*x[t] + W*s[t-1])
		//o[t] = softmax(V* s[t])
		if(t > 0){
			s_t = (helper.dot(weight, train_seq_data.get_row(t).Ts()) + helper.dot(pre_weight, state.get_row(t - 1).Ts())).tanh();
		}else{
			s_t = helper.dot(weight, train_seq_data.get_row(t).Ts()).tanh();
		}

		state.set_row(t, s_t.Ts());
		activation.set_row(t, helper.dot(act_weight, s_t).softmax().Ts());
	}
}

void Layer::backward(const abcdl::algebra::Mat& train_seq_data,
					 const abcdl::algebra::Mat& train_seq_label,
					 abcdl::algebra::Mat& weight,
					 abcdl::algebra::Mat& pre_weight,
					 abcdl::algebra::Mat& act_weight,
					 const abcdl::algebra::Mat& state,
					 const abcdl::algebra::Mat& activation,
					 abcdl::algebra::Mat& derivate_weight,
					 abcdl::algebra::Mat& derivate_pre_weight,
					 abcdl::algebra::Mat& derivate_act_weight){

	//todo cost function
	abcdl::algebra::Mat derivate_output;
	_cost->delta(derivate_output, activation,train_seq_label);

	size_t seq_size = train_seq_data.rows();
    auto now = []{return std::chrono::system_clock::now();};
    auto start_time = now();

	for(size_t s = seq_size; s > 0 ; s--){
		size_t t = s - 1;
		auto derivate_output_t = derivate_output.get_row(t);
		derivate_output_t.transpose();

		auto state_t = state.get_row(t).transpose();

        //update derivate_act_weight
		derivate_output_t.outer(state_t);
		derivate_act_weight += derivate_output_t;

        //calc derivate_t
		abcdl::algebra::Mat state_derivate;
		helper.sigmoid_derivative(state_derivate, state_t);
		auto derivate_t = helper.dot(act_weight.Ts(), derivate_output_t.Ts()) * state_derivate;

		//back_propagation steps
		for(size_t step = 0; step < _bptt_truncate && (int)step <= t; step++){
			size_t bptt_step = t - step;

    		printf("Backpropagation step t=%ld bptt step=%ld\n", t, bptt_step);

			abcdl::algebra::Mat derivate_state_t;
			if(bptt_step > 0){
				state.get_row(&derivate_state_t, bptt_step -1);
			}else{
				derivate_state_t.reset(0, state.cols(), 1);
			}

            //update derivate_pre_weight
			derivate_pre_weight += helper.outer(derivate_t, derivate_state_t.Ts());

            //update derivate_weight
			auto train_data_t = train_seq_data.get_row(bptt_step).Ts();
            auto derivate_weight_t = helper.dot(derivate_weight, train_data_t) + derivate_t;

            size_t idx = train_data_t.argmax(0, abcdl::algebra::Axis_type::ROW);
            derivate_weight.set_col(idx, derivate_weight.get_col(idx) + derivate_weight_t);

			//update delta
			if(bptt_step > 0){
				helper.sigmoid_derivative(derivate_state_t, derivate_state_t);
				derivate_t = pre_weight.Ts().dot(derivate_t) * derivate_state_t;
			}
		}
	}
    printf("thread[%lu][%ld-%ld][%ld].\n", std::this_thread::get_id(), start_time, now(), std::chrono::duration_cast<std::chrono::milliseconds>(now() - start_time).count());
}

}//namespace rnn
}//namespace abcdl
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sstring.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:33:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TOOLS_STRINGLIST
#  define _TOOLS_STRINGLIST
#endif

#include "sstring.hxx"

SByteStringList::SByteStringList()
{
}

SByteStringList::~SByteStringList()
{
}

ULONG SByteStringList::IsString( ByteString* pStr )
{
    ULONG nRet = NOT_THERE;
    if ( (nRet = GetPrevString( pStr )) != 0 )
    {
        ByteString* pString = GetObject( nRet );
        if ( *pString == *pStr )
            return nRet;
        else
            return NOT_THERE;
    }
    else
    {
        ByteString* pString = GetObject( 0 );
        if ( pString && (*pString == *pStr) )
            return 0;
        else
            return NOT_THERE;
    }
    return nRet;
}

ULONG SByteStringList::GetPrevString( ByteString* pStr )
{
    ULONG nRet = 0;
    BOOL bFound = FALSE;
    ULONG nCount = Count();
    ULONG nUpper = nCount;
    ULONG nLower = 0;
    ULONG nCurrent = nUpper / 2;
    ULONG nRem = 0;
    ByteString* pString;

    do
    {
        if ( (nCurrent == nLower) || (nCurrent == nUpper) )
            return nLower;
        pString = GetObject( nCurrent );
        ULONG nResult =  pStr->CompareTo( *pString );
        if ( nResult == COMPARE_LESS )
        {
            nUpper = nCurrent;
            nCurrent = (nCurrent + nLower) /2;
        }
        else if ( nResult == COMPARE_GREATER )
        {
            nLower = nCurrent;
            nCurrent = (nUpper + nCurrent) /2;
        }
        else if ( nResult == COMPARE_EQUAL )
            return nCurrent;
        if ( nRem == nCurrent )
            return nCurrent;
        nRem = nCurrent;
    }
    while ( !bFound );
    return nRet;
}

/**************************************************************************
*
*   Sortiert einen ByteString in die Liste ein und gibt die Position,
*   an der einsortiert wurde, zurueck
*
**************************************************************************/

ULONG SByteStringList::PutString( ByteString* pStr )
{
    ULONG nPos = GetPrevString ( pStr );
    if ( Count() )
    {
        {
            ByteString* pString = GetObject( 0 );
            if ( pString->CompareTo( *pStr ) == COMPARE_GREATER )
            {
                Insert( pStr, (ULONG)0 );
                return (ULONG)0;
            }
        }
        ByteString* pString = GetObject( nPos );
        if ( *pStr != *pString )
        {
            Insert( pStr, nPos+1 );
            return ( nPos +1 );
        }
    }
    else
    {
        Insert( pStr );
        return (ULONG)0;
    }

    return NOT_THERE;
}

ByteString* SByteStringList::RemoveString( const ByteString& rName )
{
    ULONG i;
    ByteString* pReturn;

    for( i = 0 ; i < Count(); i++ )
    {
        if ( rName == *GetObject( i ) )
        {
            pReturn = GetObject(i);
            Remove(i);
            return pReturn;
        }
    }

    return NULL;
}

SUniStringList::SUniStringList()
{
}

SUniStringList::~SUniStringList()
{
}

ULONG SUniStringList::IsString( UniString* pStr )
{
    ULONG nRet = NOT_THERE;
    if ( (nRet = GetPrevString( pStr )) != 0 )
    {
        UniString* pString = GetObject( nRet );
        if ( *pString == *pStr )
            return nRet;
        else
            return NOT_THERE;
    }
    else
    {
        UniString* pString = GetObject( 0 );
        if ( pString && (*pString == *pStr) )
            return 0;
        else
            return NOT_THERE;
    }
    return nRet;
}

ULONG SUniStringList::GetPrevString( UniString* pStr )
{
    ULONG nRet = 0;
    BOOL bFound = FALSE;
    ULONG nCount = Count();
    ULONG nUpper = nCount;
    ULONG nLower = 0;
    ULONG nCurrent = nUpper / 2;
    ULONG nRem = 0;
    UniString* pString;

    do
    {
        if ( (nCurrent == nLower) || (nCurrent == nUpper) )
            return nLower;
        pString = GetObject( nCurrent );
        ULONG nResult =  pStr->CompareTo( *pString );
        if ( nResult == COMPARE_LESS )
        {
            nUpper = nCurrent;
            nCurrent = (nCurrent + nLower) /2;
        }
        else if ( nResult == COMPARE_GREATER )
        {
            nLower = nCurrent;
            nCurrent = (nUpper + nCurrent) /2;
        }
        else if ( nResult == COMPARE_EQUAL )
            return nCurrent;
        if ( nRem == nCurrent )
            return nCurrent;
        nRem = nCurrent;
    }
    while ( !bFound );
    return nRet;
}

/**************************************************************************
*
*   Sortiert einen UniString in die Liste ein und gibt die Position,
*   an der einsortiert wurde, zurueck
*
**************************************************************************/

ULONG SUniStringList::PutString( UniString* pStr )
{
    ULONG nPos = GetPrevString ( pStr );
    if ( Count() )
    {
        {
            UniString* pString = GetObject( 0 );
            if ( pString->CompareTo( *pStr ) == COMPARE_GREATER )
            {
                Insert( pStr, (ULONG)0);
                return (ULONG)0;
            }
        }
        UniString* pString = GetObject( nPos );
        if ( *pStr != *pString )
        {
            Insert( pStr, nPos+1 );
            return ( nPos +1 );
        }
    }
    else
    {
        Insert( pStr );
        return (ULONG)0;
    }

    return NOT_THERE;
}

UniString* SUniStringList::RemoveString( const UniString& rName )
{
    ULONG i;
    UniString* pReturn;

    for( i = 0 ; i < Count(); i++ )
    {
        if ( rName == *GetObject( i ) )
        {
            pReturn = GetObject(i);
            Remove(i);
            return pReturn;
        }
    }

    return NULL;
}
<commit_msg>INTEGRATION: CWS warnings01 (1.3.8); FILE MERGED 2005/11/10 11:20:39 pl 1.3.8.3: #i53898# removed warnings 2005/10/27 12:28:49 sb 1.3.8.2: #i53898# Made code warning-free. 2005/10/14 11:19:25 sb 1.3.8.1: #i53898# Made code warning-free; cleanup.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sstring.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 13:22:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TOOLS_STRINGLIST
#  define _TOOLS_STRINGLIST
#endif

#include "bootstrp/sstring.hxx"

SByteStringList::SByteStringList()
{
}

SByteStringList::~SByteStringList()
{
}

ULONG SByteStringList::IsString( ByteString* pStr )
{
    ULONG nRet = NOT_THERE;
    if ( (nRet = GetPrevString( pStr )) != 0 )
    {
        ByteString* pString = GetObject( nRet );
        if ( *pString == *pStr )
            return nRet;
        else
            return NOT_THERE;
    }
    else
    {
        ByteString* pString = GetObject( 0 );
        if ( pString && (*pString == *pStr) )
            return 0;
        else
            return NOT_THERE;
    }
}

ULONG SByteStringList::GetPrevString( ByteString* pStr )
{
    ULONG nRet = 0;
    BOOL bFound = FALSE;
    ULONG nCountMember = Count();
    ULONG nUpper = nCountMember;
    ULONG nLower = 0;
    ULONG nCurrent = nUpper / 2;
    ULONG nRem = 0;
    ByteString* pString;

    do
    {
        if ( (nCurrent == nLower) || (nCurrent == nUpper) )
            return nLower;
        pString = GetObject( nCurrent );
        StringCompare nResult =  pStr->CompareTo( *pString );
        if ( nResult == COMPARE_LESS )
        {
            nUpper = nCurrent;
            nCurrent = (nCurrent + nLower) /2;
        }
        else if ( nResult == COMPARE_GREATER )
        {
            nLower = nCurrent;
            nCurrent = (nUpper + nCurrent) /2;
        }
        else if ( nResult == COMPARE_EQUAL )
            return nCurrent;
        if ( nRem == nCurrent )
            return nCurrent;
        nRem = nCurrent;
    }
    while ( !bFound );
    return nRet;
}

/**************************************************************************
*
*   Sortiert einen ByteString in die Liste ein und gibt die Position,
*   an der einsortiert wurde, zurueck
*
**************************************************************************/

ULONG SByteStringList::PutString( ByteString* pStr )
{
    ULONG nPos = GetPrevString ( pStr );
    if ( Count() )
    {
        {
            ByteString* pString = GetObject( 0 );
            if ( pString->CompareTo( *pStr ) == COMPARE_GREATER )
            {
                Insert( pStr, (ULONG)0 );
                return (ULONG)0;
            }
        }
        ByteString* pString = GetObject( nPos );
        if ( *pStr != *pString )
        {
            Insert( pStr, nPos+1 );
            return ( nPos +1 );
        }
    }
    else
    {
        Insert( pStr );
        return (ULONG)0;
    }

    return NOT_THERE;
}

ByteString* SByteStringList::RemoveString( const ByteString& rName )
{
    ULONG i;
    ByteString* pReturn;

    for( i = 0 ; i < Count(); i++ )
    {
        if ( rName == *GetObject( i ) )
        {
            pReturn = GetObject(i);
            Remove(i);
            return pReturn;
        }
    }

    return NULL;
}

SUniStringList::SUniStringList()
{
}

SUniStringList::~SUniStringList()
{
}

ULONG SUniStringList::IsString( UniString* pStr )
{
    ULONG nRet = NOT_THERE;
    if ( (nRet = GetPrevString( pStr )) != 0 )
    {
        UniString* pString = GetObject( nRet );
        if ( *pString == *pStr )
            return nRet;
        else
            return NOT_THERE;
    }
    else
    {
        UniString* pString = GetObject( 0 );
        if ( pString && (*pString == *pStr) )
            return 0;
        else
            return NOT_THERE;
    }
}

ULONG SUniStringList::GetPrevString( UniString* pStr )
{
    ULONG nRet = 0;
    BOOL bFound = FALSE;
    ULONG nCountMember = Count();
    ULONG nUpper = nCountMember;
    ULONG nLower = 0;
    ULONG nCurrent = nUpper / 2;
    ULONG nRem = 0;
    UniString* pString;

    do
    {
        if ( (nCurrent == nLower) || (nCurrent == nUpper) )
            return nLower;
        pString = GetObject( nCurrent );
        StringCompare nResult =  pStr->CompareTo( *pString );
        if ( nResult == COMPARE_LESS )
        {
            nUpper = nCurrent;
            nCurrent = (nCurrent + nLower) /2;
        }
        else if ( nResult == COMPARE_GREATER )
        {
            nLower = nCurrent;
            nCurrent = (nUpper + nCurrent) /2;
        }
        else if ( nResult == COMPARE_EQUAL )
            return nCurrent;
        if ( nRem == nCurrent )
            return nCurrent;
        nRem = nCurrent;
    }
    while ( !bFound );
    return nRet;
}

/**************************************************************************
*
*   Sortiert einen UniString in die Liste ein und gibt die Position,
*   an der einsortiert wurde, zurueck
*
**************************************************************************/

ULONG SUniStringList::PutString( UniString* pStr )
{
    ULONG nPos = GetPrevString ( pStr );
    if ( Count() )
    {
        {
            UniString* pString = GetObject( 0 );
            if ( pString->CompareTo( *pStr ) == COMPARE_GREATER )
            {
                Insert( pStr, (ULONG)0);
                return (ULONG)0;
            }
        }
        UniString* pString = GetObject( nPos );
        if ( *pStr != *pString )
        {
            Insert( pStr, nPos+1 );
            return ( nPos +1 );
        }
    }
    else
    {
        Insert( pStr );
        return (ULONG)0;
    }

    return NOT_THERE;
}

UniString* SUniStringList::RemoveString( const UniString& rName )
{
    ULONG i;
    UniString* pReturn;

    for( i = 0 ; i < Count(); i++ )
    {
        if ( rName == *GetObject( i ) )
        {
            pReturn = GetObject(i);
            Remove(i);
            return pReturn;
        }
    }

    return NULL;
}
<|endoftext|>


<commit_before># define CATCH_CONFIG_RUNNER
# include "catch.hpp"
# include <cmath>
# include <string>

int gcd(int a, int b)
{
	if (b == 0)
	{
	return a
	}
	else
	{
		return gcd(b, a%b);
	}
}

double mileToKilometer(double mile)
{
	cout<<"Bitte geben sie die Distanz in Meilen ein:"<<endl;
	cin>>mile;
	kilometer = mile*1.60934;
	cout>>mile>>"Meilen sind umgerechnet ">>kilometer>>" Kilometer.">>endl;
	return kilometer;
}

float ZylinderOberfl(float r, float h)
{
    float oberfl = (2*M_PI*r^2)+(2*M_PI*r*h);
    return oberfl;
}

float ZylinderVol(float r, float h)
{
    float vol = M_PI*(r^2)*h
    return vol;
}

float frac(float x)
{
    int y = (int)x;
    int z = y-x;
    return z;
}

int checksum(int Zahl)
{
    int sum = 0;
	while(Zahl>0)
	{
        sum += Zahl%10;
        Zahl /= 10;
	}
    return sum;
}

int sumMultiples()
{
    int sum = 0;
	for (int i = 0; i < 1000; i++)
	{
		if (i % 3 == 0)
		{
			sum += i;
		}
		else if (i % 5 == 0)
		{
			sum += i;
		}

	}
    return sum;
}

TEST_CASE("describe_gcd ", "[gcd]")
{
	REQUIRE(gcd(2, 4) == 2);
	REQUIRE(gcd(6, 9) == 3);
	REQUIRE(gcd(3, 7) == 1);
}

TEST_CASE("describe_sumMultiples ", "[sumMultiples]")
{
	REQUIRE(sumMultiples() ==234168);
}

TEST_CASE("describe_checksum ", "[checksum]")
{
	REQUIRE(chekcsum(15) == 6);
	REQUIRE(checksum(25) == 7);
	REQUIRE(checksum(35) == 8);
}

TEST_CASE("describe_ZylinderVol","[ZylinderVol]")
{
	REQUIRE(ZylinderVol(1,2) == Approx(6.283));
}

TEST_CASE("describe_ZylinderOberfl","[ZylinderOberfl]")
{
	REQUIRE(ZylinderOberfl(1,2) == Approx(18.85));
}

TEST_CASE("describe_mileToKilometer","[mileToKilometer]")
{
	REQUIRE(mileToKilometer(1) == Approx(1.60934));
	REQUIRE(mileToKilometer(2) == Approx(3,21869));
	REQUIRE(mileToKilometer(5) == Approx(8,04672));
}

TEST_CASE("describe_frac","[frac]")
{
	REQUIRE(frac(1.11) == Approx(0.11));
	REQUIRE(frac(45.1234) == Approx(0.1234));
}

int main(int argc, char* argv[])
{
  return Catch::Session().run(argc, argv);
}

<commit_msg>Update tests.cpp<commit_after># define CATCH_CONFIG_RUNNER
# include "catch.hpp"
# include <cmath>
# include <string>

int gcd(int a, int b)
{
	if (b == 0)
	{
	return a
	}
	else
	{
		return gcd(b, a%b);
	}
}

double mileToKilometer(double mile)
{
	double kilometer;
	cout<<"Bitte geben sie die Distanz in Meilen ein:"<<endl;
	cin>>mile;
	kilometer = mile*1.60934;
	cout>>mile>>"Meilen sind umgerechnet ">>kilometer>>" Kilometer.">>endl;
	return kilometer;
}

float ZylinderOberfl(float r, float h)
{
    float oberfl = (2*M_PI*r^2)+(2*M_PI*r*h);
    return oberfl;
}

float ZylinderVol(float r, float h)
{
    float vol = M_PI*(r^2)*h
    return vol;
}

float frac(float x)
{
    int y = (int)x;
    int z = y-x;
    return z;
}

int checksum(int Zahl)
{
    int sum = 0;
	while(Zahl>0)
	{
        sum += Zahl%10;
        Zahl /= 10;
	}
    return sum;
}

int sumMultiples()
{
    int sum = 0;
	for (int i = 0; i < 1000; i++)
	{
		if (i % 3 == 0)
		{
			sum += i;
		}
		else if (i % 5 == 0)
		{
			sum += i;
		}

	}
    return sum;
}

TEST_CASE("describe_gcd ", "[gcd]")
{
	REQUIRE(gcd(2, 4) == 2);
	REQUIRE(gcd(6, 9) == 3);
	REQUIRE(gcd(3, 7) == 1);
}

TEST_CASE("describe_sumMultiples ", "[sumMultiples]")
{
	REQUIRE(sumMultiples() ==234168);
}

TEST_CASE("describe_checksum ", "[checksum]")
{
	REQUIRE(chekcsum(15) == 6);
	REQUIRE(checksum(25) == 7);
	REQUIRE(checksum(35) == 8);
}

TEST_CASE("describe_ZylinderVol","[ZylinderVol]")
{
	REQUIRE(ZylinderVol(1,2) == Approx(6.283));
}

TEST_CASE("describe_ZylinderOberfl","[ZylinderOberfl]")
{
	REQUIRE(ZylinderOberfl(1,2) == Approx(18.85));
}

TEST_CASE("describe_mileToKilometer","[mileToKilometer]")
{
	REQUIRE(mileToKilometer(1) == Approx(1.60934));
	REQUIRE(mileToKilometer(2) == Approx(3,21869));
	REQUIRE(mileToKilometer(5) == Approx(8,04672));
}

TEST_CASE("describe_frac","[frac]")
{
	REQUIRE(frac(1.11) == Approx(0.11));
	REQUIRE(frac(45.1234) == Approx(0.1234));
}

int main(int argc, char* argv[])
{
  return Catch::Session().run(argc, argv);
}

<|endoftext|>


<commit_before>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_LITERAL_HPP
#define TOML11_LITERAL_HPP
#include "parser.hpp"

namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{

inline ::toml::value operator""_toml(const char* str, std::size_t len)
{
    ::toml::detail::location<std::vector<char>>
        loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
            /* contents = */ std::vector<char>(str, str + len));

    // if there are some comments or empty lines, skip them.
    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
            ::toml::detail::maybe<::toml::detail::lex_ws>,
            ::toml::detail::maybe<::toml::detail::lex_comment>,
            ::toml::detail::lex_newline
        >, ::toml::detail::at_least<1>>;
    skip_line::invoke(loc);

    // if there are some whitespaces before a value, skip them.
    using skip_ws = ::toml::detail::repeat<
        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
    skip_ws::invoke(loc);

    // literal may be a bare value. try them first.
    if(auto data = ::toml::detail::parse_value(loc))
    {
        return data.unwrap();
    }

    // literal is a TOML file (i.e. multiline table).
    if(auto data = ::toml::detail::parse_toml_file(loc))
    {
        loc.reset(loc.begin()); // rollback to the top of the literal
        return ::toml::value(std::move(data.unwrap()),
                ::toml::detail::region<std::vector<char>>(std::move(loc)));
    }
    else // none of them.
    {
        throw ::toml::syntax_error(data.unwrap_err());
    }
}

} // toml_literals
} // literals
} // toml
#endif//TOML11_LITERAL_HPP
<commit_msg>fix: check literal has a table or an array first<commit_after>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_LITERAL_HPP
#define TOML11_LITERAL_HPP
#include "parser.hpp"

namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{

inline ::toml::value operator""_toml(const char* str, std::size_t len)
{
    ::toml::detail::location<std::vector<char>>
        loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
            /* contents = */ std::vector<char>(str, str + len));

    // if there are some comments or empty lines, skip them.
    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
            ::toml::detail::maybe<::toml::detail::lex_ws>,
            ::toml::detail::maybe<::toml::detail::lex_comment>,
            ::toml::detail::lex_newline
        >, ::toml::detail::at_least<1>>;
    skip_line::invoke(loc);

    // if there are some whitespaces before a value, skip them.
    using skip_ws = ::toml::detail::repeat<
        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
    skip_ws::invoke(loc);

    // to distinguish arrays and tables, first check it is a table or not.
    //
    // "[1,2,3]"_toml;   // this is an array
    // "[table]"_toml;   // a table that has an empty table named "table" inside.
    // "[[1,2,3]]"_toml; // this is an array of arrays
    // "[[table]]"_toml; // this is a table that has an array of tables inside.
    //
    // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
    // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
    // "[[1,]]"_toml;    // this is an array of arrays.
    // "[[1],]"_toml;    // this also.

    const auto the_front = loc.iter();

    const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
    loc.reset(the_front);

    const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
    loc.reset(the_front);

    // If it is neither a table-key or a array-of-table-key, it may be a value.
    if(!is_table_key && !is_aots_key)
    {
        if(auto data = ::toml::detail::parse_value(loc))
        {
            return data.unwrap();
        }
    }

    // Note that still it can be a table, because the literal might be something
    // like the following.
    // ```cpp
    // R"( // c++11 raw string literals
    //   key = "value"
    //   int = 42
    // )"_toml;
    // ```
    // It is a valid toml file.
    // It should be parsed as if we parse a file with this content.

    if(auto data = ::toml::detail::parse_toml_file(loc))
    {
        loc.reset(loc.begin()); // rollback to the top of the literal
        return ::toml::value(std::move(data.unwrap()),
                ::toml::detail::region<std::vector<char>>(std::move(loc)));
    }
    else // none of them.
    {
        throw ::toml::syntax_error(data.unwrap_err());
    }
}

} // toml_literals
} // literals
} // toml
#endif//TOML11_LITERAL_HPP
<|endoftext|>


<commit_before>#include "ghost/types.h"
#include "ghost/complex.h"
#include "ghost/locality.h"
#include "ghost/util.h"
#include "ghost/timing.h"
#include "ghost/machine.h"
#include "ghost/sparsemat.h"
#include "ghost/math.h"
//#include "ghost/sell_kacz_mc_gen.h"
//#include "ghost/sell_kacz_avx_gen.h"
#include "ghost/sell_kacz_bmc_gen.h"
#include <complex>
#include <unordered_map>

using namespace std;

const ghost_kacz_opts GHOST_KACZ_OPTS_INITIALIZER = {
    .omega = NULL,
    .direction = GHOST_KACZ_DIRECTION_UNDEFINED,
    .normalize = no
};

// Hash function for unordered_map
namespace std
{
    template<> struct hash<ghost_kacz_parameters>
    {
        typedef ghost_kacz_parameters argument_type;
        typedef std::size_t result_type;
        result_type operator()(argument_type const& a) const
        {
            return ghost_hash(ghost_hash(a.mdt,a.blocksz,a.storage),
                    ghost_hash(a.vdt,a.impl,a.chunkheight),ghost_hash(a.alignment,a.method,0));
        }
    };
}

static bool operator==(const ghost_kacz_parameters& a, const ghost_kacz_parameters& b)
{
    return a.mdt == b.mdt && a.blocksz == b.blocksz && a.storage == b.storage &&
           a.vdt == b.vdt && a.impl == b.impl && a.chunkheight == b.chunkheight &&
           a.alignment == b.alignment && a.method == b.method;
}

static unordered_map<ghost_kacz_parameters, ghost_kacz_kernel>
ghost_kacz_kernels = unordered_map<ghost_kacz_parameters,ghost_kacz_kernel>();

template<typename m_t, typename v_t, bool forward>
static ghost_error kacz_fallback(ghost_densemat *x, ghost_sparsemat *mat, ghost_densemat *b, ghost_kacz_opts opts)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH|GHOST_FUNCTYPE_KERNEL);

    if (!mat->color_ptr || mat->ncolors == 0) {
        WARNING_LOG("Matrix has not been colored!");
    }
    if (x->traits.ncols > 1) {
        ERROR_LOG("Multi-vec not implemented!");
        return GHOST_ERR_NOT_IMPLEMENTED;
    }

    ghost_lidx c;
    ghost_lidx row;
    ghost_lidx rowinchunk;
    ghost_lidx j;
    ghost_lidx color;
    ghost_sell *sellmat = SELL(mat);
    ghost_lidx fchunk, lchunk;
    v_t *bval = (v_t *)(b->val);
    v_t *xval = (v_t *)(x->val);
    m_t *mval = (m_t *)sellmat->val;
    v_t omega = *(v_t *)opts.omega;

    int rank;
    ghost_rank(&rank,mat->context->mpicomm);

    ghost_lidx firstcolor, lastcolor, stride;

    if (forward) {
        firstcolor = 0;
        lastcolor = mat->ncolors;
        stride = 1;
    } else {
        firstcolor = mat->ncolors-1;
        lastcolor = -1;
        stride = -1;
    }

    for (color=firstcolor; color!=lastcolor; color+=stride) {
        fchunk = mat->color_ptr[color]/mat->traits.C;
        lchunk = mat->color_ptr[color+1]/mat->traits.C;
#pragma omp parallel
        {
            m_t *rownorm;
            ghost_malloc((void **)&rownorm,mat->traits.C*sizeof(m_t));
#pragma omp for private(j,row,rowinchunk)
            for (c=fchunk; c<lchunk; c++) {
                for (rowinchunk = 0; rowinchunk < mat->traits.C; rowinchunk++) {
                    row = rowinchunk + c*mat->traits.C;
                    rownorm[rowinchunk] = 0.;

                    ghost_lidx idx = sellmat->chunkStart[c]+rowinchunk;
                    v_t scal = -bval[row];

                    for (j=0; j<sellmat->rowLen[row]; j++) {
                        scal += (v_t)mval[idx] * xval[sellmat->col[idx]];
                        rownorm[rowinchunk] += mval[idx]*mval[idx];
                        idx += mat->traits.C;
                    }

                    idx -= mat->traits.C*sellmat->rowLen[row];
                    scal /= (v_t)rownorm[rowinchunk];

                    for (j=0; j<sellmat->rowLen[row]; j++) {
                        xval[sellmat->col[idx]] = xval[sellmat->col[idx]] - omega * scal * (v_t)mval[idx];
                        idx += mat->traits.C;
                    }
                }
            }
            free(rownorm);
            rownorm = NULL;
        }
    }

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH|GHOST_FUNCTYPE_KERNEL);
    return GHOST_SUCCESS;
}

ghost_error ghost_kacz(ghost_densemat *x, ghost_sparsemat *mat, ghost_densemat *b, ghost_kacz_opts opts)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error ret = GHOST_SUCCESS;
    ghost_kacz_parameters p;

    if(!(mat->traits.flags & GHOST_SPARSEMAT_COLOR)) {
    	if(!(mat->traits.flags & GHOST_SPARSEMAT_BLOCKCOLOR) && (mat->kaczRatio >= 2*mat->kacz_setting.active_threads)) {
		INFO_LOG("BMC KACZ without transition called");
		p.method = BMC_RB;
    	}
    	else {
		INFO_LOG("BMC KACZ with transition called");
		p.method = BMC;
    	}
    } else {
        INFO_LOG("Using unoptimal kernel KACZ with MC");
		p.method = MC;
    }
    // if map is empty include generated code for map construction
    if (ghost_kacz_kernels.empty()) {
#include "sell_kacz_bmc.def"
//#include "sell_kacz_mc.def"

//#include "sell_kacz_avx.def"

    }

    ghost_kacz_kernel kernel = NULL;
    ghost_implementation opt_impl;
    ghost_alignment opt_align;

    p.vdt = x->traits.datatype;
    p.mdt = mat->traits.datatype;
    p.storage = x->traits.storage;
    if (p.storage == GHOST_DENSEMAT_ROWMAJOR && x->stride == 1 && b->stride == 1) {
        INFO_LOG("Chose col-major kernel for row-major densemat with 1 column");
        p.storage = GHOST_DENSEMAT_COLMAJOR;
    }
    if ((b->traits.flags & GHOST_DENSEMAT_SCATTERED) ||
            (x->traits.flags & GHOST_DENSEMAT_SCATTERED)) {
        PERFWARNING_LOG("Use plain implementation for scattered views");
        opt_impl = GHOST_IMPLEMENTATION_PLAIN;
    } else {
        if (x->stride > 1 && x->traits.storage == GHOST_DENSEMAT_ROWMAJOR) {
            opt_impl = ghost_get_best_implementation_for_bytesize(x->traits.ncols*x->elSize);
            if (opt_impl == GHOST_IMPLEMENTATION_PLAIN) {
                // this branch is taken for odd numbers
                // choose a version with remainder loops in this case!
                opt_impl = ghost_get_best_implementation_for_bytesize(PAD(x->traits.ncols*x->elSize,ghost_machine_simd_width()));
            }
        } else {
            opt_impl = ghost_get_best_implementation_for_bytesize(mat->traits.C*mat->elSize);
        }
    }

    int try_chunkheight[2] = {mat->traits.C,-1};
    int try_blocksz[2] = {x->traits.ncols,-1};

    int n_chunkheight = sizeof(try_chunkheight)/sizeof(int);
    int n_blocksz = sizeof(try_blocksz)/sizeof(int);
    int pos_chunkheight, pos_blocksz, method;

    bool optimal = true;

   for (pos_chunkheight = 0; pos_chunkheight < n_chunkheight; pos_chunkheight++) {
        for (pos_blocksz = 0; pos_blocksz < n_blocksz; pos_blocksz++) {
            for (p.impl = opt_impl; (int)p.impl >= GHOST_IMPLEMENTATION_PLAIN; p.impl  = (ghost_implementation)((int)p.impl-1)) {
                /*if (p.impl == GHOST_IMPLEMENTATION_SSE && p.storage == GHOST_DENSEMAT_ROWMAJOR && try_blocksz[pos_blocksz] % 2) {
                    PERFWARNING_LOG("Remainder loops not yet implemented for SSE, fallback to plain");
                    p.impl  = (ghost_implementation)((int)p.impl-1);
                }*/

                int al = ghost_implementation_alignment(p.impl);
                if (IS_ALIGNED(b->val,al) && IS_ALIGNED(x->val,al) && ((b->traits.ncols == 1 && b->stride == 1) || (!((b->stride*b->elSize) % al) && !((x->stride*x->elSize) % al)))) {
                    opt_align = GHOST_ALIGNED;
                } else {
                    if (!IS_ALIGNED(b->val,al)) {
                        PERFWARNING_LOG("Using unaligned kernel because base address of result vector is not aligned");
                    }
                    if (!IS_ALIGNED(x->val,al)) {
                        PERFWARNING_LOG("Using unaligned kernel because base address of input vector is not aligned");
                    }
                    if (b->stride*b->elSize % al) {
                        PERFWARNING_LOG("Using unaligned kernel because stride of result vector does not yield aligned addresses");
                    }
                    if (x->stride*b->elSize % al) {
                        PERFWARNING_LOG("Using unaligned kernel because stride of input vector does not yield aligned addresses");
                    }
                    opt_align = GHOST_UNALIGNED;
                }

                for (p.alignment = opt_align; (int)p.alignment >= GHOST_UNALIGNED; p.alignment = (ghost_alignment)((int)p.alignment-1)) {
                    p.chunkheight = try_chunkheight[pos_chunkheight];
                    p.blocksz = try_blocksz[pos_blocksz];

                    INFO_LOG("Try chunkheight=%s, blocksz=%s, impl=%s, %s",
                            p.chunkheight==-1?"arbitrary":std::to_string((long long)p.chunkheight).c_str(),
                            p.blocksz==-1?"arbitrary":std::to_string((long long)p.blocksz).c_str(),
                            ghost_implementation_string(p.impl),p.alignment==GHOST_UNALIGNED?"unaligned":"aligned");
                    kernel = ghost_kacz_kernels[p];
                    if (kernel) {
	                goto end_of_loop;
                    }
                    optimal = false;
                }
            }
        }
    }
end_of_loop:

    if (kernel) {
        if (optimal) {
            INFO_LOG("Found kernel with highest specialization grade: C=%d blocksz=%d align=%d impl=%s",p.chunkheight,p.blocksz,p.alignment,ghost_implementation_string(p.impl));
        } else {
            PERFWARNING_LOG("Using potentially non-optimal kernel: C=%d blocksz=%d align=%d impl=%s",p.chunkheight,p.blocksz,p.alignment,ghost_implementation_string(p.impl));
        }
        ret = kernel(x,mat,b,opts);
    } else { // execute plain kernel as fallback
        PERFWARNING_LOG("Execute fallback Kaczmarz kernel which is potentially slow!");

        if (b->traits.datatype & GHOST_DT_COMPLEX) {
            if (b->traits.datatype & GHOST_DT_DOUBLE) {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<std::complex<double>, std::complex<double>, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<std::complex<double>, std::complex<double>, false>(x,mat,b,opts);
                }
            } else {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<std::complex<float>, std::complex<float>, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<std::complex<float>, std::complex<float>, false>(x,mat,b,opts);
                }
            }
        } else {
            if (b->traits.datatype & GHOST_DT_DOUBLE) {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<double, double, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<double, double, false>(x,mat,b,opts);
                }
            } else {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<float, float, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<float, float, false>(x,mat,b,opts);
                }
            }
        }
    }

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);
    return ret;
}
<commit_msg>selection still not working<commit_after>#include "ghost/types.h"
#include "ghost/complex.h"
#include "ghost/locality.h"
#include "ghost/util.h"
#include "ghost/timing.h"
#include "ghost/machine.h"
#include "ghost/sparsemat.h"
#include "ghost/math.h"
//#include "ghost/sell_kacz_mc_gen.h"
//#include "ghost/sell_kacz_avx_gen.h"
#include "ghost/sell_kacz_bmc_gen.h"
#include <complex>
#include <unordered_map>

using namespace std;

const ghost_kacz_opts GHOST_KACZ_OPTS_INITIALIZER = {
    .omega = NULL,
    .direction = GHOST_KACZ_DIRECTION_UNDEFINED,
    .normalize = no
};

// Hash function for unordered_map
namespace std
{
    template<> struct hash<ghost_kacz_parameters>
    {
        typedef ghost_kacz_parameters argument_type;
        typedef std::size_t result_type;
        result_type operator()(argument_type const& a) const
        {
            return ghost_hash(ghost_hash(a.mdt,a.blocksz,a.storage),
                    ghost_hash(a.vdt,a.impl,a.chunkheight),ghost_hash(a.alignment,a.method,0));
        }
    };
}

static bool operator==(const ghost_kacz_parameters& a, const ghost_kacz_parameters& b)
{
    return a.mdt == b.mdt && a.blocksz == b.blocksz && a.storage == b.storage &&
           a.vdt == b.vdt && a.impl == b.impl && a.chunkheight == b.chunkheight &&
           a.alignment == b.alignment && a.method == b.method;
}

static unordered_map<ghost_kacz_parameters, ghost_kacz_kernel>
ghost_kacz_kernels = unordered_map<ghost_kacz_parameters,ghost_kacz_kernel>();

template<typename m_t, typename v_t, bool forward>
static ghost_error kacz_fallback(ghost_densemat *x, ghost_sparsemat *mat, ghost_densemat *b, ghost_kacz_opts opts)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH|GHOST_FUNCTYPE_KERNEL);

    if (!mat->color_ptr || mat->ncolors == 0) {
        WARNING_LOG("Matrix has not been colored!");
    }
    if (x->traits.ncols > 1) {
        ERROR_LOG("Multi-vec not implemented!");
        return GHOST_ERR_NOT_IMPLEMENTED;
    }

    ghost_lidx c;
    ghost_lidx row;
    ghost_lidx rowinchunk;
    ghost_lidx j;
    ghost_lidx color;
    ghost_sell *sellmat = SELL(mat);
    ghost_lidx fchunk, lchunk;
    v_t *bval = (v_t *)(b->val);
    v_t *xval = (v_t *)(x->val);
    m_t *mval = (m_t *)sellmat->val;
    v_t omega = *(v_t *)opts.omega;

    int rank;
    ghost_rank(&rank,mat->context->mpicomm);

    ghost_lidx firstcolor, lastcolor, stride;

    if (forward) {
        firstcolor = 0;
        lastcolor = mat->ncolors;
        stride = 1;
    } else {
        firstcolor = mat->ncolors-1;
        lastcolor = -1;
        stride = -1;
    }

    for (color=firstcolor; color!=lastcolor; color+=stride) {
        fchunk = mat->color_ptr[color]/mat->traits.C;
        lchunk = mat->color_ptr[color+1]/mat->traits.C;
#pragma omp parallel
        {
            m_t *rownorm;
            ghost_malloc((void **)&rownorm,mat->traits.C*sizeof(m_t));
#pragma omp for private(j,row,rowinchunk)
            for (c=fchunk; c<lchunk; c++) {
                for (rowinchunk = 0; rowinchunk < mat->traits.C; rowinchunk++) {
                    row = rowinchunk + c*mat->traits.C;
                    rownorm[rowinchunk] = 0.;

                    ghost_lidx idx = sellmat->chunkStart[c]+rowinchunk;
                    v_t scal = -bval[row];

                    for (j=0; j<sellmat->rowLen[row]; j++) {
                        scal += (v_t)mval[idx] * xval[sellmat->col[idx]];
                        rownorm[rowinchunk] += mval[idx]*mval[idx];
                        idx += mat->traits.C;
                    }

                    idx -= mat->traits.C*sellmat->rowLen[row];
                    scal /= (v_t)rownorm[rowinchunk];

                    for (j=0; j<sellmat->rowLen[row]; j++) {
                        xval[sellmat->col[idx]] = xval[sellmat->col[idx]] - omega * scal * (v_t)mval[idx];
                        idx += mat->traits.C;
                    }
                }
            }
            free(rownorm);
            rownorm = NULL;
        }
    }

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH|GHOST_FUNCTYPE_KERNEL);
    return GHOST_SUCCESS;
}

ghost_error ghost_kacz(ghost_densemat *x, ghost_sparsemat *mat, ghost_densemat *b, ghost_kacz_opts opts)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error ret = GHOST_SUCCESS;
    ghost_kacz_parameters p;

    if(!(mat->traits.flags & GHOST_SPARSEMAT_COLOR)) {
    	if(!(mat->traits.flags & GHOST_SPARSEMAT_BLOCKCOLOR) && (mat->kaczRatio >= 2*mat->kacz_setting.active_threads)) {
		INFO_LOG("BMC KACZ without transition called");
		p.method = BMC_RB;
    	}
    	else {
		INFO_LOG("BMC KACZ with transition called");
		p.method = BMC;
    	}
    } else {
        INFO_LOG("Using unoptimal kernel KACZ with MC");
		p.method = MC;
    }
    // if map is empty include generated code for map construction
    if (ghost_kacz_kernels.empty()) {
#include "sell_kacz_bmc.def"
//#include "sell_kacz_mc.def"

//#include "sell_kacz_avx.def"

    }

    ghost_kacz_kernel kernel = NULL;
    ghost_implementation opt_impl;
    ghost_alignment opt_align;

    p.vdt = x->traits.datatype;
    p.mdt = mat->traits.datatype;
    p.storage = x->traits.storage;
    if (p.storage == GHOST_DENSEMAT_ROWMAJOR && x->stride == 1 && b->stride == 1) {
        INFO_LOG("Chose col-major kernel for row-major densemat with 1 column");
        p.storage = GHOST_DENSEMAT_COLMAJOR;
    }
    if ((b->traits.flags & GHOST_DENSEMAT_SCATTERED) ||
            (x->traits.flags & GHOST_DENSEMAT_SCATTERED)) {
        PERFWARNING_LOG("Use plain implementation for scattered views");
        opt_impl = GHOST_IMPLEMENTATION_PLAIN;
    } else {
        if (x->stride > 1 && x->traits.storage == GHOST_DENSEMAT_ROWMAJOR) {
            opt_impl = ghost_get_best_implementation_for_bytesize(x->traits.ncols*x->elSize);
            if (opt_impl == GHOST_IMPLEMENTATION_PLAIN) {
                // this branch is taken for odd numbers
                // choose a version with remainder loops in this case!
                opt_impl = ghost_get_best_implementation_for_bytesize(PAD(x->traits.ncols*x->elSize,ghost_machine_simd_width()));
            }
        } else {
            opt_impl = ghost_get_best_implementation_for_bytesize(mat->traits.C*mat->elSize);
        }
    }

    int try_chunkheight[2] = {mat->traits.C,-1};
    int try_blocksz[2] = {x->traits.ncols,-1};

    int n_chunkheight = sizeof(try_chunkheight)/sizeof(int);
    int n_blocksz = sizeof(try_blocksz)/sizeof(int);
    int pos_chunkheight, pos_blocksz;

    bool optimal = true;

   for (pos_chunkheight = 0; pos_chunkheight < n_chunkheight; pos_chunkheight++) {
        for (pos_blocksz = 0; pos_blocksz < n_blocksz; pos_blocksz++) {
            for (p.impl = opt_impl; (int)p.impl >= GHOST_IMPLEMENTATION_PLAIN; p.impl  = (ghost_implementation)((int)p.impl-1)) {
                /*if (p.impl == GHOST_IMPLEMENTATION_SSE && p.storage == GHOST_DENSEMAT_ROWMAJOR && try_blocksz[pos_blocksz] % 2) {
                    PERFWARNING_LOG("Remainder loops not yet implemented for SSE, fallback to plain");
                    p.impl  = (ghost_implementation)((int)p.impl-1);
                }*/

                int al = ghost_implementation_alignment(p.impl);
                if (IS_ALIGNED(b->val,al) && IS_ALIGNED(x->val,al) && ((b->traits.ncols == 1 && b->stride == 1) || (!((b->stride*b->elSize) % al) && !((x->stride*x->elSize) % al)))) {
                    opt_align = GHOST_ALIGNED;
                } else {
                    if (!IS_ALIGNED(b->val,al)) {
                        PERFWARNING_LOG("Using unaligned kernel because base address of result vector is not aligned");
                    }
                    if (!IS_ALIGNED(x->val,al)) {
                        PERFWARNING_LOG("Using unaligned kernel because base address of input vector is not aligned");
                    }
                    if (b->stride*b->elSize % al) {
                        PERFWARNING_LOG("Using unaligned kernel because stride of result vector does not yield aligned addresses");
                    }
                    if (x->stride*b->elSize % al) {
                        PERFWARNING_LOG("Using unaligned kernel because stride of input vector does not yield aligned addresses");
                    }
                    opt_align = GHOST_UNALIGNED;
                }

                for (p.alignment = opt_align; (int)p.alignment >= GHOST_UNALIGNED; p.alignment = (ghost_alignment)((int)p.alignment-1)) {
                    p.chunkheight = try_chunkheight[pos_chunkheight];
                    p.blocksz = try_blocksz[pos_blocksz];

                    INFO_LOG("Try chunkheight=%s, blocksz=%s, impl=%s, %s",
                            p.chunkheight==-1?"arbitrary":std::to_string((long long)p.chunkheight).c_str(),
                            p.blocksz==-1?"arbitrary":std::to_string((long long)p.blocksz).c_str(),
                            ghost_implementation_string(p.impl),p.alignment==GHOST_UNALIGNED?"unaligned":"aligned");
                    kernel = ghost_kacz_kernels[p];
                    if (kernel) {
	                goto end_of_loop;
                    }
                    optimal = false;
                }
            }
        }
    }
end_of_loop:

    if (kernel) {
        if (optimal) {
            INFO_LOG("Found kernel with highest specialization grade: C=%d blocksz=%d align=%d impl=%s",p.chunkheight,p.blocksz,p.alignment,ghost_implementation_string(p.impl));
        } else {
            PERFWARNING_LOG("Using potentially non-optimal kernel: C=%d blocksz=%d align=%d impl=%s",p.chunkheight,p.blocksz,p.alignment,ghost_implementation_string(p.impl));
        }
        ret = kernel(x,mat,b,opts);
    } else { // execute plain kernel as fallback
        PERFWARNING_LOG("Execute fallback Kaczmarz kernel which is potentially slow!");

        if (b->traits.datatype & GHOST_DT_COMPLEX) {
            if (b->traits.datatype & GHOST_DT_DOUBLE) {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<std::complex<double>, std::complex<double>, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<std::complex<double>, std::complex<double>, false>(x,mat,b,opts);
                }
            } else {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<std::complex<float>, std::complex<float>, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<std::complex<float>, std::complex<float>, false>(x,mat,b,opts);
                }
            }
        } else {
            if (b->traits.datatype & GHOST_DT_DOUBLE) {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<double, double, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<double, double, false>(x,mat,b,opts);
                }
            } else {
                if (opts.direction == GHOST_KACZ_DIRECTION_FORWARD) {
                    ret = kacz_fallback<float, float, true>(x,mat,b,opts);
                } else {
                    ret = kacz_fallback<float, float, false>(x,mat,b,opts);
                }
            }
        }
    }

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);
    return ret;
}
<|endoftext|>


<commit_before>/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "../third_party/skcms/skcms.h"
#include "SkColorSpacePriv.h"
#include "SkData.h"
#include "SkImage.h"
#include "SkStream.h"

int main(int argc, char** argv) {
    const char* source_path = argc > 1 ? argv[1] : nullptr;
    if (!source_path) {
        SkDebugf("Please pass an image or profile to convert"
                 " as the first argument to this program.\n");
        return 1;
    }

    const char* dst_profile_path = argc > 2 ? argv[2] : nullptr;
    skcms_ICCProfile dst_profile = *skcms_sRGB_profile();
    if (dst_profile_path) {
        sk_sp<SkData> blob = SkData::MakeFromFileName(dst_profile_path);
        if (!skcms_Parse(blob->data(), blob->size(), &dst_profile)) {
            SkDebugf("Can't parse %s as an ICC profile.\n", dst_profile_path);
            return 1;
        }
    }

    auto blob = SkData::MakeFromFileName(source_path);

    skcms_ICCProfile src_profile;
    if (skcms_Parse(blob->data(), blob->size(), &src_profile)) {
        // Transform white, black, primaries, and primary complements.
        float src[] = {
           0,0,0,
           1,1,1,

           1,0,0,
           0,1,0,
           0,0,1,

           0,1,1,
           1,0,1,
           1,1,0,
        };
        float dst[24] = {0};

        if (!skcms_Transform(
                    src, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &src_profile,
                    dst, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &dst_profile,
                    8)) {
            SkDebugf("Cannot transform.\n");
            return 1;
        }
        for (int i = 0; i < 8; i++) {
            SkDebugf("(%g, %g, %g) --> (%+.4f, %+.4f, %+.4f)\n",
                     src[3*i+0], src[3*i+1], src[3*i+2],
                     dst[3*i+0], dst[3*i+1], dst[3*i+2]);
        }
        return 0;
    }

    sk_sp<SkImage> image = SkImage::MakeFromEncoded(blob);
    if (!image) {
        SkDebugf("Couldn't decode %s as an SkImage or an ICC profile.\n", source_path);
        return 1;
    }

    image = image->makeRasterImage();
    if (!image) {
        SkDebugf("Converting to raster image failed.\n");
        return 1;
    }

    SkPixmap pixmap;
    if (!image->peekPixels(&pixmap)) {
        SkDebugf("We really should be able to peek raster pixels.\n");
        return 1;
    }

    SkColorSpace* src_cs = image->colorSpace() ? image->colorSpace()
                                               : sk_srgb_singleton();
    src_cs->toProfile(&src_profile);

    skcms_PixelFormat fmt;
    switch (pixmap.colorType()) {
        case kRGBA_8888_SkColorType: fmt = skcms_PixelFormat_RGBA_8888; break;
        case kBGRA_8888_SkColorType: fmt = skcms_PixelFormat_BGRA_8888; break;
        default:
            SkDebugf("color type %d not yet supported, imgcvt.cpp needs an update.\n",
                     pixmap.colorType());
            return 1;
    }

    if (pixmap.alphaType() != kPremul_SkAlphaType) {
        SkDebugf("not premul, that's weird.\n");
        return 1;
    }
    auto alpha = skcms_AlphaFormat_PremulAsEncoded;

    if (pixmap.rowBytes() != (size_t)pixmap.width() * pixmap.info().bytesPerPixel()) {
        SkDebugf("not a tight pixmap, need a loop here\n");
        return 1;
    }

    skcms_Transform(pixmap.addr(),          fmt,alpha, &src_profile,
                    pixmap.writable_addr(), fmt,alpha, &dst_profile,
                    pixmap.width() * pixmap.height());
    pixmap.setColorSpace(SkColorSpace::Make(dst_profile));

    sk_sp<SkImage> transformed = SkImage::MakeRasterCopy(pixmap);
    sk_sp<SkData>  png = transformed->encodeToData();

    SkFILEWStream("transformed.png").write(png->data(), png->size());

    return 0;
}
<commit_msg>add a few more ways to convert images to imgcvt<commit_after>/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "../third_party/skcms/skcms.h"
#include "SkCanvas.h"
#include "SkColorSpacePriv.h"
#include "SkData.h"
#include "SkImage.h"
#include "SkStream.h"
#include "SkSurface.h"

static void write_png(const char* path, sk_sp<SkImage> img) {
    sk_sp<SkData>  png = img->encodeToData();
    SkFILEWStream(path).write(png->data(), png->size());
}

int main(int argc, char** argv) {
    const char* source_path = argc > 1 ? argv[1] : nullptr;
    if (!source_path) {
        SkDebugf("Please pass an image or profile to convert"
                 " as the first argument to this program.\n");
        return 1;
    }

    const char* dst_profile_path = argc > 2 ? argv[2] : nullptr;
    skcms_ICCProfile dst_profile = *skcms_sRGB_profile();
    if (dst_profile_path) {
        sk_sp<SkData> blob = SkData::MakeFromFileName(dst_profile_path);
        if (!skcms_Parse(blob->data(), blob->size(), &dst_profile)) {
            SkDebugf("Can't parse %s as an ICC profile.\n", dst_profile_path);
            return 1;
        }
    }

    auto blob = SkData::MakeFromFileName(source_path);

    skcms_ICCProfile src_profile;
    if (skcms_Parse(blob->data(), blob->size(), &src_profile)) {
        // Transform white, black, primaries, and primary complements.
        float src[] = {
           0,0,0,
           1,1,1,

           1,0,0,
           0,1,0,
           0,0,1,

           0,1,1,
           1,0,1,
           1,1,0,
        };
        float dst[24] = {0};

        if (!skcms_Transform(
                    src, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &src_profile,
                    dst, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &dst_profile,
                    8)) {
            SkDebugf("Cannot transform.\n");
            return 1;
        }
        for (int i = 0; i < 8; i++) {
            SkDebugf("(%g, %g, %g) --> (%+.4f, %+.4f, %+.4f)\n",
                     src[3*i+0], src[3*i+1], src[3*i+2],
                     dst[3*i+0], dst[3*i+1], dst[3*i+2]);
        }
        return 0;
    }

    sk_sp<SkImage> image = SkImage::MakeFromEncoded(blob);
    if (!image) {
        SkDebugf("Couldn't decode %s as an SkImage or an ICC profile.\n", source_path);
        return 1;
    }

    image = image->makeRasterImage();
    if (!image) {
        SkDebugf("Converting to raster image failed.\n");
        return 1;
    }

    SkPixmap pixmap;
    if (!image->peekPixels(&pixmap)) {
        SkDebugf("We really should be able to peek raster pixels.\n");
        return 1;
    }

    sk_sp<SkColorSpace> dst_cs = SkColorSpace::Make(dst_profile);
    if (!dst_cs) {
        SkDebugf("We can't convert to this destination profile.\n");
        return 1;
    }

    { // transform with skcms
        SkColorSpace* src_cs = image->colorSpace() ? image->colorSpace()
                                                   : sk_srgb_singleton();
        src_cs->toProfile(&src_profile);

        skcms_PixelFormat fmt;
        switch (pixmap.colorType()) {
            case kRGBA_8888_SkColorType: fmt = skcms_PixelFormat_RGBA_8888; break;
            case kBGRA_8888_SkColorType: fmt = skcms_PixelFormat_BGRA_8888; break;
            default:
                SkDebugf("color type %d not yet supported, imgcvt.cpp needs an update.\n",
                         pixmap.colorType());
                return 1;
        }

        if (pixmap.alphaType() != kPremul_SkAlphaType) {
            SkDebugf("not premul, that's weird.\n");
            return 1;
        }
        auto alpha = skcms_AlphaFormat_PremulAsEncoded;

        if (pixmap.rowBytes() != (size_t)pixmap.width() * pixmap.info().bytesPerPixel()) {
            SkDebugf("not a tight pixmap, need a loop here\n");
            return 1;
        }

        if (!skcms_Transform(pixmap.addr(),          fmt,alpha, &src_profile,
                             pixmap.writable_addr(), fmt,alpha, &dst_profile,
                             pixmap.width() * pixmap.height())) {
            SkDebugf("skcms_Transform() failed\n");
            return 1;
        }
        pixmap.setColorSpace(dst_cs);

        write_png("transformed-skcms.png", SkImage::MakeRasterCopy(pixmap));
    }

    { // transform with writePixels()
        sk_sp<SkSurface> surface = SkSurface::MakeRaster(pixmap.info().makeColorSpace(dst_cs));
        if (!surface) {
            SkDebugf("couldn't create a surface\n");
            return 1;
        }

        surface->writePixels(pixmap, 0,0);

        write_png("transformed-writepixels.png", surface->makeImageSnapshot());
    }

    { // transform by drawing
        sk_sp<SkSurface> surface = SkSurface::MakeRaster(pixmap.info().makeColorSpace(dst_cs));
        if (!surface) {
            SkDebugf("couldn't create a surface\n");
            return 1;
        }

        surface->getCanvas()->drawImage(image, 0,0);

        write_png("transformed-draw.png", surface->makeImageSnapshot());
    }

    return 0;
}
<|endoftext|>


<commit_before>// http://www.nuonsoft.com/blog/2017/08/10/implementing-a-thread-safe-singleton-with-c11-using-magic-statics/
// http://blog.mbedded.ninja/programming/languages/c-plus-plus/magic-statics

#include <iostream>

class CSingleton final {
 public:
  static CSingleton& GetInstance();
  int getValue() const { return mValue; }

  CSingleton(const CSingleton&) = delete;
  CSingleton& operator=(const CSingleton&) = delete;
  CSingleton(CSingleton&&) = delete;
  CSingleton& operator=(CSingleton&&) = delete;

 private:
  CSingleton() = default;
  ~CSingleton() = default;

  int mValue = 0;
};

CSingleton& CSingleton::GetInstance() {
  static CSingleton instance;
  return instance;
}

int main() {
  auto const value{CSingleton::GetInstance().getValue()};
  std::cout << value << '\n';
}
<commit_msg>Make deleted special member functions private.<commit_after>// http://www.nuonsoft.com/blog/2017/08/10/implementing-a-thread-safe-singleton-with-c11-using-magic-statics/
// http://blog.mbedded.ninja/programming/languages/c-plus-plus/magic-statics

#include <iostream>

class CSingleton final {
 public:
  static CSingleton& GetInstance() {
    static CSingleton instance;
    return instance;
  }

  int getValue() const { return mValue; }

 private:
  CSingleton() = default;
  ~CSingleton() = default;

  CSingleton(const CSingleton&) = delete;
  CSingleton& operator=(const CSingleton&) = delete;
  CSingleton(CSingleton&&) = delete;
  CSingleton& operator=(CSingleton&&) = delete;

  int mValue = 0;
};

int main() {
  auto const value{CSingleton::GetInstance().getValue()};
  std::cout << value << '\n';
}
<|endoftext|>