<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/*
 * mcbench is a program used to test the single frontend thread performance
 * on a memcached service
 */
#include "config.h"

#include <memcached/protocol_binary.h>

#include <getopt.h>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <string.h>
#include <list>
#include <vector>
#include <iostream>
#include <stdint.h>
#include <cassert>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <cerrno>
#include <chrono>
#include <thread>
#include <atomic>
#include <platform/platform.h>

class Connection;
static void thread_main(Connection *c);

class Connection {
public:
    Connection(const std::string &_host, const std::string &_port,
               uint8_t *sndbuf, size_t sndbufsz) :
        sendBuffer(sndbuf), sendBufferSize(sndbufsz),
        sendBufferOffset(0),
        sock(INVALID_SOCKET), host(_host), port(_port), currentOps(0)
    {
        currentOps.store(0, std::memory_order_release);
        recvBuffer.reserve(2 * 1024 * 1024);
    }

    void start() {
        running.store(true, std::memory_order_release);
        tid = std::thread(thread_main, this);
    }

    void stop() {
        running.store(false, std::memory_order_acquire);
        tid.join();

    }

    size_t getOpsPerSec() const {
        using namespace std::chrono;

        std::chrono::time_point<std::chrono::steady_clock> now;
        if (running) {
            now = steady_clock::now();
        } else {
            now = stopTime;
        }

        auto delta = duration_cast<seconds>(now - startTime).count();
        if (delta == 0) {
            return currentOps.load(std::memory_order_acquire);
        } else {
            return currentOps.load(std::memory_order_acquire) / delta;
        }
    }

    size_t getDuration() const {
        using namespace std::chrono;
        return duration_cast<seconds>(stopTime - startTime).count();
    }

    size_t getTotalOps() const {
        return currentOps.load(std::memory_order_acquire);
    }

    ~Connection() {
        if (sock != INVALID_SOCKET) {
            closesocket(sock);
        }
    }

protected:
    friend void thread_main(Connection *c);

    void run(void) {
        startTime = std::chrono::steady_clock::now();

        while (running.load(std::memory_order_acquire)) {
            if (sock == INVALID_SOCKET) {
                connect();
            }

            while (sock != INVALID_SOCKET && running.load(std::memory_order_acquire)) {
                struct pollfd fds[1];
                fds[0].fd = sock;
                if (toSend == 0) {
                    fds[0].events = POLLIN;
                } else {
                    fds[0].events = POLLIN | POLLOUT;
                }
                cb_assert(poll(fds, 1, -1) != -1);

                if (fds[0].revents & POLLIN) {
                    drainInput();
                } else if (fds[0].revents & POLLOUT) {
                    doSendData();
                } else {
                    // what is this?
                    abort();
                }
            }
        }
        stopTime = std::chrono::steady_clock::now();
    }

    /**
     * Try to connect to the server
     * @return false if we failed to connect to the server
     */
    bool connect(void)
    {
        struct addrinfo *ai = NULL;
        struct addrinfo hints;

        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_socktype = SOCK_STREAM;

        if (getaddrinfo(host.c_str(), port.c_str(), &hints, &ai) != 0) {
            return false;
        }

        struct addrinfo *e = ai;
        do {
            if ((sock = socket(e->ai_family, e->ai_socktype,
                               e->ai_protocol)) != -1) {
                if (::connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
                    close(sock);
                    sock = -1;
                }
            }
            if (sock == -1) {
                e = e->ai_next;
            } else {
                break;
            }
        } while (e) ;

        fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);

        freeaddrinfo(ai);

        sendBufferOffset = 0;
        toSend = sendBufferSize - sendBufferOffset;
        return true;
    }

    void drainInput(void) {
        ssize_t nr;
        size_t currsize = recvBuffer.size();
        recvBuffer.resize(2 * 1024 * 1024);
        while ((nr = recv(sock, recvBuffer.data() + currsize,
                          (2 * 1024 * 1024) - currsize, 0)) > 0) {
            /* Parse packets */
            recvBuffer.resize(currsize + nr);
            size_t size = recvBuffer.size();
            uint8_t *curr = recvBuffer.data();

            while (size > 24) {
                protocol_binary_response_no_extras *res;
                res = reinterpret_cast<protocol_binary_response_no_extras *>(curr);
                assert(res->message.header.response.magic == 0x81);
                uint32_t bodylen = ntohl(res->message.header.response.bodylen);

                if (size < (24 + bodylen)) {
                    break;
                }

                size -= (24 + bodylen);
                currentOps.fetch_add(1, std::memory_order_release);;
                curr += 24 + bodylen;
            }

            /* repack the buffer */
            memmove(recvBuffer.data(), curr, size);
            currsize = size;
            recvBuffer.resize(2 * 1024 * 1024);
        }

        recvBuffer.resize(currsize);

        if ((nr == -1 && errno != EWOULDBLOCK) || nr == 0) {
            close(sock);
            sock = -1;
        }
    }

    void doSendData(void) {
        ssize_t nw;
        cb_assert(toSend > 0);

        while ((nw = send(sock, sendBuffer+sendBufferOffset, toSend, 0)) > 0) {
            sendBufferOffset += nw;
            toSend = sendBufferSize - sendBufferOffset;
            if (toSend == 0) {
                sendBufferOffset = 0;
                toSend = sendBufferSize - sendBufferOffset;
            }
        }

        if (nw == -1 && errno != EWOULDBLOCK) {
            close(sock);
            sock = -1;
        }
    }

    uint8_t *sendBuffer;
    size_t toSend;
    size_t sendBufferSize;
    size_t sendBufferOffset;

    std::vector<uint8_t> recvBuffer;
    int sock;
    const std::string host;
    const std::string port;
    std::chrono::time_point<std::chrono::steady_clock> startTime;
    std::chrono::time_point<std::chrono::steady_clock> stopTime;
    std::atomic<size_t> currentOps;
    std::thread tid;
    std::atomic<bool> running;
};

static void thread_main(Connection *c)
{
    c->run();
}

static void buildSetStream(std::vector<uint8_t> &vector, size_t size) {
    /* preformat a buffer that's roughly 2MB big */
    vector.reserve(2 * 1024 * 1024);
    while (vector.size() < (2 * 1024 * 1024)) {
        protocol_binary_request_set req;
        memset(&req, 0, sizeof(req));

        req.message.header.request.magic = PROTOCOL_BINARY_REQ;
        req.message.header.request.opcode = PROTOCOL_BINARY_CMD_SET;
        req.message.header.request.keylen = htons(3);
        req.message.header.request.extlen = 8;
        req.message.header.request.bodylen = htonl(11 + size);
        req.message.body.flags = 0;
        req.message.body.expiration = 0;

        for (size_t ii = 0; ii < sizeof(req.bytes); ++ii) {
            vector.push_back(req.bytes[ii]);
        }

        vector.push_back('f');
        vector.push_back('o');
        vector.push_back('o');

        vector.resize(vector.size() + size, ' ');
    }
}

static void set_test(const std::string &host, const std::string &port, int duration) {
    std::list<int> sizes;
    sizes.push_back(256);
    sizes.push_back(512);
    sizes.push_back(1 * 1024);
    sizes.push_back(2 * 1024);
    sizes.push_back(4 * 1024);
    sizes.push_back(8 * 1024);
    sizes.push_back(16 * 1024);
    sizes.push_back(512 * 1024);

    for (auto iter = sizes.begin(); iter != sizes.end(); ++iter) {
        std::vector<uint8_t> message;
        buildSetStream(message, *iter);
        Connection c(host, port, message.data(), message.size());

        int end = time(NULL) + duration;
        c.start();

        while (time(NULL) < (end)) {
            std::cout << "\rSet test with objects of " << *iter << " bytes: "
                      << c.getOpsPerSec() << " set/sec";
            std::cout.flush();
            sleep(1);
        }

        // Loop and print stats for the duration
        c.stop();

        std::cout << "\r " << *iter << " bytes: "
                  << "Duration " << c.getDuration()
                  << "s Total ops " << c.getTotalOps()
                  << " avg: " << c.getOpsPerSec() << std::endl;
        std::cout.flush();
    }
}

/**
 * Program entry point.
 *
 * @param argc argument count
 * @param argv argument vector
 * @return 0 if success, error code otherwise
 */
int main(int argc, char **argv)
{
    int cmd;
    std::string host("localhost");
    std::string port("12000");
    int duration = 60;
    char *ptr;

    /* Initialize the socket subsystem */
    cb_initialize_sockets();

    while ((cmd = getopt(argc, argv, "h:p:d:")) != EOF) {
        switch (cmd) {
        case 'h' :
            ptr = strchr(optarg, ':');
            if (ptr != NULL) {
                *ptr = '\0';
                port.assign(ptr + 1);
            }
            host.assign(optarg);
            break;
        case 'p' :
            port.assign(optarg);
            break;
        case 'd':
            duration = atoi(optarg);
            break;
        default:
            fprintf(stderr,
                    "Usage mcbench [-h host[:port]] [-p port] [-d duration]\n");
            return 1;
        }
    }

    set_test(host, port, duration);

    return 0;
}
<commit_msg>mcbench: Fix memory ordering for store<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/*
 * mcbench is a program used to test the single frontend thread performance
 * on a memcached service
 */
#include "config.h"

#include <memcached/protocol_binary.h>

#include <getopt.h>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <string.h>
#include <list>
#include <vector>
#include <iostream>
#include <stdint.h>
#include <cassert>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <cerrno>
#include <chrono>
#include <thread>
#include <atomic>
#include <platform/platform.h>

class Connection;
static void thread_main(Connection *c);

class Connection {
public:
    Connection(const std::string &_host, const std::string &_port,
               uint8_t *sndbuf, size_t sndbufsz) :
        sendBuffer(sndbuf), sendBufferSize(sndbufsz),
        sendBufferOffset(0),
        sock(INVALID_SOCKET), host(_host), port(_port), currentOps(0)
    {
        currentOps.store(0, std::memory_order_release);
        recvBuffer.reserve(2 * 1024 * 1024);
    }

    void start() {
        running.store(true, std::memory_order_release);
        tid = std::thread(thread_main, this);
    }

    void stop() {
        running.store(false, std::memory_order_release);
        tid.join();

    }

    size_t getOpsPerSec() const {
        using namespace std::chrono;

        std::chrono::time_point<std::chrono::steady_clock> now;
        if (running) {
            now = steady_clock::now();
        } else {
            now = stopTime;
        }

        auto delta = duration_cast<seconds>(now - startTime).count();
        if (delta == 0) {
            return currentOps.load(std::memory_order_acquire);
        } else {
            return currentOps.load(std::memory_order_acquire) / delta;
        }
    }

    size_t getDuration() const {
        using namespace std::chrono;
        return duration_cast<seconds>(stopTime - startTime).count();
    }

    size_t getTotalOps() const {
        return currentOps.load(std::memory_order_acquire);
    }

    ~Connection() {
        if (sock != INVALID_SOCKET) {
            closesocket(sock);
        }
    }

protected:
    friend void thread_main(Connection *c);

    void run(void) {
        startTime = std::chrono::steady_clock::now();

        while (running.load(std::memory_order_acquire)) {
            if (sock == INVALID_SOCKET) {
                connect();
            }

            while (sock != INVALID_SOCKET && running.load(std::memory_order_acquire)) {
                struct pollfd fds[1];
                fds[0].fd = sock;
                if (toSend == 0) {
                    fds[0].events = POLLIN;
                } else {
                    fds[0].events = POLLIN | POLLOUT;
                }
                cb_assert(poll(fds, 1, -1) != -1);

                if (fds[0].revents & POLLIN) {
                    drainInput();
                } else if (fds[0].revents & POLLOUT) {
                    doSendData();
                } else {
                    // what is this?
                    abort();
                }
            }
        }
        stopTime = std::chrono::steady_clock::now();
    }

    /**
     * Try to connect to the server
     * @return false if we failed to connect to the server
     */
    bool connect(void)
    {
        struct addrinfo *ai = NULL;
        struct addrinfo hints;

        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_socktype = SOCK_STREAM;

        if (getaddrinfo(host.c_str(), port.c_str(), &hints, &ai) != 0) {
            return false;
        }

        struct addrinfo *e = ai;
        do {
            if ((sock = socket(e->ai_family, e->ai_socktype,
                               e->ai_protocol)) != -1) {
                if (::connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
                    close(sock);
                    sock = -1;
                }
            }
            if (sock == -1) {
                e = e->ai_next;
            } else {
                break;
            }
        } while (e) ;

        fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);

        freeaddrinfo(ai);

        sendBufferOffset = 0;
        toSend = sendBufferSize - sendBufferOffset;
        return true;
    }

    void drainInput(void) {
        ssize_t nr;
        size_t currsize = recvBuffer.size();
        recvBuffer.resize(2 * 1024 * 1024);
        while ((nr = recv(sock, recvBuffer.data() + currsize,
                          (2 * 1024 * 1024) - currsize, 0)) > 0) {
            /* Parse packets */
            recvBuffer.resize(currsize + nr);
            size_t size = recvBuffer.size();
            uint8_t *curr = recvBuffer.data();

            while (size > 24) {
                protocol_binary_response_no_extras *res;
                res = reinterpret_cast<protocol_binary_response_no_extras *>(curr);
                assert(res->message.header.response.magic == 0x81);
                uint32_t bodylen = ntohl(res->message.header.response.bodylen);

                if (size < (24 + bodylen)) {
                    break;
                }

                size -= (24 + bodylen);
                currentOps.fetch_add(1, std::memory_order_release);;
                curr += 24 + bodylen;
            }

            /* repack the buffer */
            memmove(recvBuffer.data(), curr, size);
            currsize = size;
            recvBuffer.resize(2 * 1024 * 1024);
        }

        recvBuffer.resize(currsize);

        if ((nr == -1 && errno != EWOULDBLOCK) || nr == 0) {
            close(sock);
            sock = -1;
        }
    }

    void doSendData(void) {
        ssize_t nw;
        cb_assert(toSend > 0);

        while ((nw = send(sock, sendBuffer+sendBufferOffset, toSend, 0)) > 0) {
            sendBufferOffset += nw;
            toSend = sendBufferSize - sendBufferOffset;
            if (toSend == 0) {
                sendBufferOffset = 0;
                toSend = sendBufferSize - sendBufferOffset;
            }
        }

        if (nw == -1 && errno != EWOULDBLOCK) {
            close(sock);
            sock = -1;
        }
    }

    uint8_t *sendBuffer;
    size_t toSend;
    size_t sendBufferSize;
    size_t sendBufferOffset;

    std::vector<uint8_t> recvBuffer;
    int sock;
    const std::string host;
    const std::string port;
    std::chrono::time_point<std::chrono::steady_clock> startTime;
    std::chrono::time_point<std::chrono::steady_clock> stopTime;
    std::atomic<size_t> currentOps;
    std::thread tid;
    std::atomic<bool> running;
};

static void thread_main(Connection *c)
{
    c->run();
}

static void buildSetStream(std::vector<uint8_t> &vector, size_t size) {
    /* preformat a buffer that's roughly 2MB big */
    vector.reserve(2 * 1024 * 1024);
    while (vector.size() < (2 * 1024 * 1024)) {
        protocol_binary_request_set req;
        memset(&req, 0, sizeof(req));

        req.message.header.request.magic = PROTOCOL_BINARY_REQ;
        req.message.header.request.opcode = PROTOCOL_BINARY_CMD_SET;
        req.message.header.request.keylen = htons(3);
        req.message.header.request.extlen = 8;
        req.message.header.request.bodylen = htonl(11 + size);
        req.message.body.flags = 0;
        req.message.body.expiration = 0;

        for (size_t ii = 0; ii < sizeof(req.bytes); ++ii) {
            vector.push_back(req.bytes[ii]);
        }

        vector.push_back('f');
        vector.push_back('o');
        vector.push_back('o');

        vector.resize(vector.size() + size, ' ');
    }
}

static void set_test(const std::string &host, const std::string &port, int duration) {
    std::list<int> sizes;
    sizes.push_back(256);
    sizes.push_back(512);
    sizes.push_back(1 * 1024);
    sizes.push_back(2 * 1024);
    sizes.push_back(4 * 1024);
    sizes.push_back(8 * 1024);
    sizes.push_back(16 * 1024);
    sizes.push_back(512 * 1024);

    for (auto iter = sizes.begin(); iter != sizes.end(); ++iter) {
        std::vector<uint8_t> message;
        buildSetStream(message, *iter);
        Connection c(host, port, message.data(), message.size());

        int end = time(NULL) + duration;
        c.start();

        while (time(NULL) < (end)) {
            std::cout << "\rSet test with objects of " << *iter << " bytes: "
                      << c.getOpsPerSec() << " set/sec";
            std::cout.flush();
            sleep(1);
        }

        // Loop and print stats for the duration
        c.stop();

        std::cout << "\r " << *iter << " bytes: "
                  << "Duration " << c.getDuration()
                  << "s Total ops " << c.getTotalOps()
                  << " avg: " << c.getOpsPerSec() << std::endl;
        std::cout.flush();
    }
}

/**
 * Program entry point.
 *
 * @param argc argument count
 * @param argv argument vector
 * @return 0 if success, error code otherwise
 */
int main(int argc, char **argv)
{
    int cmd;
    std::string host("localhost");
    std::string port("12000");
    int duration = 60;
    char *ptr;

    /* Initialize the socket subsystem */
    cb_initialize_sockets();

    while ((cmd = getopt(argc, argv, "h:p:d:")) != EOF) {
        switch (cmd) {
        case 'h' :
            ptr = strchr(optarg, ':');
            if (ptr != NULL) {
                *ptr = '\0';
                port.assign(ptr + 1);
            }
            host.assign(optarg);
            break;
        case 'p' :
            port.assign(optarg);
            break;
        case 'd':
            duration = atoi(optarg);
            break;
        default:
            fprintf(stderr,
                    "Usage mcbench [-h host[:port]] [-p port] [-d duration]\n");
            return 1;
        }
    }

    set_test(host, port, duration);

    return 0;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <schwa/base.h>
#include <schwa/msgpack.h>
#include <schwa/dr.h>
#include "test_utils.h"

#include <boost/test/unit_test.hpp>

namespace dr = schwa::dr;
namespace mp = schwa::msgpack;

class DocWithField : public dr::Document {
public:
  std::string name;

  class Schema;
};

class DocWithField::Schema : public dr::DocumentSchema<DocWithField> {
public:
  DR_FIELD(&DocWithField::name) name;

  Schema(void) :
    dr::DocumentSchema<DocWithField>("Document", "Some help text about this Document class"),
    name(*this, "name", "some help text about name", dr::LOAD_RW, "name")
    { }
  virtual ~Schema(void) { }
};

class DocWithFieldWithSerial : public dr::Document {
public:
  std::string name;

  class Schema;
};

class DocWithFieldWithSerial::Schema : public dr::DocumentSchema<DocWithFieldWithSerial> {
public:
  DR_FIELD(&DocWithFieldWithSerial::name) name;

  Schema(void) :
    dr::DocumentSchema<DocWithFieldWithSerial>("Document", "Some help text about this Document class"),
    name(*this, "name", "some help text about name", dr::LOAD_RW, "filename")
    { }
  virtual ~Schema(void) { }
};

BOOST_AUTO_TEST_SUITE(schwa_dr_writer)

BOOST_AUTO_TEST_CASE(DocWithField__name_is_null) {
  std::stringstream out, correct;
  DocWithField::Schema schema;
  dr::Writer writer(out, schema);

  DocWithField d;
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << "\xa8__meta__";  // <klass_name>: 8-bytes of utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << "\xa4name";  // 4-bytes of utf-8 encoded "name"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x01';  // <instance_nbytes>: 1 byte after this
  correct << '\x80';  // <instance>: 0-element map

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithField__name) {
  std::stringstream out, correct;
  DocWithField::Schema schema;
  dr::Writer writer(out, schema);

  DocWithField d;
  d.name = "/etc/passwd";
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << "\xa8__meta__";  // <klass_name>: utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << "\xa4name";  // utf-8 encoded "name"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x0e';  // <instance_nbytes>: 14 bytes after this
  correct << '\x81';  // <instance>: 1-element map
  correct << '\x00';  // 0: field number 0 (=> name;
  correct << "\xab/etc/passwd";  // utf-8 encoded "/etc/passwd"

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithFieldWithSerial__name_is_null) {
  std::stringstream out, correct;
  DocWithFieldWithSerial::Schema schema;
  dr::Writer writer(out, schema);

  DocWithFieldWithSerial d;
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << "\xa8__meta__";  // <klass_name>: 8-bytes of utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa8' << "filename";  // utf-8 encoded "filename"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x01';  // <instance_nbytes>: 1 byte after this
  correct << '\x80';  // <instance>: 0-element map

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithFieldWithSerial__name) {
  std::stringstream out, correct;
  DocWithFieldWithSerial::Schema schema;
  dr::Writer writer(out, schema);

  DocWithFieldWithSerial d;
  d.name = "/etc/passwd";
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << "\xa8__meta__";  // <klass_name>: utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa8' << "filename";  // utf-8 encoded "filename"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x0e';  // <instance_nbytes>: 14 bytes after this
  correct << '\x81';  // <instance>: 1-element map
  correct << '\x00';  // 0: field number 0 (=> name;
  correct << "\xab/etc/passwd";  // utf-8 encoded "/etc/passwd"

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>* more writer unit test porting<commit_after>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <schwa/base.h>
#include <schwa/msgpack.h>
#include <schwa/dr.h>
#include "test_utils.h"

#include <boost/test/unit_test.hpp>

namespace dr = schwa::dr;
namespace mp = schwa::msgpack;

// ============================================================================
// ============================================================================
class DocWithField : public dr::Document {
public:
  std::string name;
  class Schema;
};

class DocWithField::Schema : public dr::DocumentSchema<DocWithField> {
public:
  DR_FIELD(&DocWithField::name) name;

  Schema(void) :
    dr::DocumentSchema<DocWithField>("Document", "Some help text about this Document class"),
    name(*this, "name", "some help text about name", dr::LOAD_RW, "name")
    { }
  virtual ~Schema(void) { }
};

// ============================================================================
// ============================================================================
class DocWithFieldWithSerial : public dr::Document {
public:
  std::string name;
  class Schema;
};

class DocWithFieldWithSerial::Schema : public dr::DocumentSchema<DocWithFieldWithSerial> {
public:
  DR_FIELD(&DocWithFieldWithSerial::name) name;

  Schema(void) :
    dr::DocumentSchema<DocWithFieldWithSerial>("Document", "Some help text about this Document class"),
    name(*this, "name", "some help text about name", dr::LOAD_RW, "filename")
    { }
  virtual ~Schema(void) { }
};

// ============================================================================
// ============================================================================
class A1 : public dr::Annotation {
public:
  std::string value;
  class Schema;
};

class DocWithA : public dr::Document {
public:
  dr::Store<A1> as;
  class Schema;
};

class DocWithA::Schema : public dr::DocumentSchema<DocWithA> {
public:
  DR_STORE(&DocWithA::as) as;

  Schema(void) :
    dr::DocumentSchema<DocWithA>("Document", "Some help text about this Document class"),
    as(*this, "as", "some help text about as", dr::LOAD_RW, "as")
    { }
  virtual ~Schema(void) { }
};

class A1::Schema : public dr::AnnotationSchema<A1> {
public:
  DR_FIELD(&A1::value) value;

  Schema(void) :
    dr::AnnotationSchema<A1>("A", "Some help text about A", "A"),
    value(*this, "value", "some help text about value", dr::LOAD_RW, "value")
    { }
  virtual ~Schema(void) { }
};

// ============================================================================
// ============================================================================

BOOST_AUTO_TEST_SUITE(schwa_dr_writer)

BOOST_AUTO_TEST_CASE(DocWithField__name_is_null) {
  std::stringstream out, correct;
  DocWithField::Schema schema;
  dr::Writer writer(out, schema);

  DocWithField d;
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "__meta__";  // <klass_name>: 8-bytes of utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa4' << "name";  // 4-bytes of utf-8 encoded "name"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x01';  // <instance_nbytes>: 1 byte after this
  correct << '\x80';  // <instance>: 0-element map

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithField__name) {
  std::stringstream out, correct;
  DocWithField::Schema schema;
  dr::Writer writer(out, schema);

  DocWithField d;
  d.name = "/etc/passwd";
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "__meta__";  // <klass_name>: utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa4' << "name";  // utf-8 encoded "name"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x0e';  // <instance_nbytes>: 14 bytes after this
  correct << '\x81';  // <instance>: 1-element map
  correct << '\x00';  // 0: field number 0 (=> name;
  correct << '\xab' << "/etc/passwd";  // utf-8 encoded "/etc/passwd"

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithFieldWithSerial__name_is_null) {
  std::stringstream out, correct;
  DocWithFieldWithSerial::Schema schema;
  dr::Writer writer(out, schema);

  DocWithFieldWithSerial d;
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "__meta__";  // <klass_name>: 8-bytes of utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa8' << "filename";  // utf-8 encoded "filename"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x01';  // <instance_nbytes>: 1 byte after this
  correct << '\x80';  // <instance>: 0-element map

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithFieldWithSerial__name) {
  std::stringstream out, correct;
  DocWithFieldWithSerial::Schema schema;
  dr::Writer writer(out, schema);

  DocWithFieldWithSerial d;
  d.name = "/etc/passwd";
  writer << d;

  correct << '\x91';  // <klasses>: 1-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "__meta__";  // <klass_name>: utf-8 encoded "__meta__"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa8' << "filename";  // utf-8 encoded "filename"
  correct << '\x90';  // <stores>: 0-element array
  correct << '\x0e';  // <instance_nbytes>: 14 bytes after this
  correct << '\x81';  // <instance>: 1-element map
  correct << '\x00';  // 0: field number 0 (=> name;
  correct << '\xab' << "/etc/passwd";  // utf-8 encoded "/etc/passwd"

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_CASE(DocWithA__empty) {
  std::stringstream out, correct;
  DocWithA::Schema schema;
  dr::Writer writer(out, schema);

  schema.types<A1>().serial = "writer.A";

  DocWithA d;
  writer << d;

  correct << '\x92';  // <klasses>: 2-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "__meta__";  // <klass_name>: utf-8 encoded "__meta__"
  correct << '\x90';  // <fields>: 0-element array
  correct << '\x92';  // <klass>: 2-element array
  correct << '\xa8' << "writer.A";  // <klass_name>: utf-8 encoded "writer.A"
  correct << '\x91';  // <fields>: 1-element array
  correct << '\x81';  // <field>: 1-element map
  correct << '\x00';  // 0: NAME
  correct << '\xa5' << "value";  // utf-8 encoded "value"
  correct << '\x91';  // <stores>: 1-element array
  correct << '\x93';  // <store>: 3-element array
  correct << '\xa2' << "as";  // <store_name>: utf-8 encoded "as"
  correct << '\x01';  // <klass_id>: 1
  correct << '\x00';  // <store_nelem>: 0
  correct << '\x01';  // <instance_nbytes>: 1 byte after this for the document
  correct << '\x80';  // <instance>: 0-element map
  correct << '\x01';  // <instance_nbytes>: 1 byte after this for the "as" store
  correct << '\x90';  // <instance>: 0-element array

  BOOST_CHECK( compare_bytes(out.str(), correct.str()) );
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before><commit_msg>pdn: use generator sizing when checking constraints<commit_after><|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html

#ifndef BSE_EVALUATOR_SYMBOLS_H
#define BSE_EVALUATOR_SYMBOLS_H

#include <string>
#include <map>

namespace Bse {
namespace EvaluatorUtils {

class Symbols {
    std::map<std::string,int> symbol_map;
    int n_registers;

public:
    Symbols()
    {
	n_registers = 0;
    }

    int alloc() {
	return n_registers++;
    }

    int alloc(const std::string& name)
    {
	std::map<std::string,int>::iterator smi = symbol_map.find(name);
	if (smi == symbol_map.end())
	    return symbol_map[name] = alloc();
	else
	    return smi->second;
    }

    std::string name(int reg) const
    {
	/* sloow ;) */
	std::map<std::string,int>::const_iterator smi;
	for(smi = symbol_map.begin(); smi != symbol_map.end(); smi++)
	{
	    if (smi->second == reg)
		return smi->first;
	}

	char buffer[1024];
	sprintf(buffer,"R%02d", reg);
	return buffer;
    }

    void clear()
    {
	symbol_map.clear();
	n_registers = 0;
    }
};

}
}

#endif // BSE_EVALUATOR_SYMBOLS_H
<commit_msg>PLUGINS: use Rapicorn's string_format()<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html

#ifndef BSE_EVALUATOR_SYMBOLS_H
#define BSE_EVALUATOR_SYMBOLS_H

#include <string>
#include <map>

namespace Bse {
namespace EvaluatorUtils {

class Symbols {
    std::map<std::string,int> symbol_map;
    int n_registers;

public:
    Symbols()
    {
	n_registers = 0;
    }

    int alloc() {
	return n_registers++;
    }

    int alloc(const std::string& name)
    {
	std::map<std::string,int>::iterator smi = symbol_map.find(name);
	if (smi == symbol_map.end())
	    return symbol_map[name] = alloc();
	else
	    return smi->second;
    }

    std::string name(int reg) const
    {
	/* sloow ;) */
	std::map<std::string,int>::const_iterator smi;
	for(smi = symbol_map.begin(); smi != symbol_map.end(); smi++)
	{
	    if (smi->second == reg)
		return smi->first;
	}

	return string_format ("R%02d", reg);
    }

    void clear()
    {
	symbol_map.clear();
	n_registers = 0;
    }
};

}
}

#endif // BSE_EVALUATOR_SYMBOLS_H
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_CONFIG_PARSER_H
#define __BH_CONFIG_PARSER_H

#include <boost/property_tree/ptree.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>

// We need to specialize lexical_cast() in order to support booleans
// other then the standard 0/1 to true/false conversion.
namespace boost {
    template<>
    inline bool lexical_cast<bool, std::string>(const std::string& arg) {
        switch(arg[0]) {
            case 'y':
            case 'Y':
            case '1':
            case 't':
            case 'T':
                return true;
            case 'n':
            case 'N':
            case '0':
            case 'f':
            case 'F':
                return false;
            default:
                throw boost::bad_lexical_cast();
        }
    }
}

namespace bohrium {

//Representation of the Bohrium configuration file
class ConfigParser {
  public:
    // Path to the config file e.g. ~/.bohrium/config.ini
    const std::string file_path;
    // The stack level of the calling component
    const unsigned int stack_level;
  private:
    // The list of components in the user-specified stack starting
    // at the bridge
    std::vector<std::string> _stack_list;
    // The config data
    boost::property_tree::ptree _config;
    // Return section/option first looking at the environment variable
    // and then the ini file.
    std::string lookup(const std::string &section,
                       const std::string &option) const;
  public:
    /* Uses 'stack_level' to find the default section to use with get()
     * and when calculating the child in getChild()
     *
     * @stack_level  Is the level of the calling component
     */
    ConfigParser(unsigned int stack_level);

    /* Get the value of the 'option' within the 'section'
     *
     * @section  The ini section e.g. [gpu]. If omitted, the default
     *           section is used.
     * @option   The ini option e.g. timing = True
     * @return   The value, which is lexically converted to type 'T'
     * Throws property_tree::ptree_bad_path if the section/option does not exist
     * Throws bad_lexical_cast if the value cannot be converted
     */
    template<typename T>
    T get(const std::string &section, const std::string &option) const {
        using namespace std;
        using namespace boost;
        //Retrieve the option
        string ret;
        try {
            ret = lookup(section, option);
        } catch (const property_tree::ptree_bad_path&) {
            cerr << "Error parsing the config file '" << file_path << "', '"
                 << section << "." << option << "' not found!" << endl;
            throw;
        }
        //Now let's try to convert the value to the requested type
        try {
            return lexical_cast<T>(ret);
        } catch (const boost::bad_lexical_cast&) {
            string s = _config.get<string>(section + "." + option);
            cerr << "ConfigParser cannot convert '" << section << "." << option
                 << "=" << s << "' to type <" << typeid(T).name() << ">" << endl;
            throw;
        }
    }
    template<typename T>
    T get(const std::string &option) const {
        return get<T>(_stack_list[stack_level], option);
    }

    /* Get the value of the 'option' within the 'section' and if it
     * does not exist return 'default_value' instead
     *
     * @section        The ini section e.g. [gpu]. If omitted, the
     *                 default section is used.
     * @option         The ini option e.g. timing = True
     * @default_value  The default value of type 'T'
     * @return         The value, which is lexically converted to
     *                 type 'T' or the 'default_value'
     */
    template<typename T>
    T defaultGet(const std::string &section, const std::string &option,
                 const T &default_value) const {
        try {
            return get<T>(section, option);
        } catch (const boost::property_tree::ptree_bad_path&) {
            return default_value;
        }
    }
    template<typename T>
    T defaultGet(const std::string &option, const T &default_value) const {
        return defaultGet(_stack_list[stack_level], option, default_value);
    }

    /* Get the value of the 'option' within the 'section' and convert the value,
     * which must be a comma separated list, into a vector of strings.
     *
     * @section        The ini section e.g. [gpu]. If omitted, the
     *                 default section is used.
     * @option         The ini option e.g. timing = True
     * @return         Vector of strings
     * Throws property_tree::ptree_bad_path if the section/option does not exist
     */
    std::vector<std::string> getList(const std::string &section,
                                     const std::string &option) const;
    std::vector<std::string> getList(const std::string &option) const {
        return getList(_stack_list[stack_level], option);
    }
    /* Return the path to the library that implements
     * the calling component's child.
     *
     * @return File path to shared library
     * Throw exception if the calling component has not children
     */
    std::string getChildLibraryPath() const;

    /* Retrieve the name of the calling component
     *
     * @return Component name as given in the config file
     */
    std::string getName() const { return _stack_list[stack_level]; };
};

} //namespace bohrium

#endif

<commit_msg>Implemented a ConfigKeyNotFound exception<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_CONFIG_PARSER_H
#define __BH_CONFIG_PARSER_H

#include <boost/property_tree/ptree.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>

// We need to specialize lexical_cast() in order to support booleans
// other then the standard 0/1 to true/false conversion.
namespace boost {
    template<>
    inline bool lexical_cast<bool, std::string>(const std::string& arg) {
        switch(arg[0]) {
            case 'y':
            case 'Y':
            case '1':
            case 't':
            case 'T':
                return true;
            case 'n':
            case 'N':
            case '0':
            case 'f':
            case 'F':
                return false;
            default:
                throw boost::bad_lexical_cast();
        }
    }
}

namespace bohrium {

// Exception thrown when a config key is not found
class ConfigKeyNotFound : public std::exception {
    std::string _msg;
public:
    ConfigKeyNotFound(const std::string& msg) : _msg(msg) {}
    virtual const char* what() const throw() { return _msg.c_str(); }
};

//Representation of the Bohrium configuration file
class ConfigParser {
  public:
    // Path to the config file e.g. ~/.bohrium/config.ini
    const std::string file_path;
    // The stack level of the calling component
    const unsigned int stack_level;
  private:
    // The list of components in the user-specified stack starting
    // at the bridge
    std::vector<std::string> _stack_list;
    // The config data
    boost::property_tree::ptree _config;
    // Return section/option first looking at the environment variable
    // and then the ini file.
    std::string lookup(const std::string &section,
                       const std::string &option) const;
  public:
    /* Uses 'stack_level' to find the default section to use with get()
     * and when calculating the child in getChild()
     *
     * @stack_level  Is the level of the calling component
     */
    ConfigParser(unsigned int stack_level);

    /* Get the value of the 'option' within the 'section'
     *
     * @section  The ini section e.g. [gpu]. If omitted, the default
     *           section is used.
     * @option   The ini option e.g. timing = True
     * @return   The value, which is lexically converted to type 'T'
     * Throws property_tree::ptree_bad_path if the section/option does not exist
     * Throws bad_lexical_cast if the value cannot be converted
     */
    template<typename T>
    T get(const std::string &section, const std::string &option) const {
        using namespace std;
        using namespace boost;
        //Retrieve the option
        string ret;
        try {
            ret = lookup(section, option);
        } catch (const property_tree::ptree_bad_path&) {
            stringstream ss;
            ss << "Error parsing the config file '" << file_path << "': '" \
               << section << "." << option << "' not found!" << endl;
            throw ConfigKeyNotFound(ss.str());
        }
        //Now let's try to convert the value to the requested type
        try {
            return lexical_cast<T>(ret);
        } catch (const boost::bad_lexical_cast&) {
            cerr << "ConfigParser cannot convert '" << section << "." << option
                 << "=" << ret << "' to type <" << typeid(T).name() << ">" << endl;
            throw;
        }
    }
    template<typename T>
    T get(const std::string &option) const {
        return get<T>(_stack_list[stack_level], option);
    }

    /* Get the value of the 'option' within the 'section' and if it
     * does not exist return 'default_value' instead
     *
     * @section        The ini section e.g. [gpu]. If omitted, the
     *                 default section is used.
     * @option         The ini option e.g. timing = True
     * @default_value  The default value of type 'T'
     * @return         The value, which is lexically converted to
     *                 type 'T' or the 'default_value'
     */
    template<typename T>
    T defaultGet(const std::string &section, const std::string &option,
                 const T &default_value) const {
        try {
            return get<T>(section, option);
        } catch (const ConfigKeyNotFound&) {
            return default_value;
        }
    }
    template<typename T>
    T defaultGet(const std::string &option, const T &default_value) const {
        return defaultGet(_stack_list[stack_level], option, default_value);
    }

    /* Get the value of the 'option' within the 'section' and convert the value,
     * which must be a comma separated list, into a vector of strings.
     *
     * @section        The ini section e.g. [gpu]. If omitted, the
     *                 default section is used.
     * @option         The ini option e.g. timing = True
     * @return         Vector of strings
     * Throws property_tree::ptree_bad_path if the section/option does not exist
     */
    std::vector<std::string> getList(const std::string &section,
                                     const std::string &option) const;
    std::vector<std::string> getList(const std::string &option) const {
        return getList(_stack_list[stack_level], option);
    }

    /* Return the path to the library that implements
     * the calling component's child.
     *
     * @return File path to shared library
     * Throw exception if the calling component has not children
     */
    std::string getChildLibraryPath() const;

    /* Retrieve the name of the calling component
     *
     * @return Component name as given in the config file
     */
    std::string getName() const { return _stack_list[stack_level]; };
};

} //namespace bohrium

#endif

<|endoftext|>


<commit_before>/*
   Copyright (c) 2009-2014, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#pragma once
#ifndef ELEM_SPY_HPP
#define ELEM_SPY_HPP

#include "./spy_window/decl.hpp"
#include "./spy_widget/impl.hpp"
#include "./Display.hpp" // for ProcessEvents

#ifdef ELEM_HAVE_QT5
# include <QApplication>
#endif

namespace elem {

template<typename T>
inline void
Spy( const Matrix<T>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");

    // Convert A to double-precision since Qt's MOC does not support templates
    const Int m = A.Height();
    const Int n = A.Width();
    Matrix<Int>* ASpy = new Matrix<Int>( m, n );
    for( Int j=0; j<n; ++j )
        for( Int i=0; i<m; ++i )
            ASpy->Set( i, j, ( Abs(A.Get(i,j))>tol ? 1 : 0 ) );

    QString qTitle = QString::fromStdString( title );
    SpyWindow* spyWindow = new SpyWindow;
    spyWindow->Spy( ASpy, qTitle );
    spyWindow->show();

    // Spend at most 200 milliseconds rendering
    ProcessEvents( 200 );
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

template<typename T,Distribution U,Distribution V>
inline void
Spy( const DistMatrix<T,U,V>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");
    if( U == A.UGath && V == A.VGath )
    {
        if( A.CrossRank() == A.Root() && A.RedundantRank() == 0 )
            Spy( A.Matrix(), title, tol );
    }
    else
    {
        DistMatrix<T,CIRC,CIRC> A_CIRC_CIRC( A );
        if( A_CIRC_CIRC.CrossRank() == A_CIRC_CIRC.Root() )
            Spy( A_CIRC_CIRC.Matrix(), title, tol );
    }
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

template<typename T,Dist U,Dist V>
inline void
Spy
( const BlockDistMatrix<T,U,V>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");
    if( U == A.UGath && V == A.VGath )
    {
        if( A.CrossRank() == A.Root() && A.RedundantRank() == 0 )
            Spy( A.Matrix(), title, tol );
    }
    else
    {
        BlockDistMatrix<T,CIRC,CIRC> A_CIRC_CIRC( A );
        if( A_CIRC_CIRC.CrossRank() == A_CIRC_CIRC.Root() )
            Spy( A_CIRC_CIRC.Matrix(), title, tol );
    }
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

} // namespace elem

#endif // ifndef ELEM_SPY_HPP
<commit_msg>Avoiding mistaken access to modifiable local matrix in distributed Spy.<commit_after>/*
   Copyright (c) 2009-2014, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#pragma once
#ifndef ELEM_SPY_HPP
#define ELEM_SPY_HPP

#include "./spy_window/decl.hpp"
#include "./spy_widget/impl.hpp"
#include "./Display.hpp" // for ProcessEvents

#ifdef ELEM_HAVE_QT5
# include <QApplication>
#endif

namespace elem {

template<typename T>
inline void
Spy( const Matrix<T>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");

    // Convert A to double-precision since Qt's MOC does not support templates
    const Int m = A.Height();
    const Int n = A.Width();
    Matrix<Int>* ASpy = new Matrix<Int>( m, n );
    for( Int j=0; j<n; ++j )
        for( Int i=0; i<m; ++i )
            ASpy->Set( i, j, ( Abs(A.Get(i,j))>tol ? 1 : 0 ) );

    QString qTitle = QString::fromStdString( title );
    SpyWindow* spyWindow = new SpyWindow;
    spyWindow->Spy( ASpy, qTitle );
    spyWindow->show();

    // Spend at most 200 milliseconds rendering
    ProcessEvents( 200 );
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

template<typename T,Distribution U,Distribution V>
inline void
Spy( const DistMatrix<T,U,V>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");
    if( U == A.UGath && V == A.VGath )
    {
        if( A.CrossRank() == A.Root() && A.RedundantRank() == 0 )
            Spy( A.LockedMatrix(), title, tol );
    }
    else
    {
        DistMatrix<T,CIRC,CIRC> A_CIRC_CIRC( A );
        if( A_CIRC_CIRC.CrossRank() == A_CIRC_CIRC.Root() )
            Spy( A_CIRC_CIRC.Matrix(), title, tol );
    }
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

template<typename T,Dist U,Dist V>
inline void
Spy
( const BlockDistMatrix<T,U,V>& A, std::string title="Default", BASE(T) tol=0 )
{
    DEBUG_ONLY(CallStackEntry cse("Spy"))
#ifdef ELEM_HAVE_QT5
    if( GuiDisabled() )
        LogicError("GUI was disabled");
    if( U == A.UGath && V == A.VGath )
    {
        if( A.CrossRank() == A.Root() && A.RedundantRank() == 0 )
            Spy( A.LockedMatrix(), title, tol );
    }
    else
    {
        BlockDistMatrix<T,CIRC,CIRC> A_CIRC_CIRC( A );
        if( A_CIRC_CIRC.CrossRank() == A_CIRC_CIRC.Root() )
            Spy( A_CIRC_CIRC.Matrix(), title, tol );
    }
#else
    LogicError("Qt5 not available");
#endif // ifdef ELEM_HAVE_QT5
}

} // namespace elem

#endif // ifndef ELEM_SPY_HPP
<|endoftext|>


<commit_before>#pragma once
/**
 * \file	exemodel/devicee.hpp
 * \author	justgaoyuan<gao_yuangy@126.com>
 */
#include <sys/stat.h>

#include <stdint.h>

#include "exemodel/pollee.hpp"
#include "exemodel/evt_cb.hpp"

/**
 *\class devicee
 *\brief device pollee,used by \em poller
 */
namespace exemodel{
class poller;

template< typename T >
class devicee
: public pollee
, public evt_cb< T& > {
public:
	/**
	 * \brief ctor of devicee
	 * \param path	point to a pathname to open.
	 */
	explicit devicee(const char* path)
	: pollee(::open(path, O_RDWR), uint32_t(::EPOLLIN))
	, m_path(path)
	{
	}

	virtual ~devicee() {};
public:
	/**
	 * \brief used for disposing the event caught by the \em poller attached.
	 */
	virtual void dispose(poller &mgr, uint32_t evts)
	{
		ssize_t ret = this->read(&m_data, sizeof(m_data));
		if (ret == -1) {
			return;
		}

		this->exe(m_data);
	}
private:
	devicee(const devicee &rhs ) = delete;
	devicee &operator = (devicee & rhs) = delete;
private:
	const char* const m_path;
	T m_data;
};

template<>
class devicee<void>
: public pollee {
public:
	explicit devicee(const char* path, int oflag = O_RDWR)
	: pollee(::open(path, oflag), 0)
	, m_path(path)
	{
	}

	virtual ~devicee() {};
public:
	virtual void dispose(poller &mgr, uint32_t evts) {}
private:
	devicee(const devicee &rhs ) = delete;
	devicee &operator = (devicee & rhs) = delete;
private:
	const char* const m_path;
};

}
<commit_msg>devicee: add interface: path()<commit_after>#pragma once
/**
 * \file	exemodel/devicee.hpp
 * \author	justgaoyuan<gao_yuangy@126.com>
 */
#include <sys/stat.h>

#include <stdint.h>

#include "exemodel/pollee.hpp"
#include "exemodel/evt_cb.hpp"

/**
 *\class devicee
 *\brief device pollee,used by \em poller
 */
namespace exemodel{
class poller;

template< typename T >
class devicee
: public pollee
, public evt_cb< T& > {
public:
	/**
	 * \brief ctor of devicee
	 * \param path	point to a pathname to open.
	 */
	explicit devicee(const char* path)
	: pollee(::open(path, O_RDWR), uint32_t(::EPOLLIN))
	, m_path(path)
	{
	}

	virtual ~devicee() {};
public:
	/**
	 * \brief used for disposing the event caught by the \em poller attached.
	 */
	virtual void dispose(poller &mgr, uint32_t evts)
	{
		ssize_t ret = this->read(&m_data, sizeof(m_data));
		if (ret == -1) {
			return;
		}

		this->exe(m_data);
	}
	const char * path(void) const
	{
		return m_path;
	}
private:
	devicee(const devicee &rhs ) = delete;
	devicee &operator = (devicee & rhs) = delete;
private:
	const char* const m_path;
	T m_data;
};

template<>
class devicee<void>
: public pollee {
public:
	explicit devicee(const char* path, int oflag = O_RDWR)
	: pollee(::open(path, oflag), 0)
	, m_path(path)
	{
	}

	virtual ~devicee() {};
public:
	virtual void dispose(poller &mgr, uint32_t evts) {}
	const char * path(void) const
	{
		return m_path;
	}
private:
	devicee(const devicee &rhs ) = delete;
	devicee &operator = (devicee & rhs) = delete;
private:
	const char* const m_path;
};

}
<|endoftext|>


<commit_before>//============================================================================
// MCKL/include/mckl/random/seed.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef MCKL_RANDOM_SEED_HPP
#define MCKL_RANDOM_SEED_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/skein.hpp>
#include <mckl/random/threefry.hpp>

namespace mckl
{

/// \brief Seed generator
/// \ingroup Random
template <typename ResultType,
    typename ID = std::integral_constant<std::size_t, sizeof(ResultType)>,
    bool Randomize = true>
class SeedGenerator
{
    static_assert(sizeof(ResultType) % sizeof(std::uint32_t) == 0,
        "**SeedGenerator** size of ResultType is not a multiple of uint32_t");

    public:
    /// \brief The type of the internal seed
    using seed_type =
        typename std::conditional<sizeof(ResultType) % sizeof(std::uint64_t) ==
                0,
            std::uint64_t, std::uint32_t>::type;

    using result_type = ResultType;

    SeedGenerator(const SeedGenerator<ResultType, ID, Randomize> &) = delete;

    SeedGenerator<ResultType, ID, Randomize> &operator=(
        const SeedGenerator<ResultType, ID, Randomize> &) = delete;

    static SeedGenerator<ResultType, ID, Randomize> &instance()
    {
        static SeedGenerator<ResultType, ID, Randomize> seed;

        return seed;
    }

    /// \brief Set the internal seed
    void set(seed_type s) { seed_ = s; }

    /// \brief Get the next key
    result_type get() { return get(std::integral_constant<bool, (M_ > 1)>()); }

    /// \brief The number of partitions
    seed_type np() const { return np_; }

    /// \brief The rank of this partition
    seed_type rank() const { return rank_; }

    /// \brief Set the number of partitions and the rank of this partition
    void partition(seed_type np, seed_type rank)
    {
        partition(np, rank, std::integral_constant<bool, (M_ > 1)>());
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const SeedGenerator<ResultType, ID, Randomize> &sg)
    {
        if (!os)
            return os;

        os << sg.np_ << ' ';
        os << sg.rank_ << ' ';
        os << sg.maxs_ << ' ';
        os << sg.seed_ << ' ';

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        SeedGenerator<ResultType, ID, Randomize> &sg)
    {
        if (!is)
            return is;

        seed_type np;
        seed_type rank;
        seed_type maxs;
        seed_type seed;
        is >> std::ws >> np;
        is >> std::ws >> rank;
        is >> std::ws >> maxs;
        is >> std::ws >> seed;

        if (is) {
            sg.np_ = np;
            sg.rank_ = rank;
            sg.maxs_ = maxs;
            sg.seed_ = seed;
        }

        return is;
    }

    private:
    static constexpr std::size_t M_ = sizeof(result_type) / sizeof(seed_type);

    seed_type np_;
    seed_type rank_;
    seed_type maxs_;
    std::atomic<seed_type> seed_;

    SeedGenerator() : seed_(1) { partition(1, 0); }

    void partition(seed_type np, seed_type rank, std::true_type)
    {
        np_ = np;
        rank_ = rank;
        maxs_ = std::numeric_limits<seed_type>::max();
    }

    void partition(seed_type np, seed_type rank, std::false_type)
    {
        runtime_assert(np > 0,
            "**SeedGenerator::partition** the number of the partitions is "
            "zero");
        if (np < 1)
            np = 1;

        runtime_assert(np > rank,
            "**SeedGenerator::partition** the rank is not smaller than the "
            "number of partitions");
        if (rank >= np)
            rank = 0;

        seed_type maxs = std::numeric_limits<seed_type>::max();
        if (np > 1)
            maxs = (maxs - rank) / np + 1;

        np_ = np;
        rank_ = rank;
        maxs_ = maxs;
    }

    result_type get(std::true_type)
    {
        seed_type s = seed_.fetch_add(1);
        std::array<seed_type, M_> k = {{0}};
        k.front() = s;
        k.back() = rank_;

        return randomize(k, std::integral_constant<bool, Randomize>());
    }

    result_type get(std::false_type)
    {
        seed_type s = seed_.fetch_add(1);
        s %= maxs_;
        s *= np_;
        s += rank_;
        std::array<seed_type, M_> k = {{s}};

        return randomize(k, std::integral_constant<bool, Randomize>());
    }

    result_type randomize(const std::array<seed_type, M_> &k, std::false_type)
    {
        union {
            result_type result;
            std::array<seed_type, M_> k;
        } buf;

        buf.k = k;

        return buf.result;
    }

    result_type randomize(const std::array<seed_type, M_> &k, std::true_type)
    {
        return randomize(
            k, std::integral_constant<int,
                   std::numeric_limits<seed_type>::digits * M_>());
    }

    template <int D>
    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, D>)
    {
        result_type result;
        Skein512::hash(Skein512::param_type(D, k.data()), D, &result);

        return result;
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 32>)
    {
        union {
            std::array<std::uint16_t, 2> state;
            std::array<seed_type, M_> k;
            result_type result;
        } buf;

        buf.k = k;
        std::uint16_t x = std::get<0>(buf.state);
        std::uint16_t y = std::get<1>(buf.state);
        for (int i = 0; i != 22; ++i) {
            x = static_cast<std::uint16_t>((x << 9) | (x >> 7));
            x += y;
            y = static_cast<std::uint16_t>((y << 2) | (y >> 14));
            y ^= x;
        }
        std::get<0>(buf.state) = x;
        std::get<1>(buf.state) = y;

        return buf.result;
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 64>)
    {
        return randomize<Threefry2x32>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 128>)
    {
        return randomize<Threefry2x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 256>)
    {
        return randomize<Threefry4x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 512>)
    {
        return randomize<Threefry8x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 1024>)
    {
        return randomize<Threefry16x64>(k);
    }

    template <typename RNGType>
    result_type randomize(const std::array<seed_type, M_> &k)
    {
        union {
            typename RNGType::ctr_type ctr;
            std::array<seed_type, M_> k;
            result_type result;
        } buf;

        buf.k = k;
        RNGType rng(0);
        rng.enc(buf.ctr, buf.ctr);

        return buf.result;
    }
}; // class Seed

/// \brief RNG default seed generator
/// \ingroup Random
template <typename RNGType, typename ID = std::integral_constant<std::size_t,
                                sizeof(typename SeedType<RNGType>::type)>,
    bool Randomize = true>
using Seed = SeedGenerator<typename SeedType<RNGType>::type, ID, Randomize>;

} // namespace mckl

#endif // MCKL_RANDOM_SEED_HPP
<commit_msg>make Seed a class and can be specialized<commit_after>//============================================================================
// MCKL/include/mckl/random/seed.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef MCKL_RANDOM_SEED_HPP
#define MCKL_RANDOM_SEED_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/skein.hpp>
#include <mckl/random/threefry.hpp>

namespace mckl
{

/// \brief Seed generator
/// \ingroup Random
template <typename ResultType,
    typename ID = std::integral_constant<std::size_t, sizeof(ResultType)>,
    bool Randomize = true>
class SeedGenerator
{
    static_assert(sizeof(ResultType) % sizeof(std::uint32_t) == 0,
        "**SeedGenerator** size of ResultType is not a multiple of uint32_t");

    public:
    /// \brief The type of the internal seed
    using seed_type =
        typename std::conditional<sizeof(ResultType) % sizeof(std::uint64_t) ==
                0,
            std::uint64_t, std::uint32_t>::type;

    using result_type = ResultType;

    SeedGenerator(const SeedGenerator<ResultType, ID, Randomize> &) = delete;

    SeedGenerator<ResultType, ID, Randomize> &operator=(
        const SeedGenerator<ResultType, ID, Randomize> &) = delete;

    static SeedGenerator<ResultType, ID, Randomize> &instance()
    {
        static SeedGenerator<ResultType, ID, Randomize> seed;

        return seed;
    }

    /// \brief Set the internal seed
    void set(seed_type s) { seed_ = s; }

    /// \brief Get the next key
    result_type get() { return get(std::integral_constant<bool, (M_ > 1)>()); }

    /// \brief The number of partitions
    seed_type np() const { return np_; }

    /// \brief The rank of this partition
    seed_type rank() const { return rank_; }

    /// \brief Set the number of partitions and the rank of this partition
    void partition(seed_type np, seed_type rank)
    {
        partition(np, rank, std::integral_constant<bool, (M_ > 1)>());
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const SeedGenerator<ResultType, ID, Randomize> &sg)
    {
        if (!os)
            return os;

        os << sg.np_ << ' ';
        os << sg.rank_ << ' ';
        os << sg.maxs_ << ' ';
        os << sg.seed_ << ' ';

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        SeedGenerator<ResultType, ID, Randomize> &sg)
    {
        if (!is)
            return is;

        seed_type np;
        seed_type rank;
        seed_type maxs;
        seed_type seed;
        is >> std::ws >> np;
        is >> std::ws >> rank;
        is >> std::ws >> maxs;
        is >> std::ws >> seed;

        if (is) {
            sg.np_ = np;
            sg.rank_ = rank;
            sg.maxs_ = maxs;
            sg.seed_ = seed;
        }

        return is;
    }

    private:
    static constexpr std::size_t M_ = sizeof(result_type) / sizeof(seed_type);

    seed_type np_;
    seed_type rank_;
    seed_type maxs_;
    std::atomic<seed_type> seed_;

    SeedGenerator() : seed_(1) { partition(1, 0); }

    void partition(seed_type np, seed_type rank, std::true_type)
    {
        np_ = np;
        rank_ = rank;
        maxs_ = std::numeric_limits<seed_type>::max();
    }

    void partition(seed_type np, seed_type rank, std::false_type)
    {
        runtime_assert(np > 0,
            "**SeedGenerator::partition** the number of the partitions is "
            "zero");
        if (np < 1)
            np = 1;

        runtime_assert(np > rank,
            "**SeedGenerator::partition** the rank is not smaller than the "
            "number of partitions");
        if (rank >= np)
            rank = 0;

        seed_type maxs = std::numeric_limits<seed_type>::max();
        if (np > 1)
            maxs = (maxs - rank) / np + 1;

        np_ = np;
        rank_ = rank;
        maxs_ = maxs;
    }

    result_type get(std::true_type)
    {
        seed_type s = seed_.fetch_add(1);
        std::array<seed_type, M_> k = {{0}};
        k.front() = s;
        k.back() = rank_;

        return randomize(k, std::integral_constant<bool, Randomize>());
    }

    result_type get(std::false_type)
    {
        seed_type s = seed_.fetch_add(1);
        s %= maxs_;
        s *= np_;
        s += rank_;
        std::array<seed_type, M_> k = {{s}};

        return randomize(k, std::integral_constant<bool, Randomize>());
    }

    result_type randomize(const std::array<seed_type, M_> &k, std::false_type)
    {
        union {
            result_type result;
            std::array<seed_type, M_> k;
        } buf;

        buf.k = k;

        return buf.result;
    }

    result_type randomize(const std::array<seed_type, M_> &k, std::true_type)
    {
        return randomize(
            k, std::integral_constant<int,
                   std::numeric_limits<seed_type>::digits * M_>());
    }

    template <int D>
    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, D>)
    {
        result_type result;
        Skein512::hash(Skein512::param_type(D, k.data()), D, &result);

        return result;
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 32>)
    {
        union {
            std::array<std::uint16_t, 2> state;
            std::array<seed_type, M_> k;
            result_type result;
        } buf;

        buf.k = k;
        std::uint16_t x = std::get<0>(buf.state);
        std::uint16_t y = std::get<1>(buf.state);
        for (int i = 0; i != 22; ++i) {
            x = static_cast<std::uint16_t>((x << 9) | (x >> 7));
            x += y;
            y = static_cast<std::uint16_t>((y << 2) | (y >> 14));
            y ^= x;
        }
        std::get<0>(buf.state) = x;
        std::get<1>(buf.state) = y;

        return buf.result;
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 64>)
    {
        return randomize<Threefry2x32>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 128>)
    {
        return randomize<Threefry2x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 256>)
    {
        return randomize<Threefry4x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 512>)
    {
        return randomize<Threefry8x64>(k);
    }

    result_type randomize(
        const std::array<seed_type, M_> &k, std::integral_constant<int, 1024>)
    {
        return randomize<Threefry16x64>(k);
    }

    template <typename RNGType>
    result_type randomize(const std::array<seed_type, M_> &k)
    {
        union {
            typename RNGType::ctr_type ctr;
            std::array<seed_type, M_> k;
            result_type result;
        } buf;

        buf.k = k;
        RNGType rng(0);
        rng.enc(buf.ctr, buf.ctr);

        return buf.result;
    }
}; // class Seed

/// \brief RNG default seed generator
/// \ingroup Random
template <typename RNGType>
class Seed : public SeedGenerator<typename SeedType<RNGType>::type>
{
};

} // namespace mckl

#endif // MCKL_RANDOM_SEED_HPP
<|endoftext|>


<commit_before>#ifndef COFFEE_MILL_MATH_VECTOR_HPP
#define COFFEE_MILL_MATH_VECTOR_HPP
#include "Matrix.hpp"
#include <mill/util/scalar_type_of.hpp>
#include <algorithm>
#include <cmath>

namespace mill
{

template<typename realT, std::size_t N>
using Vector = Matrix<realT, N, 1>;

// for vector 3d
template<typename coordT>
inline typename scalar_type_of<coordT>::type
dot_product(const coordT& lhs, const coordT& rhs)
{
    return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
}

template<typename coordT>
inline coordT
cross_product(const coordT& lhs, const coordT& rhs)
{
    return coordT(lhs[1] * rhs[2] - lhs[2] * rhs[1],
                  lhs[2] * rhs[0] - lhs[0] * rhs[2],
                  lhs[0] * rhs[1] - lhs[1] * rhs[0]);
}

template<typename coordT>
inline typename scalar_type_of<coordT>::type
scalar_triple_product(const coordT& lhs, const coordT& mid, const coordT& rhs)
{
    return (lhs[1] * mid[2] - lhs[2] * mid[1]) * rhs[0] +
           (lhs[2] * mid[0] - lhs[0] * mid[2]) * rhs[1] +
           (lhs[0] * mid[1] - lhs[1] * mid[0]) * rhs[2];
}

template<typename coordT>
inline typename scalar_type_of<coordT>::type
length_sq(const coordT& lhs)
{
    return lhs[0] * lhs[0] + lhs[1] * lhs[1] + lhs[2] * lhs[2];
}

template<typename coordT>
inline typename scalar_type_of<coordT>::type
length(const coordT& lhs)
{
    return std::sqrt(length_sq(lhs));
}

template<typename coordT>
inline coordT regularize(const coordT& v)
{
    return v / length(v);
}

template<typename coordT>
inline typename scalar_type_of<coordT>::type
angle(const coordT& lhs, const coordT& rhs)
{
    using real_type = typename scalar_type_of<coordT>::type;
    const auto l_reg = regularize(lhs);
    const auto r_reg = regularize(rhs);
    return std::acos(std::clamp<real_type>(dot_product(l_reg, r_reg), -1, 1));
}

} // mill
#endif /* COFFEE_MILL_VECTOR */
<commit_msg>:recycle: assume that vec funcs are mill specific<commit_after>#ifndef COFFEE_MILL_MATH_VECTOR_HPP
#define COFFEE_MILL_MATH_VECTOR_HPP
#include "Matrix.hpp"
#include <algorithm>
#include <cmath>

namespace mill
{

template<typename realT, std::size_t N>
using Vector = Matrix<realT, N, 1>;

// for vector 3d
template<typename realT>
realT dot_product(const Vector<realT, 3>& lhs, const Vector<realT, 3>& rhs) noexcept
{
    return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
}

template<typename realT>
Vector<realT, 3>
cross_product(const Vector<realT, 3>& lhs, const Vector<realT, 3>& rhs) noexcept
{
    return Vector<realT, 3>(lhs[1] * rhs[2] - lhs[2] * rhs[1],
                            lhs[2] * rhs[0] - lhs[0] * rhs[2],
                            lhs[0] * rhs[1] - lhs[1] * rhs[0]);
}

template<typename realT>
realT scalar_triple_product(const Vector<realT, 3>& lhs,
        const Vector<realT, 3>& mid, const Vector<realT, 3>& rhs) noexcept
{
    return (lhs[1] * mid[2] - lhs[2] * mid[1]) * rhs[0] +
           (lhs[2] * mid[0] - lhs[0] * mid[2]) * rhs[1] +
           (lhs[0] * mid[1] - lhs[1] * mid[0]) * rhs[2];
}

template<typename realT>
realT length_sq(const Vector<realT, 3>& lhs) noexcept
{
    return lhs[0] * lhs[0] + lhs[1] * lhs[1] + lhs[2] * lhs[2];
}

template<typename realT>
realT length(const Vector<realT, 3>& lhs) noexcept
{
    return std::sqrt(length_sq(lhs));
}

template<typename coordT>
Vector<realT, 3> regularize(const Vector<realT, 3>& v) noexcept
{
    return v * (1.0 / length(v));
}

template<typename realT>
realT angle(const Vector<realT, 3>& lhs, const Vector<realT, 3>& rhs) noexcept
{
    const auto l_reg = regularize(lhs);
    const auto r_reg = regularize(rhs);
    return std::acos(std::clamp<realT>(dot_product(l_reg, r_reg), -1, 1));
}

} // mill
#endif /* COFFEE_MILL_VECTOR */
<|endoftext|>


<commit_before><commit_msg>loplugin:cstylecast: deal with remaining pointer casts<commit_after><|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    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 "Magnum/Context.h"
#include "Magnum/Extensions.h"

namespace Magnum {

void Context::setupDriverWorkarounds() {
    #define _setRequiredVersion(extension, version)                           \
        if(_extensionRequiredVersion[Extensions::extension::Index] < Version::version) \
            _extensionRequiredVersion[Extensions::extension::Index] = Version::version

    #ifndef MAGNUM_TARGET_GLES
    /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30
       on NVidia and 1.40 on Mac OS X */
    /** @todo Different version on different vendors? */
    _setRequiredVersion(GL::ARB::explicit_attrib_location, GL320);
    _setRequiredVersion(GL::ARB::explicit_uniform_location, GL320);
    _setRequiredVersion(GL::ARB::shading_language_420pack, GL320);
    #endif

    #ifdef MAGNUM_TARGET_GLES
    /* Disable extensions for which we need extension loader, as they would
       crash otherwise. */
    /** @todo Remove this when extension loader for ES is available */
    #ifndef CORRADE_TARGET_NACL
    _setRequiredVersion(GL::CHROMIUM::map_sub, None);
    #endif
    _setRequiredVersion(GL::EXT::debug_label, None);
    _setRequiredVersion(GL::EXT::debug_marker, None);
    _setRequiredVersion(GL::EXT::disjoint_timer_query, None);
    _setRequiredVersion(GL::EXT::separate_shader_objects, None);
    _setRequiredVersion(GL::EXT::multisampled_render_to_texture, None);
    _setRequiredVersion(GL::EXT::robustness, None);
    _setRequiredVersion(GL::KHR::debug, None);
    _setRequiredVersion(GL::NV::read_buffer_front, None);
    _setRequiredVersion(GL::OES::mapbuffer, None);
    #ifdef MAGNUM_TARGET_GLES2
    _setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::EXT::discard_framebuffer, None);
    _setRequiredVersion(GL::EXT::blend_minmax, None);
    #ifndef CORRADE_TARGET_NACL
    _setRequiredVersion(GL::EXT::occlusion_query_boolean, None);
    #endif
    _setRequiredVersion(GL::EXT::texture_storage, None);
    _setRequiredVersion(GL::EXT::map_buffer_range, None);
    _setRequiredVersion(GL::NV::draw_buffers, None);
    _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
    _setRequiredVersion(GL::NV::read_buffer, None);
    _setRequiredVersion(GL::NV::framebuffer_multisample, None);
    _setRequiredVersion(GL::OES::texture_3D, None);
    _setRequiredVersion(GL::OES::vertex_array_object, None);
    #endif
    #endif

    #undef _setRequiredVersion
}

}
<commit_msg>Disable ARB_explicit_uniform_location on AMD drivers.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    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 "Magnum/Context.h"
#include "Magnum/Extensions.h"

namespace Magnum {

void Context::setupDriverWorkarounds() {
    #define _setRequiredVersion(extension, version)                           \
        if(_extensionRequiredVersion[Extensions::extension::Index] < Version::version) \
            _extensionRequiredVersion[Extensions::extension::Index] = Version::version

    #ifndef MAGNUM_TARGET_GLES
    /* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */
    const std::string renderer = rendererString();
    if(renderer.find("Advanced Micro Devices") != std::string::npos)
        _setRequiredVersion(GL::ARB::explicit_uniform_location, None);
    #endif

    #ifndef MAGNUM_TARGET_GLES
    /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30
       on NVidia and 1.40 on Mac OS X */
    /** @todo Different version on different vendors? */
    _setRequiredVersion(GL::ARB::explicit_attrib_location, GL320);
    _setRequiredVersion(GL::ARB::explicit_uniform_location, GL320);
    _setRequiredVersion(GL::ARB::shading_language_420pack, GL320);
    #endif

    #ifdef MAGNUM_TARGET_GLES
    /* Disable extensions for which we need extension loader, as they would
       crash otherwise. */
    /** @todo Remove this when extension loader for ES is available */
    #ifndef CORRADE_TARGET_NACL
    _setRequiredVersion(GL::CHROMIUM::map_sub, None);
    #endif
    _setRequiredVersion(GL::EXT::debug_label, None);
    _setRequiredVersion(GL::EXT::debug_marker, None);
    _setRequiredVersion(GL::EXT::disjoint_timer_query, None);
    _setRequiredVersion(GL::EXT::separate_shader_objects, None);
    _setRequiredVersion(GL::EXT::multisampled_render_to_texture, None);
    _setRequiredVersion(GL::EXT::robustness, None);
    _setRequiredVersion(GL::KHR::debug, None);
    _setRequiredVersion(GL::NV::read_buffer_front, None);
    _setRequiredVersion(GL::OES::mapbuffer, None);
    #ifdef MAGNUM_TARGET_GLES2
    _setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::EXT::discard_framebuffer, None);
    _setRequiredVersion(GL::EXT::blend_minmax, None);
    #ifndef CORRADE_TARGET_NACL
    _setRequiredVersion(GL::EXT::occlusion_query_boolean, None);
    #endif
    _setRequiredVersion(GL::EXT::texture_storage, None);
    _setRequiredVersion(GL::EXT::map_buffer_range, None);
    _setRequiredVersion(GL::NV::draw_buffers, None);
    _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
    _setRequiredVersion(GL::NV::read_buffer, None);
    _setRequiredVersion(GL::NV::framebuffer_multisample, None);
    _setRequiredVersion(GL::OES::texture_3D, None);
    _setRequiredVersion(GL::OES::vertex_array_object, None);
    #endif
    #endif

    #undef _setRequiredVersion
}

}
<|endoftext|>