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

#include <iostream>
#include <string>
#include "planar_movements_recognizer.hpp"
#include "platform.hpp"
#include "platform_utilities.hpp"
#include "strings.hpp"

int main()
{
    using namespace nstd::platform::utilities;

    auto res { shell_execute("gcc -E -Wp,-v -xc++ nul 2>&1") };

    std::cout << "shell_execute: " << std::endl << res << std::endl;

    using namespace nstd::platform;

    std::cout << "Is Little Endian: " << nstd::str::boolalpha[is_little_endian] << std::endl;
    std::cout << "Is 64 bit: " << nstd::str::boolalpha[is_64bit] << std::endl;
    std::cout << "      OS: " << get_current_os_type_name() << std::endl;
    std::cout << "Platform: " << get_current_os_family_name() << std::endl;
    std::cout << "Compiler: " << get_current_compiler_name() << std::endl << std::endl;

    using namespace std::string_literals;
    using namespace nstd::pmr;

    enum command : uint8_t
    {
        open_file = 100, close_file,
        go_back, go_forward,
        reload
    };

    std::map<uint8_t, std::string> command_map
    {
        {0, "Unknown"s},
        {command::open_file, "Open file"s},
        {command::close_file, "Close file"s},
        {command::go_back, "Go back"s},
        {command::go_forward, "Go forward"s},
        {command::reload, "Reload"s}
    };

    using event = planar_movements_event_provider::event;

    planar_movements_event_provider pmep;
    command_recognizer<event, command> cr;
    remove_noise_filter rnf;

    cr. add_command(command::open_file,  { event::up }).
        add_command(command::close_file, { event::down }).
        add_command(command::go_back,    { event::left }).
        add_command(command::go_forward, { event::right }).
        add_command(command::reload,     { event::down, event::up })
    ;

    {
        std::vector<event> coords { pmep(100., 100.), pmep(150., 105.), pmep(200., 103.), pmep(250., 102.), pmep(300., 95.) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        event_filter<event> ef(true);
        ef.set(event::right, event::left);

         // moving right, but mapping the right event to the left one using event_filter
        std::vector<event> coords { ef(pmep(100., 100.)), ef(pmep(150., 105.)), ef(pmep(200., 103.)), ef(pmep(250., 102.)), ef(pmep(300., 95.)) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.) }; // moving down

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.),
                                                                     pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving down & up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    std::cout << "exiting..." << std::endl;

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

#include <iostream>
#include <string>
#include "planar_movements_recognizer.hpp"
#include "platform.hpp"
#include "platform_utilities.hpp"
#include "strings.hpp"

int main()
{
    using namespace nstd::str;
    using namespace nstd::platform;
    using namespace nstd::platform::utilities;

    constexpr const bool if_windows { (current_os_family == os_family::Windows) };

    auto cmd { compose_string((if_windows ? "where" : "which"), " gcc 2>&1") };
    auto res { shell_execute(cmd) };

    std::cout << "shell_execute: " << std::endl << res << std::endl;

    std::cout << "Is Little Endian: " << boolalpha[is_little_endian] << std::endl;
    std::cout << "Is 64 bit: " << boolalpha[is_64bit] << std::endl;
    std::cout << "      OS: " << get_current_os_type_name() << std::endl;
    std::cout << "Platform: " << get_current_os_family_name() << std::endl;
    std::cout << "Compiler: " << get_current_compiler_name() << std::endl << std::endl;

    using namespace std::string_literals;
    using namespace nstd::pmr;

    enum command : uint8_t
    {
        open_file = 100, close_file,
        go_back, go_forward,
        reload
    };

    std::map<uint8_t, std::string> command_map
    {
        {0, "Unknown"s},
        {command::open_file, "Open file"s},
        {command::close_file, "Close file"s},
        {command::go_back, "Go back"s},
        {command::go_forward, "Go forward"s},
        {command::reload, "Reload"s}
    };

    using event = planar_movements_event_provider::event;

    planar_movements_event_provider pmep;
    command_recognizer<event, command> cr;
    remove_noise_filter rnf;

    cr. add_command(command::open_file,  { event::up }).
        add_command(command::close_file, { event::down }).
        add_command(command::go_back,    { event::left }).
        add_command(command::go_forward, { event::right }).
        add_command(command::reload,     { event::down, event::up })
    ;

    {
        std::vector<event> coords { pmep(100., 100.), pmep(150., 105.), pmep(200., 103.), pmep(250., 102.), pmep(300., 95.) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        event_filter<event> ef(true);
        ef.set(event::right, event::left);

         // moving right, but mapping the right event to the left one using event_filter
        std::vector<event> coords { ef(pmep(100., 100.)), ef(pmep(150., 105.)), ef(pmep(200., 103.)), ef(pmep(250., 102.)), ef(pmep(300., 95.)) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.) }; // moving down

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.),
                                                                     pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving down & up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    std::cout << "exiting..." << std::endl;

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>A quick fix for Issue 18353. This is my stupid mistake that I forgot removing the platform-dependent code in our renderer code. This change just add defined(OS_MACOSX) instead of removing #ifdef blocks since they are used by Chrome OS.<commit_after><|endoftext|>


<commit_before>
#include "connection.h"
#include "room.h"
#include "user.h"
#include "csapi/room_send.h"
#include "csapi/joining.h"
#include "csapi/leaving.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QStringBuilder>
#include <QtCore/QTimer>
#include <iostream>
#include <functional>

using namespace QMatrixClient;
using std::cout;
using std::endl;
using namespace std::placeholders;

class QMCTest : public QObject
{
    public:
        QMCTest(Connection* conn, QString targetRoomName, QString source);

    private slots:
        void setupAndRun();
        void onNewRoom(Room* r);
        void run();
        void doTests();
            void loadMembers();
            void sendMessage();
            void addAndRemoveTag();
            void sendAndRedact();
                void checkRedactionOutcome(const QString& evtIdToRedact,
                                   RoomEventsRange events);
            void markDirectChat();
                void checkDirectChatOutcome(
                        const Connection::DirectChatsMap& added);
        void leave();
        void finalize();

    private:
        QScopedPointer<Connection, QScopedPointerDeleteLater> c;
        QStringList running;
        QStringList succeeded;
        QStringList failed;
        QString origin;
        QString targetRoomName;
        Room* targetRoom = nullptr;
};

#define QMC_CHECK(description, condition) \
{ \
    Q_ASSERT(running.removeOne(description)); \
    if (!!(condition)) \
    { \
        succeeded.push_back(description); \
        cout << (description) << " successful" << endl; \
        if (targetRoom) \
            targetRoom->postMessage( \
                origin % ": " % (description) % " successful", \
                MessageEventType::Notice); \
    } else { \
        failed.push_back(description); \
        cout << (description) << " FAILED" << endl; \
        if (targetRoom) \
            targetRoom->postPlainText( \
                origin % ": " % (description) % " FAILED"); \
    } \
}

QMCTest::QMCTest(Connection* conn, QString testRoomName, QString source)
    : c(conn), origin(std::move(source)), targetRoomName(std::move(testRoomName))
{
    if (!origin.isEmpty())
        cout << "Origin for the test message: " << origin.toStdString() << endl;
    if (!targetRoomName.isEmpty())
        cout << "Test room name: " << targetRoomName.toStdString() << endl;

    connect(c.data(), &Connection::connected, this, &QMCTest::setupAndRun);
    connect(c.data(), &Connection::loadedRoomState, this, &QMCTest::onNewRoom);
    // Big countdown watchdog
    QTimer::singleShot(180000, this, &QMCTest::leave);
}

void QMCTest::setupAndRun()
{
    cout << "Connected, server: "
         << c->homeserver().toDisplayString().toStdString() << endl;
    cout << "Access token: " << c->accessToken().toStdString() << endl;

    if (!targetRoomName.isEmpty())
    {
        cout << "Joining " << targetRoomName.toStdString() << endl;
        running.push_back("Join room");
        auto joinJob = c->joinRoom(targetRoomName);
        connect(joinJob, &BaseJob::failure, this,
            [this] { QMC_CHECK("Join room", false); finalize(); });
        // Connection::joinRoom() creates a Room object upon JoinRoomJob::success
        // but this object is empty until the first sync is done.
        connect(joinJob, &BaseJob::success, this, [this,joinJob] {
            targetRoom = c->room(joinJob->roomId(), JoinState::Join);
            QMC_CHECK("Join room", targetRoom != nullptr);

            run();
        });
    } else
        run();
}

void QMCTest::onNewRoom(Room* r)
{
    cout << "New room: " << r->id().toStdString() << endl
         << "  Name: " << r->name().toStdString() << endl
         << "  Canonical alias: " << r->canonicalAlias().toStdString() << endl
         << endl;
    connect(r, &Room::aboutToAddNewMessages, r, [r] (RoomEventsRange timeline) {
        cout << timeline.size() << " new event(s) in room "
             << r->canonicalAlias().toStdString() << endl;
//        for (const auto& item: timeline)
//        {
//            cout << "From: "
//                 << r->roomMembername(item->senderId()).toStdString()
//                 << endl << "Timestamp:"
//                 << item->timestamp().toString().toStdString() << endl
//                 << "JSON:" << endl << item->originalJson().toStdString() << endl;
//        }
    });
}

void QMCTest::run()
{
    c->setLazyLoading(true);
    c->sync();
    connectSingleShot(c.data(), &Connection::syncDone, this, &QMCTest::doTests);
    connect(c.data(), &Connection::syncDone, c.data(), [this] {
        cout << "Sync complete, "
             << running.size() << " tests in the air" << endl;
        if (!running.isEmpty())
            c->sync(10000);
        else if (targetRoom)
        {
            // TODO: Waiting for proper futures to come so that it could be:
//            targetRoom->postPlainText(origin % ": All tests finished")
//            .then(this, &QMCTest::leave);
            auto txnId =
                    targetRoom->postPlainText(origin % ": All tests finished");
            connect(targetRoom, &Room::messageSent, this,
                    [this,txnId] (QString serverTxnId) {
                if (txnId == serverTxnId)
                    leave();
            });
        }
        else
            finalize();
    });
}

void QMCTest::doTests()
{
    cout << "Starting tests" << endl;

    loadMembers();
    // Add here tests not requiring the test room
    if (targetRoomName.isEmpty())
        return;

    sendMessage();
    addAndRemoveTag();
    sendAndRedact();
    markDirectChat();
    // Add here tests with the test room
}

void QMCTest::loadMembers()
{
    running.push_back("Loading members");
    // The dedicated qmc-test room is too small to test
    // lazy-loading-then-full-loading; use #qmatrixclient:matrix.org instead.
    // TODO: #264
    auto* r = c->room(QStringLiteral("!PCzUtxtOjUySxSelof:matrix.org"));
    if (!r)
    {
        cout << "#test:matrix.org is not found in the test user's rooms" << endl;
        QMC_CHECK("Loading members", false);
        return;
    }
    // It's not exactly correct because an arbitrary server might not support
    // lazy loading; but in the absence of capabilities framework we assume
    // it does.
    if (r->memberNames().size() >= r->joinedCount())
    {
        cout << "Lazy loading doesn't seem to be enabled" << endl;
        QMC_CHECK("Loading members", false);
        return;
    }
    r->setDisplayed();
    connect(r, &Room::allMembersLoaded, [this,r] {
        QMC_CHECK("Loading members",
                  r->memberNames().size() >= r->joinedCount());
    });
}

void QMCTest::sendMessage()
{
    running.push_back("Message sending");
    cout << "Sending a message" << endl;
    auto txnId = targetRoom->postPlainText("Hello, " % origin % " is here");
    auto& pending = targetRoom->pendingEvents();
    if (pending.empty())
    {
        QMC_CHECK("Message sending", false);
        return;
    }
    auto it = std::find_if(pending.begin(), pending.end(),
                [&txnId] (const auto& e) {
                    return e->transactionId() == txnId;
                });
    QMC_CHECK("Message sending", it != pending.end());
    // TODO: Wait when it actually gets sent; check that it obtained an id
    // Independently, check when it shows up in the timeline.
}

void QMCTest::addAndRemoveTag()
{
    running.push_back("Tagging test");
    static const auto TestTag = QStringLiteral("org.qmatrixclient.test");
    // Pre-requisite
    if (targetRoom->tags().contains(TestTag))
        targetRoom->removeTag(TestTag);

    // Connect first because the signal is emitted synchronously.
    connect(targetRoom, &Room::tagsChanged, targetRoom, [=] {
        cout << "Room " << targetRoom->id().toStdString()
             << ", tag(s) changed:" << endl
             << "  " << targetRoom->tagNames().join(", ").toStdString() << endl;
        if (targetRoom->tags().contains(TestTag))
        {
            cout << "Test tag set, removing it now" << endl;
            targetRoom->removeTag(TestTag);
            QMC_CHECK("Tagging test", !targetRoom->tags().contains(TestTag));
            QObject::disconnect(targetRoom, &Room::tagsChanged, nullptr, nullptr);
        }
    });
    cout << "Adding a tag" << endl;
    targetRoom->addTag(TestTag);
}

void QMCTest::sendAndRedact()
{
    running.push_back("Redaction");
    cout << "Sending a message to redact" << endl;
    if (auto* job = targetRoom->connection()->sendMessage(targetRoom->id(),
            RoomMessageEvent(origin % ": message to redact")))
    {
        connect(job, &BaseJob::success, targetRoom, [job,this] {
            cout << "Redacting the message" << endl;
            targetRoom->redactEvent(job->eventId(), origin);
            // Make sure to save the event id because the job is about to end.
            connect(targetRoom, &Room::aboutToAddNewMessages, this,
                    std::bind(&QMCTest::checkRedactionOutcome,
                              this, job->eventId(), _1));
        });
    } else
        QMC_CHECK("Redaction", false);
}

void QMCTest::checkRedactionOutcome(const QString& evtIdToRedact,
                                    RoomEventsRange events)
{
    static bool checkSucceeded = false;
    // There are two possible (correct) outcomes: either the event comes already
    // redacted at the next sync, or the nearest sync completes with
    // the unredacted event but the next one brings redaction.
    auto it = std::find_if(events.begin(), events.end(),
                [=] (const RoomEventPtr& e) {
                    return e->id() == evtIdToRedact;
                });
    if (it == events.end())
        return; // Waiting for the next sync

    if ((*it)->isRedacted())
    {
        if (checkSucceeded)
        {
            const auto msg =
                    "The redacted event came in with the sync again, ignoring";
            cout << msg << endl;
            targetRoom->postPlainText(msg);
            return;
        }
        cout << "The sync brought already redacted message" << endl;
        QMC_CHECK("Redaction", true);
        // Not disconnecting because there are other connections from this class
        // to aboutToAddNewMessages
        checkSucceeded = true;
        return;
    }
    // The event is not redacted
    if (checkSucceeded)
    {
        const auto msg =
                "Warning: the redacted event came non-redacted with the sync!";
        cout << msg << endl;
        targetRoom->postPlainText(msg);
    }
    cout << "Message came non-redacted with the sync, waiting for redaction" << endl;
    connect(targetRoom, &Room::replacedEvent, targetRoom,
        [=] (const RoomEvent* newEvent, const RoomEvent* oldEvent) {
            QMC_CHECK("Redaction", oldEvent->id() == evtIdToRedact &&
                      newEvent->isRedacted() &&
                      newEvent->redactionReason() == origin);
            checkSucceeded = true;
            disconnect(targetRoom, &Room::replacedEvent, nullptr, nullptr);
        });

}

void QMCTest::markDirectChat()
{
    if (targetRoom->directChatUsers().contains(c->user()))
    {
        cout << "Warning: the room is already a direct chat,"
                " only unmarking will be tested" << endl;
        checkDirectChatOutcome({{ c->user(), targetRoom->id() }});
        return;
    }
    // Connect first because the signal is emitted synchronously.
    connect(c.data(), &Connection::directChatsListChanged,
            this, &QMCTest::checkDirectChatOutcome);
    cout << "Marking the room as a direct chat" << endl;
    c->addToDirectChats(targetRoom, c->user());
}

void QMCTest::checkDirectChatOutcome(const Connection::DirectChatsMap& added)
{
    running.push_back("Direct chat test");
    disconnect(c.data(), &Connection::directChatsListChanged, nullptr, nullptr);
    if (!targetRoom->isDirectChat())
    {
        cout << "The room has not been marked as a direct chat" << endl;
        QMC_CHECK("Direct chat test", false);
        return;
    }
    if (!added.contains(c->user(), targetRoom->id()))
    {
        cout << "The room has not been listed in new direct chats" << endl;
        QMC_CHECK("Direct chat test", false);
        return;
    }

    cout << "Unmarking the direct chat" << endl;
    c->removeFromDirectChats(targetRoom->id(), c->user());
    QMC_CHECK("Direct chat test", !c->isDirectChat(targetRoom->id()));
}

void QMCTest::leave()
{
    if (targetRoom)
    {
        cout << "Leaving the room" << endl;
        connect(targetRoom->leaveRoom(), &BaseJob::finished,
                this, &QMCTest::finalize);
    }
    else
        finalize();
}

void QMCTest::finalize()
{
    cout << "Logging out" << endl;
    c->logout();
    connect(c.data(), &Connection::loggedOut, qApp,
        [this] {
            if (!failed.isEmpty())
                cout << "FAILED: " << failed.join(", ").toStdString() << endl;
            if (!running.isEmpty())
                cout << "DID NOT FINISH: "
                     << running.join(", ").toStdString() << endl;
            QCoreApplication::processEvents();
            QCoreApplication::exit(failed.size() + running.size());
        });
}

int main(int argc, char* argv[])
{
    QCoreApplication app(argc, argv);
    if (argc < 4)
    {
        cout << "Usage: qmc-example <user> <passwd> <device_name> [<room_alias> [origin]]" << endl;
        return -1;
    }

    cout << "Connecting to the server as " << argv[1] << endl;
    auto conn = new Connection;
    conn->connectToServer(argv[1], argv[2], argv[3]);
    QMCTest test { conn, argc >= 5 ? argv[4] : nullptr,
                         argc >= 6 ? argv[5] : nullptr };
    return app.exec();
}
<commit_msg>qmc-example: streamline redaction test<commit_after>
#include "connection.h"
#include "room.h"
#include "user.h"
#include "csapi/room_send.h"
#include "csapi/joining.h"
#include "csapi/leaving.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QStringBuilder>
#include <QtCore/QTimer>
#include <iostream>
#include <functional>

using namespace QMatrixClient;
using std::cout;
using std::endl;
using namespace std::placeholders;

class QMCTest : public QObject
{
    public:
        QMCTest(Connection* conn, QString targetRoomName, QString source);

    private slots:
        void setupAndRun();
        void onNewRoom(Room* r);
        void run();
        void doTests();
            void loadMembers();
            void sendMessage();
            void addAndRemoveTag();
            void sendAndRedact();
                void checkRedactionOutcome(const QString& evtIdToRedact,
                                           const QMetaObject::Connection& sc);
            void markDirectChat();
                void checkDirectChatOutcome(
                        const Connection::DirectChatsMap& added);
        void leave();
        void finalize();

    private:
        QScopedPointer<Connection, QScopedPointerDeleteLater> c;
        QStringList running;
        QStringList succeeded;
        QStringList failed;
        QString origin;
        QString targetRoomName;
        Room* targetRoom = nullptr;
};

#define QMC_CHECK(description, condition) \
{ \
    Q_ASSERT(running.removeOne(description)); \
    if (!!(condition)) \
    { \
        succeeded.push_back(description); \
        cout << (description) << " successful" << endl; \
        if (targetRoom) \
            targetRoom->postMessage( \
                origin % ": " % (description) % " successful", \
                MessageEventType::Notice); \
    } else { \
        failed.push_back(description); \
        cout << (description) << " FAILED" << endl; \
        if (targetRoom) \
            targetRoom->postPlainText( \
                origin % ": " % (description) % " FAILED"); \
    } \
}

QMCTest::QMCTest(Connection* conn, QString testRoomName, QString source)
    : c(conn), origin(std::move(source)), targetRoomName(std::move(testRoomName))
{
    if (!origin.isEmpty())
        cout << "Origin for the test message: " << origin.toStdString() << endl;
    if (!targetRoomName.isEmpty())
        cout << "Test room name: " << targetRoomName.toStdString() << endl;

    connect(c.data(), &Connection::connected, this, &QMCTest::setupAndRun);
    connect(c.data(), &Connection::loadedRoomState, this, &QMCTest::onNewRoom);
    // Big countdown watchdog
    QTimer::singleShot(180000, this, &QMCTest::leave);
}

void QMCTest::setupAndRun()
{
    cout << "Connected, server: "
         << c->homeserver().toDisplayString().toStdString() << endl;
    cout << "Access token: " << c->accessToken().toStdString() << endl;

    if (!targetRoomName.isEmpty())
    {
        cout << "Joining " << targetRoomName.toStdString() << endl;
        running.push_back("Join room");
        auto joinJob = c->joinRoom(targetRoomName);
        connect(joinJob, &BaseJob::failure, this,
            [this] { QMC_CHECK("Join room", false); finalize(); });
        // Connection::joinRoom() creates a Room object upon JoinRoomJob::success
        // but this object is empty until the first sync is done.
        connect(joinJob, &BaseJob::success, this, [this,joinJob] {
            targetRoom = c->room(joinJob->roomId(), JoinState::Join);
            QMC_CHECK("Join room", targetRoom != nullptr);

            run();
        });
    } else
        run();
}

void QMCTest::onNewRoom(Room* r)
{
    cout << "New room: " << r->id().toStdString() << endl
         << "  Name: " << r->name().toStdString() << endl
         << "  Canonical alias: " << r->canonicalAlias().toStdString() << endl
         << endl;
    connect(r, &Room::aboutToAddNewMessages, r, [r] (RoomEventsRange timeline) {
        cout << timeline.size() << " new event(s) in room "
             << r->canonicalAlias().toStdString() << endl;
//        for (const auto& item: timeline)
//        {
//            cout << "From: "
//                 << r->roomMembername(item->senderId()).toStdString()
//                 << endl << "Timestamp:"
//                 << item->timestamp().toString().toStdString() << endl
//                 << "JSON:" << endl << item->originalJson().toStdString() << endl;
//        }
    });
}

void QMCTest::run()
{
    c->setLazyLoading(true);
    c->sync();
    connectSingleShot(c.data(), &Connection::syncDone, this, &QMCTest::doTests);
    connect(c.data(), &Connection::syncDone, c.data(), [this] {
        cout << "Sync complete, "
             << running.size() << " tests in the air" << endl;
        if (!running.isEmpty())
            c->sync(10000);
        else if (targetRoom)
        {
            // TODO: Waiting for proper futures to come so that it could be:
//            targetRoom->postPlainText(origin % ": All tests finished")
//            .then(this, &QMCTest::leave);
            auto txnId =
                    targetRoom->postPlainText(origin % ": All tests finished");
            connect(targetRoom, &Room::messageSent, this,
                    [this,txnId] (QString serverTxnId) {
                if (txnId == serverTxnId)
                    leave();
            });
        }
        else
            finalize();
    });
}

void QMCTest::doTests()
{
    cout << "Starting tests" << endl;

    loadMembers();
    // Add here tests not requiring the test room
    if (targetRoomName.isEmpty())
        return;

    sendMessage();
    addAndRemoveTag();
    sendAndRedact();
    markDirectChat();
    // Add here tests with the test room
}

void QMCTest::loadMembers()
{
    running.push_back("Loading members");
    // The dedicated qmc-test room is too small to test
    // lazy-loading-then-full-loading; use #qmatrixclient:matrix.org instead.
    // TODO: #264
    auto* r = c->room(QStringLiteral("!PCzUtxtOjUySxSelof:matrix.org"));
    if (!r)
    {
        cout << "#test:matrix.org is not found in the test user's rooms" << endl;
        QMC_CHECK("Loading members", false);
        return;
    }
    // It's not exactly correct because an arbitrary server might not support
    // lazy loading; but in the absence of capabilities framework we assume
    // it does.
    if (r->memberNames().size() >= r->joinedCount())
    {
        cout << "Lazy loading doesn't seem to be enabled" << endl;
        QMC_CHECK("Loading members", false);
        return;
    }
    r->setDisplayed();
    connect(r, &Room::allMembersLoaded, [this,r] {
        QMC_CHECK("Loading members",
                  r->memberNames().size() >= r->joinedCount());
    });
}

void QMCTest::sendMessage()
{
    running.push_back("Message sending");
    cout << "Sending a message" << endl;
    auto txnId = targetRoom->postPlainText("Hello, " % origin % " is here");
    auto& pending = targetRoom->pendingEvents();
    if (pending.empty())
    {
        QMC_CHECK("Message sending", false);
        return;
    }
    auto it = std::find_if(pending.begin(), pending.end(),
                [&txnId] (const auto& e) {
                    return e->transactionId() == txnId;
                });
    QMC_CHECK("Message sending", it != pending.end());
    // TODO: Wait when it actually gets sent; check that it obtained an id
    // Independently, check when it shows up in the timeline.
}

void QMCTest::addAndRemoveTag()
{
    running.push_back("Tagging test");
    static const auto TestTag = QStringLiteral("org.qmatrixclient.test");
    // Pre-requisite
    if (targetRoom->tags().contains(TestTag))
        targetRoom->removeTag(TestTag);

    // Connect first because the signal is emitted synchronously.
    connect(targetRoom, &Room::tagsChanged, targetRoom, [=] {
        cout << "Room " << targetRoom->id().toStdString()
             << ", tag(s) changed:" << endl
             << "  " << targetRoom->tagNames().join(", ").toStdString() << endl;
        if (targetRoom->tags().contains(TestTag))
        {
            cout << "Test tag set, removing it now" << endl;
            targetRoom->removeTag(TestTag);
            QMC_CHECK("Tagging test", !targetRoom->tags().contains(TestTag));
            QObject::disconnect(targetRoom, &Room::tagsChanged, nullptr, nullptr);
        }
    });
    cout << "Adding a tag" << endl;
    targetRoom->addTag(TestTag);
}

void QMCTest::sendAndRedact()
{
    running.push_back("Redaction");
    cout << "Sending a message to redact" << endl;
    auto txnId = targetRoom->postPlainText(origin % ": message to redact");
    if (txnId.isEmpty())
    {
        QMC_CHECK("Redaction", false);
        return;
    }
    connect(targetRoom, &Room::messageSent, this,
        [this,txnId] (const QString& tId, const QString& evtId) {
            if (tId != txnId)
                return;

            cout << "Redacting the message" << endl;
            targetRoom->redactEvent(evtId, origin);
            QMetaObject::Connection sc;
            sc = connect(targetRoom, &Room::addedMessages, this,
                         [this,sc,evtId] { checkRedactionOutcome(evtId, sc); });
        });
}

void QMCTest::checkRedactionOutcome(const QString& evtIdToRedact,
                                    const QMetaObject::Connection& sc)
{
    // There are two possible (correct) outcomes: either the event comes already
    // redacted at the next sync, or the nearest sync completes with
    // the unredacted event but the next one brings redaction.
    auto it = targetRoom->findInTimeline(evtIdToRedact);
    if (it == targetRoom->timelineEdge())
        return; // Waiting for the next sync

    if ((*it)->isRedacted())
    {
        cout << "The sync brought already redacted message" << endl;
        QMC_CHECK("Redaction", true);
        disconnect(sc);
        return;
    }
    cout << "Message came non-redacted with the sync, waiting for redaction"
         << endl;
    connect(targetRoom, &Room::replacedEvent, this,
        [this,evtIdToRedact]
        (const RoomEvent* newEvent, const RoomEvent* oldEvent) {
            if (oldEvent->id() == evtIdToRedact)
            {
                QMC_CHECK("Redaction", newEvent->isRedacted() &&
                                       newEvent->redactionReason() == origin);
                disconnect(targetRoom, &Room::replacedEvent, nullptr, nullptr);
            }
        });
}

void QMCTest::markDirectChat()
{
    if (targetRoom->directChatUsers().contains(c->user()))
    {
        cout << "Warning: the room is already a direct chat,"
                " only unmarking will be tested" << endl;
        checkDirectChatOutcome({{ c->user(), targetRoom->id() }});
        return;
    }
    // Connect first because the signal is emitted synchronously.
    connect(c.data(), &Connection::directChatsListChanged,
            this, &QMCTest::checkDirectChatOutcome);
    cout << "Marking the room as a direct chat" << endl;
    c->addToDirectChats(targetRoom, c->user());
}

void QMCTest::checkDirectChatOutcome(const Connection::DirectChatsMap& added)
{
    running.push_back("Direct chat test");
    disconnect(c.data(), &Connection::directChatsListChanged, nullptr, nullptr);
    if (!targetRoom->isDirectChat())
    {
        cout << "The room has not been marked as a direct chat" << endl;
        QMC_CHECK("Direct chat test", false);
        return;
    }
    if (!added.contains(c->user(), targetRoom->id()))
    {
        cout << "The room has not been listed in new direct chats" << endl;
        QMC_CHECK("Direct chat test", false);
        return;
    }

    cout << "Unmarking the direct chat" << endl;
    c->removeFromDirectChats(targetRoom->id(), c->user());
    QMC_CHECK("Direct chat test", !c->isDirectChat(targetRoom->id()));
}

void QMCTest::leave()
{
    if (targetRoom)
    {
        cout << "Leaving the room" << endl;
        connect(targetRoom->leaveRoom(), &BaseJob::finished,
                this, &QMCTest::finalize);
    }
    else
        finalize();
}

void QMCTest::finalize()
{
    cout << "Logging out" << endl;
    c->logout();
    connect(c.data(), &Connection::loggedOut, qApp,
        [this] {
            if (!failed.isEmpty())
                cout << "FAILED: " << failed.join(", ").toStdString() << endl;
            if (!running.isEmpty())
                cout << "DID NOT FINISH: "
                     << running.join(", ").toStdString() << endl;
            QCoreApplication::processEvents();
            QCoreApplication::exit(failed.size() + running.size());
        });
}

int main(int argc, char* argv[])
{
    QCoreApplication app(argc, argv);
    if (argc < 4)
    {
        cout << "Usage: qmc-example <user> <passwd> <device_name> [<room_alias> [origin]]" << endl;
        return -1;
    }

    cout << "Connecting to the server as " << argv[1] << endl;
    auto conn = new Connection;
    conn->connectToServer(argv[1], argv[2], argv[3]);
    QMCTest test { conn, argc >= 5 ? argv[4] : nullptr,
                         argc >= 6 ? argv[5] : nullptr };
    return app.exec();
}
<|endoftext|>


<commit_before>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
//#include <iostream>

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;
static void new_file(GtkToolItem *button, Data *data)
{
	data->buffer = nullptr;
}
static void load_file(GtkToolItem *button, Data *data)
{
	static GtkWidget *dialog = nullptr;
	if (dialog == nullptr)
	{
		dialog = gtk_file_chooser_dialog_new("Open File",
			data->parent, GTK_FILE_CHOOSER_ACTION_OPEN,
			GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
	}
	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		gchar *text_data;
		printf("Open: %s\n", filename);
		g_file_get_contents( filename, &text_data, NULL, NULL );
		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source_view ));
		gtk_text_buffer_set_text( buff, text_data, -1 );

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);
		gtk_source_buffer_set_language(
			GTK_SOURCE_BUFFER(buff), s_lang);

		g_free( filename );
		g_free( text_data );
	}
	gtk_widget_hide(dialog);
}
static void save_file(GtkToolItem *button, Data *data)
{
	static GtkWidget *dialog = nullptr;

	if(dialog == nullptr)
	{
		dialog = gtk_file_chooser_dialog_new("Save file",
			data->parent, GTK_FILE_CHOOSER_ACTION_SAVE,
			GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
	}
	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename;
		gchar *text_data;

		g_object_get( G_OBJECT( data->buffer ), "text",
			&text_data, NULL);

		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		g_free( text_data );
	}
	gtk_widget_hide(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	GtkTextBuffer *buffer;
	Data *data;
	// initialize
	data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	source_view = gtk_source_view_new();
	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source_view ));
	swin = gtk_scrolled_window_new(NULL, NULL);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), data);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), data);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_box_pack_start( GTK_BOX( hbox ), swin, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);
	gtk_container_add(GTK_CONTAINER(swin), source_view);

	data->buffer = buffer;
	data->parent = GTK_WINDOW(window);
	gtk_widget_show(toolbar);
	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	int status;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<commit_msg>added new_file function and integrating a tab feature<commit_after>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
//#include <iostream>

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkWidget* notebook = nullptr;
GtkWidget* frame	= nullptr;
GtkWidget* label	= nullptr;
int frame_num = 1;
char bufferf[32];
char bufferl[32];
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;
static void new_file(GtkToolItem *button, Data *data)
{
	frame = gtk_frame_new(bufferf);
	//gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
	//gtk_widget_set_size_request(frame, 400, 500);
	gtk_widget_show(frame);

	/*label = gtk_label_new (bufferf);
	gtk_container_add(GTK_CONTAINER(frame), label);
	gtk_widget_show(label);*/

	label = gtk_label_new(bufferl);
	gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), frame, label);
}
static void load_file(GtkToolItem *button, Data *data)
{
	static GtkWidget *dialog = nullptr;
	if (dialog == nullptr)
	{
		dialog = gtk_file_chooser_dialog_new("Open File",
			data->parent, GTK_FILE_CHOOSER_ACTION_OPEN,
			GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
	}
	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		gchar *text_data;
		printf("Open: %s\n", filename);
		g_file_get_contents( filename, &text_data, NULL, NULL );
		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source_view ));
		gtk_text_buffer_set_text( buff, text_data, -1 );

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);
		gtk_source_buffer_set_language(
			GTK_SOURCE_BUFFER(buff), s_lang);

		g_free( filename );
		g_free( text_data );
	}
	gtk_widget_hide(dialog);
}
static void save_file(GtkToolItem *button, Data *data)
{
	static GtkWidget *dialog = nullptr;

	if(dialog == nullptr)
	{
		dialog = gtk_file_chooser_dialog_new("Save file",
			data->parent, GTK_FILE_CHOOSER_ACTION_SAVE,
			GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
	}
	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename;
		gchar *text_data;

		g_object_get( G_OBJECT( data->buffer ), "text",
			&text_data, NULL);

		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		g_free( text_data );
	}
	gtk_widget_hide(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	GtkTextBuffer *buffer;
	Data *data;
	// initialize
	notebook = gtk_notebook_new();
	data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	source_view = gtk_source_view_new();
	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source_view ));
	swin = gtk_scrolled_window_new(NULL, NULL);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), data);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), data);
	g_signal_connect (new_button, "clicked", G_CALLBACK(new_file), data);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
	gtk_box_pack_start( GTK_BOX( hbox ), swin, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);
	//gtk_container_add(GTK_CONTAINER(hbox), notebook);
	gtk_container_add(GTK_CONTAINER(swin), notebook);
	gtk_container_add(GTK_CONTAINER(notebook), source_view);

	data->buffer = buffer;
	data->parent = GTK_WINDOW(window);
	//gtk_widget_show(toolbar);
	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	int status;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<|endoftext|>


<commit_before>#include <thread>

#include "../chan.hh"

bool ok = false;
bool sent = false;

void producer(chan::write_chan<int>* ch) {
	for (int i = 2 ; ok ; i++) {
		printf("w %d\n", i);
		sent = true;
		ch->send(i);
	}
}

void consumer(chan::read_chan<int>* ch) {
	for (int i = 0 ; ok || sent ; i++) {
		int x = 0;
		ch->recv(x);
		printf("r %d\n", x);
		sent = false;
	}
}

int main() {
	// auto ch = new chan::unbuffered_chan<int>();
	chan::unbuffered_chan<int> ch;

	ok = true;

	std::thread t1(producer, &ch);
	std::thread t2(consumer, &ch);

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

	ok = false;

	t1.join();
	t2.join();
}
<commit_msg>examples/raw_pointers: remove races and segfaults<commit_after>#include <thread>

#include "../chan.hh"

void producer(chan::write_chan<int>* ch) {
	for (int i = 0 ; i < 100 ; i++) {
		printf("w %d\n", i);
		ch->send(i);
	}
}

void consumer(chan::read_chan<int>* ch) {
	for (int i = 0 ; i < 100 ; i++) {
		int x = 0;
		ch->recv(x);
		printf("r %d\n", x);
	}
}

int main() {
	// auto ch = new chan::unbuffered_chan<int>();
	chan::unbuffered_chan<int> ch;

	std::thread t1(producer, &ch);
	std::thread t2(consumer, &ch);

	t1.join();
	t2.join();
}
<|endoftext|>


<commit_before>//
//  data_normalization.cpp
//  XAA1
//
//  Created by Michele Colombo on 16/12/2015.
//  Copyright (c) 2015 Michele Colombo. All rights reserved.
//

#include "data_normalization.h"
#include <cmath>
#include <numeric>
#include <algorithm>

MinMaxNormalizer::MinMaxNormalizer(double min_target, double max_target){
    this->min_target = min_target;
    this->max_target = max_target;
}

void MinMaxNormalizer::setDataSource(const Doubles &values){
    auto mm = std::minmax_element(values.begin(), values.end());
    this->min_value = *mm.first;
    this->max_value = *mm.second;
}

double MinMaxNormalizer::normalize(double value){
    return min_target + (max_target - min_target) * (value - min_value) / (max_value - min_value);
}

double MinMaxNormalizer::denormalize(double value){
    return (value - min_target) * (max_value - min_value) / (max_target - min_target) + min_value;
}

void ZNormalizer::setDataSource(const Doubles &values){
    double sum = std::accumulate(values.begin(), values.end(), 0);
    mean = sum / (double)values.size();

    double accum = 0.0;
    std::for_each (std::begin(values), std::end(values), [&](const double d) {
        accum += (d - mean) * (d - mean);
    });
    sd = std::sqrt(accum/(double)values.size());
}
<commit_msg>Fixed znorm implicit conversion issue<commit_after>//
//  data_normalization.cpp
//  XAA1
//
//  Created by Michele Colombo on 16/12/2015.
//  Copyright (c) 2015 Michele Colombo. All rights reserved.
//

#include "data_normalization.h"
#include <cmath>
#include <numeric>
#include <algorithm>

MinMaxNormalizer::MinMaxNormalizer(double min_target, double max_target){
    this->min_target = min_target;
    this->max_target = max_target;
}

void MinMaxNormalizer::setDataSource(const Doubles &values){
    auto mm = std::minmax_element(values.begin(), values.end());
    this->min_value = *mm.first;
    this->max_value = *mm.second;
}

double MinMaxNormalizer::normalize(double value){
    return min_target + (max_target - min_target) * (value - min_value) / (max_value - min_value);
}

double MinMaxNormalizer::denormalize(double value){
    return (value - min_target) * (max_value - min_value) / (max_target - min_target) + min_value;
}

void ZNormalizer::setDataSource(const Doubles &values){
    double sum = std::accumulate(values.begin(), values.end(), 0.0);
    mean = sum / (double)values.size();

    double accum = 0.0;
    std::for_each (std::begin(values), std::end(values), [&](const double d) {
        accum += (d - mean) * (d - mean);
    });
    sd = std::sqrt(accum/(double)values.size());
}
<|endoftext|>


<commit_before>// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#ifndef MFEM_CONSTRAINED
#define MFEM_CONSTRAINED

#include "solvers.hpp"
#include "blockoperator.hpp"
#include "sparsemat.hpp"
#include "hypre.hpp"

namespace mfem
{

class ParFiniteElementSpace;

/** @brief An abstract class to solve the constrained system \f$ Ax = f \f$
    subject to the constraint \f$ B x = r \f$.

    Although implementations may not use the below formulation, for
    understanding some of its methods and notation you can think of
    it as solving the saddle-point system

     (  A   B^T  )  ( x )          (  f  )
     (  B        )  ( lambda )  =  (  r  )

    Do not confuse with ConstrainedOperator, which despite the similar name
    has very different functionality.

    The height and width of this object as an IterativeSolver are for
    the above saddle point system, but one can use its PrimalMult() method
    to solve just \f$ Ax = f \f$ subject to a constraint with \f$ r \f$
    defaulting to zero or set via SetConstraintRHS().

    This abstract object unifies handling of the "dual" rhs \f$ r \f$
    and the Lagrange multiplier solution \f$ \lambda \f$, so that derived
    classses can reuse that code. */
class ConstrainedSolver : public IterativeSolver
{
public:
#ifdef MFEM_USE_MPI
   ConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_);
#endif
   ConstrainedSolver(Operator& A_, Operator& B_);

   virtual ~ConstrainedSolver() { }

   virtual void SetOperator(const Operator& op) override { }

   /** @brief Set the right-hand side r for the constraint B x = r

       (r defaults to zero if you don't call this) */
   virtual void SetConstraintRHS(const Vector& r);

   /** @brief Return the Lagrange multiplier solution in lambda

       PrimalMult() only gives you x, this provides access to lambda

       Does not make sense unless you've already solved the constrained
       system with Mult() or PrimalMult() */
   void GetMultiplierSolution(Vector& lambda) const { lambda = multiplier_sol; }

   /** @brief Solve for \f$ x \f$ given \f$ f \f$.

       If you want to set \f$ r \f$, call SetConstraintRHS() before this.

       If you want to get \f$ \lambda \f$, call GetMultiplierSolution() after
       this.

       The base class implementation calls Mult(), so derived classes must
       implement either this or Mult() */
   virtual void PrimalMult(const Vector& f, Vector& x) const;

   /** @brief Solve for (x, lambda) given (f, r)

       The base class implementation calls PrimalMult(), so derived classes
       must implement either this or PrimalMult() */
   virtual void Mult(const Vector& f_and_r, Vector& x_and_lambda) const override;

protected:
   Operator& A;
   Operator& B;

   mutable Vector constraint_rhs;
   mutable Vector multiplier_sol;
   mutable Vector workb;
   mutable Vector workx;

private:
   void Initialize();
};

/** @brief Perform elimination of a single constraint.

    See EliminationProjection, EliminationCGSolver

    This keeps track of primary / secondary tdofs and does small dense block
    solves to eliminate constraints from a global system.

    \f$ B_s^{-1} \f$ maps the lagrange space into secondary dofs, while
    \f$ -B_s^{-1} B_p \f$ maps primary dofs to secondary dofs. */
class Eliminator
{
public:
   Eliminator(const SparseMatrix& B, const Array<int>& lagrange_dofs,
              const Array<int>& primary_tdofs,
              const Array<int>& secondary_tdofs);

   const Array<int>& LagrangeDofs() const { return lagrange_tdofs; }
   const Array<int>& PrimaryDofs() const { return primary_tdofs; }
   const Array<int>& SecondaryDofs() const { return secondary_tdofs; }

   /// Given primary displacements, return secondary displacements
   /// This applies \f$ -B_s^{-1} B_p \f$.
   void Eliminate(const Vector& in, Vector& out) const;

   /// Transpose of Eliminate(), applies \f$ -B_p^T B_s^{-T} \f$
   void EliminateTranspose(const Vector& in, Vector& out) const;

   /// Maps Lagrange multipliers to secondary displacements,
   /// applies \f$ B_s^{-1} \f$
   void LagrangeSecondary(const Vector& in, Vector& out) const;

   /// Transpose of LagrangeSecondary()
   void LagrangeSecondaryTranspose(const Vector& in, Vector& out) const;

   /// Return \f$ -B_s^{-1} B_p \f$ explicitly assembled in mat
   void ExplicitAssembly(DenseMatrix& mat) const;

private:
   Array<int> lagrange_tdofs;
   Array<int> primary_tdofs;
   Array<int> secondary_tdofs;

   DenseMatrix Bp;
   DenseMatrix Bs;  // gets inverted in place
   LUFactors Bsinverse;
   DenseMatrix BsT;   // gets inverted in place
   LUFactors BsTinverse;
   Array<int> ipiv;
   Array<int> ipivT;
};

/** Collects action of several Eliminator objects to perform elimination of
    constraints.

    Works in parallel, but each Eliminator must be processor local, and must
    operate on disjoint degrees of freedom (ie, the primary and secondary dofs
    for one Eliminator must have no overlap with any dofs from a different
    Eliminator). */
class EliminationProjection : public Operator
{
public:
   EliminationProjection(const Operator& A, Array<Eliminator*>& eliminators);

   void Mult(const Vector& x, Vector& y) const override;

   void MultTranspose(const Vector& x, Vector& y) const override;

   /** @brief Assemble this projector as a (processor-local) SparseMatrix.

       Some day we may also want to try approximate variants. */
   SparseMatrix * AssembleExact() const;

   /** Given Lagrange multiplier right-hand-side \f$ g \f$, return
       \f$ \tilde{g} \f$ */
   void BuildGTilde(const Vector& g, Vector& gtilde) const;

   /** After a solve, recover the Lagrange multiplier. */
   void RecoverMultiplier(const Vector& disprhs,
                          const Vector& disp, Vector& lm) const;

private:
   const Operator& Aop;
   Array<Eliminator*> eliminators;
};

#ifdef MFEM_USE_MPI
/** @brief Solve constrained system by eliminating the constraint; see
    ConstrainedSolver

    Solves the system with the operator \f$ P^T A P + Z_P \f$, where P is
    EliminationProjection and Z_P is the identity on the eliminated dofs. */
class EliminationSolver : public ConstrainedSolver
{
public:
   /** @brief Constructor, with explicit splitting into primary/secondary dofs.

       This constructor uses a single elimination block (per processor), which
       provides the most general algorithm but is also not scalable

       The secondary_dofs are eliminated from the system in this algorithm,
       as they can be written in terms of the primary_dofs. */
   EliminationSolver(HypreParMatrix& A, SparseMatrix& B,
                     Array<int>& primary_dofs,
                     Array<int>& secondary_dofs);

   /** @brief Constructor, elimination is by blocks.

       The nonzeros in B are assumed to be in disjoint rows and columns; the
       rows are identified with the constraint_rowstarts array, the secondary
       dofs are assumed to be the first nonzeros in the rows. */
   EliminationSolver(HypreParMatrix& A, SparseMatrix& B,
                     Array<int>& constraint_rowstarts);

   ~EliminationSolver();

   void PrimalMult(const Vector& x, Vector& y) const override;

protected:
   /// Internal utility routine; assembles eliminated matrix explicitly
   void BuildExplicitOperator();

   /// Build preconditioner for eliminated system
   virtual Solver* BuildPreconditioner() const = 0;
   /// Select krylov solver for eliminated system
   virtual IterativeSolver* BuildKrylov() const = 0;

   HypreParMatrix& hA;
   Array<Eliminator*> eliminators;
   EliminationProjection * projector;
   HypreParMatrix * h_explicit_operator;
   mutable Solver* prec;
};

/** EliminationSolver using CG and HypreBoomerAMG */
class EliminationCGSolver : public EliminationSolver
{
public:
   EliminationCGSolver(HypreParMatrix& A, SparseMatrix& B,
                       Array<int>& constraint_rowstarts,
                       int dimension_=0, bool reorder_=false) :
      EliminationSolver(A, B, constraint_rowstarts),
      dimension(dimension_), reorder(reorder_)
   { BuildExplicitOperator(); }

protected:
   virtual Solver* BuildPreconditioner() const override
   {
      HypreBoomerAMG * h_prec = new HypreBoomerAMG(*h_explicit_operator);
      h_prec->SetPrintLevel(0);
      if (dimension > 0) { h_prec->SetSystemsOptions(dimension, reorder); }
      return h_prec;
   }

   virtual IterativeSolver* BuildKrylov() const override
   { return new CGSolver(GetComm()); }

private:
   int dimension;
   bool reorder;
};

/** @brief Solve constrained system with penalty method; see ConstrainedSolver.

    Only approximates the solution, better approximation with higher penalty,
    but with higher penalty the preconditioner is less effective. */
class PenaltyConstrainedSolver : public ConstrainedSolver
{
public:
   PenaltyConstrainedSolver(HypreParMatrix& A, SparseMatrix& B,
                            double penalty_);

   PenaltyConstrainedSolver(HypreParMatrix& A, HypreParMatrix& B,
                            double penalty_);

   ~PenaltyConstrainedSolver();

   void PrimalMult(const Vector& x, Vector& y) const override;

protected:
   void Initialize(HypreParMatrix& A, HypreParMatrix& B);

   /// Build preconditioner for penalized system
   virtual Solver* BuildPreconditioner() const = 0;
   /// Select krylov solver for penalized system
   virtual IterativeSolver* BuildKrylov() const = 0;

   double penalty;
   Operator& constraintB;
   HypreParMatrix * penalized_mat;
   mutable Solver * prec;
};

/** Uses CG and a HypreBoomerAMG preconditioner for the penalized system. */
class PenaltyPCGSolver : public PenaltyConstrainedSolver
{
public:
   PenaltyPCGSolver(HypreParMatrix& A, SparseMatrix& B, double penalty_,
                    int dimension=0, bool reorder=false) :
      PenaltyConstrainedSolver(A, B, penalty_),
      dimension_(dimension), reorder_(reorder)
   { }

   PenaltyPCGSolver(HypreParMatrix& A, HypreParMatrix& B, double penalty_,
                    int dimension=0, bool reorder=false) :
      PenaltyConstrainedSolver(A, B, penalty_),
      dimension_(dimension), reorder_(reorder)
   { }

protected:
   virtual Solver* BuildPreconditioner() const override
   {
      HypreBoomerAMG* h_prec = new HypreBoomerAMG(*penalized_mat);
      h_prec->SetPrintLevel(0);
      if (dimension_ > 0) { h_prec->SetSystemsOptions(dimension_, reorder_); }
      return h_prec;
   }

   virtual IterativeSolver* BuildKrylov() const override
   { return new CGSolver(GetComm()); }

private:
   int dimension_;
   bool reorder_;
};

#endif

/** @brief Solve constrained system by solving original mixed sysetm;
    see ConstrainedSolver.

    Solves the saddle-point problem with a block-diagonal preconditioner, with
    user-provided preconditioner in the top-left block and (by default) an
    identity matrix in the bottom-right.

    This is the most general ConstrainedSolver, needing only Operator objects
    to function. But in general it is not very efficient or scalable. */
class SchurConstrainedSolver : public ConstrainedSolver
{
public:
   /// Setup constrained system, with primal_pc a user-provided preconditioner
   /// for the top-left block.
#ifdef MFEM_USE_MPI
   SchurConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_,
                          Solver& primal_pc_);
#endif
   SchurConstrainedSolver(Operator& A_, Operator& B_, Solver& primal_pc_);
   virtual ~SchurConstrainedSolver();

   virtual void Mult(const Vector& x, Vector& y) const override;

protected:
#ifdef MFEM_USE_MPI
   SchurConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_);
#endif
   SchurConstrainedSolver(Operator& A_, Operator& B_);

   Array<int> offsets;
   BlockOperator * block_op;  // owned
   TransposeOperator * tr_B;  // owned
   Solver * primal_pc; // NOT owned
   BlockDiagonalPreconditioner * block_pc;  // owned
   Solver * dual_pc;  // owned

private:
   void Initialize();
};

#ifdef MFEM_USE_MPI
/** @brief Basic saddle-point solver with assembled blocks (ie, the
    operators are assembled HypreParMatrix objects.)

    This uses a block-diagonal preconditioner that approximates
    \f$ [ A^{-1} 0; 0 (B A^{-1} B^T)^{-1} ] \f$.

    In the top-left block, we approximate \f$ A^{-1} \f$ with HypreBoomerAMG.
    In the bottom-right, we approximate \f$ A^{-1} \f$ with the inverse of the
    diagonal of \f$ A \f$, assemble \f$ B D^{-1} B^T \f$, and use
    HypreBoomerAMG on that assembled matrix. */
class SchurConstrainedHypreSolver : public SchurConstrainedSolver
{
public:
   SchurConstrainedHypreSolver(MPI_Comm comm, HypreParMatrix& hA_,
                               HypreParMatrix& hB_, int dimension=0,
                               bool reorder=false);
   virtual ~SchurConstrainedHypreSolver();

private:
   HypreParMatrix& hA;
   HypreParMatrix& hB;
   HypreParMatrix * schur_mat;
};
#endif

}

#endif
<commit_msg>Even clearer differentiation of ConstrainedSolver from ConstrainedOperator in documenation.<commit_after>// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#ifndef MFEM_CONSTRAINED
#define MFEM_CONSTRAINED

#include "solvers.hpp"
#include "blockoperator.hpp"
#include "sparsemat.hpp"
#include "hypre.hpp"

namespace mfem
{

class ParFiniteElementSpace;

/** @brief An abstract class to solve the constrained system \f$ Ax = f \f$
    subject to the constraint \f$ B x = r \f$.

    Although implementations may not use the below formulation, for
    understanding some of its methods and notation you can think of
    it as solving the saddle-point system

     (  A   B^T  )  ( x )          (  f  )
     (  B        )  ( lambda )  =  (  r  )

    Do not confuse with ConstrainedOperator, which handles only simple
    pointwise constraints and is not a Solver.

    The height and width of this object as an IterativeSolver are for
    the above saddle point system, but one can use its PrimalMult() method
    to solve just \f$ Ax = f \f$ subject to a constraint with \f$ r \f$
    defaulting to zero or set via SetConstraintRHS().

    This abstract object unifies handling of the "dual" rhs \f$ r \f$
    and the Lagrange multiplier solution \f$ \lambda \f$, so that derived
    classses can reuse that code. */
class ConstrainedSolver : public IterativeSolver
{
public:
#ifdef MFEM_USE_MPI
   ConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_);
#endif
   ConstrainedSolver(Operator& A_, Operator& B_);

   virtual ~ConstrainedSolver() { }

   virtual void SetOperator(const Operator& op) override { }

   /** @brief Set the right-hand side r for the constraint B x = r

       (r defaults to zero if you don't call this) */
   virtual void SetConstraintRHS(const Vector& r);

   /** @brief Return the Lagrange multiplier solution in lambda

       PrimalMult() only gives you x, this provides access to lambda

       Does not make sense unless you've already solved the constrained
       system with Mult() or PrimalMult() */
   void GetMultiplierSolution(Vector& lambda) const { lambda = multiplier_sol; }

   /** @brief Solve for \f$ x \f$ given \f$ f \f$.

       If you want to set \f$ r \f$, call SetConstraintRHS() before this.

       If you want to get \f$ \lambda \f$, call GetMultiplierSolution() after
       this.

       The base class implementation calls Mult(), so derived classes must
       implement either this or Mult() */
   virtual void PrimalMult(const Vector& f, Vector& x) const;

   /** @brief Solve for (x, lambda) given (f, r)

       The base class implementation calls PrimalMult(), so derived classes
       must implement either this or PrimalMult() */
   virtual void Mult(const Vector& f_and_r, Vector& x_and_lambda) const override;

protected:
   Operator& A;
   Operator& B;

   mutable Vector constraint_rhs;
   mutable Vector multiplier_sol;
   mutable Vector workb;
   mutable Vector workx;

private:
   void Initialize();
};

/** @brief Perform elimination of a single constraint.

    See EliminationProjection, EliminationCGSolver

    This keeps track of primary / secondary tdofs and does small dense block
    solves to eliminate constraints from a global system.

    \f$ B_s^{-1} \f$ maps the lagrange space into secondary dofs, while
    \f$ -B_s^{-1} B_p \f$ maps primary dofs to secondary dofs. */
class Eliminator
{
public:
   Eliminator(const SparseMatrix& B, const Array<int>& lagrange_dofs,
              const Array<int>& primary_tdofs,
              const Array<int>& secondary_tdofs);

   const Array<int>& LagrangeDofs() const { return lagrange_tdofs; }
   const Array<int>& PrimaryDofs() const { return primary_tdofs; }
   const Array<int>& SecondaryDofs() const { return secondary_tdofs; }

   /// Given primary displacements, return secondary displacements
   /// This applies \f$ -B_s^{-1} B_p \f$.
   void Eliminate(const Vector& in, Vector& out) const;

   /// Transpose of Eliminate(), applies \f$ -B_p^T B_s^{-T} \f$
   void EliminateTranspose(const Vector& in, Vector& out) const;

   /// Maps Lagrange multipliers to secondary displacements,
   /// applies \f$ B_s^{-1} \f$
   void LagrangeSecondary(const Vector& in, Vector& out) const;

   /// Transpose of LagrangeSecondary()
   void LagrangeSecondaryTranspose(const Vector& in, Vector& out) const;

   /// Return \f$ -B_s^{-1} B_p \f$ explicitly assembled in mat
   void ExplicitAssembly(DenseMatrix& mat) const;

private:
   Array<int> lagrange_tdofs;
   Array<int> primary_tdofs;
   Array<int> secondary_tdofs;

   DenseMatrix Bp;
   DenseMatrix Bs;  // gets inverted in place
   LUFactors Bsinverse;
   DenseMatrix BsT;   // gets inverted in place
   LUFactors BsTinverse;
   Array<int> ipiv;
   Array<int> ipivT;
};

/** Collects action of several Eliminator objects to perform elimination of
    constraints.

    Works in parallel, but each Eliminator must be processor local, and must
    operate on disjoint degrees of freedom (ie, the primary and secondary dofs
    for one Eliminator must have no overlap with any dofs from a different
    Eliminator). */
class EliminationProjection : public Operator
{
public:
   EliminationProjection(const Operator& A, Array<Eliminator*>& eliminators);

   void Mult(const Vector& x, Vector& y) const override;

   void MultTranspose(const Vector& x, Vector& y) const override;

   /** @brief Assemble this projector as a (processor-local) SparseMatrix.

       Some day we may also want to try approximate variants. */
   SparseMatrix * AssembleExact() const;

   /** Given Lagrange multiplier right-hand-side \f$ g \f$, return
       \f$ \tilde{g} \f$ */
   void BuildGTilde(const Vector& g, Vector& gtilde) const;

   /** After a solve, recover the Lagrange multiplier. */
   void RecoverMultiplier(const Vector& disprhs,
                          const Vector& disp, Vector& lm) const;

private:
   const Operator& Aop;
   Array<Eliminator*> eliminators;
};

#ifdef MFEM_USE_MPI
/** @brief Solve constrained system by eliminating the constraint; see
    ConstrainedSolver

    Solves the system with the operator \f$ P^T A P + Z_P \f$, where P is
    EliminationProjection and Z_P is the identity on the eliminated dofs. */
class EliminationSolver : public ConstrainedSolver
{
public:
   /** @brief Constructor, with explicit splitting into primary/secondary dofs.

       This constructor uses a single elimination block (per processor), which
       provides the most general algorithm but is also not scalable

       The secondary_dofs are eliminated from the system in this algorithm,
       as they can be written in terms of the primary_dofs. */
   EliminationSolver(HypreParMatrix& A, SparseMatrix& B,
                     Array<int>& primary_dofs,
                     Array<int>& secondary_dofs);

   /** @brief Constructor, elimination is by blocks.

       The nonzeros in B are assumed to be in disjoint rows and columns; the
       rows are identified with the constraint_rowstarts array, the secondary
       dofs are assumed to be the first nonzeros in the rows. */
   EliminationSolver(HypreParMatrix& A, SparseMatrix& B,
                     Array<int>& constraint_rowstarts);

   ~EliminationSolver();

   void PrimalMult(const Vector& x, Vector& y) const override;

protected:
   /// Internal utility routine; assembles eliminated matrix explicitly
   void BuildExplicitOperator();

   /// Build preconditioner for eliminated system
   virtual Solver* BuildPreconditioner() const = 0;
   /// Select krylov solver for eliminated system
   virtual IterativeSolver* BuildKrylov() const = 0;

   HypreParMatrix& hA;
   Array<Eliminator*> eliminators;
   EliminationProjection * projector;
   HypreParMatrix * h_explicit_operator;
   mutable Solver* prec;
};

/** EliminationSolver using CG and HypreBoomerAMG */
class EliminationCGSolver : public EliminationSolver
{
public:
   EliminationCGSolver(HypreParMatrix& A, SparseMatrix& B,
                       Array<int>& constraint_rowstarts,
                       int dimension_=0, bool reorder_=false) :
      EliminationSolver(A, B, constraint_rowstarts),
      dimension(dimension_), reorder(reorder_)
   { BuildExplicitOperator(); }

protected:
   virtual Solver* BuildPreconditioner() const override
   {
      HypreBoomerAMG * h_prec = new HypreBoomerAMG(*h_explicit_operator);
      h_prec->SetPrintLevel(0);
      if (dimension > 0) { h_prec->SetSystemsOptions(dimension, reorder); }
      return h_prec;
   }

   virtual IterativeSolver* BuildKrylov() const override
   { return new CGSolver(GetComm()); }

private:
   int dimension;
   bool reorder;
};

/** @brief Solve constrained system with penalty method; see ConstrainedSolver.

    Only approximates the solution, better approximation with higher penalty,
    but with higher penalty the preconditioner is less effective. */
class PenaltyConstrainedSolver : public ConstrainedSolver
{
public:
   PenaltyConstrainedSolver(HypreParMatrix& A, SparseMatrix& B,
                            double penalty_);

   PenaltyConstrainedSolver(HypreParMatrix& A, HypreParMatrix& B,
                            double penalty_);

   ~PenaltyConstrainedSolver();

   void PrimalMult(const Vector& x, Vector& y) const override;

protected:
   void Initialize(HypreParMatrix& A, HypreParMatrix& B);

   /// Build preconditioner for penalized system
   virtual Solver* BuildPreconditioner() const = 0;
   /// Select krylov solver for penalized system
   virtual IterativeSolver* BuildKrylov() const = 0;

   double penalty;
   Operator& constraintB;
   HypreParMatrix * penalized_mat;
   mutable Solver * prec;
};

/** Uses CG and a HypreBoomerAMG preconditioner for the penalized system. */
class PenaltyPCGSolver : public PenaltyConstrainedSolver
{
public:
   PenaltyPCGSolver(HypreParMatrix& A, SparseMatrix& B, double penalty_,
                    int dimension=0, bool reorder=false) :
      PenaltyConstrainedSolver(A, B, penalty_),
      dimension_(dimension), reorder_(reorder)
   { }

   PenaltyPCGSolver(HypreParMatrix& A, HypreParMatrix& B, double penalty_,
                    int dimension=0, bool reorder=false) :
      PenaltyConstrainedSolver(A, B, penalty_),
      dimension_(dimension), reorder_(reorder)
   { }

protected:
   virtual Solver* BuildPreconditioner() const override
   {
      HypreBoomerAMG* h_prec = new HypreBoomerAMG(*penalized_mat);
      h_prec->SetPrintLevel(0);
      if (dimension_ > 0) { h_prec->SetSystemsOptions(dimension_, reorder_); }
      return h_prec;
   }

   virtual IterativeSolver* BuildKrylov() const override
   { return new CGSolver(GetComm()); }

private:
   int dimension_;
   bool reorder_;
};

#endif

/** @brief Solve constrained system by solving original mixed sysetm;
    see ConstrainedSolver.

    Solves the saddle-point problem with a block-diagonal preconditioner, with
    user-provided preconditioner in the top-left block and (by default) an
    identity matrix in the bottom-right.

    This is the most general ConstrainedSolver, needing only Operator objects
    to function. But in general it is not very efficient or scalable. */
class SchurConstrainedSolver : public ConstrainedSolver
{
public:
   /// Setup constrained system, with primal_pc a user-provided preconditioner
   /// for the top-left block.
#ifdef MFEM_USE_MPI
   SchurConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_,
                          Solver& primal_pc_);
#endif
   SchurConstrainedSolver(Operator& A_, Operator& B_, Solver& primal_pc_);
   virtual ~SchurConstrainedSolver();

   virtual void Mult(const Vector& x, Vector& y) const override;

protected:
#ifdef MFEM_USE_MPI
   SchurConstrainedSolver(MPI_Comm comm, Operator& A_, Operator& B_);
#endif
   SchurConstrainedSolver(Operator& A_, Operator& B_);

   Array<int> offsets;
   BlockOperator * block_op;  // owned
   TransposeOperator * tr_B;  // owned
   Solver * primal_pc; // NOT owned
   BlockDiagonalPreconditioner * block_pc;  // owned
   Solver * dual_pc;  // owned

private:
   void Initialize();
};

#ifdef MFEM_USE_MPI
/** @brief Basic saddle-point solver with assembled blocks (ie, the
    operators are assembled HypreParMatrix objects.)

    This uses a block-diagonal preconditioner that approximates
    \f$ [ A^{-1} 0; 0 (B A^{-1} B^T)^{-1} ] \f$.

    In the top-left block, we approximate \f$ A^{-1} \f$ with HypreBoomerAMG.
    In the bottom-right, we approximate \f$ A^{-1} \f$ with the inverse of the
    diagonal of \f$ A \f$, assemble \f$ B D^{-1} B^T \f$, and use
    HypreBoomerAMG on that assembled matrix. */
class SchurConstrainedHypreSolver : public SchurConstrainedSolver
{
public:
   SchurConstrainedHypreSolver(MPI_Comm comm, HypreParMatrix& hA_,
                               HypreParMatrix& hB_, int dimension=0,
                               bool reorder=false);
   virtual ~SchurConstrainedHypreSolver();

private:
   HypreParMatrix& hA;
   HypreParMatrix& hB;
   HypreParMatrix * schur_mat;
};
#endif

}

#endif
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <common/EFUArgs.h>
#include <test/TestBase.h>

class EFUArgsTest : public TestBase {};

TEST_F(EFUArgsTest, Constructor) {
  EFUArgs efu_args;
  auto settings = efu_args.GetBaseSettings();

  // ASSERT_EQ(12, settings.cpustart); /**< todo fixme */
  ASSERT_EQ("0.0.0.0", settings.DetectorAddress);
  ASSERT_EQ(9000, settings.DetectorPort);
  ASSERT_EQ("localhost:9092", settings.KafkaBroker);
  ASSERT_EQ("127.0.0.1", settings.GraphiteAddress);
  ASSERT_EQ(2003, settings.GraphitePort);
  ASSERT_EQ(0xffffffffU, settings.StopAfterSec);
}

TEST_F(EFUArgsTest, VerifyCommandLineOptions) {

  // clang-format off
  const char *myargv[] = {"progname",
                        "-b", "mybroker:9091",
                        "-c" , "99",
                        "-d", "myinst",
                        "-i", "1.2.3.4",
                        "-p", "9876",
                        "-g", "4.3.2.1",
                        "-o", "2323",
                        "-s", "5",
                        "-a", "10.0.0.1",
                        "-m", "8989" };
  // clang-format on
  int myargc = 21;
  EFUArgs efu_args;
  auto ret = efu_args.parseAndProceed(myargc, (char **)myargv);
  ASSERT_EQ(ret, true); // has detector
  auto settings = efu_args.GetBaseSettings();
  auto glsettings = efu_args.getGraylogSettings();

  ASSERT_EQ("mybroker:9091", settings.KafkaBroker);
  // ASSERT_EQ(99, opts.cpustart); /**< todo fixme */
  ASSERT_EQ("myinst", settings.DetectorPluginName);
  ASSERT_EQ("1.2.3.4", settings.DetectorAddress);
  ASSERT_EQ(9876, settings.DetectorPort);
  ASSERT_EQ("4.3.2.1", settings.GraphiteAddress);
  ASSERT_EQ(2323, settings.GraphitePort);
  ASSERT_EQ(5, settings.StopAfterSec);
  ASSERT_EQ("10.0.0.1", glsettings.address);
  ASSERT_EQ(8989, settings.CommandServerPort);
}

TEST_F(EFUArgsTest, HelpText) {
  int myargc = 2;
  const char *myargv[] = {"progname", "-h"};

  EFUArgs efu_args;
  auto ret = efu_args.parseAndProceed(myargc, (char **)myargv);
  ASSERT_EQ(ret, false); // has detector

  ASSERT_EQ(myargc, 2);
  ASSERT_TRUE(myargv != NULL);
}

TEST_F(EFUArgsTest, XTRACE_Text) {
  EFUArgs efu_args;
  MESSAGE() << "This is not a test, just ensuring printout is done once\n" ;
  efu_args.printSettings();
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>pre merge commit - working on EFUArgsTest<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <common/EFUArgs.h>
#include <test/TestBase.h>

class EFUArgsTest : public TestBase {};

TEST_F(EFUArgsTest, Constructor) {
  EFUArgs efu_args;
  auto settings = efu_args.GetBaseSettings();

  // ASSERT_EQ(12, settings.cpustart); /**< todo fixme */
  ASSERT_EQ("0.0.0.0", settings.DetectorAddress);
  ASSERT_EQ(9000, settings.DetectorPort);
  ASSERT_EQ("localhost:9092", settings.KafkaBroker);
  ASSERT_EQ("127.0.0.1", settings.GraphiteAddress);
  ASSERT_EQ(2003, settings.GraphitePort);
  ASSERT_EQ(0xffffffffU, settings.StopAfterSec);
}

TEST_F(EFUArgsTest, VerifyCommandLineOptions) {

  // clang-format off
  const char *myargv[] = {"progname",
                        "-b", "mybroker:9091",
                        "-c" , "99",
                        "-d", "myinst",
                        "-i", "1.2.3.4",
                        "-p", "9876",
                        "-g", "4.3.2.1",
                        "-o", "2323",
                        "-s", "5",
                        "-a", "10.0.0.1",
                        "-m", "8989" };
  // clang-format on
  int myargc = 21;
  EFUArgs efu_args;
  auto ret = efu_args.parseAndProceed(myargc, (char **)myargv);
  ASSERT_EQ(ret, true); // has detector
  auto settings = efu_args.GetBaseSettings();
  auto glsettings = efu_args.getGraylogSettings();

  ASSERT_EQ("mybroker:9091", settings.KafkaBroker);
  // ASSERT_EQ(99, opts.cpustart); /**< todo fixme */
  ASSERT_EQ("myinst", settings.DetectorPluginName);
  ASSERT_EQ("1.2.3.4", settings.DetectorAddress);
  ASSERT_EQ(9876, settings.DetectorPort);
  ASSERT_EQ("4.3.2.1", settings.GraphiteAddress);
  ASSERT_EQ(2323, settings.GraphitePort);
  ASSERT_EQ(5, settings.StopAfterSec);
  ASSERT_EQ("10.0.0.1", glsettings.address);
  ASSERT_EQ(8989, settings.CommandServerPort);
}

TEST_F(EFUArgsTest, HelpText) {
  int myargc = 2;
  const char *myargv[] = {"progname", "-h"};

  EFUArgs efu_args;
  auto ret = efu_args.parseAndProceed(myargc, (char **)myargv);
  ASSERT_EQ(ret, false); // has detector

  ASSERT_EQ(myargc, 2);
  ASSERT_TRUE(myargv != NULL);
}

TEST_F(EFUArgsTest, CoreAffinityOption) {
  int myargc = 5;
  const char *myargv[] = {"progname", "-d", "dummydetector", "-c", "thread1:5"};

  EFUArgs efu_args;
  auto ret = efu_args.parseAndProceed(myargc, (char **)myargv);
  ASSERT_EQ(ret, false); // has detector

  ASSERT_EQ(myargc, 5);
  ASSERT_TRUE(myargv != NULL);
}

TEST_F(EFUArgsTest, PrintHelpText) {
  EFUArgs efu_args;
  MESSAGE() << "This is not a test, just ensuring printout is done once\n" ;
  efu_args.printHelp();
}

TEST_F(EFUArgsTest, XTRACE_Text) {
  EFUArgs efu_args;
  MESSAGE() << "This is not a test, just ensuring printout is done once\n" ;
  efu_args.printSettings();
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "kugouwindow.h"

#ifdef MUSIC_WEBKIT
# if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#  include <QtWebKitWidgets/QWebView>
#  include <QtWebKitWidgets/QWebFrame>
# else
#  include <QWebView>
#  include <QWebFrame>
# endif
#endif
#include <QLabel>
#include <QBoxLayout>
#include <QPushButton>
#include <QButtonGroup>

KugouWindow::KugouWindow(QWidget *parent)
    : QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
#ifdef MUSIC_WEBKIT
    const QString radioStyle = "QPushButton{ border:none; color:rgb(135, 135, 135);} \
                                QPushButton:hover{ color:rgb(104, 169, 236);} \
                                QPushButton:checked{ color:rgb(40, 143, 231);} \
                                QWidget{background: white;}";
    QWidget *top = new QWidget(this);
    top->setFixedHeight(25);
    top->setStyleSheet( radioStyle );
    QHBoxLayout *topLayout = new QHBoxLayout(top);
    topLayout->setContentsMargins(0, 0, 0, 0);

    QButtonGroup *buttonGroup = new QButtonGroup(this);
    QPushButton *bt = new QPushButton(tr(" Recommend "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 0);
    bt = new QPushButton(tr(" Radio "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 1);
    bt = new QPushButton(tr(" Rank "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 2);
    bt = new QPushButton(tr(" Singer "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 3);
    bt = new QPushButton(tr(" Category "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 4);
    bt = new QPushButton(tr(" Show "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 5);
    bt = new QPushButton(tr(" CCTV "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 6);
    connect(buttonGroup, SIGNAL(buttonClicked(int)), SLOT(differButtonIndexChanged(int)));

    topLayout->addStretch(1);
    topLayout->addWidget(buttonGroup->button(0));
    topLayout->addWidget(buttonGroup->button(1));
    topLayout->addWidget(buttonGroup->button(2));
    topLayout->addWidget(buttonGroup->button(3));
    topLayout->addWidget(buttonGroup->button(4));
    topLayout->addWidget(buttonGroup->button(5));
    topLayout->addWidget(buttonGroup->button(6));
    topLayout->addStretch(1);

    QWebView *view = new QWebView(this);
    view->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    view->setUrl(QUrl( KugouUrl::getRecommendUrl() ));

    layout->addWidget(top);
    layout->addWidget(m_webView = view);
#else
    QLabel *pix = new QLabel(this);
    pix->setPixmap(QPixmap(":/image/nowebkit"));
    layout->addWidget(pix);
#endif
    setLayout(layout);
}

KugouWindow::~KugouWindow()
{
    delete m_webView;
}

QString KugouWindow::getClassName()
{
    return staticMetaObject.className();
}

void KugouWindow::differButtonIndexChanged(int index)
{
    QString url = KugouUrl::getRecommendUrl();
    switch(index)
    {
        case 0: url = KugouUrl::getRecommendUrl(); break;
        case 1: url = KugouUrl::getRadioUrl(); break;
        case 2: url = KugouUrl::getRankUrl(); break;
        case 3: url = KugouUrl::getSingerUrl(); break;
        case 4: url = KugouUrl::getCategoryUrl(); break;
        case 5: url = KugouUrl::getShowUrl(); break;
        case 6: url = KugouUrl::getCCTVUrl(); break;
    }
#ifdef MUSIC_WEBKIT
    static_cast<QWebView*>(m_webView)->setUrl(QUrl( url ));
#endif
}
<commit_msg>set pointer to null while no macro effected[741258]<commit_after>#include "kugouwindow.h"

#ifdef MUSIC_WEBKIT
# if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#  include <QtWebKitWidgets/QWebView>
#  include <QtWebKitWidgets/QWebFrame>
# else
#  include <QWebView>
#  include <QWebFrame>
# endif
#endif
#include <QLabel>
#include <QBoxLayout>
#include <QPushButton>
#include <QButtonGroup>

KugouWindow::KugouWindow(QWidget *parent)
    : QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
#ifdef MUSIC_WEBKIT
    const QString radioStyle = "QPushButton{ border:none; color:rgb(135, 135, 135);} \
                                QPushButton:hover{ color:rgb(104, 169, 236);} \
                                QPushButton:checked{ color:rgb(40, 143, 231);} \
                                QWidget{background: white;}";
    QWidget *top = new QWidget(this);
    top->setFixedHeight(25);
    top->setStyleSheet( radioStyle );
    QHBoxLayout *topLayout = new QHBoxLayout(top);
    topLayout->setContentsMargins(0, 0, 0, 0);

    QButtonGroup *buttonGroup = new QButtonGroup(this);
    QPushButton *bt = new QPushButton(tr(" Recommend "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 0);
    bt = new QPushButton(tr(" Radio "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 1);
    bt = new QPushButton(tr(" Rank "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 2);
    bt = new QPushButton(tr(" Singer "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 3);
    bt = new QPushButton(tr(" Category "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 4);
    bt = new QPushButton(tr(" Show "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 5);
    bt = new QPushButton(tr(" CCTV "), top);
    bt->setCursor(QCursor(Qt::PointingHandCursor));
    buttonGroup->addButton(bt, 6);
    connect(buttonGroup, SIGNAL(buttonClicked(int)), SLOT(differButtonIndexChanged(int)));

    topLayout->addStretch(1);
    topLayout->addWidget(buttonGroup->button(0));
    topLayout->addWidget(buttonGroup->button(1));
    topLayout->addWidget(buttonGroup->button(2));
    topLayout->addWidget(buttonGroup->button(3));
    topLayout->addWidget(buttonGroup->button(4));
    topLayout->addWidget(buttonGroup->button(5));
    topLayout->addWidget(buttonGroup->button(6));
    topLayout->addStretch(1);

    QWebView *view = new QWebView(this);
    view->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    view->setUrl(QUrl( KugouUrl::getRecommendUrl() ));

    layout->addWidget(top);
    layout->addWidget(m_webView = view);
#else
    m_webView = nullptr;
    QLabel *pix = new QLabel(this);
    pix->setPixmap(QPixmap(":/image/nowebkit"));
    layout->addWidget(pix);
#endif
    setLayout(layout);
}

KugouWindow::~KugouWindow()
{
    delete m_webView;
}

QString KugouWindow::getClassName()
{
    return staticMetaObject.className();
}

void KugouWindow::differButtonIndexChanged(int index)
{
    QString url = KugouUrl::getRecommendUrl();
    switch(index)
    {
        case 0: url = KugouUrl::getRecommendUrl(); break;
        case 1: url = KugouUrl::getRadioUrl(); break;
        case 2: url = KugouUrl::getRankUrl(); break;
        case 3: url = KugouUrl::getSingerUrl(); break;
        case 4: url = KugouUrl::getCategoryUrl(); break;
        case 5: url = KugouUrl::getShowUrl(); break;
        case 6: url = KugouUrl::getCCTVUrl(); break;
    }
#ifdef MUSIC_WEBKIT
    static_cast<QWebView*>(m_webView)->setUrl(QUrl( url ));
#endif
}
<|endoftext|>