<commit_before>/*
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "net/byteorder.hh"
#include "core/unaligned.hh"
#include "hashing.hh"

/**
 * Utility for writing data into a buffer when its final size is not known up front.
 *
 * Internally the data is written into a chain of chunks allocated on-demand.
 * No resizing of previously written data happens.
 *
 */
class bytes_ostream {
public:
    using size_type = bytes::size_type;
    using value_type = bytes::value_type;
private:
    static_assert(sizeof(value_type) == 1, "value_type is assumed to be one byte long");
    struct chunk {
        // FIXME: group fragment pointers to reduce pointer chasing when packetizing
        std::unique_ptr<chunk> next;
        size_type offset; // Also means "size" after chunk is closed
        size_type size;
        value_type data[0];
        void operator delete(void* ptr) { free(ptr); }
    };
    // FIXME: consider increasing chunk size as the buffer grows
    static constexpr size_type chunk_size{512};
    static constexpr size_type usable_chunk_size{chunk_size - sizeof(chunk)};
private:
    std::unique_ptr<chunk> _begin;
    chunk* _current;
    size_type _size;
public:
    class fragment_iterator : public std::iterator<std::input_iterator_tag, bytes_view> {
        chunk* _current;
    public:
        fragment_iterator(chunk* current) : _current(current) {}
        fragment_iterator(const fragment_iterator&) = default;
        fragment_iterator& operator=(const fragment_iterator&) = default;
        bytes_view operator*() const {
            return { _current->data, _current->offset };
        }
        bytes_view operator->() const {
            return *(*this);
        }
        fragment_iterator& operator++() {
            _current = _current->next.get();
            return *this;
        }
        fragment_iterator operator++(int) {
            fragment_iterator tmp(*this);
            ++(*this);
            return tmp;
        }
        bool operator==(const fragment_iterator& other) const {
            return _current == other._current;
        }
        bool operator!=(const fragment_iterator& other) const {
            return _current != other._current;
        }
    };
private:
    inline size_type current_space_left() const {
        if (!_current) {
            return 0;
        }
        return _current->size - _current->offset;
    }
    // Makes room for a contiguous region of given size.
    // The region is accounted for as already written.
    // size must not be zero.
    value_type* alloc(size_type size) {
        if (size <= current_space_left()) {
            auto ret = _current->data + _current->offset;
            _current->offset += size;
            _size += size;
            return ret;
        } else {
            auto alloc_size = size <= usable_chunk_size ? chunk_size : (size + sizeof(chunk));
            auto space = malloc(alloc_size);
            if (!space) {
                throw std::bad_alloc();
            }
            auto new_chunk = std::unique_ptr<chunk>(new (space) chunk());
            new_chunk->offset = size;
            new_chunk->size = alloc_size - sizeof(chunk);
            if (_current) {
                _current->next = std::move(new_chunk);
                _current = _current->next.get();
            } else {
                _begin = std::move(new_chunk);
                _current = _begin.get();
            }
            _size += size;
            return _current->data;
        };
    }
public:
    bytes_ostream() noexcept
        : _begin()
        , _current(nullptr)
        , _size(0)
    { }

    bytes_ostream(bytes_ostream&& o) noexcept
        : _begin(std::move(o._begin))
        , _current(o._current)
        , _size(o._size)
    {
        o._current = nullptr;
        o._size = 0;
    }

    bytes_ostream(const bytes_ostream& o)
        : _begin()
        , _current(nullptr)
        , _size(0)
    {
        append(o);
    }

    bytes_ostream& operator=(const bytes_ostream& o) {
        _size = 0;
        _current = nullptr;
        _begin = {};
        append(o);
        return *this;
    }

    bytes_ostream& operator=(bytes_ostream&& o) noexcept {
        _size = o._size;
        _begin = std::move(o._begin);
        _current = o._current;
        o._current = nullptr;
        o._size = 0;
        return *this;
    }

    template <typename T>
    struct place_holder {
        value_type* ptr;
    };

    // Writes given values in big-endian format
    template <typename T>
    inline
    std::enable_if_t<std::is_fundamental<T>::value, void>
    write(T val) {
        *reinterpret_cast<unaligned<T>*>(alloc(sizeof(T))) = net::hton(val);
    }

    // Returns a place holder for a value to be written later.
    template <typename T>
    inline
    std::enable_if_t<std::is_fundamental<T>::value, place_holder<T>>
    write_place_holder() {
        return place_holder<T>{alloc(sizeof(T))};
    }

    value_type* write_place_holder(size_type size) {
        return alloc(size);
    }

    // Writes given sequence of bytes
    inline void write(bytes_view v) {
        if (v.empty()) {
            return;
        }
        auto space_left = current_space_left();
        if (v.size() <= space_left) {
            memcpy(_current->data + _current->offset, v.begin(), v.size());
            _current->offset += v.size();
            _size += v.size();
        } else {
            if (space_left) {
                memcpy(_current->data + _current->offset, v.begin(), space_left);
                _current->offset += space_left;
                _size += space_left;
                v.remove_prefix(space_left);
            }
            memcpy(alloc(v.size()), v.begin(), v.size());
        }
    }

    void write(const char* ptr, size_t size) {
        write(bytes_view(reinterpret_cast<const signed char*>(ptr), size));
    }

    // Writes given sequence of bytes with a preceding length component encoded in big-endian format
    inline void write_blob(bytes_view v) {
        assert((size_type)v.size() == v.size());
        write<size_type>(v.size());
        write(v);
    }

    // Writes given value into the place holder in big-endian format
    template <typename T>
    inline void set(place_holder<T> ph, T val) {
        *reinterpret_cast<unaligned<T>*>(ph.ptr) = net::hton(val);
    }

    bool is_linearized() const {
        return !_begin || !_begin->next;
    }

    // Call only when is_linearized()
    bytes_view view() const {
        assert(is_linearized());
        if (!_current) {
            return bytes_view();
        }

        return bytes_view(_current->data, _size);
    }

    // Makes the underlying storage contiguous and returns a view to it.
    // Invalidates all previously created placeholders.
    bytes_view linearize() {
        if (is_linearized()) {
            return view();
        }

        auto space = malloc(_size + sizeof(chunk));
        if (!space) {
            throw std::bad_alloc();
        }

        auto new_chunk = std::unique_ptr<chunk>(new (space) chunk());
        new_chunk->offset = _size;
        new_chunk->size = _size;

        auto dst = new_chunk->data;
        auto r = _begin.get();
        while (r) {
            auto next = r->next.get();
            dst = std::copy_n(r->data, r->offset, dst);
            r = next;
        }

        _current = new_chunk.get();
        _begin = std::move(new_chunk);
        return bytes_view(_current->data, _size);
    }

    // Returns the amount of bytes written so far
    size_type size() const {
        return _size;
    }

    bool empty() const {
        return _size == 0;
    }

    void reserve(size_t size) {
        // FIXME: implement
    }

    void append(const bytes_ostream& o) {
        if (o.size() > 0) {
            auto dst = alloc(o.size());
            auto r = o._begin.get();
            while (r) {
                dst = std::copy_n(r->data, r->offset, dst);
                r = r->next.get();
            }
        }
    }

    // begin() and end() form an input range to bytes_view representing fragments.
    // Any modification of this instance invalidates iterators.
    fragment_iterator begin() const { return { _begin.get() }; }
    fragment_iterator end() const { return { nullptr }; }

    boost::iterator_range<fragment_iterator> fragments() const {
        return { begin(), end() };
    }

    struct position {
        chunk* _chunk;
        size_type _offset;
    };

    position pos() const {
        return { _current, _current ? _current->offset : 0 };
    }

    // Returns the amount of bytes written since given position.
    // "pos" must be valid.
    size_type written_since(position pos) {
        chunk* c = pos._chunk;
        if (!c) {
            return _size;
        }
        size_type total = c->offset - pos._offset;
        c = c->next.get();
        while (c) {
            total += c->offset;
            c = c->next.get();
        }
        return total;
    }

    // Rollbacks all data written after "pos".
    // Invalidates all placeholders and positions created after "pos".
    void retract(position pos) {
        if (!pos._chunk) {
            *this = {};
            return;
        }
        _size -= written_since(pos);
        _current = pos._chunk;
        _current->next = nullptr;
        _current->offset = pos._offset;
    }
};

template<>
struct appending_hash<bytes_ostream> {
    template<typename Hasher>
    void operator()(Hasher& h, const bytes_ostream& b) const {
        for (auto&& frag : b.fragments()) {
            feed_hash(h, frag);
        }
    }
};
<commit_msg>bytes_ostream: Allow place holder return a stream<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "net/byteorder.hh"
#include "core/unaligned.hh"
#include "hashing.hh"
#include "seastar/core/simple-stream.hh"
/**
 * Utility for writing data into a buffer when its final size is not known up front.
 *
 * Internally the data is written into a chain of chunks allocated on-demand.
 * No resizing of previously written data happens.
 *
 */
class bytes_ostream {
public:
    using size_type = bytes::size_type;
    using value_type = bytes::value_type;
private:
    static_assert(sizeof(value_type) == 1, "value_type is assumed to be one byte long");
    struct chunk {
        // FIXME: group fragment pointers to reduce pointer chasing when packetizing
        std::unique_ptr<chunk> next;
        size_type offset; // Also means "size" after chunk is closed
        size_type size;
        value_type data[0];
        void operator delete(void* ptr) { free(ptr); }
    };
    // FIXME: consider increasing chunk size as the buffer grows
    static constexpr size_type chunk_size{512};
    static constexpr size_type usable_chunk_size{chunk_size - sizeof(chunk)};
private:
    std::unique_ptr<chunk> _begin;
    chunk* _current;
    size_type _size;
public:
    class fragment_iterator : public std::iterator<std::input_iterator_tag, bytes_view> {
        chunk* _current;
    public:
        fragment_iterator(chunk* current) : _current(current) {}
        fragment_iterator(const fragment_iterator&) = default;
        fragment_iterator& operator=(const fragment_iterator&) = default;
        bytes_view operator*() const {
            return { _current->data, _current->offset };
        }
        bytes_view operator->() const {
            return *(*this);
        }
        fragment_iterator& operator++() {
            _current = _current->next.get();
            return *this;
        }
        fragment_iterator operator++(int) {
            fragment_iterator tmp(*this);
            ++(*this);
            return tmp;
        }
        bool operator==(const fragment_iterator& other) const {
            return _current == other._current;
        }
        bool operator!=(const fragment_iterator& other) const {
            return _current != other._current;
        }
    };
private:
    inline size_type current_space_left() const {
        if (!_current) {
            return 0;
        }
        return _current->size - _current->offset;
    }
    // Makes room for a contiguous region of given size.
    // The region is accounted for as already written.
    // size must not be zero.
    value_type* alloc(size_type size) {
        if (size <= current_space_left()) {
            auto ret = _current->data + _current->offset;
            _current->offset += size;
            _size += size;
            return ret;
        } else {
            auto alloc_size = size <= usable_chunk_size ? chunk_size : (size + sizeof(chunk));
            auto space = malloc(alloc_size);
            if (!space) {
                throw std::bad_alloc();
            }
            auto new_chunk = std::unique_ptr<chunk>(new (space) chunk());
            new_chunk->offset = size;
            new_chunk->size = alloc_size - sizeof(chunk);
            if (_current) {
                _current->next = std::move(new_chunk);
                _current = _current->next.get();
            } else {
                _begin = std::move(new_chunk);
                _current = _begin.get();
            }
            _size += size;
            return _current->data;
        };
    }
public:
    bytes_ostream() noexcept
        : _begin()
        , _current(nullptr)
        , _size(0)
    { }

    bytes_ostream(bytes_ostream&& o) noexcept
        : _begin(std::move(o._begin))
        , _current(o._current)
        , _size(o._size)
    {
        o._current = nullptr;
        o._size = 0;
    }

    bytes_ostream(const bytes_ostream& o)
        : _begin()
        , _current(nullptr)
        , _size(0)
    {
        append(o);
    }

    bytes_ostream& operator=(const bytes_ostream& o) {
        _size = 0;
        _current = nullptr;
        _begin = {};
        append(o);
        return *this;
    }

    bytes_ostream& operator=(bytes_ostream&& o) noexcept {
        _size = o._size;
        _begin = std::move(o._begin);
        _current = o._current;
        o._current = nullptr;
        o._size = 0;
        return *this;
    }

    template <typename T>
    struct place_holder {
        value_type* ptr;
        // makes the place_holder looks like a stream
        seastar::simple_output_stream get_stream() {
            return seastar::simple_output_stream{reinterpret_cast<char*>(ptr)};
        }
    };

    // Writes given values in big-endian format
    template <typename T>
    inline
    std::enable_if_t<std::is_fundamental<T>::value, void>
    write(T val) {
        *reinterpret_cast<unaligned<T>*>(alloc(sizeof(T))) = net::hton(val);
    }

    // Returns a place holder for a value to be written later.
    template <typename T>
    inline
    std::enable_if_t<std::is_fundamental<T>::value, place_holder<T>>
    write_place_holder() {
        return place_holder<T>{alloc(sizeof(T))};
    }

    value_type* write_place_holder(size_type size) {
        return alloc(size);
    }

    // Writes given sequence of bytes
    inline void write(bytes_view v) {
        if (v.empty()) {
            return;
        }
        auto space_left = current_space_left();
        if (v.size() <= space_left) {
            memcpy(_current->data + _current->offset, v.begin(), v.size());
            _current->offset += v.size();
            _size += v.size();
        } else {
            if (space_left) {
                memcpy(_current->data + _current->offset, v.begin(), space_left);
                _current->offset += space_left;
                _size += space_left;
                v.remove_prefix(space_left);
            }
            memcpy(alloc(v.size()), v.begin(), v.size());
        }
    }

    void write(const char* ptr, size_t size) {
        write(bytes_view(reinterpret_cast<const signed char*>(ptr), size));
    }

    // Writes given sequence of bytes with a preceding length component encoded in big-endian format
    inline void write_blob(bytes_view v) {
        assert((size_type)v.size() == v.size());
        write<size_type>(v.size());
        write(v);
    }

    // Writes given value into the place holder in big-endian format
    template <typename T>
    inline void set(place_holder<T> ph, T val) {
        *reinterpret_cast<unaligned<T>*>(ph.ptr) = net::hton(val);
    }

    bool is_linearized() const {
        return !_begin || !_begin->next;
    }

    // Call only when is_linearized()
    bytes_view view() const {
        assert(is_linearized());
        if (!_current) {
            return bytes_view();
        }

        return bytes_view(_current->data, _size);
    }

    // Makes the underlying storage contiguous and returns a view to it.
    // Invalidates all previously created placeholders.
    bytes_view linearize() {
        if (is_linearized()) {
            return view();
        }

        auto space = malloc(_size + sizeof(chunk));
        if (!space) {
            throw std::bad_alloc();
        }

        auto new_chunk = std::unique_ptr<chunk>(new (space) chunk());
        new_chunk->offset = _size;
        new_chunk->size = _size;

        auto dst = new_chunk->data;
        auto r = _begin.get();
        while (r) {
            auto next = r->next.get();
            dst = std::copy_n(r->data, r->offset, dst);
            r = next;
        }

        _current = new_chunk.get();
        _begin = std::move(new_chunk);
        return bytes_view(_current->data, _size);
    }

    // Returns the amount of bytes written so far
    size_type size() const {
        return _size;
    }

    bool empty() const {
        return _size == 0;
    }

    void reserve(size_t size) {
        // FIXME: implement
    }

    void append(const bytes_ostream& o) {
        if (o.size() > 0) {
            auto dst = alloc(o.size());
            auto r = o._begin.get();
            while (r) {
                dst = std::copy_n(r->data, r->offset, dst);
                r = r->next.get();
            }
        }
    }

    // begin() and end() form an input range to bytes_view representing fragments.
    // Any modification of this instance invalidates iterators.
    fragment_iterator begin() const { return { _begin.get() }; }
    fragment_iterator end() const { return { nullptr }; }

    boost::iterator_range<fragment_iterator> fragments() const {
        return { begin(), end() };
    }

    struct position {
        chunk* _chunk;
        size_type _offset;
    };

    position pos() const {
        return { _current, _current ? _current->offset : 0 };
    }

    // Returns the amount of bytes written since given position.
    // "pos" must be valid.
    size_type written_since(position pos) {
        chunk* c = pos._chunk;
        if (!c) {
            return _size;
        }
        size_type total = c->offset - pos._offset;
        c = c->next.get();
        while (c) {
            total += c->offset;
            c = c->next.get();
        }
        return total;
    }

    // Rollbacks all data written after "pos".
    // Invalidates all placeholders and positions created after "pos".
    void retract(position pos) {
        if (!pos._chunk) {
            *this = {};
            return;
        }
        _size -= written_since(pos);
        _current = pos._chunk;
        _current->next = nullptr;
        _current->offset = pos._offset;
    }
};

template<>
struct appending_hash<bytes_ostream> {
    template<typename Hasher>
    void operator()(Hasher& h, const bytes_ostream& b) const {
        for (auto&& frag : b.fragments()) {
            feed_hash(h, frag);
        }
    }
};
<|endoftext|>


<commit_before>// Copyright 2010-2013 RethinkDB, all rights reserved.
#ifndef CONTAINERS_SCOPED_HPP_
#define CONTAINERS_SCOPED_HPP_

#include <string.h>

#include <utility>

#include "errors.hpp"

// Like boost::scoped_ptr only with release, init, no bool conversion, no boost headers!
template <class T>
class scoped_ptr_t {
public:
    template <class U>
    friend class scoped_ptr_t;

    scoped_ptr_t() : ptr_(NULL) { }
    explicit scoped_ptr_t(T *p) : ptr_(p) { }
    scoped_ptr_t(scoped_ptr_t &&movee) : ptr_(movee.ptr_) {
        movee.ptr_ = NULL;
    }
    template <class U>
    scoped_ptr_t(scoped_ptr_t<U> &&movee) : ptr_(movee.ptr_) {
        movee.ptr_ = NULL;
    }

    ~scoped_ptr_t() {
        reset();
    }

    scoped_ptr_t &operator=(scoped_ptr_t &&movee) {
        scoped_ptr_t tmp(std::move(movee));
        swap(tmp);
        return *this;
    }

    template <class U>
    scoped_ptr_t &operator=(scoped_ptr_t<U> &&movee) {
        scoped_ptr_t tmp(std::move(movee));
        swap(tmp);
        return *this;
    }

    template <class U>
    void init(scoped_ptr_t<U> &&movee) {
        rassert(ptr_ == NULL);

        operator=(std::move(movee));
    }

    // includes a sanity-check for first-time use.
    void init(T *value) {
        rassert(ptr_ == NULL);

        // This is like reset with an assert.
        T *tmp = ptr_;
        ptr_ = value;
        delete tmp;
    }

    void reset() {
        T *tmp = ptr_;
        ptr_ = NULL;
        delete tmp;
    }

    MUST_USE T *release() {
        T *tmp = ptr_;
        ptr_ = NULL;
        return tmp;
    }

    void swap(scoped_ptr_t& other) {
        T *tmp = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = tmp;
    }

    T &operator*() const {
        rassert(ptr_);
        return *ptr_;
    }

    T *get() const {
        rassert(ptr_);
        return ptr_;
    }

    T *get_or_null() const {
        return ptr_;
    }

    T *operator->() const {
        rassert(ptr_);
        return ptr_;
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;

    DISABLE_COPYING(scoped_ptr_t);
};

template <class T, class... Args>
scoped_ptr_t<T> make_scoped_ptr(Args&&... args) {
    return scoped_ptr_t<T>(new T(std::forward<Args>(args)...));
}

// Not really like boost::scoped_array.  A fascist array.
template <class T>
class scoped_array_t {
public:
    scoped_array_t() : ptr_(NULL), size_(0) { }
    explicit scoped_array_t(ssize_t n) : ptr_(NULL), size_(0) {
        init(n);
    }

    scoped_array_t(T *ptr, ssize_t size) : ptr_(NULL), size_(0) {
        init(ptr, size);
    }

    ~scoped_array_t() {
        reset();
    }

    void init(ssize_t n) {
        rassert(ptr_ == NULL);
        rassert(n >= 0);

        ptr_ = new T[n];
        size_ = n;
    }

    // The opposite of release.
    void init(T *ptr, ssize_t size) {
        rassert(ptr != NULL);
        rassert(ptr_ == NULL);
        rassert(size >= 0);

        ptr_ = ptr;
        size_ = size;
    }

    void reset() {
        T *tmp = ptr_;
        ptr_ = NULL;
        size_ = 0;
        delete[] tmp;
    }

    MUST_USE T *release(ssize_t *size_out) {
        *size_out = size_;
        T *tmp = ptr_;
        ptr_ = NULL;
        size_ = 0;
        return tmp;
    }

    void swap(scoped_array_t &other) {
        T *tmp = ptr_;
        ssize_t tmpsize = size_;
        ptr_ = other.ptr_;
        size_ = other.size_;
        other.ptr_ = tmp;
        other.size_ = tmpsize;
    }

    T& operator[](ssize_t i) const {
        rassert(ptr_);
        rassert(0 <= i && i < size_);
        return ptr_[i];
    }

    T *data() const {
        rassert(ptr_);
        return ptr_;
    }

    ssize_t size() const {
        rassert(ptr_);
        return size_;
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;
    ssize_t size_;

    DISABLE_COPYING(scoped_array_t);
};

// For dumb structs that get malloc/free for allocation.

template <class T>
class scoped_malloc_t {
public:
    scoped_malloc_t() : ptr_(NULL) { }
    explicit scoped_malloc_t(size_t n) : ptr_(reinterpret_cast<T *>(malloc(n))) { }
    scoped_malloc_t(const char *beg, const char *end) {
        rassert(beg <= end);
        size_t n = end - beg;
        ptr_ = reinterpret_cast<T *>(malloc(n));
        memcpy(ptr_, beg, n);
    }
    ~scoped_malloc_t() {
        free(ptr_);
    }

    T *get() { return ptr_; }
    const T *get() const { return ptr_; }
    T *operator->() { return ptr_; }
    const T *operator->() const { return ptr_; }
    T& operator*() { return *ptr_; }

    void reset() {
        scoped_malloc_t tmp;
        swap(tmp);
    }

    void swap(scoped_malloc_t& other) {  // NOLINT
        T *tmp = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = tmp;
    }

    template <class U>
    friend class scoped_malloc_t;

    template <class U>
    void reinterpret_swap(scoped_malloc_t<U>& other) {
        T *tmp = ptr_;
        ptr_ = reinterpret_cast<T *>(other.ptr_);
        other.ptr_ = reinterpret_cast<U *>(tmp);
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;

    // DISABLE_COPYING
    scoped_malloc_t(const scoped_malloc_t&);
    void operator=(const scoped_malloc_t&);
};

#endif  // CONTAINERS_SCOPED_HPP_
<commit_msg>Renamed make_scoped_ptr to make_scoped.<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.
#ifndef CONTAINERS_SCOPED_HPP_
#define CONTAINERS_SCOPED_HPP_

#include <string.h>

#include <utility>

#include "errors.hpp"

// Like boost::scoped_ptr only with release, init, no bool conversion, no boost headers!
template <class T>
class scoped_ptr_t {
public:
    template <class U>
    friend class scoped_ptr_t;

    scoped_ptr_t() : ptr_(NULL) { }
    explicit scoped_ptr_t(T *p) : ptr_(p) { }
    scoped_ptr_t(scoped_ptr_t &&movee) : ptr_(movee.ptr_) {
        movee.ptr_ = NULL;
    }
    template <class U>
    scoped_ptr_t(scoped_ptr_t<U> &&movee) : ptr_(movee.ptr_) {
        movee.ptr_ = NULL;
    }

    ~scoped_ptr_t() {
        reset();
    }

    scoped_ptr_t &operator=(scoped_ptr_t &&movee) {
        scoped_ptr_t tmp(std::move(movee));
        swap(tmp);
        return *this;
    }

    template <class U>
    scoped_ptr_t &operator=(scoped_ptr_t<U> &&movee) {
        scoped_ptr_t tmp(std::move(movee));
        swap(tmp);
        return *this;
    }

    template <class U>
    void init(scoped_ptr_t<U> &&movee) {
        rassert(ptr_ == NULL);

        operator=(std::move(movee));
    }

    // includes a sanity-check for first-time use.
    void init(T *value) {
        rassert(ptr_ == NULL);

        // This is like reset with an assert.
        T *tmp = ptr_;
        ptr_ = value;
        delete tmp;
    }

    void reset() {
        T *tmp = ptr_;
        ptr_ = NULL;
        delete tmp;
    }

    MUST_USE T *release() {
        T *tmp = ptr_;
        ptr_ = NULL;
        return tmp;
    }

    void swap(scoped_ptr_t& other) {
        T *tmp = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = tmp;
    }

    T &operator*() const {
        rassert(ptr_);
        return *ptr_;
    }

    T *get() const {
        rassert(ptr_);
        return ptr_;
    }

    T *get_or_null() const {
        return ptr_;
    }

    T *operator->() const {
        rassert(ptr_);
        return ptr_;
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;

    DISABLE_COPYING(scoped_ptr_t);
};

template <class T, class... Args>
scoped_ptr_t<T> make_scoped(Args&&... args) {
    return scoped_ptr_t<T>(new T(std::forward<Args>(args)...));
}

// Not really like boost::scoped_array.  A fascist array.
template <class T>
class scoped_array_t {
public:
    scoped_array_t() : ptr_(NULL), size_(0) { }
    explicit scoped_array_t(ssize_t n) : ptr_(NULL), size_(0) {
        init(n);
    }

    scoped_array_t(T *ptr, ssize_t size) : ptr_(NULL), size_(0) {
        init(ptr, size);
    }

    ~scoped_array_t() {
        reset();
    }

    void init(ssize_t n) {
        rassert(ptr_ == NULL);
        rassert(n >= 0);

        ptr_ = new T[n];
        size_ = n;
    }

    // The opposite of release.
    void init(T *ptr, ssize_t size) {
        rassert(ptr != NULL);
        rassert(ptr_ == NULL);
        rassert(size >= 0);

        ptr_ = ptr;
        size_ = size;
    }

    void reset() {
        T *tmp = ptr_;
        ptr_ = NULL;
        size_ = 0;
        delete[] tmp;
    }

    MUST_USE T *release(ssize_t *size_out) {
        *size_out = size_;
        T *tmp = ptr_;
        ptr_ = NULL;
        size_ = 0;
        return tmp;
    }

    void swap(scoped_array_t &other) {
        T *tmp = ptr_;
        ssize_t tmpsize = size_;
        ptr_ = other.ptr_;
        size_ = other.size_;
        other.ptr_ = tmp;
        other.size_ = tmpsize;
    }

    T& operator[](ssize_t i) const {
        rassert(ptr_);
        rassert(0 <= i && i < size_);
        return ptr_[i];
    }

    T *data() const {
        rassert(ptr_);
        return ptr_;
    }

    ssize_t size() const {
        rassert(ptr_);
        return size_;
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;
    ssize_t size_;

    DISABLE_COPYING(scoped_array_t);
};

// For dumb structs that get malloc/free for allocation.

template <class T>
class scoped_malloc_t {
public:
    scoped_malloc_t() : ptr_(NULL) { }
    explicit scoped_malloc_t(size_t n) : ptr_(reinterpret_cast<T *>(malloc(n))) { }
    scoped_malloc_t(const char *beg, const char *end) {
        rassert(beg <= end);
        size_t n = end - beg;
        ptr_ = reinterpret_cast<T *>(malloc(n));
        memcpy(ptr_, beg, n);
    }
    ~scoped_malloc_t() {
        free(ptr_);
    }

    T *get() { return ptr_; }
    const T *get() const { return ptr_; }
    T *operator->() { return ptr_; }
    const T *operator->() const { return ptr_; }
    T& operator*() { return *ptr_; }

    void reset() {
        scoped_malloc_t tmp;
        swap(tmp);
    }

    void swap(scoped_malloc_t& other) {  // NOLINT
        T *tmp = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = tmp;
    }

    template <class U>
    friend class scoped_malloc_t;

    template <class U>
    void reinterpret_swap(scoped_malloc_t<U>& other) {
        T *tmp = ptr_;
        ptr_ = reinterpret_cast<T *>(other.ptr_);
        other.ptr_ = reinterpret_cast<U *>(tmp);
    }

    bool has() const {
        return ptr_ != NULL;
    }

private:
    T *ptr_;

    // DISABLE_COPYING
    scoped_malloc_t(const scoped_malloc_t&);
    void operator=(const scoped_malloc_t&);
};

#endif  // CONTAINERS_SCOPED_HPP_
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  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.
 */

/**
 * @file
 *   This file includes functions for debugging.
 */

#ifndef DEBUG_HPP_
#define DEBUG_HPP_

#include "openthread-core-config.h"

#include <ctype.h>
#include <stdio.h>
#include "utils/wrap_string.h"

#if defined(OPENTHREAD_TARGET_DARWIN) || defined(OPENTHREAD_TARGET_LINUX)

#include <assert.h>

#elif OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT

#include "openthread/platform/misc.h"

/**
 * Allow the build system to provide a custom file name.
 *
 */
#ifndef FILE_NAME
#define FILE_NAME __FILE__
#endif

#define assert(cond)                               \
    do                                             \
    {                                              \
        if (!(cond))                               \
        {                                          \
            otPlatAssertFail(FILE_NAME, __LINE__); \
            while (1)                              \
            {                                      \
            }                                      \
        }                                          \
    } while (0)

#else

#define assert(cond)  \
    do                \
    {                 \
        if (!(cond))  \
        {             \
            while (1) \
            {         \
            }         \
        }             \
    } while (0)

#endif

#endif // DEBUG_HPP_
<commit_msg>[debug] override any existing assert definitions (#4329)<commit_after>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  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.
 */

/**
 * @file
 *   This file includes functions for debugging.
 */

#ifndef DEBUG_HPP_
#define DEBUG_HPP_

#include "openthread-core-config.h"

#include <ctype.h>
#include <stdio.h>
#include "utils/wrap_string.h"

#if defined(OPENTHREAD_TARGET_DARWIN) || defined(OPENTHREAD_TARGET_LINUX)

#include <assert.h>

#elif OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT

#include "openthread/platform/misc.h"

/**
 * Allow the build system to provide a custom file name.
 *
 */
#ifndef FILE_NAME
#define FILE_NAME __FILE__
#endif

#ifdef assert
#undef assert
#endif

#define assert(cond)                               \
    do                                             \
    {                                              \
        if (!(cond))                               \
        {                                          \
            otPlatAssertFail(FILE_NAME, __LINE__); \
            while (1)                              \
            {                                      \
            }                                      \
        }                                          \
    } while (0)

#else

#ifdef assert
#undef assert
#endif

#define assert(cond)  \
    do                \
    {                 \
        if (!(cond))  \
        {             \
            while (1) \
            {         \
            }         \
        }             \
    } while (0)

#endif

#endif // DEBUG_HPP_
<|endoftext|>


<commit_before>#include "KeyCode.hpp"

namespace org_pqrs_KeyRemap4MacBook {
#include "keycode/output/include.EventType.cpp"
#include "keycode/output/include.KeyboardType.cpp"
#include "keycode/output/include.ModifierFlag.cpp"
#include "keycode/output/include.KeyCode.cpp"
#include "keycode/output/include.ConsumerKeyCode.cpp"
#include "keycode/output/include.PointingButton.cpp"

  // ------------------------------------------------------------
  bool
  EventType::isKeyDownOrModifierDown(KeyCode key, Flags flags) const
  {
    if (*this == EventType::DOWN) return true;
    if (*this == EventType::MODIFY) {
      return flags.isOn(key.getModifierFlag());
    }
    return false;
  }

  bool
  KeyCode::FNKeyHack::remap(KeyCode& key, Flags flags, EventType eventType, bool& active, KeyCode fromKeyCode, KeyCode toKeyCode)
  {
    if (key != fromKeyCode) return false;

    bool isKeyDown = eventType.isKeyDownOrModifierDown(key, flags);
    if (isKeyDown) {
      if (! flags.isOn(ModifierFlag::FN)) return false;
      active = true;
    } else {
      if (! active) return false;
      active = false;
    }

    key = toKeyCode;

    return true;
  }

  namespace {
    KeyCode::FNKeyHack fnkeyhack[] = {
      KeyCode::FNKeyHack(KeyCode::KEYPAD_0, KeyCode::M),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_1, KeyCode::J),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_2, KeyCode::K),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_3, KeyCode::L),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_4, KeyCode::U),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_5, KeyCode::I),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_6, KeyCode::O),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_7, KeyCode::KEY_7),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_8, KeyCode::KEY_8),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_9, KeyCode::KEY_9),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_CLEAR, KeyCode::KEY_6),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_PLUS, KeyCode::SLASH),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_MINUS, KeyCode::SEMICOLON),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_MULTIPLY, KeyCode::P),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_SLASH, KeyCode::KEY_0),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_EQUAL, KeyCode::MINUS),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_DOT, KeyCode::DOT),
      KeyCode::FNKeyHack(KeyCode::PAGEUP, KeyCode::CURSOR_UP),
      KeyCode::FNKeyHack(KeyCode::PAGEDOWN, KeyCode::CURSOR_DOWN),
      KeyCode::FNKeyHack(KeyCode::HOME, KeyCode::CURSOR_LEFT),
      KeyCode::FNKeyHack(KeyCode::END, KeyCode::CURSOR_RIGHT),
      KeyCode::FNKeyHack(KeyCode::ENTER, KeyCode::RETURN),
      KeyCode::FNKeyHack(KeyCode::FORWARD_DELETE, KeyCode::DELETE),
    };
  }

  void
  KeyCode::normalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType)
  {
    // We can drop CURSOR and KEYPAD flags, because we'll set these flags at reverseNormalizeKey.
    flags.stripCURSOR().stripKEYPAD();

    if (keyboardType == KeyboardType::POWERBOOK ||
        keyboardType == KeyboardType::POWERBOOK_G4 ||
        keyboardType == KeyboardType::POWERBOOK_G4_TI) {
      if (*this == KeyCode::ENTER_POWERBOOK) { *this = KeyCode::ENTER; }
    }

    for (unsigned int i = 0; i < sizeof(fnkeyhack) / sizeof(fnkeyhack[0]); ++i) {
      fnkeyhack[i].normalize(*this, flags, eventType);
    }
  }

  void
  KeyCode::reverseNormalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType)
  {
    for (unsigned int i = 0; i < sizeof(fnkeyhack) / sizeof(fnkeyhack[0]); ++i) {
      fnkeyhack[i].reverse(*this, flags, eventType);
    }

    if (keyboardType == KeyboardType::POWERBOOK ||
        keyboardType == KeyboardType::POWERBOOK_G4 ||
        keyboardType == KeyboardType::POWERBOOK_G4_TI) {
      if (*this == KeyCode::ENTER) { *this = KeyCode::ENTER_POWERBOOK; }
    }

    // ------------------------------------------------------------
    // set ModifierFlag::FN
    //
    // We add ModifierFlag::FN for Cocoa Application.
    // Cocoa Application manages the flag status inside,
    // so unless we attach FN, the flag status becomes invalid in Cocoa.
    if (*this == KeyCode::HOME ||
        *this == KeyCode::END ||
        *this == KeyCode::PAGEUP ||
        *this == KeyCode::PAGEDOWN ||
        *this == KeyCode::FORWARD_DELETE ||
        *this == KeyCode::HELP) {
      flags.add(ModifierFlag::FN);
    }

    // ------------------------------------------------------------
    // set ModifierFlag::KEYPAD, ModifierFlag::CURSOR
    flags.stripCURSOR().stripKEYPAD();

    // Note: KEYPAD_CLEAR, KEYPAD_COMMA have no ModifierFlag::KEYPAD bit.
    if (*this == KeyCode::KEYPAD_0 || *this == KeyCode::KEYPAD_1 || *this == KeyCode::KEYPAD_2 ||
        *this == KeyCode::KEYPAD_3 || *this == KeyCode::KEYPAD_4 || *this == KeyCode::KEYPAD_5 ||
        *this == KeyCode::KEYPAD_6 || *this == KeyCode::KEYPAD_7 || *this == KeyCode::KEYPAD_8 ||
        *this == KeyCode::KEYPAD_9 ||
        *this == KeyCode::KEYPAD_DOT ||
        *this == KeyCode::KEYPAD_MULTIPLY ||
        *this == KeyCode::KEYPAD_PLUS ||
        *this == KeyCode::KEYPAD_SLASH ||
        *this == KeyCode::KEYPAD_MINUS ||
        *this == KeyCode::KEYPAD_EQUAL) {
      flags.add(ModifierFlag::KEYPAD);
    }

    if (*this == KeyCode::CURSOR_UP ||
        *this == KeyCode::CURSOR_DOWN ||
        *this == KeyCode::CURSOR_LEFT ||
        *this == KeyCode::CURSOR_RIGHT) {
      flags.add(ModifierFlag::CURSOR);
    }
  }

  KeyCode
  ModifierFlag::getKeyCode(void) const {
    if (*this == ModifierFlag::CAPSLOCK) return KeyCode::CAPSLOCK;
    if (*this == ModifierFlag::SHIFT_L) return KeyCode::SHIFT_L;
    if (*this == ModifierFlag::SHIFT_R) return KeyCode::SHIFT_R;
    if (*this == ModifierFlag::CONTROL_L) return KeyCode::CONTROL_L;
    if (*this == ModifierFlag::CONTROL_R) return KeyCode::CONTROL_R;
    if (*this == ModifierFlag::OPTION_L) return KeyCode::OPTION_L;
    if (*this == ModifierFlag::OPTION_R) return KeyCode::OPTION_R;
    if (*this == ModifierFlag::COMMAND_L) return KeyCode::COMMAND_L;
    if (*this == ModifierFlag::COMMAND_R) return KeyCode::COMMAND_R;
    if (*this == ModifierFlag::FN) return KeyCode::FN;
    if (*this == ModifierFlag::EXTRA1) return KeyCode::VK_MODIFIER_EXTRA1;
    if (*this == ModifierFlag::EXTRA2) return KeyCode::VK_MODIFIER_EXTRA2;
    if (*this == ModifierFlag::EXTRA3) return KeyCode::VK_MODIFIER_EXTRA3;
    if (*this == ModifierFlag::EXTRA4) return KeyCode::VK_MODIFIER_EXTRA4;
    if (*this == ModifierFlag::EXTRA5) return KeyCode::VK_MODIFIER_EXTRA5;

    return KeyCode::VK_NONE;
  }

  ModifierFlag
  KeyCode::getModifierFlag(void) const
  {
    if (*this == KeyCode::CAPSLOCK) return ModifierFlag::CAPSLOCK;
    if (*this == KeyCode::SHIFT_L) return ModifierFlag::SHIFT_L;
    if (*this == KeyCode::SHIFT_R) return ModifierFlag::SHIFT_R;
    if (*this == KeyCode::CONTROL_L) return ModifierFlag::CONTROL_L;
    if (*this == KeyCode::CONTROL_R) return ModifierFlag::CONTROL_R;
    if (*this == KeyCode::OPTION_L) return ModifierFlag::OPTION_L;
    if (*this == KeyCode::OPTION_R) return ModifierFlag::OPTION_R;
    if (*this == KeyCode::COMMAND_L) return ModifierFlag::COMMAND_L;
    if (*this == KeyCode::COMMAND_R) return ModifierFlag::COMMAND_R;
    if (*this == KeyCode::FN) return ModifierFlag::FN;
    if (*this == KeyCode::VK_MODIFIER_EXTRA1) return ModifierFlag::EXTRA1;
    if (*this == KeyCode::VK_MODIFIER_EXTRA2) return ModifierFlag::EXTRA2;
    if (*this == KeyCode::VK_MODIFIER_EXTRA3) return ModifierFlag::EXTRA3;
    if (*this == KeyCode::VK_MODIFIER_EXTRA4) return ModifierFlag::EXTRA4;
    if (*this == KeyCode::VK_MODIFIER_EXTRA5) return ModifierFlag::EXTRA5;

    return ModifierFlag::NONE;
  }
}
<commit_msg>update KeyCode.cpp<commit_after>#include "KeyCode.hpp"

namespace org_pqrs_KeyRemap4MacBook {
#include "keycode/output/include.EventType.cpp"
#include "keycode/output/include.KeyboardType.cpp"
#include "keycode/output/include.ModifierFlag.cpp"
#include "keycode/output/include.KeyCode.cpp"
#include "keycode/output/include.ConsumerKeyCode.cpp"
#include "keycode/output/include.PointingButton.cpp"

  // ------------------------------------------------------------
  bool
  EventType::isKeyDownOrModifierDown(KeyCode key, Flags flags) const
  {
    if (*this == EventType::DOWN) return true;
    if (*this == EventType::MODIFY) {
      return flags.isOn(key.getModifierFlag());
    }
    return false;
  }

  bool
  KeyCode::FNKeyHack::remap(KeyCode& key, Flags flags, EventType eventType, bool& active, KeyCode fromKeyCode, KeyCode toKeyCode)
  {
    if (key != fromKeyCode) return false;

    bool isKeyDown = eventType.isKeyDownOrModifierDown(key, flags);
    if (isKeyDown) {
      if (! flags.isOn(ModifierFlag::FN)) return false;
      active = true;
    } else {
      if (! active) return false;
      active = false;
    }

    key = toKeyCode;

    return true;
  }

  namespace {
    KeyCode::FNKeyHack fnkeyhack[] = {
      KeyCode::FNKeyHack(KeyCode::KEYPAD_0, KeyCode::M),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_1, KeyCode::J),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_2, KeyCode::K),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_3, KeyCode::L),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_4, KeyCode::U),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_5, KeyCode::I),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_6, KeyCode::O),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_7, KeyCode::KEY_7),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_8, KeyCode::KEY_8),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_9, KeyCode::KEY_9),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_CLEAR, KeyCode::KEY_6),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_PLUS, KeyCode::SLASH),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_MINUS, KeyCode::SEMICOLON),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_MULTIPLY, KeyCode::P),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_SLASH, KeyCode::KEY_0),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_EQUAL, KeyCode::MINUS),
      KeyCode::FNKeyHack(KeyCode::KEYPAD_DOT, KeyCode::DOT),
      KeyCode::FNKeyHack(KeyCode::PAGEUP, KeyCode::CURSOR_UP),
      KeyCode::FNKeyHack(KeyCode::PAGEDOWN, KeyCode::CURSOR_DOWN),
      KeyCode::FNKeyHack(KeyCode::HOME, KeyCode::CURSOR_LEFT),
      KeyCode::FNKeyHack(KeyCode::END, KeyCode::CURSOR_RIGHT),
      KeyCode::FNKeyHack(KeyCode::ENTER, KeyCode::RETURN),
      KeyCode::FNKeyHack(KeyCode::FORWARD_DELETE, KeyCode::DELETE),
    };
  }

  void
  KeyCode::normalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType)
  {
    // We can drop CURSOR and KEYPAD flags, because we'll set these flags at reverseNormalizeKey.
    flags.stripCURSOR().stripKEYPAD();

    if (keyboardType == KeyboardType::POWERBOOK ||
        keyboardType == KeyboardType::POWERBOOK_G4 ||
        keyboardType == KeyboardType::POWERBOOK_G4_TI) {
      if (*this == KeyCode::ENTER_POWERBOOK) { *this = KeyCode::ENTER; }
    }

    for (unsigned int i = 0; i < sizeof(fnkeyhack) / sizeof(fnkeyhack[0]); ++i) {
      if (fnkeyhack[i].normalize(*this, flags, eventType)) break;
    }
  }

  void
  KeyCode::reverseNormalizeKey(Flags& flags, EventType eventType, KeyboardType keyboardType)
  {
    for (unsigned int i = 0; i < sizeof(fnkeyhack) / sizeof(fnkeyhack[0]); ++i) {
      if (fnkeyhack[i].reverse(*this, flags, eventType)) break;
    }

    if (keyboardType == KeyboardType::POWERBOOK ||
        keyboardType == KeyboardType::POWERBOOK_G4 ||
        keyboardType == KeyboardType::POWERBOOK_G4_TI) {
      if (*this == KeyCode::ENTER) { *this = KeyCode::ENTER_POWERBOOK; }
    }

    // ------------------------------------------------------------
    // set ModifierFlag::FN
    //
    // We add ModifierFlag::FN for Cocoa Application.
    // Cocoa Application manages the flag status inside,
    // so unless we attach FN, the flag status becomes invalid in Cocoa.
    if (*this == KeyCode::HOME ||
        *this == KeyCode::END ||
        *this == KeyCode::PAGEUP ||
        *this == KeyCode::PAGEDOWN ||
        *this == KeyCode::FORWARD_DELETE ||
        *this == KeyCode::HELP) {
      flags.add(ModifierFlag::FN);
    }

    // ------------------------------------------------------------
    // set ModifierFlag::KEYPAD, ModifierFlag::CURSOR
    flags.stripCURSOR().stripKEYPAD();

    // Note: KEYPAD_CLEAR, KEYPAD_COMMA have no ModifierFlag::KEYPAD bit.
    if (*this == KeyCode::KEYPAD_0 || *this == KeyCode::KEYPAD_1 || *this == KeyCode::KEYPAD_2 ||
        *this == KeyCode::KEYPAD_3 || *this == KeyCode::KEYPAD_4 || *this == KeyCode::KEYPAD_5 ||
        *this == KeyCode::KEYPAD_6 || *this == KeyCode::KEYPAD_7 || *this == KeyCode::KEYPAD_8 ||
        *this == KeyCode::KEYPAD_9 ||
        *this == KeyCode::KEYPAD_DOT ||
        *this == KeyCode::KEYPAD_MULTIPLY ||
        *this == KeyCode::KEYPAD_PLUS ||
        *this == KeyCode::KEYPAD_SLASH ||
        *this == KeyCode::KEYPAD_MINUS ||
        *this == KeyCode::KEYPAD_EQUAL) {
      flags.add(ModifierFlag::KEYPAD);
    }

    if (*this == KeyCode::CURSOR_UP ||
        *this == KeyCode::CURSOR_DOWN ||
        *this == KeyCode::CURSOR_LEFT ||
        *this == KeyCode::CURSOR_RIGHT) {
      flags.add(ModifierFlag::CURSOR);
    }
  }

  KeyCode
  ModifierFlag::getKeyCode(void) const {
    if (*this == ModifierFlag::CAPSLOCK) return KeyCode::CAPSLOCK;
    if (*this == ModifierFlag::SHIFT_L) return KeyCode::SHIFT_L;
    if (*this == ModifierFlag::SHIFT_R) return KeyCode::SHIFT_R;
    if (*this == ModifierFlag::CONTROL_L) return KeyCode::CONTROL_L;
    if (*this == ModifierFlag::CONTROL_R) return KeyCode::CONTROL_R;
    if (*this == ModifierFlag::OPTION_L) return KeyCode::OPTION_L;
    if (*this == ModifierFlag::OPTION_R) return KeyCode::OPTION_R;
    if (*this == ModifierFlag::COMMAND_L) return KeyCode::COMMAND_L;
    if (*this == ModifierFlag::COMMAND_R) return KeyCode::COMMAND_R;
    if (*this == ModifierFlag::FN) return KeyCode::FN;
    if (*this == ModifierFlag::EXTRA1) return KeyCode::VK_MODIFIER_EXTRA1;
    if (*this == ModifierFlag::EXTRA2) return KeyCode::VK_MODIFIER_EXTRA2;
    if (*this == ModifierFlag::EXTRA3) return KeyCode::VK_MODIFIER_EXTRA3;
    if (*this == ModifierFlag::EXTRA4) return KeyCode::VK_MODIFIER_EXTRA4;
    if (*this == ModifierFlag::EXTRA5) return KeyCode::VK_MODIFIER_EXTRA5;

    return KeyCode::VK_NONE;
  }

  ModifierFlag
  KeyCode::getModifierFlag(void) const
  {
    if (*this == KeyCode::CAPSLOCK) return ModifierFlag::CAPSLOCK;
    if (*this == KeyCode::SHIFT_L) return ModifierFlag::SHIFT_L;
    if (*this == KeyCode::SHIFT_R) return ModifierFlag::SHIFT_R;
    if (*this == KeyCode::CONTROL_L) return ModifierFlag::CONTROL_L;
    if (*this == KeyCode::CONTROL_R) return ModifierFlag::CONTROL_R;
    if (*this == KeyCode::OPTION_L) return ModifierFlag::OPTION_L;
    if (*this == KeyCode::OPTION_R) return ModifierFlag::OPTION_R;
    if (*this == KeyCode::COMMAND_L) return ModifierFlag::COMMAND_L;
    if (*this == KeyCode::COMMAND_R) return ModifierFlag::COMMAND_R;
    if (*this == KeyCode::FN) return ModifierFlag::FN;
    if (*this == KeyCode::VK_MODIFIER_EXTRA1) return ModifierFlag::EXTRA1;
    if (*this == KeyCode::VK_MODIFIER_EXTRA2) return ModifierFlag::EXTRA2;
    if (*this == KeyCode::VK_MODIFIER_EXTRA3) return ModifierFlag::EXTRA3;
    if (*this == KeyCode::VK_MODIFIER_EXTRA4) return ModifierFlag::EXTRA4;
    if (*this == KeyCode::VK_MODIFIER_EXTRA5) return ModifierFlag::EXTRA5;

    return ModifierFlag::NONE;
  }
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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.
 *
 */

#include <grpc/support/port_platform.h>

#include <grpc/support/alloc.h>

#include <grpc/support/log.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/profiling/timers.h"

static void* zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }

static void* zalloc_with_gpr_malloc(size_t sz) {
  void* p = gpr_malloc(sz);
  memset(p, 0, sz);
  return p;
}

#ifndef NDEBUG
static constexpr bool is_power_of_two(size_t value) {
  // 2^N =     100000...000
  // 2^N - 1 = 011111...111
  // (2^N) && ((2^N)-1)) = 0
  return (value & (value - 1)) == 0;
}
#endif

static void* aligned_alloc_with_gpr_malloc(size_t size, size_t alignment) {
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  size_t extra = alignment - 1 + sizeof(void*);
  void* p = gpr_malloc(size + extra);
  void** ret = (void**)(((uintptr_t)p + extra) & ~(alignment - 1));
  ret[-1] = p;
  return (void*)ret;
}

static void aligned_free_with_gpr_malloc(void* ptr) {
  gpr_free((static_cast<void**>(ptr))[-1]);
}

static void* platform_malloc_aligned(size_t size, size_t alignment) {
#if defined(GPR_HAS_ALIGNED_ALLOC)
  size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size, alignment);
  void* ret = aligned_alloc(alignment, size);
  GPR_ASSERT(ret != nullptr);
  return ret;
#elif defined(GPR_HAS_ALIGNED_MALLOC)
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  void* ret = _aligned_malloc(size, alignment);
  GPR_ASSERT(ret != nullptr);
  return ret;
#elif defined(GPR_HAS_POSIX_MEMALIGN)
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  GPR_DEBUG_ASSERT(alignment % sizeof(void*) == 0);
  void* ret = nullptr;
  GPR_ASSERT(posix_memalign(&ret, alignment, size) == 0);
  return ret;
#else
  return aligned_alloc_with_gpr_malloc(size, alignment);
#endif
}

static void platform_free_aligned(void* ptr) {
#if defined(GPR_HAS_ALIGNED_ALLOC) || defined(GPR_HAS_POSIX_MEMALIGN)
  free(ptr);
#elif defined(GPR_HAS_ALIGNED_MALLOC)
  _aligned_free(ptr);
#else
  aligned_free_with_gpr_malloc(ptr);
#endif
}

static gpr_allocation_functions g_alloc_functions = {
    malloc, zalloc_with_calloc,      realloc,
    free,   platform_malloc_aligned, platform_free_aligned};

gpr_allocation_functions gpr_get_allocation_functions() {
  return g_alloc_functions;
}

void gpr_set_allocation_functions(gpr_allocation_functions functions) {
  GPR_ASSERT(functions.malloc_fn != nullptr);
  GPR_ASSERT(functions.realloc_fn != nullptr);
  GPR_ASSERT(functions.free_fn != nullptr);
  if (functions.zalloc_fn == nullptr) {
    functions.zalloc_fn = zalloc_with_gpr_malloc;
  }
  GPR_ASSERT((functions.aligned_alloc_fn == nullptr) ==
             (functions.aligned_free_fn == nullptr));
  if (functions.aligned_alloc_fn == nullptr) {
    functions.aligned_alloc_fn = aligned_alloc_with_gpr_malloc;
    functions.aligned_free_fn = aligned_free_with_gpr_malloc;
  }
  g_alloc_functions = functions;
}

void* gpr_malloc(size_t size) {
  GPR_TIMER_SCOPE("gpr_malloc", 0);
  void* p;
  if (size == 0) return nullptr;
  p = g_alloc_functions.malloc_fn(size);
  if (!p) {
    abort();
  }
  return p;
}

void* gpr_zalloc(size_t size) {
  GPR_TIMER_SCOPE("gpr_zalloc", 0);
  void* p;
  if (size == 0) return nullptr;
  p = g_alloc_functions.zalloc_fn(size);
  if (!p) {
    abort();
  }
  return p;
}

void gpr_free(void* p) {
  GPR_TIMER_SCOPE("gpr_free", 0);
  g_alloc_functions.free_fn(p);
}

void* gpr_realloc(void* p, size_t size) {
  GPR_TIMER_SCOPE("gpr_realloc", 0);
  if ((size == 0) && (p == nullptr)) return nullptr;
  p = g_alloc_functions.realloc_fn(p, size);
  if (!p) {
    abort();
  }
  return p;
}

void* gpr_malloc_aligned(size_t size, size_t alignment) {
  GPR_TIMER_SCOPE("gpr_malloc_aligned", 0);
  if (size == 0) return nullptr;
  return g_alloc_functions.aligned_alloc_fn(size, alignment);
}

void gpr_free_aligned(void* ptr) {
  GPR_TIMER_SCOPE("gpr_free_aligned", 0);
  g_alloc_functions.aligned_free_fn(ptr);
}
<commit_msg>Use platform align_malloc function when setting custom allocators and no override provided<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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.
 *
 */

#include <grpc/support/port_platform.h>

#include <grpc/support/alloc.h>

#include <grpc/support/log.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/profiling/timers.h"

static void* zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }

static void* zalloc_with_gpr_malloc(size_t sz) {
  void* p = gpr_malloc(sz);
  memset(p, 0, sz);
  return p;
}

#ifndef NDEBUG
static constexpr bool is_power_of_two(size_t value) {
  // 2^N =     100000...000
  // 2^N - 1 = 011111...111
  // (2^N) && ((2^N)-1)) = 0
  return (value & (value - 1)) == 0;
}
#endif

static void* platform_malloc_aligned(size_t size, size_t alignment) {
#if defined(GPR_HAS_ALIGNED_ALLOC)
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size, alignment);
  void* ret = aligned_alloc(alignment, size);
  GPR_ASSERT(ret != nullptr);
  return ret;
#elif defined(GPR_HAS_ALIGNED_MALLOC)
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  void* ret = _aligned_malloc(size, alignment);
  GPR_ASSERT(ret != nullptr);
  return ret;
#elif defined(GPR_HAS_POSIX_MEMALIGN)
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  GPR_DEBUG_ASSERT(alignment % sizeof(void*) == 0);
  void* ret = nullptr;
  GPR_ASSERT(posix_memalign(&ret, alignment, size) == 0);
  return ret;
#else
  GPR_DEBUG_ASSERT(is_power_of_two(alignment));
  size_t extra = alignment - 1 + sizeof(void*);
  void* p = gpr_malloc(size + extra);
  void** ret = (void**)(((uintptr_t)p + extra) & ~(alignment - 1));
  ret[-1] = p;
  return (void*)ret;
#endif
}

static void platform_free_aligned(void* ptr) {
#if defined(GPR_HAS_ALIGNED_ALLOC) || defined(GPR_HAS_POSIX_MEMALIGN)
  free(ptr);
#elif defined(GPR_HAS_ALIGNED_MALLOC)
  _aligned_free(ptr);
#else
  gpr_free((static_cast<void**>(ptr))[-1]);
#endif
}

static gpr_allocation_functions g_alloc_functions = {
    malloc, zalloc_with_calloc,      realloc,
    free,   platform_malloc_aligned, platform_free_aligned};

gpr_allocation_functions gpr_get_allocation_functions() {
  return g_alloc_functions;
}

void gpr_set_allocation_functions(gpr_allocation_functions functions) {
  GPR_ASSERT(functions.malloc_fn != nullptr);
  GPR_ASSERT(functions.realloc_fn != nullptr);
  GPR_ASSERT(functions.free_fn != nullptr);
  if (functions.zalloc_fn == nullptr) {
    functions.zalloc_fn = zalloc_with_gpr_malloc;
  }
  GPR_ASSERT((functions.aligned_alloc_fn == nullptr) ==
             (functions.aligned_free_fn == nullptr));
  if (functions.aligned_alloc_fn == nullptr) {
    functions.aligned_alloc_fn = platform_malloc_aligned;
    functions.aligned_free_fn = platform_free_aligned;
  }
  g_alloc_functions = functions;
}

void* gpr_malloc(size_t size) {
  GPR_TIMER_SCOPE("gpr_malloc", 0);
  void* p;
  if (size == 0) return nullptr;
  p = g_alloc_functions.malloc_fn(size);
  if (!p) {
    abort();
  }
  return p;
}

void* gpr_zalloc(size_t size) {
  GPR_TIMER_SCOPE("gpr_zalloc", 0);
  void* p;
  if (size == 0) return nullptr;
  p = g_alloc_functions.zalloc_fn(size);
  if (!p) {
    abort();
  }
  return p;
}

void gpr_free(void* p) {
  GPR_TIMER_SCOPE("gpr_free", 0);
  g_alloc_functions.free_fn(p);
}

void* gpr_realloc(void* p, size_t size) {
  GPR_TIMER_SCOPE("gpr_realloc", 0);
  if ((size == 0) && (p == nullptr)) return nullptr;
  p = g_alloc_functions.realloc_fn(p, size);
  if (!p) {
    abort();
  }
  return p;
}

void* gpr_malloc_aligned(size_t size, size_t alignment) {
  GPR_TIMER_SCOPE("gpr_malloc_aligned", 0);
  if (size == 0) return nullptr;
  return g_alloc_functions.aligned_alloc_fn(size, alignment);
}

void gpr_free_aligned(void* ptr) {
  GPR_TIMER_SCOPE("gpr_free_aligned", 0);
  g_alloc_functions.aligned_free_fn(ptr);
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2009-2013, 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
*/
#include "elemental.hpp"

namespace {
elem::mpi::Datatype typeIntInt;
elem::mpi::Datatype typeFloatInt;
elem::mpi::Datatype typeDoubleInt;

elem::mpi::Op maxLocIntOp;
elem::mpi::Op maxLocFloatOp;
elem::mpi::Op maxLocDoubleOp;
}

namespace elem {
namespace mpi {

template<typename T>
void
MaxLocFunc
( ValueInt<T>* inData, ValueInt<T>* outData, int* length, Datatype* datatype )
{
    for( int j=0; j<*length; ++j )
        if( inData[j].value > outData[j].value )
            outData[j] = inData[j];
}

template<>
Datatype& ValueIntType<Int>()
{ return ::typeIntInt; }

template<>
Datatype& ValueIntType<float>()
{ return ::typeFloatInt; }

template<>
Datatype& ValueIntType<double>()
{ return ::typeDoubleInt; }

template<typename T>
void CreateValueIntType()
{
#ifndef RELEASE
    CallStackEntry cse("CreateValueIntType<Int>");
#endif
    Datatype& type = ValueIntType<T>();
#ifndef RELEASE
    if( type != 0 )
        LogicError("type was already created");
#endif
    Datatype typeList[2];
    typeList[0] = TypeMap<T>();
    typeList[1] = TypeMap<Int>();

    int blockLengths[2];
    blockLengths[0] = 1;
    blockLengths[1] = 1;

    ValueInt<T> v;
    MPI_Aint startAddr, valueAddr, indexAddr;
    MPI_Address( &v,       &startAddr );
    MPI_Address( &v.value, &valueAddr );
    MPI_Address( &v.index, &indexAddr );

    MPI_Aint displs[2];
    displs[0] = valueAddr - startAddr;
    displs[1] = indexAddr - startAddr;

    MPI_Type_create_struct( 2, blockLengths, displs, typeList, &type );
    MPI_Type_commit( &type );
}
template void CreateValueIntType<Int>();
template void CreateValueIntType<float>();
template void CreateValueIntType<double>();

template<>
void CreateMaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<Int>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<Int>, true, ::maxLocIntOp );
}

template<>
void CreateMaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<float>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<float>, true, ::maxLocFloatOp );
}

template<>
void CreateMaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<double>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<double>, true, ::maxLocDoubleOp );
}

template<>
void DestroyMaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<Int>");
#endif
    OpFree( ::maxLocIntOp );
}

template<>
void DestroyMaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<float>");
#endif
    OpFree( ::maxLocFloatOp );
}

template<>
void DestroyMaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<double>");
#endif
    OpFree( ::maxLocDoubleOp );
}

template<>
Op MaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<Int>");
#endif
    return ::maxLocIntOp;
}

template<>
Op MaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<float>");
#endif
    return ::maxLocFloatOp;
}

template<>
Op MaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<double>");
#endif
    return ::maxLocDoubleOp;
}

template void
MaxLocFunc<Int>
( ValueInt<Int>* inData, ValueInt<Int>* outData, int* length,
  Datatype* datatype );
template void
MaxLocFunc<float>
( ValueInt<float>* inData, ValueInt<float>* outData, int* length,
  Datatype* datatype );
template void
MaxLocFunc<double>
( ValueInt<double>* inData, ValueInt<double>* outData, int* length,
  Datatype* datatype );

} // namespace mpi
} // namespace elem
<commit_msg>Fixing a few artifacts in src/core/mpi_register.cpp which were left from the large amount of different approaches tried before settling on the current one.<commit_after>/*
   Copyright (c) 2009-2013, 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
*/
#include "elemental.hpp"

namespace {
elem::mpi::Datatype typeIntInt;
elem::mpi::Datatype typeFloatInt;
elem::mpi::Datatype typeDoubleInt;

elem::mpi::Op maxLocIntOp;
elem::mpi::Op maxLocFloatOp;
elem::mpi::Op maxLocDoubleOp;
}

namespace elem {
namespace mpi {

template<typename T>
void
MaxLocFunc
( ValueInt<T>* inData, ValueInt<T>* outData, int* length, Datatype* datatype )
{
    for( int j=0; j<*length; ++j )
        if( inData[j].value > outData[j].value )
            outData[j] = inData[j];
}

template<>
Datatype& ValueIntType<Int>()
{ return ::typeIntInt; }

template<>
Datatype& ValueIntType<float>()
{ return ::typeFloatInt; }

template<>
Datatype& ValueIntType<double>()
{ return ::typeDoubleInt; }

template<typename T>
void CreateValueIntType()
{
#ifndef RELEASE
    CallStackEntry cse("CreateValueIntType");
#endif
    Datatype typeList[2];
    typeList[0] = TypeMap<T>();
    typeList[1] = TypeMap<Int>();

    int blockLengths[2];
    blockLengths[0] = 1;
    blockLengths[1] = 1;

    ValueInt<T> v;
    MPI_Aint startAddr, valueAddr, indexAddr;
    MPI_Address( &v,       &startAddr );
    MPI_Address( &v.value, &valueAddr );
    MPI_Address( &v.index, &indexAddr );

    MPI_Aint displs[2];
    displs[0] = valueAddr - startAddr;
    displs[1] = indexAddr - startAddr;

    Datatype& type = ValueIntType<T>();
    MPI_Type_create_struct( 2, blockLengths, displs, typeList, &type );
    MPI_Type_commit( &type );
}
template void CreateValueIntType<Int>();
template void CreateValueIntType<float>();
template void CreateValueIntType<double>();

template<>
void CreateMaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<Int>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<Int>, true, ::maxLocIntOp );
}

template<>
void CreateMaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<float>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<float>, true, ::maxLocFloatOp );
}

template<>
void CreateMaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("CreateMaxLocOp<double>");
#endif
    OpCreate( (UserFunction*)MaxLocFunc<double>, true, ::maxLocDoubleOp );
}

template<>
void DestroyMaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<Int>");
#endif
    OpFree( ::maxLocIntOp );
}

template<>
void DestroyMaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<float>");
#endif
    OpFree( ::maxLocFloatOp );
}

template<>
void DestroyMaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("DestroyMaxLocOp<double>");
#endif
    OpFree( ::maxLocDoubleOp );
}

template<>
Op MaxLocOp<Int>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<Int>");
#endif
    return ::maxLocIntOp;
}

template<>
Op MaxLocOp<float>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<float>");
#endif
    return ::maxLocFloatOp;
}

template<>
Op MaxLocOp<double>()
{
#ifndef RELEASE
    CallStackEntry cse("MaxLocOp<double>");
#endif
    return ::maxLocDoubleOp;
}

template void
MaxLocFunc<Int>
( ValueInt<Int>* inData, ValueInt<Int>* outData, int* length,
  Datatype* datatype );
template void
MaxLocFunc<float>
( ValueInt<float>* inData, ValueInt<float>* outData, int* length,
  Datatype* datatype );
template void
MaxLocFunc<double>
( ValueInt<double>* inData, ValueInt<double>* outData, int* length,
  Datatype* datatype );

} // namespace mpi
} // namespace elem
<|endoftext|>


<commit_before>/**
 * This file is part of Slideshow.
 * Copyright (C) 2013 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "module_loader.h"
#include "opengl.h"
#include "graphics.h"
#include "log.hpp"
#include "path.h"
#include "Transition.h"

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cerrno>
#include <cmath>
#include <getopt.h>
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <IL/il.h>
#include <IL/ilu.h>

enum Mode {
	MODE_PREVIEW = 0,
	MODE_LIST,
};

static const char* program_name;
static enum Mode mode = MODE_PREVIEW;
static bool fullscreen = false;
static int width = 0;
static int height = 0;
static bool running = true;
static const char* name = "fade";
static bool automatic = true;
static float s = 0.0f;
static enum Severity severity = Log_Info;
static float min(float a, float b){
	return a < b ? a : b;
}

static float max(float a, float b){
	return a > b ? a : b;
}

static float clamp(float x, float hi, float lo){
	if ( x > hi ) return hi;
	if ( x < lo ) return lo;
	return x;
}

static void init(){
	/* use default resolution 0x0 (native) for fullscreen and 800x600 for
	   windowed */
	if ( !fullscreen && width == 0 ){
		width = 800;
		height = 600;
	}

	/* Initialize SDL */
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ){
		fprintf(stderr, "%s: Failed to initialize SDL: %s", program_name, SDL_GetError());
		exit(1);
	}
	if ( SDL_SetVideoMode(width, height, 0, (fullscreen ? SDL_FULLSCREEN : 0) | SDL_OPENGL) == NULL ){
		fprintf(stderr, "%s: Failed to initialize SDL: %s", program_name, SDL_GetError());
		exit(1);
	}
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);

	/* read actual resolution */
	const SDL_VideoInfo* vi = SDL_GetVideoInfo();
	if ( !vi ){
		fprintf(stderr, "%s: SDL_GetVideoInfo() failed\n", program_name);
		exit(1);
	}
	width = vi->current_w;
	height = vi->current_h;

	graphics_init(width, height);
	graphics_load_image("resources/transition_a.png", 1);
	graphics_load_image("resources/transition_b.png", 1);

	/* load transition module */
	moduleloader_init(pluginpath());
	graphics_set_transition(name);
}

static void cleanup(){
	SDL_Quit();
}

static void update(){
	SDL_Event event;
	while(SDL_PollEvent(&event) ){
		switch(event.type){
		case SDL_KEYDOWN:
			switch ( event.key.keysym.sym ){
			case SDLK_ESCAPE:
				running = false;
				break;

			case SDLK_LEFT:
			case SDLK_RIGHT:
				automatic = false;
				break;

			case SDLK_SPACE:
				automatic = true;
				break;

			default:
				break;
			}
			break;

		case SDL_MOUSEBUTTONDOWN:
			if ( event.button.button == 4){
				automatic = false;
				s = max(s - 0.02f, 0.0f);
			} else if ( event.button.button == 5){
				automatic = 0;
				s = min(s + 0.02f, 1.0f);
			}
			break;

		case SDL_QUIT:
			running = false;
			break;
		}
	}

	Uint8* keys = SDL_GetKeyState(NULL);
	if ( keys[SDLK_LEFT]  ) s = max(s - 0.01f, 0.0f);
	if ( keys[SDLK_RIGHT] ) s = min(s + 0.01f, 1.0f);

	if ( automatic ){
		const Uint32 t = SDL_GetTicks();
		const float x = (float)t / 1000.0f;
		s = clamp(asinf(sinf(x)) / (float)M_PI_2, 0.5f, -0.5f) + 0.5f;
	}
}

static void render(){
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	graphics_render(s);
	SDL_GL_SwapBuffers();
}

static int preview(){
	init();
	while ( running ){
		update();
		render();
	}
	cleanup();
	return 0;
}

static int list_transitions(){
	moduleloader_init(pluginpath());
	module_enumerate(TRANSITION_MODULE, [](const char* name, const module_handle mod){
		printf("%s:%s\n", name, module_get_name(mod));
	});
	return 0;
}

static const char* shortopts = "lfbvh";
static struct option longopts[] = {
	{"list",        no_argument, 0, 'l'},
	{"fullscreen",  no_argument, 0, 'f'},
	{"vebose",      no_argument, 0, 'v'},
	{"help",        no_argument, 0, 'h'},
	{0, 0, 0, 0}, /* sentinel */
};

static void show_usage(void){
	printf("%s-%s\n", program_name, VERSION);
	printf("(c) 2013 David Sveningsson <ext@sidvind.com>\n\n");
	printf("Preview and manage slideshow transitions.\n");
	printf("Usage: %s [OPTIONS] [TRANSITION]\n\n"
	       "  -l, --list                 List available transitions\n"
	       "  -f, --fullscreen           Run in fullscreen mode\n"
	       "  -b                         Format output as machine-parsable text\n"
	       "  -v, --verbose              Verbose output\n"
	       "  -h, --help                 Show this text.\n",
	       program_name);
}

int main(int argc, char* argv[]){
	/* extract program name from path. e.g. /path/to/foo -> foo */
	const char* separator = strrchr(argv[0], '/');
	if ( separator ){
		program_name = separator + 1;
	} else {
		program_name = argv[0];
	}

	int option_index = 0;
	int op;

	/* parse arguments */
	while ( (op=getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){
		switch ( op ){
		case 'l': /* --list */
			mode = MODE_LIST;
			break;

		case 'f': /* --fullscreen */
			fullscreen = true;
			break;

		case 'b':
			/* not implemented as of now as the output is already machine-parsable but
			   in case it changes this should be implemented */
			break;

		case 'v':
			severity = Log_Debug;
			break;

		case 'h': /* --help */
			show_usage();
			return 0;
		}
	}

	if ( optind < argc ){
		name = argv[optind];
	}

	int (*func[])() = {
		preview,
		list_transitions,
	};

	Log::add_destination(new FileDestination(stdout), severity);
	return func[mode]();
}
<commit_msg>cosmetic: alignment<commit_after>/**
 * This file is part of Slideshow.
 * Copyright (C) 2013 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "module_loader.h"
#include "opengl.h"
#include "graphics.h"
#include "log.hpp"
#include "path.h"
#include "Transition.h"

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cerrno>
#include <cmath>
#include <getopt.h>
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <IL/il.h>
#include <IL/ilu.h>

enum Mode {
	MODE_PREVIEW = 0,
	MODE_LIST,
};

static const char* program_name;
static enum Mode mode = MODE_PREVIEW;
static bool fullscreen = false;
static int width = 0;
static int height = 0;
static bool running = true;
static const char* name = "fade";
static bool automatic = true;
static float s = 0.0f;
static enum Severity severity = Log_Info;
static float min(float a, float b){
	return a < b ? a : b;
}

static float max(float a, float b){
	return a > b ? a : b;
}

static float clamp(float x, float hi, float lo){
	if ( x > hi ) return hi;
	if ( x < lo ) return lo;
	return x;
}

static void init(){
	/* use default resolution 0x0 (native) for fullscreen and 800x600 for
	   windowed */
	if ( !fullscreen && width == 0 ){
		width = 800;
		height = 600;
	}

	/* Initialize SDL */
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ){
		fprintf(stderr, "%s: Failed to initialize SDL: %s", program_name, SDL_GetError());
		exit(1);
	}
	if ( SDL_SetVideoMode(width, height, 0, (fullscreen ? SDL_FULLSCREEN : 0) | SDL_OPENGL) == NULL ){
		fprintf(stderr, "%s: Failed to initialize SDL: %s", program_name, SDL_GetError());
		exit(1);
	}
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);

	/* read actual resolution */
	const SDL_VideoInfo* vi = SDL_GetVideoInfo();
	if ( !vi ){
		fprintf(stderr, "%s: SDL_GetVideoInfo() failed\n", program_name);
		exit(1);
	}
	width = vi->current_w;
	height = vi->current_h;

	graphics_init(width, height);
	graphics_load_image("resources/transition_a.png", 1);
	graphics_load_image("resources/transition_b.png", 1);

	/* load transition module */
	moduleloader_init(pluginpath());
	graphics_set_transition(name);
}

static void cleanup(){
	SDL_Quit();
}

static void update(){
	SDL_Event event;
	while(SDL_PollEvent(&event) ){
		switch(event.type){
		case SDL_KEYDOWN:
			switch ( event.key.keysym.sym ){
			case SDLK_ESCAPE:
				running = false;
				break;

			case SDLK_LEFT:
			case SDLK_RIGHT:
				automatic = false;
				break;

			case SDLK_SPACE:
				automatic = true;
				break;

			default:
				break;
			}
			break;

		case SDL_MOUSEBUTTONDOWN:
			if ( event.button.button == 4){
				automatic = false;
				s = max(s - 0.02f, 0.0f);
			} else if ( event.button.button == 5){
				automatic = 0;
				s = min(s + 0.02f, 1.0f);
			}
			break;

		case SDL_QUIT:
			running = false;
			break;
		}
	}

	Uint8* keys = SDL_GetKeyState(NULL);
	if ( keys[SDLK_LEFT]  ) s = max(s - 0.01f, 0.0f);
	if ( keys[SDLK_RIGHT] ) s = min(s + 0.01f, 1.0f);

	if ( automatic ){
		const Uint32 t = SDL_GetTicks();
		const float x = (float)t / 1000.0f;
		s = clamp(asinf(sinf(x)) / (float)M_PI_2, 0.5f, -0.5f) + 0.5f;
	}
}

static void render(){
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	graphics_render(s);
	SDL_GL_SwapBuffers();
}

static int preview(){
	init();
	while ( running ){
		update();
		render();
	}
	cleanup();
	return 0;
}

static int list_transitions(){
	moduleloader_init(pluginpath());
	module_enumerate(TRANSITION_MODULE, [](const char* name, const module_handle mod){
		printf("%s:%s\n", name, module_get_name(mod));
	});
	return 0;
}

static const char* shortopts = "lfbvh";
static struct option longopts[] = {
	{"list",        no_argument,       0, 'l'},
	{"fullscreen",  no_argument,       0, 'f'},
	{"vebose",      no_argument,       0, 'v'},
	{"help",        no_argument,       0, 'h'},
	{0, 0, 0, 0}, /* sentinel */
};

static void show_usage(void){
	printf("%s-%s\n", program_name, VERSION);
	printf("(c) 2013 David Sveningsson <ext@sidvind.com>\n\n");
	printf("Preview and manage slideshow transitions.\n");
	printf("Usage: %s [OPTIONS] [TRANSITION]\n\n"
	       "  -l, --list                 List available transitions\n"
	       "  -f, --fullscreen           Run in fullscreen mode\n"
	       "  -b                         Format output as machine-parsable text\n"
	       "  -v, --verbose              Verbose output\n"
	       "  -h, --help                 Show this text.\n",
	       program_name);
}

int main(int argc, char* argv[]){
	/* extract program name from path. e.g. /path/to/foo -> foo */
	const char* separator = strrchr(argv[0], '/');
	if ( separator ){
		program_name = separator + 1;
	} else {
		program_name = argv[0];
	}

	int option_index = 0;
	int op;

	/* parse arguments */
	while ( (op=getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){
		switch ( op ){
		case 'l': /* --list */
			mode = MODE_LIST;
			break;

		case 'f': /* --fullscreen */
			fullscreen = true;
			break;

		case 'b':
			/* not implemented as of now as the output is already machine-parsable but
			   in case it changes this should be implemented */
			break;

		case 'v':
			severity = Log_Debug;
			break;

		case 'h': /* --help */
			show_usage();
			return 0;
		}
	}

	if ( optind < argc ){
		name = argv[optind];
	}

	int (*func[])() = {
		preview,
		list_transitions,
	};

	Log::add_destination(new FileDestination(stdout), severity);
	return func[mode]();
}
<|endoftext|>


<commit_before>/*
    Essentially, for

        u(n) = 1 - n + n^2 - ... + n^10
             = (n^11 + 1) / (n + 1)

    we look for the interpolating polynomial p_1, p_2, ..., p_10 for the first
    1, 2, ..., 10 terms of u_n.

    For each interpolating polynomial p_i we find the first value of n such that
    p_i(n) != u(n). The values p_i(n) are collected and summed to give the
    required result.

    For interpolation, we use Lagrange's Interpolation. The idea is that we
    explictly construct terms for each value in the set of interpolating points.
    Every term will be "annihilated" except when n equals to the x value of the
    point corresponding to the term. For example to interpolating (1, 1), (2,
    8), (3, 15), we have

        p(n) = 1 * (n - 8)(n - 15) / ((1 - 8)(1 - 15)) +
               8 * (n - 1)(n - 15) / ((2 - 1)(2 - 15))
               15 * (n - 1)(n - 2) / ((3 - 1)(3 - 2))

    Indeed, for each term, when n is not equal to the corresponding x value, the
    numerator is "annihilated" and the term becomes zero. If n is equal to the
    corresponding x value, the denominator is constructed to cancel out the
    numerator to give 1, which is multiplied by the y value of the point.
*/

#include <iostream>
#include <vector>
#include <gmpxx.h>
#include "number_util.h"

struct term_struct
{
    mpz_class value;
    std::vector<int> offsets;
    mpz_class denominator = 1;
};

std::vector<term_struct> interpolate(std::vector<mpz_class> values)
{
    std::vector<term_struct> terms;

    for (int n = 0; n < values.size(); n++)
    {
        mpz_class value = values[n];

        terms.emplace_back();
        term_struct &term = terms.back();
        term.value = value;
        for (int _n = 0; _n < values.size(); _n++)
        {
            if (_n != n)
            {
                term.offsets.emplace_back(_n + 1);
                term.denominator *= n - _n;
            }
        }
    }

    return terms;
}

mpz_class evaluate(std::vector<term_struct> terms, int n)
{
    mpz_class s = 0;
    for (term_struct &term : terms)
    {
        mpz_class _s = term.value;
        for (int &offset : term.offsets)
            _s *= n - offset;
        _s /= term.denominator;
        s += _s;
    }
    return s;
}

mpz_class evaluate_U(int n)
{
    return (util::pow(n, 11) + 1) / (n + 1);
}

int main()
{
    mpz_class s = 0;
    for (int k = 1; k < 11; k++)
    {
        std::vector<mpz_class> values;
        for (int n = 1; n <= k; n++)
            values.emplace_back(evaluate_U(n));

        std::vector<term_struct> polynomial = interpolate(values);

        int n = 0;
        mpz_class p_n;
        do {
            n++;
            p_n = evaluate(polynomial, n);
        } while(p_n == values[n - 1]);
        s += p_n;
    }

    std::cout << s;
}
<commit_msg>Enforce const correctness.<commit_after>/*
    Essentially, for

        u(n) = 1 - n + n^2 - ... + n^10
             = (n^11 + 1) / (n + 1)

    we look for the interpolating polynomial p_1, p_2, ..., p_10 for the first
    1, 2, ..., 10 terms of u_n.

    For each interpolating polynomial p_i we find the first value of n such that
    p_i(n) != u(n). The values p_i(n) are collected and summed to give the
    required result.

    For interpolation, we use Lagrange's Interpolation. The idea is that we
    explictly construct terms for each value in the set of interpolating points.
    Every term will be "annihilated" except when n equals to the x value of the
    point corresponding to the term. For example to interpolating (1, 1), (2,
    8), (3, 15), we have

        p(n) = 1 * (n - 8)(n - 15) / ((1 - 8)(1 - 15)) +
               8 * (n - 1)(n - 15) / ((2 - 1)(2 - 15))
               15 * (n - 1)(n - 2) / ((3 - 1)(3 - 2))

    Indeed, for each term, when n is not equal to the corresponding x value, the
    numerator is "annihilated" and the term becomes zero. If n is equal to the
    corresponding x value, the denominator is constructed to cancel out the
    numerator to give 1, which is multiplied by the y value of the point.
*/

#include <iostream>
#include <vector>
#include <gmpxx.h>
#include "number_util.h"

struct term_struct
{
    mpz_class value;
    std::vector<int> offsets;
    mpz_class denominator = 1;
};

std::vector<term_struct> interpolate(std::vector<mpz_class> const &values)
{
    std::vector<term_struct> terms;

    for (int n = 0; n < values.size(); n++)
    {
        mpz_class value = values[n];

        terms.emplace_back();
        term_struct &term = terms.back();
        term.value = value;
        for (int _n = 0; _n < values.size(); _n++)
        {
            if (_n != n)
            {
                term.offsets.emplace_back(_n + 1);
                term.denominator *= n - _n;
            }
        }
    }

    return terms;
}

mpz_class evaluate(std::vector<term_struct> const &terms, int n)
{
    mpz_class s = 0;
    for (term_struct const &term : terms)
    {
        mpz_class _s = term.value;
        for (int const &offset : term.offsets)
            _s *= n - offset;
        _s /= term.denominator;
        s += _s;
    }
    return s;
}

mpz_class evaluate_U(int n)
{
    return (util::pow(n, 11) + 1) / (n + 1);
}

int main()
{
    mpz_class s = 0;
    for (int k = 1; k < 11; k++)
    {
        std::vector<mpz_class> values;
        for (int n = 1; n <= k; n++)
            values.emplace_back(evaluate_U(n));

        std::vector<term_struct> polynomial = interpolate(values);

        int n = 0;
        mpz_class p_n;
        do {
            n++;
            p_n = evaluate(polynomial, n);
        } while(p_n == values[n - 1]);
        s += p_n;
    }

    std::cout << s;
}
<|endoftext|>


<commit_before>/*
    We need primes p such that

       10^(10^9) \equiv 1 \pmod 9p

    For some p, we need to look for a power q such that:

       1) 10^q \equiv 1 \pmod 9p
       2) q | 10^9 (so that RHS remains as 1 while raising both sides to the
          power of the quotient)

    If such q exists then p is a prime factor.

    Since q | 10^9, q must have the form q = 2^a5^b for some non-negative
    integers 0 <= a, b <= 9.

    Furthermore, we know that if 10^q \equiv 1 \pmod 9p, then q | \phi(9p). In
    addition, \phi(9p) can be calculated easily: \phi(27) = 18 and \phi(9p) =
    6(p - 1) for p > 3.

    Combining the two constraints, we need to look for factors q of \phi(9p) of
    the form q = 2^a5^b where 0 <= a, b <= 9 such that 9n | 10^q.
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include "number_util.h"
#include "prime_util.h"

bool is_factor(int p)
{
    int order_max = p == 3 ? 18 : 6 * (p - 1);
    int a_max = 0;
    int b_max = 0;
    while (order_max % 2 == 0)
    {
        a_max++;
        order_max /= 2;
    }
    while (order_max % 5 == 0)
    {
        b_max++;
        order_max /= 5;
    }
    a_max = std::min(a_max, 9);
    b_max = std::min(b_max, 9);

    for (int a = 0; a <= a_max; a++)
    {
        for (int b = 0; b <= b_max; b++)
        {
            unsigned long long q = std::pow(2, a) * std::pow(5, b);
            if (util::pow(mpz_class(10), q) % (9 * p) == 1)
                return true;
        }
    }

    return false;
}

int main()
{
    std::vector<int> primes = { 2 };
    int s = 0;
    int count = 0;
    while (count < 40)
    {
        int &prime = primes.back();
        if (is_factor(prime))
        {
            s += prime;
            count++;
        }
        primes.emplace_back(util::get_next_prime(prime));
    }

    std::cout << s;
}
<commit_msg>Changed to pow_mod.<commit_after>/*
    We need primes p such that

       10^(10^9) \equiv 1 \pmod 9p

    For some p, we need to look for a power q such that:

       1) 10^q \equiv 1 \pmod 9p
       2) q | 10^9 (so that RHS remains as 1 while raising both sides to the
          power of the quotient)

    If such q exists then p is a prime factor.

    Since q | 10^9, q must have the form q = 2^a5^b for some non-negative
    integers 0 <= a, b <= 9.

    Furthermore, we know that if 10^q \equiv 1 \pmod 9p, then q | \phi(9p). In
    addition, \phi(9p) can be calculated easily: \phi(27) = 18 and \phi(9p) =
    6(p - 1) for p > 3.

    Combining the two constraints, we need to look for factors q of \phi(9p) of
    the form q = 2^a5^b where 0 <= a, b <= 9 such that 9n | 10^q.
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include "number_util.h"
#include "prime_util.h"

bool is_factor(int p)
{
    int order_max = p == 3 ? 18 : 6 * (p - 1);
    int a_max = 0;
    int b_max = 0;
    while (order_max % 2 == 0)
    {
        a_max++;
        order_max /= 2;
    }
    while (order_max % 5 == 0)
    {
        b_max++;
        order_max /= 5;
    }
    a_max = std::min(a_max, 9);
    b_max = std::min(b_max, 9);

    for (int a = 0; a <= a_max; a++)
    {
        for (int b = 0; b <= b_max; b++)
        {
            unsigned long long q = std::pow(2, a) * std::pow(5, b);
            if (util::pow_mod(mpz_class(10), q, mpz_class(9 * p)) == 1)
                return true;
        }
    }

    return false;
}

int main()
{
    std::vector<int> primes = { 2 };
    int s = 0;
    int count = 0;
    while (count < 40)
    {
        int &prime = primes.back();
        if (is_factor(prime))
        {
            s += prime;
            count++;
        }
        primes.emplace_back(util::get_next_prime(prime));
    }

    std::cout << s;
}
<|endoftext|>


<commit_before>#include <memory>
#include <stdexcept>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_mixer.h>
#include "App.h"
#include "Game.h"
#include "Menu.h"
#include "HighScores.h"

namespace typing
{
    const unsigned int App::MAJOR_VERSION  = 1;
    const unsigned int App::MINOR_VERSION  = 0;
    const float App::SCREEN_WIDTH          = 800.0f;
    const float App::SCREEN_HEIGHT         = 600.0f;

    std::auto_ptr<App> App::m_singleton(new App());
    App& App::GetApp ()
    {
        return *(m_singleton.get());
    }

    void App::Init ()
    {
        // Initialise SDL
        if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO))
        {
            // TODO: throw
        }

        // Initialise video
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);

        m_window = SDL_CreateWindow("Type Or Die!",
                                    SDL_WINDOWPOS_UNDEFINED,
                                    SDL_WINDOWPOS_UNDEFINED,
                                    800, 600,
                                    SDL_WINDOW_OPENGL);
        if (!m_window) {
            // TODO: throw
        }

        if (!SDL_GL_CreateContext(m_window)) {
            // TODO: throw
        }

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClearDepth(1.0f);

        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
        glEnable(GL_LINE_SMOOTH);
        glDisable(GL_LIGHTING);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glMatrixMode(GL_PROJECTION_MATRIX);
        glOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 1024.0, -1024.0);
        glMatrixMode(GL_MODELVIEW_MATRIX);

        // Initialise audio
        int     audio_rate     = 22050;
        Uint16  audio_format   = AUDIO_S16;
        int     audio_channels = 2;
        int     audio_buffers  = 4096;
        if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers))
        {
            // TODO: throw
        }

        // Initialise game stuff
        SCORES.Load();
        MENU.Init();
        GAME.Init();
    }

    void App::Run ()
    {
        SDL_Event ev;

        m_done = false;
        while (!m_done)
        {
            // Get the time of this frame
            m_currentTime = static_cast<float>(SDL_GetTicks()) / 1000.0f;

            SDL_StartTextInput();
            while(SDL_PollEvent(&ev))
            {
                switch(ev.type)
                {
                case SDL_KEYDOWN:
                    MENU.OnKeyDown(ev.key.keysym.sym);

                    if (!MENU.IsActive()) {
                        GAME.OnKeyDown(ev.key.keysym.sym);
                    }
                    break;

                case SDL_TEXTINPUT:
                    for (char *c = ev.text.text; *c != '\0'; c++) {
                        MENU.OnType(*c);

                        if (!MENU.IsActive()) {
                            GAME.OnType(*c);
                        }
                    }
                    break;

                case SDL_QUIT:
                    m_done = true;
                    break;
                }
            }

            GAME.Update();
            MENU.Update();

            glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

            GAME.Draw();

            // All the menu stuff is done in orthographic projection.
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 1024.0, -1024.0);
            MENU.Draw();

            SDL_GL_SwapWindow(m_window);

            // Prepare for the next frame
            m_keyStateValid = false;
        }
    }

    void App::Shutdown ()
    {
        Mix_CloseAudio();
        SDL_Quit();
    }
}

int main (int argc, char *argv[])
{
    try
    {
        typing::APP.Init();
        typing::APP.Run();
    }
    catch (std::exception &e)
    {
        fprintf(stderr, "%s", e.what());
    }

    typing::APP.Shutdown();

    return 0;
}

<commit_msg>Set GL attributes after initializing GL context<commit_after>#include <memory>
#include <stdexcept>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_mixer.h>
#include "App.h"
#include "Game.h"
#include "Menu.h"
#include "HighScores.h"

namespace typing
{
    const unsigned int App::MAJOR_VERSION  = 1;
    const unsigned int App::MINOR_VERSION  = 0;
    const float App::SCREEN_WIDTH          = 800.0f;
    const float App::SCREEN_HEIGHT         = 600.0f;

    std::auto_ptr<App> App::m_singleton(new App());
    App& App::GetApp ()
    {
        return *(m_singleton.get());
    }

    void App::Init ()
    {
        // Initialise SDL
        if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO))
        {
            // TODO: throw
        }

        // Initialise video
        m_window = SDL_CreateWindow("Type Or Die!",
                                    SDL_WINDOWPOS_UNDEFINED,
                                    SDL_WINDOWPOS_UNDEFINED,
                                    800, 600,
                                    SDL_WINDOW_OPENGL);
        if (!m_window) {
            // TODO: throw
        }

        if (!SDL_GL_CreateContext(m_window)) {
            // TODO: throw
        }

        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClearDepth(1.0f);

        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
        glEnable(GL_LINE_SMOOTH);
        glDisable(GL_LIGHTING);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glMatrixMode(GL_PROJECTION_MATRIX);
        glOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 1024.0, -1024.0);
        glMatrixMode(GL_MODELVIEW_MATRIX);

        // Initialise audio
        int     audio_rate     = 22050;
        Uint16  audio_format   = AUDIO_S16;
        int     audio_channels = 2;
        int     audio_buffers  = 4096;
        if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers))
        {
            // TODO: throw
        }

        // Initialise game stuff
        SCORES.Load();
        MENU.Init();
        GAME.Init();
    }

    void App::Run ()
    {
        SDL_Event ev;

        m_done = false;
        while (!m_done)
        {
            // Get the time of this frame
            m_currentTime = static_cast<float>(SDL_GetTicks()) / 1000.0f;

            SDL_StartTextInput();
            while(SDL_PollEvent(&ev))
            {
                switch(ev.type)
                {
                case SDL_KEYDOWN:
                    MENU.OnKeyDown(ev.key.keysym.sym);

                    if (!MENU.IsActive()) {
                        GAME.OnKeyDown(ev.key.keysym.sym);
                    }
                    break;

                case SDL_TEXTINPUT:
                    for (char *c = ev.text.text; *c != '\0'; c++) {
                        MENU.OnType(*c);

                        if (!MENU.IsActive()) {
                            GAME.OnType(*c);
                        }
                    }
                    break;

                case SDL_QUIT:
                    m_done = true;
                    break;
                }
            }

            GAME.Update();
            MENU.Update();

            glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

            GAME.Draw();

            // All the menu stuff is done in orthographic projection.
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 1024.0, -1024.0);
            MENU.Draw();

            SDL_GL_SwapWindow(m_window);

            // Prepare for the next frame
            m_keyStateValid = false;
        }
    }

    void App::Shutdown ()
    {
        Mix_CloseAudio();
        SDL_Quit();
    }
}

int main (int argc, char *argv[])
{
    try
    {
        typing::APP.Init();
        typing::APP.Run();
    }
    catch (std::exception &e)
    {
        fprintf(stderr, "%s", e.what());
    }

    typing::APP.Shutdown();

    return 0;
}

<|endoftext|>