<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/queue.hh>

#include <seastar/util/std-compat.hh>

/// \defgroup fiber-module Fibers
///
/// \brief Fibers of execution
///
/// Seastar continuations are normally short, but often chained to one
/// another, so that one continuation does a bit of work and then schedules
/// another continuation for later. Such chains can be long, and often even
/// involve loopings - see for example \ref repeat. We call such chains
/// "fibers" of execution.
///
/// These fibers are not threads - each is just a string of continuations -
/// but they share some common requirements with traditional threads.
/// For example, we want to avoid one fiber getting starved while a second
/// fiber continuously runs its continuations one after another.
/// As another example, fibers may want to communicate - e.g., one fiber
/// produces data that a second fiber consumes, and we wish to ensure that
/// both fibers get a chance to run, and that if one stops prematurely,
/// the other doesn't hang forever.
///
/// Consult the following table to see which APIs are useful for fiber tasks:
///
/// Task                                           | APIs
/// -----------------------------------------------|-------------------
/// Repeat a blocking task indefinitely            | \ref keep_doing()
/// Repeat a blocking task, then exit              | \ref repeat(), \ref do_until()
/// Provide mutual exclusion between two tasks     | \ref semaphore, \ref shared_mutex
/// Pass a stream of data between two fibers       | \ref seastar::pipe
/// Safely shut down a resource                    | \ref seastar::gate
/// Hold on to an object while a fiber is running  | \ref do_with()
///

/// Seastar API namespace
namespace seastar {

/// \addtogroup fiber-module
/// @{

class broken_pipe_exception : public std::exception {
public:
    virtual const char* what() const noexcept {
        return "Broken pipe";
    }
};

class unread_overflow_exception : public std::exception {
public:
    virtual const char* what() const noexcept {
        return "pipe_reader::unread() overflow";
    }
};

/// \cond internal
namespace internal {
template <typename T>
class pipe_buffer {
private:
    queue<std::optional<T>> _buf;
    bool _read_open = true;
    bool _write_open = true;
public:
    pipe_buffer(size_t size) : _buf(size) {}
    future<std::optional<T>> read() {
        return _buf.pop_eventually();
    }
    future<> write(T&& data) {
        return _buf.push_eventually(std::move(data));
    }
    bool readable() const {
        return _write_open || !_buf.empty();
    }
    bool writeable() const {
        return _read_open;
    }
    bool close_read() {
        // If a writer blocking (on a full queue), need to stop it.
        if (_buf.full()) {
            _buf.abort(std::make_exception_ptr(broken_pipe_exception()));
        }
        _read_open = false;
        return !_write_open;
    }
    bool close_write() {
        // If the queue is empty, write the EOF (disengaged optional) to the
        // queue to wake a blocked reader. If the queue is not empty, there is
        // no need to write the EOF to the queue - the reader will return an
        // EOF when it sees that _write_open == false.
        if (_buf.empty()) {
            _buf.push({});
        }
        _write_open = false;
        return !_read_open;
    }
};
} // namespace internal
/// \endcond

template <typename T>
class pipe;

/// \brief Read side of a \ref seastar::pipe
///
/// The read side of a pipe, which allows only reading from the pipe.
/// A pipe_reader object cannot be created separately, but only as part of a
/// reader/writer pair through \ref seastar::pipe.
template <typename T>
class pipe_reader {
private:
    internal::pipe_buffer<T> *_bufp;
    std::optional<T> _unread;
    pipe_reader(internal::pipe_buffer<T> *bufp) noexcept : _bufp(bufp) { }
    friend class pipe<T>;
public:
    /// \brief Read next item from the pipe
    ///
    /// Returns a future value, which is fulfilled when the pipe's buffer
    /// becomes non-empty, or the write side is closed. The value returned
    /// is an optional<T>, which is disengaged to mark and end of file
    /// (i.e., the write side was closed, and we've read everything it sent).
    future<std::optional<T>> read() {
        if (_unread) {
            auto ret = std::move(*_unread);
            _unread = {};
            return make_ready_future<std::optional<T>>(std::move(ret));
        }
        if (_bufp->readable()) {
            return _bufp->read();
        } else {
            return make_ready_future<std::optional<T>>();
        }
    }
    /// \brief Return an item to the front of the pipe
    ///
    /// Pushes the given item to the front of the pipe, so it will be
    /// returned by the next read() call. The typical use case is to
    /// unread() the last item returned by read().
    /// More generally, it is legal to unread() any item, not just one
    /// previously returned by read(), but note that the unread() is limited
    /// to just one item - two calls to unread() without an intervening call
    /// to read() will cause an exception.
    void unread(T&& item) {
        if (_unread) {
            throw unread_overflow_exception();
        }
        _unread = std::move(item);
    }
    ~pipe_reader() {
        if (_bufp && _bufp->close_read()) {
            delete _bufp;
        }
    }
    // Allow move, but not copy, of pipe_reader
    pipe_reader(pipe_reader&& other) noexcept : _bufp(other._bufp) {
        other._bufp = nullptr;
    }
    pipe_reader& operator=(pipe_reader&& other) noexcept {
        std::swap(_bufp, other._bufp);
    }
};

/// \brief Write side of a \ref seastar::pipe
///
/// The write side of a pipe, which allows only writing to the pipe.
/// A pipe_writer object cannot be created separately, but only as part of a
/// reader/writer pair through \ref seastar::pipe.
template <typename T>
class pipe_writer {
private:
    internal::pipe_buffer<T> *_bufp;
    pipe_writer(internal::pipe_buffer<T> *bufp) noexcept : _bufp(bufp) { }
    friend class pipe<T>;
public:
    /// \brief Write an item to the pipe
    ///
    /// Returns a future value, which is fulfilled when the data was written
    /// to the buffer (when it become non-full). If the data could not be
    /// written because the read side was closed, an exception
    /// \ref broken_pipe_exception is returned in the future.
    future<> write(T&& data) {
        if (_bufp->writeable()) {
            return _bufp->write(std::move(data));
        } else {
            return make_exception_future<>(broken_pipe_exception());
        }
    }
    ~pipe_writer() {
        if (_bufp && _bufp->close_write()) {
            delete _bufp;
        }
    }
    // Allow move, but not copy, of pipe_writer
    pipe_writer(pipe_writer&& other) noexcept : _bufp(other._bufp) {
        other._bufp = nullptr;
    }
    pipe_writer& operator=(pipe_writer&& other) noexcept {
        std::swap(_bufp, other._bufp);
    }
};

/// \brief A fixed-size pipe for communicating between two fibers.
///
/// A pipe<T> is a mechanism to transfer data between two fibers, one
/// producing data, and the other consuming it. The fixed-size buffer also
/// ensures a balanced execution of the two fibers, because the producer
/// fiber blocks when it writes to a full pipe, until the consumer fiber gets
/// to run and read from the pipe.
///
/// A pipe<T> resembles a Unix pipe, in that it has a read side, a write side,
/// and a fixed-sized buffer between them, and supports either end to be closed
/// independently (and EOF or broken pipe when using the other side).
/// A pipe<T> object holds the reader and write sides of the pipe as two
/// separate objects. These objects can be moved into two different fibers.
/// Importantly, if one of the pipe ends is destroyed (i.e., the continuations
/// capturing it end), the other end of the pipe will stop blocking, so the
/// other fiber will not hang.
///
/// The pipe's read and write interfaces are future-based blocking. I.e., the
/// write() and read() methods return a future which is fulfilled when the
/// operation is complete. The pipe is single-reader single-writer, meaning
/// that until the future returned by read() is fulfilled, read() must not be
/// called again (and same for write).
///
/// Note: The pipe reader and writer are movable, but *not* copyable. It is
/// often convenient to wrap each end in a shared pointer, so it can be
/// copied (e.g., used in an std::function which needs to be copyable) or
/// easily captured into multiple continuations.
template <typename T>
class pipe {
public:
    pipe_reader<T> reader;
    pipe_writer<T> writer;
    explicit pipe(size_t size) : pipe(new internal::pipe_buffer<T>(size)) { }
private:
    pipe(internal::pipe_buffer<T> *bufp) noexcept : reader(bufp), writer(bufp) { }
};

/// @}

} // namespace seastar
<commit_msg>pipe: add missing return in pipe's operator='s<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/queue.hh>

#include <seastar/util/std-compat.hh>

/// \defgroup fiber-module Fibers
///
/// \brief Fibers of execution
///
/// Seastar continuations are normally short, but often chained to one
/// another, so that one continuation does a bit of work and then schedules
/// another continuation for later. Such chains can be long, and often even
/// involve loopings - see for example \ref repeat. We call such chains
/// "fibers" of execution.
///
/// These fibers are not threads - each is just a string of continuations -
/// but they share some common requirements with traditional threads.
/// For example, we want to avoid one fiber getting starved while a second
/// fiber continuously runs its continuations one after another.
/// As another example, fibers may want to communicate - e.g., one fiber
/// produces data that a second fiber consumes, and we wish to ensure that
/// both fibers get a chance to run, and that if one stops prematurely,
/// the other doesn't hang forever.
///
/// Consult the following table to see which APIs are useful for fiber tasks:
///
/// Task                                           | APIs
/// -----------------------------------------------|-------------------
/// Repeat a blocking task indefinitely            | \ref keep_doing()
/// Repeat a blocking task, then exit              | \ref repeat(), \ref do_until()
/// Provide mutual exclusion between two tasks     | \ref semaphore, \ref shared_mutex
/// Pass a stream of data between two fibers       | \ref seastar::pipe
/// Safely shut down a resource                    | \ref seastar::gate
/// Hold on to an object while a fiber is running  | \ref do_with()
///

/// Seastar API namespace
namespace seastar {

/// \addtogroup fiber-module
/// @{

class broken_pipe_exception : public std::exception {
public:
    virtual const char* what() const noexcept {
        return "Broken pipe";
    }
};

class unread_overflow_exception : public std::exception {
public:
    virtual const char* what() const noexcept {
        return "pipe_reader::unread() overflow";
    }
};

/// \cond internal
namespace internal {
template <typename T>
class pipe_buffer {
private:
    queue<std::optional<T>> _buf;
    bool _read_open = true;
    bool _write_open = true;
public:
    pipe_buffer(size_t size) : _buf(size) {}
    future<std::optional<T>> read() {
        return _buf.pop_eventually();
    }
    future<> write(T&& data) {
        return _buf.push_eventually(std::move(data));
    }
    bool readable() const {
        return _write_open || !_buf.empty();
    }
    bool writeable() const {
        return _read_open;
    }
    bool close_read() {
        // If a writer blocking (on a full queue), need to stop it.
        if (_buf.full()) {
            _buf.abort(std::make_exception_ptr(broken_pipe_exception()));
        }
        _read_open = false;
        return !_write_open;
    }
    bool close_write() {
        // If the queue is empty, write the EOF (disengaged optional) to the
        // queue to wake a blocked reader. If the queue is not empty, there is
        // no need to write the EOF to the queue - the reader will return an
        // EOF when it sees that _write_open == false.
        if (_buf.empty()) {
            _buf.push({});
        }
        _write_open = false;
        return !_read_open;
    }
};
} // namespace internal
/// \endcond

template <typename T>
class pipe;

/// \brief Read side of a \ref seastar::pipe
///
/// The read side of a pipe, which allows only reading from the pipe.
/// A pipe_reader object cannot be created separately, but only as part of a
/// reader/writer pair through \ref seastar::pipe.
template <typename T>
class pipe_reader {
private:
    internal::pipe_buffer<T> *_bufp;
    std::optional<T> _unread;
    pipe_reader(internal::pipe_buffer<T> *bufp) noexcept : _bufp(bufp) { }
    friend class pipe<T>;
public:
    /// \brief Read next item from the pipe
    ///
    /// Returns a future value, which is fulfilled when the pipe's buffer
    /// becomes non-empty, or the write side is closed. The value returned
    /// is an optional<T>, which is disengaged to mark and end of file
    /// (i.e., the write side was closed, and we've read everything it sent).
    future<std::optional<T>> read() {
        if (_unread) {
            auto ret = std::move(*_unread);
            _unread = {};
            return make_ready_future<std::optional<T>>(std::move(ret));
        }
        if (_bufp->readable()) {
            return _bufp->read();
        } else {
            return make_ready_future<std::optional<T>>();
        }
    }
    /// \brief Return an item to the front of the pipe
    ///
    /// Pushes the given item to the front of the pipe, so it will be
    /// returned by the next read() call. The typical use case is to
    /// unread() the last item returned by read().
    /// More generally, it is legal to unread() any item, not just one
    /// previously returned by read(), but note that the unread() is limited
    /// to just one item - two calls to unread() without an intervening call
    /// to read() will cause an exception.
    void unread(T&& item) {
        if (_unread) {
            throw unread_overflow_exception();
        }
        _unread = std::move(item);
    }
    ~pipe_reader() {
        if (_bufp && _bufp->close_read()) {
            delete _bufp;
        }
    }
    // Allow move, but not copy, of pipe_reader
    pipe_reader(pipe_reader&& other) noexcept : _bufp(other._bufp) {
        other._bufp = nullptr;
    }
    pipe_reader& operator=(pipe_reader&& other) noexcept {
        std::swap(_bufp, other._bufp);
        return *this;
    }
};

/// \brief Write side of a \ref seastar::pipe
///
/// The write side of a pipe, which allows only writing to the pipe.
/// A pipe_writer object cannot be created separately, but only as part of a
/// reader/writer pair through \ref seastar::pipe.
template <typename T>
class pipe_writer {
private:
    internal::pipe_buffer<T> *_bufp;
    pipe_writer(internal::pipe_buffer<T> *bufp) noexcept : _bufp(bufp) { }
    friend class pipe<T>;
public:
    /// \brief Write an item to the pipe
    ///
    /// Returns a future value, which is fulfilled when the data was written
    /// to the buffer (when it become non-full). If the data could not be
    /// written because the read side was closed, an exception
    /// \ref broken_pipe_exception is returned in the future.
    future<> write(T&& data) {
        if (_bufp->writeable()) {
            return _bufp->write(std::move(data));
        } else {
            return make_exception_future<>(broken_pipe_exception());
        }
    }
    ~pipe_writer() {
        if (_bufp && _bufp->close_write()) {
            delete _bufp;
        }
    }
    // Allow move, but not copy, of pipe_writer
    pipe_writer(pipe_writer&& other) noexcept : _bufp(other._bufp) {
        other._bufp = nullptr;
    }
    pipe_writer& operator=(pipe_writer&& other) noexcept {
        std::swap(_bufp, other._bufp);
        return *this;
    }
};

/// \brief A fixed-size pipe for communicating between two fibers.
///
/// A pipe<T> is a mechanism to transfer data between two fibers, one
/// producing data, and the other consuming it. The fixed-size buffer also
/// ensures a balanced execution of the two fibers, because the producer
/// fiber blocks when it writes to a full pipe, until the consumer fiber gets
/// to run and read from the pipe.
///
/// A pipe<T> resembles a Unix pipe, in that it has a read side, a write side,
/// and a fixed-sized buffer between them, and supports either end to be closed
/// independently (and EOF or broken pipe when using the other side).
/// A pipe<T> object holds the reader and write sides of the pipe as two
/// separate objects. These objects can be moved into two different fibers.
/// Importantly, if one of the pipe ends is destroyed (i.e., the continuations
/// capturing it end), the other end of the pipe will stop blocking, so the
/// other fiber will not hang.
///
/// The pipe's read and write interfaces are future-based blocking. I.e., the
/// write() and read() methods return a future which is fulfilled when the
/// operation is complete. The pipe is single-reader single-writer, meaning
/// that until the future returned by read() is fulfilled, read() must not be
/// called again (and same for write).
///
/// Note: The pipe reader and writer are movable, but *not* copyable. It is
/// often convenient to wrap each end in a shared pointer, so it can be
/// copied (e.g., used in an std::function which needs to be copyable) or
/// easily captured into multiple continuations.
template <typename T>
class pipe {
public:
    pipe_reader<T> reader;
    pipe_writer<T> writer;
    explicit pipe(size_t size) : pipe(new internal::pipe_buffer<T>(size)) { }
private:
    pipe(internal::pipe_buffer<T> *bufp) noexcept : reader(bufp), writer(bufp) { }
};

/// @}

} // namespace seastar
<|endoftext|>


<commit_before>#ifndef LEFTIST_TREE_HPP
#define LEFTIST_TREE_HPP 1

#include <assert.h>
#include <algorithm>
#ifndef MAX
#define MAX 64
#endif

/* ݽṹ */
/* ڵ±ΪxĽڵ Һӽڵ±Ϊ LEFT_CHILD(x) RIGHT_CHILD(x) ڵ±Ϊ FATHER(x) */
#define LEFT_CHILD(x) (2 * (x) + 1)
#define RIGHT_CHILD(x) (2 * (x) + 2)
#define FATHER(x) (((x) - 1) / 2)

/* ڵiľΪdist[i] */
int dist[MAX * 3];

/* s[start, end]ʼΪ ڵrootΪ0 */
int LeftistTreeInit(int root, int s[MAX], int start, int end)
{
    if (start == end) {
        dist[root] = s[start];
        return dist[root];
    }

    int mid = (start + end) / 2;
    int dist = LeftistTreeInit( LEFT_CHILD(root), s, start, mid );
    int dist = LeftistTreeInit( RIGHT_CHILD(root), s, mid + 1, end );
    dist[root] = left_sum + right_sum;
    return dist[root];
}

/* s[index]v */
void LeftistTreeAdd(int root, int index, int v)
{
    if (left_node[root] > index || right_node[root] < index) {
        return;
    }

    assert( left_node[root] <= index );
    assert( right_node[root] >= index );
    sum[root] += v;

    if (left_node[root] == right_node[root]) {
        return;
    }
    LeftistTreeAdd( LEFT_CHILD(root), index, v );
    LeftistTreeAdd( RIGHT_CHILD(root), index, v );
}

/* ѯs[start, end]Χĺ */
int LeftistTreeQuery(int root, int start, int end)
{
    int mid = (left_node[root] + right_node[root]) / 2;
    if (left_node[root] >= start && right_node[root] <= end) {
        return sum[root];
    } else if (end <= mid) {
        return LeftistTreeQuery( LEFT_CHILD(root), start, end );
    } else if (start >= mid + 1) {
        return LeftistTreeQuery( RIGHT_CHILD(root), start, end );
    } else {
        return LeftistTreeQuery( LEFT_CHILD(root), start, mid)
            + LeftistTreeQuery( RIGHT_CHILD(root), mid + 1, end);
    }
}

#endif<commit_msg>TODO: not finished<commit_after>#ifndef LEFTIST_TREE_HPP
#define LEFTIST_TREE_HPP 1

#include <assert.h>
#include <algorithm>
#ifndef MAX
#define MAX 64
#endif

/* ݽṹ */
/* ڵ±ΪxĽڵ Һӽڵ±Ϊ LEFT_CHILD(x) RIGHT_CHILD(x) ڵ±Ϊ FATHER(x) */
#define LEFT_CHILD(x) (2 * (x) + 1)
#define RIGHT_CHILD(x) (2 * (x) + 2)
#define FATHER(x) (((x) - 1) / 2)

struct LeftistTree {
    /* ڵiľΪdistance[i] */
    int distance[MAX * 3];
};

/* s[start, end]ʼΪ ڵrootΪ0 */
int LeftistTreeInitRec(LeftistTree *t, int root, int s[MAX], int start, int end)
{
    if (start == end) {
        t->distance[root] = s[start];
        return dist[root];
    }

    int mid = (start + end) / 2;
    int dist = LeftistTreeInit( LEFT_CHILD(root), s, start, mid );
    int dist = LeftistTreeInit( RIGHT_CHILD(root), s, mid + 1, end );
    dist[root] = left_sum + right_sum;
    return dist[root];
}

/* s[index]v */
void LeftistTreeAdd(int root, int index, int v)
{
    if (left_node[root] > index || right_node[root] < index) {
        return;
    }

    assert( left_node[root] <= index );
    assert( right_node[root] >= index );
    sum[root] += v;

    if (left_node[root] == right_node[root]) {
        return;
    }
    LeftistTreeAdd( LEFT_CHILD(root), index, v );
    LeftistTreeAdd( RIGHT_CHILD(root), index, v );
}

/* ѯs[start, end]Χĺ */
int LeftistTreeQuery(int root, int start, int end)
{
    int mid = (left_node[root] + right_node[root]) / 2;
    if (left_node[root] >= start && right_node[root] <= end) {
        return sum[root];
    } else if (end <= mid) {
        return LeftistTreeQuery( LEFT_CHILD(root), start, end );
    } else if (start >= mid + 1) {
        return LeftistTreeQuery( RIGHT_CHILD(root), start, end );
    } else {
        return LeftistTreeQuery( LEFT_CHILD(root), start, mid)
            + LeftistTreeQuery( RIGHT_CHILD(root), mid + 1, end);
    }
}

#endif<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef YDSH_RESULT_HPP
#define YDSH_RESULT_HPP

#include <type_traits>
#include <cassert>

#include "noncopyable.h"

namespace ydsh {

template <typename T>
struct TypeHolder {
    using type = T;
};

namespace __detail {

constexpr bool andAll(bool b) {
    return b;
}

template <typename ...T>
constexpr bool andAll(bool b, T && ...t) {
    return b && andAll(std::forward<T>(t)...);
}

template <typename T>
constexpr int toTypeIndex(int) {
    return -1;
}

template <typename T, typename F, typename ...R>
constexpr int toTypeIndex(int index) {
    return std::is_same<T, F>::value ? index : toTypeIndex<T, R...>(index + 1);
}

template <std::size_t I, std::size_t N, typename F, typename ...R>
struct TypeByIndex : TypeByIndex<I + 1, N, R...> {};

template <std::size_t N, typename F, typename ...R>
struct TypeByIndex<N, N, F, R...> {
    using type = F;
};

template <typename ...T>
struct OverloadResolver;

template <typename F, typename ...T>
struct OverloadResolver<F, T...> : OverloadResolver<T...> {
    using OverloadResolver<T...>::operator();

    TypeHolder<F> operator()(F) const;
};

template <>
struct OverloadResolver<> {
    void operator()() const;
};

template <typename T>
using result_of_t = typename std::result_of<T>::type;

template <typename F, typename ...T>
using resolvedType = typename result_of_t<OverloadResolver<T...>(F)>::type;

} // namespace __detail

template <typename U, typename ...T>
struct TypeTag {
    static constexpr int value = __detail::toTypeIndex<U, T...>(0);
};

template <std::size_t N, typename T0, typename ...T>
struct TypeByIndex {
    static_assert(N < sizeof...(T) + 1, "out of range");
    using type = typename __detail::TypeByIndex<0, N, T0, T...>::type;
};

// #####################
// ##     Storage     ##
// #####################

template <typename ...T>
struct Storage {
    static_assert(sizeof...(T) > 0, "at least 1 type");

    std::aligned_union_t<1, T...> data;

    template <typename U, typename F = __detail::resolvedType<U, T...>>
    void obtain(U &&value) {
        static_assert(TypeTag<F, T...>::value > -1, "invalid type");

        using Decayed = typename std::decay<F>::type;
        new (&this->data) Decayed(std::forward<U>(value));
    }
};

template <typename T, typename ...R>
inline T &get(Storage<R...> &storage) {
    static_assert(TypeTag<T, R...>::value > -1, "invalid type");

    return *reinterpret_cast<T *>(&storage.data);
}

template <typename T, typename ...R>
inline const T &get(const Storage<R...> &storage) {
    static_assert(TypeTag<T, R...>::value > -1, "invalid type");

    return *reinterpret_cast<const T *>(&storage.data);
}

template <typename T, typename ...R>
inline void destroy(Storage<R...> &storage) {
    get<T>(storage).~T();
}

/**
 *
 * @tparam T
 * @tparam R
 * @param src
 * @param dest
 * must be uninitialized
 */
template <typename T, typename ...R>
inline void move(Storage<R...> &src, Storage<R...> &dest) {
    dest.obtain(std::move(get<T>(src)));
    destroy<T>(src);
}

template <typename T, typename ...R>
inline void copy(const Storage<R...> &src, Storage<R...> &dest) {
    dest.obtain(get<T>(src));
}

namespace __detail_union {

template <int N, typename ...R>
struct Destroyer {
    void operator()(Storage<R...> &storage, int tag) const {
        if(tag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            destroy<T>(storage);
        } else {
            Destroyer<N - 1, R...>()(storage, tag);
        }
    }
};

template <typename ...R>
struct Destroyer<-1, R...> {
    void operator()(Storage<R...> &, int) const {}
};

template <int N, typename ...R>
struct Mover {
    void operator()(Storage<R...> &src, int srcTag, Storage<R...> &dest) const {
        if(srcTag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            move<T>(src, dest);
        } else {
            Mover<N - 1, R...>()(src, srcTag, dest);
        }
    }
};

template <typename ...R>
struct Mover<-1, R...> {
    void operator()(Storage<R...> &, int, Storage<R...> &) const {}
};

template <int N, typename ...R>
struct Copier {
    void operator()(const Storage<R...> &src, int srcTag, Storage<R...> &dest) const {
        if(srcTag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            copy<T>(src, dest);
        } else {
            Copier<N - 1, R...>()(src, srcTag, dest);
        }
    }
};

template <typename ...R>
struct Copier<-1, R...> {
    void operator()(const Storage<R...> &, int, Storage<R...> &) const {}
};

} // namespace __detail_union

template <typename ...R>
inline void polyDestroy(Storage<R...> &storage, int tag) {
    __detail_union::Destroyer<sizeof...(R) - 1, R...>()(storage, tag);
}

/**
 *
 * @tparam N
 * @tparam R
 * @param src
 * @param srcTag
 * @param dest
 * must be uninitialized
 */
template <typename ...R>
inline void polyMove(Storage<R...> &src, int srcTag, Storage<R...> &dest) {
    __detail_union::Mover<sizeof...(R) - 1, R...>()(src, srcTag, dest);
}

template <typename ...R>
inline void polyCopy(const Storage<R...> &src, int srcTag, Storage<R...> &dest) {
    __detail_union::Copier<sizeof...(R) - 1, R...>()(src, srcTag, dest);
}

// ###################
// ##     Union     ##
// ###################

template <typename ...T>
class Union {
private:
    static_assert(__detail::andAll(std::is_move_constructible<T>::value...), "must be move-constructible");

    using StorageType = Storage<T...>;
    StorageType value_;
    int tag_;

public:
    template <typename R>
    static constexpr int TAG = TypeTag<R, T...>::value;

    Union() noexcept : tag_(-1) {}

    template <typename U, typename F = __detail::resolvedType<U, T...>>
    Union(U &&value) noexcept : tag_(TAG<F>) {   //NOLINT
        this->value_.obtain(std::forward<U>(value));
    }

    Union(Union &&value) noexcept : tag_(value.tag()) {
        polyMove(value.value(), this->tag(), this->value());
        value.tag_ = -1;
    }

    Union(const Union &value) : tag_(value.tag()) {
        polyCopy(value.value(), this->tag(), this->value());
    }

    ~Union() {
        polyDestroy(this->value(), this->tag());
    }

    Union &operator=(Union && value) noexcept {
        this->moveAssign(value);
        return *this;
    }

    Union &operator=(const Union &value) {
        if(this != std::addressof(value)) {
            this->copyAssign(value);
        }
        return *this;
    }

    StorageType &value() {
        return this->value_;
    }

    const StorageType &value() const {
        return this->value_;
    }

    int tag() const {
        return this->tag_;
    }

    bool hasValue() const {
        return this->tag() > -1;
    }

private:
    void moveAssign(Union &value) noexcept {
        polyDestroy(this->value(), this->tag());
        polyMove(value.value(), value.tag(), this->value());
        this->tag_ = value.tag();
        value.tag_ = -1;
    }

    void copyAssign(const Union &value) {
        polyDestroy(this->value(), this->tag());
        polyCopy(value.value(), value.tag(), this->value());
        this->tag_ = value.tag();
    }
};

template <typename T, typename ...R>
inline bool is(const Union<R...> &value) {
    return value.tag() == TypeTag<T, R...>::value;
}

template <typename T, typename ...R>
inline T &get(Union<R...> &value) {
    assert(is<T>(value));
    return get<T>(value.value());
}

template <typename T, typename ...R>
inline const T &get(const Union<R...> &value) {
    assert(is<T>(value));
    return get<T>(value.value());
}

// ######################
// ##     Optional     ##
// ######################

template <typename T>
class OptionalBase : public Union<T> {
public:
    OptionalBase() noexcept : Union<T>() {}

    OptionalBase(T &&value) noexcept : Union<T>(std::forward<T>(value)) {}  //NOLINT

    T &unwrap() noexcept {
        return get<T>(*this);
    }

    const T &unwrap() const noexcept {
        return get<T>(*this);
    }
};

template <typename ...T>
class OptionalBase<Union<T...>> : public Union<T...> {
public:
    OptionalBase() noexcept : Union<T...>() {}

    template <typename U>
    OptionalBase(U &&value) noexcept : Union<T...>(std::forward<U>(value)) {}   //NOLINT
};

template <typename T>
struct OptFlattener {
    using type = T;
};

template <typename T>
struct OptFlattener<OptionalBase<T>> : OptFlattener<T> {};

template <typename T>
using Optional = OptionalBase<typename OptFlattener<T>::type>;

// ####################
// ##     Result     ##
// ####################

template <typename T>
struct OkHolder {
    T value;

    explicit OkHolder(T &&value) : value(std::move(value)) {}
    explicit OkHolder(const T &value) : value(value) {}
};

template <typename E>
struct ErrHolder {
    E value;

    explicit ErrHolder(E &&value) : value(std::move(value)) {}
    explicit ErrHolder(const E &value) : value(value) {}
};

template <typename T, typename Decayed = typename std::decay<T>::type>
OkHolder<Decayed> Ok(T &&value) {
    return OkHolder<Decayed>(std::forward<T>(value));
}

template <typename E, typename Decayed = typename std::decay<E>::type>
ErrHolder<Decayed> Err(E &&value) {
    return ErrHolder<Decayed>(std::forward<E>(value));
}

template <typename T, typename E>
class Result : public Union<T, E> {
public:
    NON_COPYABLE(Result);

    Result() = delete;

    template <typename T0>
    Result(OkHolder<T0> &&okHolder) noexcept : Union<T, E>(std::move(okHolder.value)) {} //NOLINT

    Result(ErrHolder<E> &&errHolder) noexcept : Union<T, E>(std::move(errHolder.value)) {}  //NOLINT

    Result(Result &&result) noexcept = default;

    ~Result() = default;

    Result &operator=(Result &&result) noexcept = default;

    explicit operator bool() const {
        return is<T>(*this);
    }
    T &asOk() {
        return get<T>(*this);
    }

    E &asErr() {
        return get<E>(*this);
    }

    T &&take() {
        return std::move(this->asOk());
    }

    E &&takeError() {
        return std::move(this->asErr());
    }
};

} // namespace ydsh

#endif //YDSH_RESULT_HPP
<commit_msg>add invalid type parameter checking to Union#is<commit_after>/*
 * Copyright (C) 2018 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef YDSH_RESULT_HPP
#define YDSH_RESULT_HPP

#include <type_traits>
#include <cassert>

#include "noncopyable.h"

namespace ydsh {

template <typename T>
struct TypeHolder {
    using type = T;
};

namespace __detail {

constexpr bool andAll(bool b) {
    return b;
}

template <typename ...T>
constexpr bool andAll(bool b, T && ...t) {
    return b && andAll(std::forward<T>(t)...);
}

template <typename T>
constexpr int toTypeIndex(int) {
    return -1;
}

template <typename T, typename F, typename ...R>
constexpr int toTypeIndex(int index) {
    return std::is_same<T, F>::value ? index : toTypeIndex<T, R...>(index + 1);
}

template <std::size_t I, std::size_t N, typename F, typename ...R>
struct TypeByIndex : TypeByIndex<I + 1, N, R...> {};

template <std::size_t N, typename F, typename ...R>
struct TypeByIndex<N, N, F, R...> {
    using type = F;
};

template <typename ...T>
struct OverloadResolver;

template <typename F, typename ...T>
struct OverloadResolver<F, T...> : OverloadResolver<T...> {
    using OverloadResolver<T...>::operator();

    TypeHolder<F> operator()(F) const;
};

template <>
struct OverloadResolver<> {
    void operator()() const;
};

template <typename T>
using result_of_t = typename std::result_of<T>::type;

template <typename F, typename ...T>
using resolvedType = typename result_of_t<OverloadResolver<T...>(F)>::type;

} // namespace __detail

template <typename U, typename ...T>
struct TypeTag {
    static constexpr int value = __detail::toTypeIndex<U, T...>(0);
};

template <std::size_t N, typename T0, typename ...T>
struct TypeByIndex {
    static_assert(N < sizeof...(T) + 1, "out of range");
    using type = typename __detail::TypeByIndex<0, N, T0, T...>::type;
};

// #####################
// ##     Storage     ##
// #####################

template <typename ...T>
struct Storage {
    static_assert(sizeof...(T) > 0, "at least 1 type");

    std::aligned_union_t<1, T...> data;

    template <typename U, typename F = __detail::resolvedType<U, T...>>
    void obtain(U &&value) {
        static_assert(TypeTag<F, T...>::value > -1, "invalid type");

        using Decayed = typename std::decay<F>::type;
        new (&this->data) Decayed(std::forward<U>(value));
    }
};

template <typename T, typename ...R>
inline T &get(Storage<R...> &storage) {
    static_assert(TypeTag<T, R...>::value > -1, "invalid type");

    return *reinterpret_cast<T *>(&storage.data);
}

template <typename T, typename ...R>
inline const T &get(const Storage<R...> &storage) {
    static_assert(TypeTag<T, R...>::value > -1, "invalid type");

    return *reinterpret_cast<const T *>(&storage.data);
}

template <typename T, typename ...R>
inline void destroy(Storage<R...> &storage) {
    get<T>(storage).~T();
}

/**
 *
 * @tparam T
 * @tparam R
 * @param src
 * @param dest
 * must be uninitialized
 */
template <typename T, typename ...R>
inline void move(Storage<R...> &src, Storage<R...> &dest) {
    dest.obtain(std::move(get<T>(src)));
    destroy<T>(src);
}

template <typename T, typename ...R>
inline void copy(const Storage<R...> &src, Storage<R...> &dest) {
    dest.obtain(get<T>(src));
}

namespace __detail_union {

template <int N, typename ...R>
struct Destroyer {
    void operator()(Storage<R...> &storage, int tag) const {
        if(tag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            destroy<T>(storage);
        } else {
            Destroyer<N - 1, R...>()(storage, tag);
        }
    }
};

template <typename ...R>
struct Destroyer<-1, R...> {
    void operator()(Storage<R...> &, int) const {}
};

template <int N, typename ...R>
struct Mover {
    void operator()(Storage<R...> &src, int srcTag, Storage<R...> &dest) const {
        if(srcTag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            move<T>(src, dest);
        } else {
            Mover<N - 1, R...>()(src, srcTag, dest);
        }
    }
};

template <typename ...R>
struct Mover<-1, R...> {
    void operator()(Storage<R...> &, int, Storage<R...> &) const {}
};

template <int N, typename ...R>
struct Copier {
    void operator()(const Storage<R...> &src, int srcTag, Storage<R...> &dest) const {
        if(srcTag == N) {
            using T = typename TypeByIndex<N, R...>::type;
            copy<T>(src, dest);
        } else {
            Copier<N - 1, R...>()(src, srcTag, dest);
        }
    }
};

template <typename ...R>
struct Copier<-1, R...> {
    void operator()(const Storage<R...> &, int, Storage<R...> &) const {}
};

} // namespace __detail_union

template <typename ...R>
inline void polyDestroy(Storage<R...> &storage, int tag) {
    __detail_union::Destroyer<sizeof...(R) - 1, R...>()(storage, tag);
}

/**
 *
 * @tparam N
 * @tparam R
 * @param src
 * @param srcTag
 * @param dest
 * must be uninitialized
 */
template <typename ...R>
inline void polyMove(Storage<R...> &src, int srcTag, Storage<R...> &dest) {
    __detail_union::Mover<sizeof...(R) - 1, R...>()(src, srcTag, dest);
}

template <typename ...R>
inline void polyCopy(const Storage<R...> &src, int srcTag, Storage<R...> &dest) {
    __detail_union::Copier<sizeof...(R) - 1, R...>()(src, srcTag, dest);
}

// ###################
// ##     Union     ##
// ###################

template <typename ...T>
class Union {
private:
    static_assert(__detail::andAll(std::is_move_constructible<T>::value...), "must be move-constructible");

    using StorageType = Storage<T...>;
    StorageType value_;
    int tag_;

public:
    template <typename R>
    static constexpr int TAG = TypeTag<R, T...>::value;

    Union() noexcept : tag_(-1) {}

    template <typename U, typename F = __detail::resolvedType<U, T...>>
    Union(U &&value) noexcept : tag_(TAG<F>) {   //NOLINT
        this->value_.obtain(std::forward<U>(value));
    }

    Union(Union &&value) noexcept : tag_(value.tag()) {
        polyMove(value.value(), this->tag(), this->value());
        value.tag_ = -1;
    }

    Union(const Union &value) : tag_(value.tag()) {
        polyCopy(value.value(), this->tag(), this->value());
    }

    ~Union() {
        polyDestroy(this->value(), this->tag());
    }

    Union &operator=(Union && value) noexcept {
        this->moveAssign(value);
        return *this;
    }

    Union &operator=(const Union &value) {
        if(this != std::addressof(value)) {
            this->copyAssign(value);
        }
        return *this;
    }

    StorageType &value() {
        return this->value_;
    }

    const StorageType &value() const {
        return this->value_;
    }

    int tag() const {
        return this->tag_;
    }

    bool hasValue() const {
        return this->tag() > -1;
    }

private:
    void moveAssign(Union &value) noexcept {
        polyDestroy(this->value(), this->tag());
        polyMove(value.value(), value.tag(), this->value());
        this->tag_ = value.tag();
        value.tag_ = -1;
    }

    void copyAssign(const Union &value) {
        polyDestroy(this->value(), this->tag());
        polyCopy(value.value(), value.tag(), this->value());
        this->tag_ = value.tag();
    }
};

template <typename T, typename ...R>
inline bool is(const Union<R...> &value) {
    using Tag = TypeTag<T, R...>;
    static_assert(Tag::value > -1, "invalid type");
    return value.tag() == Tag::value;
}

template <typename T, typename ...R>
inline T &get(Union<R...> &value) {
    assert(is<T>(value));
    return get<T>(value.value());
}

template <typename T, typename ...R>
inline const T &get(const Union<R...> &value) {
    assert(is<T>(value));
    return get<T>(value.value());
}

// ######################
// ##     Optional     ##
// ######################

template <typename T>
class OptionalBase : public Union<T> {
public:
    OptionalBase() noexcept : Union<T>() {}

    OptionalBase(T &&value) noexcept : Union<T>(std::forward<T>(value)) {}  //NOLINT

    T &unwrap() noexcept {
        return get<T>(*this);
    }

    const T &unwrap() const noexcept {
        return get<T>(*this);
    }
};

template <typename ...T>
class OptionalBase<Union<T...>> : public Union<T...> {
public:
    OptionalBase() noexcept : Union<T...>() {}

    template <typename U>
    OptionalBase(U &&value) noexcept : Union<T...>(std::forward<U>(value)) {}   //NOLINT
};

template <typename T>
struct OptFlattener {
    using type = T;
};

template <typename T>
struct OptFlattener<OptionalBase<T>> : OptFlattener<T> {};

template <typename T>
using Optional = OptionalBase<typename OptFlattener<T>::type>;

// ####################
// ##     Result     ##
// ####################

template <typename T>
struct OkHolder {
    T value;

    explicit OkHolder(T &&value) : value(std::move(value)) {}
    explicit OkHolder(const T &value) : value(value) {}
};

template <typename E>
struct ErrHolder {
    E value;

    explicit ErrHolder(E &&value) : value(std::move(value)) {}
    explicit ErrHolder(const E &value) : value(value) {}
};

template <typename T, typename Decayed = typename std::decay<T>::type>
OkHolder<Decayed> Ok(T &&value) {
    return OkHolder<Decayed>(std::forward<T>(value));
}

template <typename E, typename Decayed = typename std::decay<E>::type>
ErrHolder<Decayed> Err(E &&value) {
    return ErrHolder<Decayed>(std::forward<E>(value));
}

template <typename T, typename E>
class Result : public Union<T, E> {
public:
    NON_COPYABLE(Result);

    Result() = delete;

    template <typename T0>
    Result(OkHolder<T0> &&okHolder) noexcept : Union<T, E>(std::move(okHolder.value)) {} //NOLINT

    Result(ErrHolder<E> &&errHolder) noexcept : Union<T, E>(std::move(errHolder.value)) {}  //NOLINT

    Result(Result &&result) noexcept = default;

    ~Result() = default;

    Result &operator=(Result &&result) noexcept = default;

    explicit operator bool() const {
        return is<T>(*this);
    }
    T &asOk() {
        return get<T>(*this);
    }

    E &asErr() {
        return get<E>(*this);
    }

    T &&take() {
        return std::move(this->asOk());
    }

    E &&takeError() {
        return std::move(this->asErr());
    }
};

} // namespace ydsh

#endif //YDSH_RESULT_HPP
<|endoftext|>


<commit_before>#include "perceptron\Perceptron.h"
#include "perceptron\Perceptrons.h"
#include "network\Network.h"
#include "trainer\Trainer.h"
#include <iostream>

using namespace SNN_network;

int main()
{
	Trainer trainer;

	vector<int> nb = {5 };//, 10, 10, 10
	vector<perceptron_type_t> type = { logistic, identities };//identities logistic
	vector<double> param = { 1.};
	Network net(nb, type);
	net.print();

	vector<double> a = { 0, 0, 0, 0, 1, 1, 1, 1 };
	vector<double> b = { 0, 0, 1, 1, 0, 0, 0, 1 };
	vector<double> c = { 0, 1, 0, 1, 0, 0, 0, 1 };
	vector<vector<double>*> P1 = { &a, &b, &c};

	vector<double> Ta = { 0, 1, 2, 3, 4, 4, 4, 7 };
	vector<double> Tb = { 0, 0, 0, 0, 0, 0, 2, 2 };
	vector<double> Tc = { 0, 3, 3, 0, 3, 0, 0, 3 };
	vector<double> Td = { 0, 1, 1, 2, 1, 2, 2, 3 };
	vector<vector<double>*> T1 = {/*&Ta, &Tb, */&Tc/*, &Td*/};

	vector<double> a2 = { 0, 0, 0, 1, 1, 0, 0, 0, 1 };
	vector<double> b2 = { 0, 0, 0, 1, 1, 0, 0, 0, 1 };
	vector<double> c2 = { 0, 0, 1, 1, 0, 0, 0, 0, 1 };
	vector<vector<double>*> P2 = { &a2, &b2, &c2 };

	vector<double> a3 = { 1, 0, 0, 0, 1, 1, 1, 1 };
	vector<double> b3 = { 0, 0, 1, 1, 1, 0, 1, 1 };
	vector<double> c3 = { 0, 1, 0, 1, 0, 1, 0, 1 };
	vector<vector<double>*> P3 = { &a3, &b3, &c3 };

	trainig_config_t config;
	config.training_type = GD_nesterov;
	config.error_type = mse;
	config.nb_epochs = 500;
	config.step = 0.1;
	config.stop_error = 0.00001;

	//momentum factor
	config.momentum_factor = 0.9;

	//debug config
	config.debug_level = 2;

	trainer.set_config(config);
	trainer.train(&net, P1, T1);
	net.print();

	net.sim(P2);
	net.print_output();
	net.round_output();
	net.print_output();

	net.sim(P3);
	net.print_output();
	net.round_output();
	net.print_output();

	system("PAUSE");

	return 0;
}<commit_msg>write an exemple<commit_after>#include "network\Network.h"
#include "trainer\Trainer.h"
#include <iostream>

using namespace SNN_network;

int main()
{
	/*Create your network*/
	vector<int> nb = { 1 };
	vector<perceptron_type_t> type = { identities };
	vector<double> param = { };
	Network net(nb, type, param);

	net.print();

	/*Configure your training*/

	trainig_config_t config;

	config.debug_level = 2;
	config.debug_file = "debug.txt";

	config.error_type = mae;
	config.stop_error = 0.00001;
	config.nb_epochs = 5000;

	config.training_type = GD_adagrad;
	config.step = 0.1;
	//config.momentum_factor = 0.05;

	Trainer trainer;
	trainer.set_config(config);

	/*Train your network*/

	vector<double> d = { 0, 0, 0, 0, 0, 1, 1, 0 };
	vector<double> c = { 0, 0, 0, 0, 1, 1, 0, 1 };
	vector<double> b = { 0, 0, 1, 1, 0, 0, 0, 1 };
	vector<double> a = { 0, 1, 0, 1, 0, 0, 0, 1 };
	vector<vector<double>*> P = { &a, &b, &c, &d };

	vector<double> Ta = { 0, 1, 2, 3, 4, 12, 8, 7 };
	vector<vector<double>*> T = { &Ta };

	trainer.train(&net, P, T);

	/*Use your training network*/

	vector<double> d2 = { 1, 0, 0, 0, 1, 0, 0, 1, 1 };
	vector<double> c2 = { 0, 1, 0, 0, 0, 1, 1, 0, 1 };
	vector<double> b2 = { 0, 0, 1, 0, 1, 0, 1, 0, 1 };
	vector<double> a2 = { 0, 0, 0, 1, 0, 1, 0, 1, 1 };
	vector<vector<double>*> P2 = { &a2, &b2, &c2, &d2 };

	net.sim(P2);

	net.round_output();
	net.print_output();
	vector<vector<double>> out = net.get_output_cpy();

	/*Additionals features*/
	net.print();

	Network net2;
	net2 = net;
	net2.print();

	system("PAUSE");

	return 0;
}<|endoftext|>


<commit_before>#include "globalhandler.h"
#include "host-ipmid/ipmid-api.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>

const char  *control_object_name  =  "/org/openbmc/control/bmc0";
const char  *control_intf_name    =  "org.openbmc.control.Bmc";

const char  *objectmapper_service_name =  "org.openbmc.ObjectMapper";
const char  *objectmapper_object_name  =  "/org/openbmc/ObjectMapper";
const char  *objectmapper_intf_name    =  "org.openbmc.ObjectMapper";

void register_netfn_global_functions() __attribute__((constructor));

int obj_mapper_get_connection(char** buf, const char* obj_path)
{
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus_message *m = NULL;
    sd_bus *bus = NULL;
    char *temp_buf = NULL, *intf = NULL;
    size_t buf_size = 0;
    int r;

    //Get the system bus where most system services are provided.
    bus = ipmid_get_sd_bus_connection();

    /*
     * Bus, service, object path, interface and method are provided to call
     * the method.
     * Signatures and input arguments are provided by the arguments at the
     * end.
     */
    r = sd_bus_call_method(bus,
            objectmapper_service_name,                      /* service to contact */
            objectmapper_object_name,                       /* object path */
            objectmapper_intf_name,                         /* interface name */
            "GetObject",                                    /* method name */
            &error,                                         /* object to return error in */
            &m,                                             /* return message on success */
            "s",                                            /* input signature */
            obj_path                                        /* first argument */
            );

    if (r < 0) {
        fprintf(stderr, "Failed to issue method call: %s\n", error.message);
        goto finish;
    }

    // Get the key, aka, the connection name
    sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf);

	/*
     * TODO: check the return code. Currently for no reason the message
     * parsing of object mapper is always complaining about
     * "Device or resource busy", but the result seems OK for now. Need
     *  further checks.
     */

    buf_size = strlen(temp_buf) + 1;
    printf("IPMID connection name: %s\n", temp_buf);
    *buf = (char*)malloc(buf_size);

    if (*buf == NULL) {
        fprintf(stderr, "Malloc failed for warm reset");
        r = -1;
        goto finish;
    }

    memcpy(*buf, temp_buf, buf_size);

finish:
    sd_bus_error_free(&error);
    sd_bus_message_unref(m);

    return r;
}

int dbus_reset(const char *method)
{
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus_message *m = NULL;
    sd_bus *bus = NULL;
    char* connection = NULL;
    int r;

    r = obj_mapper_get_connection(&connection, control_object_name);
    if (r < 0) {
        fprintf(stderr, "Failed to get connection, return value: %d.\n", r);
        goto finish;
    }

    printf("connection: %s\n", connection);

    // Open the system bus where most system services are provided.
    bus = ipmid_get_sd_bus_connection();

    /*
     * Bus, service, object path, interface and method are provided to call
     * the method.
     * Signatures and input arguments are provided by the arguments at the
     * end.
     */
    r = sd_bus_call_method(bus,
            connection,                                /* service to contact */
            control_object_name,                       /* object path */
            control_intf_name,                         /* interface name */
            method,                               /* method name */
            &error,                                    /* object to return error in */
            &m,                                        /* return message on success */
            NULL,
            NULL
            );

    if (r < 0) {
        fprintf(stderr, "Failed to issue method call: %s\n", error.message);
        goto finish;
    }

finish:
    sd_bus_error_free(&error);
    sd_bus_message_unref(m);
    free(connection);

    return r;
}

ipmi_ret_t ipmi_global_warm_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                              ipmi_request_t request, ipmi_response_t response,
                              ipmi_data_len_t data_len, ipmi_context_t context)
{
    printf("Handling GLOBAL warmReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);

    // TODO: call the correct dbus method for warmReset.
    dbus_reset("warmReset");

    // Status code.
    ipmi_ret_t rc = IPMI_CC_OK;
    *data_len = 0;
    return rc;
}

ipmi_ret_t ipmi_global_cold_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                              ipmi_request_t request, ipmi_response_t response,
                              ipmi_data_len_t data_len, ipmi_context_t context)
{
    printf("Handling GLOBAL coldReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);

    // TODO: call the correct dbus method for coldReset.
    dbus_reset("coldReset");

    // Status code.
    ipmi_ret_t rc = IPMI_CC_OK;
    *data_len = 0;
    return rc;
}

void register_netfn_global_functions()
{
    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_COLD_RESET);
    ipmi_register_callback(NETFUN_APP, IPMI_CMD_COLD_RESET, NULL, ipmi_global_cold_reset);

    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WARM_RESET);
    ipmi_register_callback(NETFUN_APP, IPMI_CMD_WARM_RESET, NULL, ipmi_global_warm_reset);

    return;
}
<commit_msg>global: replace mapper method with library call<commit_after>#include "globalhandler.h"
#include "host-ipmid/ipmid-api.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <mapper.h>

const char  *control_object_name  =  "/org/openbmc/control/bmc0";
const char  *control_intf_name    =  "org.openbmc.control.Bmc";

void register_netfn_global_functions() __attribute__((constructor));

int dbus_reset(const char *method)
{
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus_message *m = NULL;
    sd_bus *bus = NULL;
    char* connection = NULL;
    int r;

    bus = ipmid_get_sd_bus_connection();
    r = mapper_get_service(bus, control_object_name, &connection);
    if (r < 0) {
        fprintf(stderr, "Failed to get connection for %s: %s\n",
                control_object_name, strerror(-r));
        goto finish;
    }

    printf("connection: %s\n", connection);

    // Open the system bus where most system services are provided.
    bus = ipmid_get_sd_bus_connection();

    /*
     * Bus, service, object path, interface and method are provided to call
     * the method.
     * Signatures and input arguments are provided by the arguments at the
     * end.
     */
    r = sd_bus_call_method(bus,
            connection,                                /* service to contact */
            control_object_name,                       /* object path */
            control_intf_name,                         /* interface name */
            method,                               /* method name */
            &error,                                    /* object to return error in */
            &m,                                        /* return message on success */
            NULL,
            NULL
            );

    if (r < 0) {
        fprintf(stderr, "Failed to issue method call: %s\n", error.message);
        goto finish;
    }

finish:
    sd_bus_error_free(&error);
    sd_bus_message_unref(m);
    free(connection);

    return r;
}

ipmi_ret_t ipmi_global_warm_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                              ipmi_request_t request, ipmi_response_t response,
                              ipmi_data_len_t data_len, ipmi_context_t context)
{
    printf("Handling GLOBAL warmReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);

    // TODO: call the correct dbus method for warmReset.
    dbus_reset("warmReset");

    // Status code.
    ipmi_ret_t rc = IPMI_CC_OK;
    *data_len = 0;
    return rc;
}

ipmi_ret_t ipmi_global_cold_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                              ipmi_request_t request, ipmi_response_t response,
                              ipmi_data_len_t data_len, ipmi_context_t context)
{
    printf("Handling GLOBAL coldReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);

    // TODO: call the correct dbus method for coldReset.
    dbus_reset("coldReset");

    // Status code.
    ipmi_ret_t rc = IPMI_CC_OK;
    *data_len = 0;
    return rc;
}

void register_netfn_global_functions()
{
    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_COLD_RESET);
    ipmi_register_callback(NETFUN_APP, IPMI_CMD_COLD_RESET, NULL, ipmi_global_cold_reset);

    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WARM_RESET);
    ipmi_register_callback(NETFUN_APP, IPMI_CMD_WARM_RESET, NULL, ipmi_global_warm_reset);

    return;
}
<|endoftext|>


<commit_before>#include <agge.text/layout_builder.h>

#include <agge/math.h>
#include <agge/minmax.h>

namespace agge
{
	namespace
	{
		template <typename VectorT>
		inline typename VectorT::value_type &duplicate_last(VectorT &container)
		{
			container.reserve(container.size() + 1);
			return *container.insert(container.end(), container.back());
		}
	}

	bool layout_builder::state::operator !() const
	{	return !next;	}

	bool layout_builder::state::operator <(const state &rhs) const
	{	return next < rhs.next;	}

	layout_builder::layout_builder(positioned_glyphs_container_t &glyphs, glyph_runs_container_t &glyph_runs,
		text_lines_container_t &text_lines)
		: _state(zero()), _glyphs(glyphs), _glyph_runs(glyph_runs), _text_lines(text_lines)
	{
		_glyph_runs.clear();
		_current_run = &*_glyph_runs.insert(_glyph_runs.end(), glyph_run(_glyphs));
		_text_lines.clear();
		_current_line = &*_text_lines.insert(_text_lines.end(), text_line(_glyph_runs));
		_state.runs_size = 1;
	}

	void layout_builder::begin_style(const font::ptr &font_)
	{
		const font_metrics m = font_->get_metrics();

		commit_run();
		_current_run->font_ = font_;
		_implicit_height = m.ascent + m.descent + m.leading;
	}

	void layout_builder::trim_current_line(const state &at)
	{
		_glyph_runs.erase(_glyph_runs.begin() + at.runs_size, _glyph_runs.end());
		_current_run = &_glyph_runs.back();
		_current_run->end_index = at.next;
		_state = at;
	}

	bool layout_builder::break_current_line()
	{
		commit_run();
		bool was_empty = _current_line->empty();
		commit_line();
		_current_run->offset = zero();
		return !was_empty;
	}

	void layout_builder::break_current_line(const state &at, const state &resume_at)
	{
		state store = _state;

		_state = at;
		break_current_line();
		_state = store, _state.extent -= resume_at.extent, _state.runs_size = _glyph_runs.size();
		_current_run->end_index = _current_run->begin_index = resume_at.next;
	}

	void layout_builder::commit_run()
	{
		if (_current_run->begin_index < _state.next)
		{
			_current_run->end_index = _state.next;
			_current_run = &duplicate_last(_glyph_runs);
			_current_run->begin_index = _state.next;
			_current_line->end_index = (_state.runs_size = _glyph_runs.size()) - 1;
		}
		_current_run->offset = create_vector(_state.extent, real_t());
	}

	void layout_builder::commit_line()
	{
		if (_current_line->empty())
		{
			_current_line->extent = _state.extent = real_t();
			_current_line->offset += create_vector(real_t(), _implicit_height);
		}
		else
		{
			real_t ascent = real_t();
			real_t descent = real_t();
			real_t descent_leading = real_t();

			for (text_line::const_iterator i = _current_line->begin(), end = _current_line->end(); i != end; ++i)
			{
				const font_metrics grm = i->font_->get_metrics();

				update_max(ascent, grm.ascent);
				update_max(descent_leading, grm.descent + grm.leading);
				update_max(descent, grm.descent);
			}

			_current_line->offset += create_vector(real_t(), ascent);
			_current_line->extent = _state.extent;
			_current_line->descent = descent;
			_current_line = &duplicate_last(_text_lines);
			_current_line->begin_index = _current_line->end_index;
			_current_line->offset += create_vector(real_t(), descent_leading);
			_current_line->extent = _state.extent = real_t();
		}
	}
}
<commit_msg>small refactoring: duplicate_last now automatically collapses last inserted entry<commit_after>#include <agge.text/layout_builder.h>

#include <agge/math.h>
#include <agge/minmax.h>

namespace agge
{
	namespace
	{
		template <typename VectorT>
		inline typename VectorT::value_type &duplicate_last(VectorT &container)
		{
			container.reserve(container.size() + 1);
			typename VectorT::value_type &entry = *container.insert(container.end(), container.back());
			entry.begin_index = entry.end_index;
			return entry;
		}
	}

	bool layout_builder::state::operator !() const
	{	return !next;	}

	bool layout_builder::state::operator <(const state &rhs) const
	{	return next < rhs.next;	}

	layout_builder::layout_builder(positioned_glyphs_container_t &glyphs, glyph_runs_container_t &glyph_runs,
		text_lines_container_t &text_lines)
		: _state(zero()), _glyphs(glyphs), _glyph_runs(glyph_runs), _text_lines(text_lines)
	{
		_glyph_runs.clear();
		_current_run = &*_glyph_runs.insert(_glyph_runs.end(), glyph_run(_glyphs));
		_text_lines.clear();
		_current_line = &*_text_lines.insert(_text_lines.end(), text_line(_glyph_runs));
		_state.runs_size = 1;
	}

	void layout_builder::begin_style(const font::ptr &font_)
	{
		const font_metrics m = font_->get_metrics();

		commit_run();
		_current_run->font_ = font_;
		_current_run->offset = create_vector(_state.extent, real_t());
		_implicit_height = m.ascent + m.descent + m.leading;
	}

	void layout_builder::trim_current_line(const state &at)
	{
		_glyph_runs.erase(_glyph_runs.begin() + at.runs_size, _glyph_runs.end());
		_current_run = &_glyph_runs.back();
		_current_run->end_index = at.next;
		_state = at;
	}

	bool layout_builder::break_current_line()
	{
		commit_run();
		bool was_empty = _current_line->empty();
		commit_line();
		_current_run->offset = zero();
		return !was_empty;
	}

	void layout_builder::break_current_line(const state &at, const state &resume_at)
	{
		state store = _state;

		_state = at;
		break_current_line();
		_state = store, _state.extent -= resume_at.extent, _state.runs_size = _glyph_runs.size();
		_current_run->end_index = _current_run->begin_index = resume_at.next;
	}

	void layout_builder::commit_run()
	{
		if (_current_run->begin_index == _state.next)
			return;
		_current_run->end_index = _state.next;
		_current_run = &duplicate_last(_glyph_runs);
		_current_line->end_index = (_state.runs_size = _glyph_runs.size()) - 1;
	}

	void layout_builder::commit_line()
	{
		if (_current_line->empty())
		{
			_current_line->extent = _state.extent = real_t();
			_current_line->offset += create_vector(real_t(), _implicit_height);
		}
		else
		{
			real_t ascent = real_t();
			real_t descent = real_t();
			real_t descent_leading = real_t();

			for (text_line::const_iterator i = _current_line->begin(), end = _current_line->end(); i != end; ++i)
			{
				const font_metrics grm = i->font_->get_metrics();

				update_max(ascent, grm.ascent);
				update_max(descent_leading, grm.descent + grm.leading);
				update_max(descent, grm.descent);
			}

			_current_line->offset += create_vector(real_t(), ascent);
			_current_line->extent = _state.extent;
			_current_line->descent = descent;
			_current_line = &duplicate_last(_text_lines);
			_current_line->offset += create_vector(real_t(), descent_leading);
			_current_line->extent = _state.extent = real_t();
		}
	}
}
<|endoftext|>


<commit_before>
#include "app/gibbs/gibbs_sampling.h"
#include "app/gibbs/single_node_sampler.h"
#include "common.h"
#include <unistd.h>
#include <fstream>
#include "timer.h"

dd::GibbsSampling::GibbsSampling(FactorGraph * const _p_fg,
  CmdParser * const _p_cmd_parser, int n_datacopy)
  : p_fg(_p_fg), p_cmd_parser(_p_cmd_parser) {
    // the highest node number available
    n_numa_nodes = numa_max_node();

    // if n_datacopy is valid, use it, otherwise, use numa_max_node
    if (n_datacopy >= 1 && n_datacopy <= n_numa_nodes + 1) {
      n_numa_nodes = n_datacopy - 1;
    }

    // max possible threads per NUMA node
    n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF))/(n_numa_nodes+1);

    this->factorgraphs.push_back(*p_fg);

    // copy factor graphs
    for(int i=1;i<=n_numa_nodes;i++){

      numa_run_on_node(i);
      numa_set_localalloc();

      std::cout << "CREATE FG ON NODE ..." <<  i << std::endl;
      dd::FactorGraph fg(p_fg->n_var, p_fg->n_factor, p_fg->n_weight, p_fg->n_edge);

      fg.copy_from(p_fg);

      this->factorgraphs.push_back(fg);
    }
  };

void dd::GibbsSampling::inference(const int & n_epoch, const bool is_quiet){

  Timer t_total;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;

  // single node samplers
  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i],
      n_thread_per_numa, i));
  }

  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers[i].clear_variabletally();
  }

  // inference epochs
  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    if (!is_quiet) {
      std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode <<  "~"
        << ((i_epoch+1) * nnode) << "...." << std::flush;
    }

    // restart timer
    t.restart();

    // sample
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample();
    }

    // wait for samplers to finish
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait();
    }

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << ""  << elapsed << " sec." ;
      std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec" << std::endl;
    }
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::learn(const int & n_epoch, const int & n_sample_per_epoch,
                              const double & stepsize, const double & decay,
                              const double reg_param, const bool is_quiet){

  Timer t_total;

  double current_stepsize = stepsize;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;
  int nweight = this->factorgraphs[0].n_weight;

  // single node samplers
  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i], n_thread_per_numa, i));
  }

  double * ori_weights = new double[nweight];
  memcpy(ori_weights, this->factorgraphs[0].infrs->weight_values, sizeof(double)*nweight);

  // learning epochs
  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    if (!is_quiet) {
      std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode <<  "~"
        << ((i_epoch+1) * nnode) << "...." << std::flush;
    }

    t.restart();

    // set stepsize
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].p_fg->stepsize = current_stepsize;
    }

    // performs stochastic gradient descent with sampling
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample_sgd();
    }

    // wait the samplers to finish
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait_sgd();
    }

    FactorGraph & cfg = this->factorgraphs[0];

    // sum the weights and store in the first factor graph
    // the average weights will be calculated and assigned to all factor graphs
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph & cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        cfg.infrs->weight_values[j] += cfg_other.infrs->weight_values[j];
      }
    }

    // calculate average weights and regularize weights
    for(int j=0;j<nweight;j++){
      cfg.infrs->weight_values[j] /= nnode;
      if(cfg.infrs->weights_isfixed[j] == false){
        cfg.infrs->weight_values[j] *= (1.0/(1.0+reg_param*current_stepsize));
      }
    }

    // set weights for other factor graph to be the same as the first factor graph
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph &cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        if(cfg.infrs->weights_isfixed[j] == false){
          cfg_other.infrs->weight_values[j] = cfg.infrs->weight_values[j];
        }
      }
    }

    // calculate the norms of the difference of weights from the current epoch
    // and last epoch
    double lmax = -1000000;
    double l2=0.0;
    for(int i=0;i<nweight;i++){
      double diff = fabs(ori_weights[i] - cfg.infrs->weight_values[i]);
      ori_weights[i] = cfg.infrs->weight_values[i];
      l2 += diff*diff;
      if(lmax < diff){
        lmax = diff;
      }
    }
    lmax = lmax/current_stepsize;

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec." << ",stepsize=" << current_stepsize << ",lmax=" << lmax << ",l2=" << sqrt(l2)/current_stepsize << std::endl;
    }

    current_stepsize = current_stepsize * decay;

  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::dump_weights(const bool is_quiet){

  // learning weights snippets
  FactorGraph const & cfg = this->factorgraphs[0];
  if (!is_quiet) {
    std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
    int ct = 0;
    for(long i=0;i<cfg.infrs->nweights;i++){
      ct ++;
      std::cout << "   " << i << " " << cfg.infrs->weight_values[i] << std::endl;
      if(ct % 10 == 0){
        break;
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump learned weights
  std::string filename_text = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  for(long i=0;i<cfg.infrs->nweights;i++){
    fout_text << i << " " << cfg.infrs->weight_values[i] << std::endl;
  }
  fout_text.close();
}

void dd::GibbsSampling::aggregate_results_and_dump(const bool is_quiet){

  // sum of variable assignments
  double * agg_means = new double[factorgraphs[0].n_var];
  // number of samples
  double * agg_nsamples = new double[factorgraphs[0].n_var];
  int * multinomial_tallies = new int[factorgraphs[0].infrs->ntallies];

  for(long i=0;i<factorgraphs[0].n_var;i++){
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
    multinomial_tallies[i] = 0;
  }

  // sum variable assignments over all NUMA nodes
  for(int i=0;i<=n_numa_nodes;i++){
    const FactorGraph & cfg = factorgraphs[i];
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      agg_means[variable.id] += cfg.infrs->agg_means[variable.id];
      agg_nsamples[variable.id] += cfg.infrs->agg_nsamples[variable.id];
    }
    for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
      multinomial_tallies[i] += cfg.infrs->multinomial_tallies[i];
    }
  }

  // inference snippets
  if (!is_quiet) {
    std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
    int ct = 0;
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      if(variable.is_evid == false){
        ct ++;
        std::cout << "   " << variable.id << " EXP="
                  << agg_means[variable.id]/agg_nsamples[variable.id] << "  NSAMPLE="
                  << agg_nsamples[variable.id] << std::endl;

        if(variable.domain_type != DTYPE_BOOLEAN){
          if(variable.domain_type == DTYPE_MULTINOMIAL){
            for(int j=0;j<=variable.upper_bound;j++){
              std::cout << "        @ " << j << " -> " << 1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id] << std::endl;
            }
          }else{
            std::cerr << "ERROR: Only support boolean and multinomial variables for now!" << std::endl;
            assert(false);
          }
        }

        if(ct % 10 == 0){
          break;
        }
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump inference results
  std::string filename_text = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out.text";
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }

    if(variable.domain_type != DTYPE_BOOLEAN){
      if(variable.domain_type == DTYPE_MULTINOMIAL){
        for(int j=0;j<=variable.upper_bound;j++){

          fout_text << variable.id << " " << j << " " << (1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]) << std::endl;

        }
      }else{
        std::cerr << "ERROR: Only support boolean and multinomial variables for now!" << std::endl;
        assert(false);
      }
    }else{
      fout_text << variable.id << " " << 1 << " " << (agg_means[variable.id]/agg_nsamples[variable.id]) << std::endl;

    }
  }
  fout_text.close();

  if (is_quiet) return;

  // show a histogram of inference results
  std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
  std::vector<int> abc;
  for(int i=0;i<=10;i++){
    abc.push_back(0);
  }
  int bad = 0;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }
    int bin = (int)(agg_means[variable.id]/agg_nsamples[variable.id]*10);
    if(bin >= 0 && bin <=10){
      abc[bin] ++;
    }else{
      bad ++;
    }
  }
  abc[9] += abc[10];
  for(int i=0;i<10;i++){
    std::cout << "PROB BIN 0." << i << "~0." << (i+1) << "  -->  # " << abc[i] << std::endl;
  }

}

<commit_msg>delete dynamically allocated memory<commit_after>
#include "app/gibbs/gibbs_sampling.h"
#include "app/gibbs/single_node_sampler.h"
#include "common.h"
#include <unistd.h>
#include <fstream>
#include "timer.h"

dd::GibbsSampling::GibbsSampling(FactorGraph * const _p_fg,
  CmdParser * const _p_cmd_parser, int n_datacopy)
  : p_fg(_p_fg), p_cmd_parser(_p_cmd_parser) {
    // the highest node number available
    n_numa_nodes = numa_max_node();

    // if n_datacopy is valid, use it, otherwise, use numa_max_node
    if (n_datacopy >= 1 && n_datacopy <= n_numa_nodes + 1) {
      n_numa_nodes = n_datacopy - 1;
    }

    // max possible threads per NUMA node
    n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF))/(n_numa_nodes+1);

    this->factorgraphs.push_back(*p_fg);

    // copy factor graphs
    for(int i=1;i<=n_numa_nodes;i++){

      numa_run_on_node(i);
      numa_set_localalloc();

      std::cout << "CREATE FG ON NODE ..." <<  i << std::endl;
      dd::FactorGraph fg(p_fg->n_var, p_fg->n_factor, p_fg->n_weight, p_fg->n_edge);

      fg.copy_from(p_fg);

      this->factorgraphs.push_back(fg);
    }
  };

void dd::GibbsSampling::inference(const int & n_epoch, const bool is_quiet){

  Timer t_total;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;

  // single node samplers
  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i],
      n_thread_per_numa, i));
  }

  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers[i].clear_variabletally();
  }

  // inference epochs
  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    if (!is_quiet) {
      std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode <<  "~"
        << ((i_epoch+1) * nnode) << "...." << std::flush;
    }

    // restart timer
    t.restart();

    // sample
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample();
    }

    // wait for samplers to finish
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait();
    }

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << ""  << elapsed << " sec." ;
      std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec" << std::endl;
    }
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::learn(const int & n_epoch, const int & n_sample_per_epoch,
                              const double & stepsize, const double & decay,
                              const double reg_param, const bool is_quiet){

  Timer t_total;

  double current_stepsize = stepsize;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;
  int nweight = this->factorgraphs[0].n_weight;

  // single node samplers
  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i], n_thread_per_numa, i));
  }

  double * ori_weights = new double[nweight];
  memcpy(ori_weights, this->factorgraphs[0].infrs->weight_values, sizeof(double)*nweight);

  // learning epochs
  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    if (!is_quiet) {
      std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode <<  "~"
        << ((i_epoch+1) * nnode) << "...." << std::flush;
    }

    t.restart();

    // set stepsize
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].p_fg->stepsize = current_stepsize;
    }

    // performs stochastic gradient descent with sampling
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample_sgd();
    }

    // wait the samplers to finish
    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait_sgd();
    }

    FactorGraph & cfg = this->factorgraphs[0];

    // sum the weights and store in the first factor graph
    // the average weights will be calculated and assigned to all factor graphs
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph & cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        cfg.infrs->weight_values[j] += cfg_other.infrs->weight_values[j];
      }
    }

    // calculate average weights and regularize weights
    for(int j=0;j<nweight;j++){
      cfg.infrs->weight_values[j] /= nnode;
      if(cfg.infrs->weights_isfixed[j] == false){
        cfg.infrs->weight_values[j] *= (1.0/(1.0+reg_param*current_stepsize));
      }
    }

    // set weights for other factor graph to be the same as the first factor graph
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph &cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        if(cfg.infrs->weights_isfixed[j] == false){
          cfg_other.infrs->weight_values[j] = cfg.infrs->weight_values[j];
        }
      }
    }

    // calculate the norms of the difference of weights from the current epoch
    // and last epoch
    double lmax = -1000000;
    double l2=0.0;
    for(int i=0;i<nweight;i++){
      double diff = fabs(ori_weights[i] - cfg.infrs->weight_values[i]);
      ori_weights[i] = cfg.infrs->weight_values[i];
      l2 += diff*diff;
      if(lmax < diff){
        lmax = diff;
      }
    }
    lmax = lmax/current_stepsize;

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec." << ",stepsize=" << current_stepsize << ",lmax=" << lmax << ",l2=" << sqrt(l2)/current_stepsize << std::endl;
    }

    current_stepsize = current_stepsize * decay;

  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;
  delete[] ori_weights;
}

void dd::GibbsSampling::dump_weights(const bool is_quiet){

  // learning weights snippets
  FactorGraph const & cfg = this->factorgraphs[0];
  if (!is_quiet) {
    std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
    int ct = 0;
    for(long i=0;i<cfg.infrs->nweights;i++){
      ct ++;
      std::cout << "   " << i << " " << cfg.infrs->weight_values[i] << std::endl;
      if(ct % 10 == 0){
        break;
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump learned weights
  std::string filename_text = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  for(long i=0;i<cfg.infrs->nweights;i++){
    fout_text << i << " " << cfg.infrs->weight_values[i] << std::endl;
  }
  fout_text.close();
}

void dd::GibbsSampling::aggregate_results_and_dump(const bool is_quiet){

  // sum of variable assignments
  double * agg_means = new double[factorgraphs[0].n_var];
  // number of samples
  double * agg_nsamples = new double[factorgraphs[0].n_var];
  int * multinomial_tallies = new int[factorgraphs[0].infrs->ntallies];

  for(long i=0;i<factorgraphs[0].n_var;i++){
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
    multinomial_tallies[i] = 0;
  }

  // sum variable assignments over all NUMA nodes
  for(int i=0;i<=n_numa_nodes;i++){
    const FactorGraph & cfg = factorgraphs[i];
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      agg_means[variable.id] += cfg.infrs->agg_means[variable.id];
      agg_nsamples[variable.id] += cfg.infrs->agg_nsamples[variable.id];
    }
    for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
      multinomial_tallies[i] += cfg.infrs->multinomial_tallies[i];
    }
  }

  // inference snippets
  if (!is_quiet) {
    std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
    int ct = 0;
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      if(variable.is_evid == false){
        ct ++;
        std::cout << "   " << variable.id << " EXP="
                  << agg_means[variable.id]/agg_nsamples[variable.id] << "  NSAMPLE="
                  << agg_nsamples[variable.id] << std::endl;

        if(variable.domain_type != DTYPE_BOOLEAN){
          if(variable.domain_type == DTYPE_MULTINOMIAL){
            for(int j=0;j<=variable.upper_bound;j++){
              std::cout << "        @ " << j << " -> " << 1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id] << std::endl;
            }
          }else{
            std::cerr << "ERROR: Only support boolean and multinomial variables for now!" << std::endl;
            assert(false);
          }
        }

        if(ct % 10 == 0){
          break;
        }
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump inference results
  std::string filename_text = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out.text";
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }

    if(variable.domain_type != DTYPE_BOOLEAN){
      if(variable.domain_type == DTYPE_MULTINOMIAL){
        for(int j=0;j<=variable.upper_bound;j++){

          fout_text << variable.id << " " << j << " " << (1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]) << std::endl;

        }
      }else{
        std::cerr << "ERROR: Only support boolean and multinomial variables for now!" << std::endl;
        assert(false);
      }
    }else{
      fout_text << variable.id << " " << 1 << " " << (agg_means[variable.id]/agg_nsamples[variable.id]) << std::endl;

    }
  }
  fout_text.close();

  if (!is_quiet) {
    // show a histogram of inference results
    std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
    std::vector<int> abc;
    for(int i=0;i<=10;i++){
      abc.push_back(0);
    }
    int bad = 0;
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      if(variable.is_evid == true){
        continue;
      }
      int bin = (int)(agg_means[variable.id]/agg_nsamples[variable.id]*10);
      if(bin >= 0 && bin <=10){
        abc[bin] ++;
      }else{
        bad ++;
      }
    }
    abc[9] += abc[10];
    for(int i=0;i<10;i++){
      std::cout << "PROB BIN 0." << i << "~0." << (i+1) << "  -->  # " << abc[i] << std::endl;
    }
  }
  delete[] multinomial_tallies;
  delete[] agg_means;
  delete[] agg_nsamples;

}

<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetPreprocessingTask.cpp
 */

#include "JPetParamBankHandlerTask.h"
#include "../JPetCommonTools/JPetCommonTools.h"

JPetParamBankHandlerTask::JPetParamBankHandlerTask(const char* name) : JPetTask(name)
{

}

bool JPetParamBankHandlerTask::init(const JPetParamsInterface& inOptions)
{
  auto params = dynamic_cast<const JPetParams&>(inOptions);
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  /* 1. If the input file was hld or hldRoot, create ParamBank based on provided json file and run number
     2. If the input file was root, the ParamBank should always be read from the input file;
        even if the used provided the run number and localDB flags, they should be ignored as the TRef-s
        contained in the ROOT file would only make sense with the ParamBank from the same file
        a not with a newly created one.
     3. For any other file type, try to generate ParamBank from file, if fail and run number and localDB is provided,
        try to generate ParamBank from config.
  */

  switch (FileTypeChecker::getInputFileType(options)) {
  case FileTypeChecker::FileType::kHld:
  case FileTypeChecker::FileType::kHldRoot:
    return generateParamBankFromConfig(params);
    break;
  case FileTypeChecker::FileType::kRoot:
    return generateParamBankFromRootFile(params);
    break;
  default:
    std::map<FileTypeChecker::FileType, std::string> fileTypeToString = {
      {FileTypeChecker::kNoType, ""},
      {FileTypeChecker::kRoot, "root"},
      {FileTypeChecker::kScope, "scope"},
      {FileTypeChecker::kHld, "hld"},
      {FileTypeChecker::kHldRoot, "hldRoot"},
      {FileTypeChecker::kZip, "zip"}
    };

    WARNING("Unrecognized file format: "
            + fileTypeToString[FileTypeChecker::getInputFileType(options)]
            + " but trying to generate ParamBank from file...");
    if (generateParamBankFromRootFile(params))
      return true;
    else {
      if (getRunNumber(options) != -1 && isLocalDB(options)) {
        WARNING("Error while tring generate ParamBank from file: "
                + fileTypeToString[FileTypeChecker::getInputFileType(options)]
                + " but run number and localDB is set, trying to generate ParamBank from it...");
        return generateParamBankFromConfig(params);
      }
      break;
    }
  }
  return false;
}

bool JPetParamBankHandlerTask::run(const JPetDataInterface&)
{
  return true;
}

bool JPetParamBankHandlerTask::terminate(JPetParamsInterface&)
{
  return true;
}

bool JPetParamBankHandlerTask::generateParamBankFromRootFile(const JPetParams& params)
{
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  if (getRunNumber(options) != -1) {
    WARNING("Input file was ROOT, but run number option is set, ignoring it");
  }
  if (isLocalDB(options)) {
    WARNING("Input file was ROOT, but localDB option is set, ignoring it");
  }

  JPetReader fReader;
  fReader.openFileAndLoadData(getInputFile(options));
  auto paramMgr = params.getParamManager();

  return paramMgr->readParametersFromFile(&fReader);
}

bool JPetParamBankHandlerTask::generateParamBankFromConfig(const JPetParams& params)
{
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  if (getRunNumber(options) == -1 || !isLocalDB(options)) {
    ERROR("LocalDB and run number are required for Hld or HldRoot files");
    return false;
  }

  auto paramMgr = params.getParamManager();
  if (!paramMgr) {
    ERROR("Param manager is not set");
    return false;
  }
  auto runNum = getRunNumber(options);
  if (runNum >= 0) {
    try {
      paramMgr->fillParameterBank(runNum);
    } catch (const std::exception& e) {
      ERROR(std::string("Param bank was not generated correctly with error: ") + e.what() + "\n The run number used:" + JPetCommonTools::intToString(runNum));
      return false;
    }
    if (isLocalDBCreate(options)) {
      JPetParamSaverAscii saver;
      saver.saveParamBank(paramMgr->getParamBank(), runNum, getLocalDBCreate(options));
    }
  }
  return true;
}
<commit_msg>Add handling of Scope file type in JPetParamBankHandlerTask<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetPreprocessingTask.cpp
 */

#include "JPetParamBankHandlerTask.h"
#include "../JPetCommonTools/JPetCommonTools.h"

JPetParamBankHandlerTask::JPetParamBankHandlerTask(const char* name) : JPetTask(name)
{

}

bool JPetParamBankHandlerTask::init(const JPetParamsInterface& inOptions)
{
  auto params = dynamic_cast<const JPetParams&>(inOptions);
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  /* 1. If the input file was hld, hldRoot or Scope create ParamBank based on provided json file and run number
     2. If the input file was root, the ParamBank should always be read from the input file;
        even if the used provided the run number and localDB flags, they should be ignored as the TRef-s
        contained in the ROOT file would only make sense with the ParamBank from the same file
        a not with a newly created one.
     3. For any other file type, try to generate ParamBank from file, if fail and run number and localDB is provided,
        try to generate ParamBank from config.
  */

  switch (FileTypeChecker::getInputFileType(options)) {
  case FileTypeChecker::FileType::kHld:
  case FileTypeChecker::FileType::kHldRoot:
    return generateParamBankFromConfig(params);
    break;
  case FileTypeChecker::FileType::kRoot:
    return generateParamBankFromRootFile(params);
    break;
  case FileTypeChecker::FileType::kScope:
    return generateParamBankFromConfig(params);
    break;
  default:
    std::map<FileTypeChecker::FileType, std::string> fileTypeToString = {
      {FileTypeChecker::kNoType, ""},
      {FileTypeChecker::kRoot, "root"},
      {FileTypeChecker::kScope, "scope"},
      {FileTypeChecker::kHld, "hld"},
      {FileTypeChecker::kHldRoot, "hldRoot"},
      {FileTypeChecker::kZip, "zip"}
    };

    WARNING("Unrecognized file format: "
            + fileTypeToString[FileTypeChecker::getInputFileType(options)]
            + " but trying to generate ParamBank from file...");
    if (generateParamBankFromRootFile(params))
      return true;
    else {
      if (getRunNumber(options) != -1 && isLocalDB(options)) {
        WARNING("Error while tring generate ParamBank from file: "
                + fileTypeToString[FileTypeChecker::getInputFileType(options)]
                + " but run number and localDB is set, trying to generate ParamBank from it...");
        return generateParamBankFromConfig(params);
      }
      break;
    }
  }
  return false;
}

bool JPetParamBankHandlerTask::run(const JPetDataInterface&)
{
  return true;
}

bool JPetParamBankHandlerTask::terminate(JPetParamsInterface&)
{
  return true;
}

bool JPetParamBankHandlerTask::generateParamBankFromRootFile(const JPetParams& params)
{
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  if (getRunNumber(options) != -1) {
    WARNING("Input file was ROOT, but run number option is set, ignoring it");
  }
  if (isLocalDB(options)) {
    WARNING("Input file was ROOT, but localDB option is set, ignoring it");
  }

  JPetReader fReader;
  fReader.openFileAndLoadData(getInputFile(options));
  auto paramMgr = params.getParamManager();

  return paramMgr->readParametersFromFile(&fReader);
}

bool JPetParamBankHandlerTask::generateParamBankFromConfig(const JPetParams& params)
{
  using namespace jpet_options_tools;
  auto options = params.getOptions();

  if (getRunNumber(options) == -1 || !isLocalDB(options)) {
    ERROR("LocalDB and run number are required for Hld, HldRoot or Scope files");
    return false;
  }

  auto paramMgr = params.getParamManager();
  if (!paramMgr) {
    ERROR("Param manager is not set");
    return false;
  }
  auto runNum = getRunNumber(options);
  if (runNum >= 0) {
    try {
      paramMgr->fillParameterBank(runNum);
    } catch (const std::exception& e) {
      ERROR(std::string("Param bank was not generated correctly with error: ") + e.what() + "\n The run number used:" + JPetCommonTools::intToString(runNum));
      return false;
    }
    if (isLocalDBCreate(options)) {
      JPetParamSaverAscii saver;
      saver.saveParamBank(paramMgr->getParamBank(), runNum, getLocalDBCreate(options));
    }
  }
  return true;
}
<|endoftext|>