text:
//=======================================================================
// Copyright (c)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/**
 * @file bounded_degree_mst.hpp
 * @brief
 * @author Piotr Godlewski
 * @version 1.0
 * @date 2013-06-03
 */
#ifndef PAAL_BOUNDED_DEGREE_MST_HPP
#define PAAL_BOUNDED_DEGREE_MST_HPP

#include "paal/iterative_rounding/bounded_degree_min_spanning_tree/bounded_degree_mst_oracle.hpp"
#include "paal/iterative_rounding/ir_components.hpp"
#include "paal/iterative_rounding/iterative_rounding.hpp"
#include "paal/lp/lp_row_generation.hpp"

#include <boost/bimap.hpp>
#include <boost/range/as_array.hpp>
#include <boost/graph/connected_components.hpp>

namespace paal {
namespace ir {

namespace {
struct bounded_degree_mst_compare_traits {
    static const double EPSILON;
};

const double bounded_degree_mst_compare_traits::EPSILON = 1e-10;
}

/**
 * @class bounded_degree_mst
 * @brief The class for solving the Bounded Degree MST problem using Iterative
* Rounding.
 *
 * @tparam Graph input graph
 * @tparam DegreeBounds map from Graph vertices to degree bounds
 * @tparam CostMap map from Graph edges to costs
 * @tparam VertexIndex map from Graph vertices to indices
 * @tparam SpanningTreeOutputIterator
 * @tparam Oracle separation oracle
 */
template <typename Graph, typename DegreeBounds, typename CostMap,
          typename VertexIndex, typename SpanningTreeOutputIterator,
          typename Oracle = paal::lp::random_violated_separation_oracle>
class bounded_degree_mst {
  public:
    /**
     * Constructor.
     */
    bounded_degree_mst(const Graph & g, const DegreeBounds & deg_bounds,
                    CostMap cost_map, VertexIndex index,
                    SpanningTreeOutputIterator result_spanning_tree, Oracle oracle = Oracle{}) :
              m_g(g), m_cost_map(cost_map), m_index(index), m_deg_bounds(deg_bounds),
              m_result_spanning_tree(result_spanning_tree),
              m_compare(bounded_degree_mst_compare_traits::EPSILON),
              m_oracle(oracle)
    {}

    using Edge = typename boost::graph_traits<Graph>::edge_descriptor;
    using Vertex = typename boost::graph_traits<Graph>::vertex_descriptor;

    using EdgeMap = boost::bimap<Edge, lp::col_id>;
    using VertexMap = std::unordered_map<lp::row_id, Vertex>;

    using EdgeMapOriginal = std::vector<std::pair<lp::col_id, Edge>>;

    using ErrorMessage = boost::optional<std::string>;

    /**
     * Checks if the input graph is connected.
     */
    ErrorMessage check_input_validity() {
        // Is g connected?
        std::vector<int> components(num_vertices(m_g));
        int num = boost::connected_components(m_g, &components[0]);

        if (num > 1) {
            return ErrorMessage{ "The graph is not connected." };
        }

        return ErrorMessage{};
    }

    /**
     * @brief
     *
     * @tparam LP
     * @param lp
     *
     * @return
     */
    template <typename LP>
    auto get_find_violation(LP & lp) {
        using candidate = bdmst_violation_checker::Candidate;
        return m_oracle([&](){return m_violation_checker.get_violation_candidates(*this, lp);},
                        [&](candidate c){return m_violation_checker.check_violation(c, *this);},
                        [&](candidate c){return m_violation_checker.add_violated_constraint(c, *this, lp);});
    }

    /**
     * Returns the input graph.
     */
    const Graph &get_graph() const { return m_g; }

    /**
     * Returns the vertex index.
     */
    const VertexIndex &get_index() const { return m_index; }

    /**
     * Removes an LP column and the graph edge corresponding to it.
     */
    void remove_column(lp::col_id col_id) {
        auto ret = m_edge_map.right.erase(col_id);
        assert(ret == 1);
    }

    /**
     * Binds a graph edge to a LP column.
     */
    void bind_edge_to_col(Edge e, lp::col_id col) {
        m_edge_map_original.push_back(
            typename EdgeMapOriginal::value_type(col, e));
        m_edge_map.insert(typename EdgeMap::value_type(e, col));
    }

    /**
     * Returns the cost of a given edge.
     */
    decltype(get(std::declval<CostMap>(), std::declval<Edge>()))
        get_cost(Edge e) {
        return get(m_cost_map, e);
    }

    /**
     * Returns the degree bound of a vertex.
     */
    decltype(std::declval<DegreeBounds>()(get(std::declval<VertexIndex>(),
                                              std::declval<Vertex>())))
        get_degree_bound(Vertex v) {
        return m_deg_bounds(get(m_index, v));
    }

    /**
     * Returns the LP column corresponding to an edge, if it wasn't deleted from
     * the LP.
     */
    boost::optional<lp::col_id> edge_to_col(Edge e) const {
        auto i = m_edge_map.left.find(e);
        if (i != m_edge_map.left.end()) {
            return i->second;
        } else {
            return boost::none;
        }
    }

    /**
     * Returns a bimap between edges and LP column IDs.
     */
    const EdgeMap &get_edge_map() const { return m_edge_map; }

    /**
     * Returns a mapping between LP column IDs and edges in the original graph.
     */
    const EdgeMapOriginal &get_original_edges_map() const {
        return m_edge_map_original;
    }

    /**
     * Adds an edge to the result spanning tree.
     */
    void add_to_result_spanning_tree(Edge e) {
        *m_result_spanning_tree = e;
        ++m_result_spanning_tree;
    }

    /**
     * Returns the double comparison object.
     */
    utils::compare<double> get_compare() const {
        return m_compare;
    }

    /**
     * Binds a graph vertex to an LP row.
     */
    void bind_vertex_to_row(Vertex v, lp::row_id row) {
        m_vertex_map.insert(typename VertexMap::value_type(row, v));
    }

    /**
     * Unbinds the graph vertex from its corresponding (deleted) LP row.
     */
    void remove_row(lp::row_id row_id) {
        auto ret = m_vertex_map.erase(row_id);
        assert(ret == 1);
    }

    /**
     * Returns the graph vertex corresponding to a given LP row,
     *        unless the row doen't correspond to any vertex.
     */
    boost::optional<Vertex> row_to_vertex(lp::row_id row) {
        auto i = m_vertex_map.find(row);
        if (i != m_vertex_map.end()) {
            return i->second;
        } else {
            return boost::none;
        }
    }

  private:
    Edge col_to_edge(lp::col_id col) {
        auto i = m_edge_map.right.find(col);
        assert(i != m_edge_map.right.end());
        return i->second;
    }

    const Graph &m_g;
    CostMap m_cost_map;
    VertexIndex m_index;
    const DegreeBounds &m_deg_bounds;
    SpanningTreeOutputIterator m_result_spanning_tree;
    bdmst_violation_checker m_violation_checker;

    EdgeMapOriginal m_edge_map_original;
    EdgeMap m_edge_map;
    VertexMap m_vertex_map;

    const utils::compare<double>   m_compare;

    Oracle m_oracle;
};

namespace detail {
/**
 * @brief Creates a bounded_degree_mst object. Non-named version.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam CostMap
 * @tparam VertexIndex
 * @tparam SpanningTreeOutputIterator
 * @param g
 * @param degBoundMap
 * @param cost_map
 * @param vertex_index
 * @param result_spanning_tree
 * @param oracle
 *
 * @return bounded_degree_mst object
 */
template <typename Oracle = lp::random_violated_separation_oracle,
          typename Graph,
          typename DegreeBounds, typename CostMap, typename VertexIndex,
          typename SpanningTreeOutputIterator>
bounded_degree_mst<Graph, DegreeBounds, CostMap, VertexIndex, SpanningTreeOutputIterator, Oracle>
make_bounded_degree_mst(const Graph & g, const DegreeBounds & deg_bounds,
                      CostMap cost_map, VertexIndex vertex_index,
                      SpanningTreeOutputIterator result_spanning_tree,
                      Oracle oracle = Oracle()) {
    return bounded_degree_mst<Graph, DegreeBounds, CostMap, VertexIndex,
                SpanningTreeOutputIterator, Oracle>(g, deg_bounds, cost_map, vertex_index,
                    result_spanning_tree, oracle);
}
} // detail

/**
 * Creates a bounded_degree_mst object. Named version.
 * The returned object can be used to check input validity or to get a lower
* bound on the
 * optimal solution cost.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam SpanningTreeOutputIterator
 * @tparam P
 * @tparam T
 * @tparam R
 * @param g
 * @param deg_bounds
 * @param params
 * @param result_spanning_tree
 * @param oracle
 *
 * @return bounded_degree_mst object
 */
template <typename Oracle = lp::random_violated_separation_oracle,
          typename Graph,
          typename DegreeBounds, typename SpanningTreeOutputIterator,
          typename P, typename T, typename R>
auto
make_bounded_degree_mst(const Graph & g,
                      const DegreeBounds & deg_bounds,
                      const boost::bgl_named_params<P, T, R> & params,
                      SpanningTreeOutputIterator result_spanning_tree,
                      Oracle oracle = Oracle())
        -> bounded_degree_mst<Graph, DegreeBounds,
                decltype(choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight)),
                decltype(choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index)),
                SpanningTreeOutputIterator, Oracle> {

    return detail::make_bounded_degree_mst(g, deg_bounds,
                choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight),
                choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index),
                result_spanning_tree, oracle);
}

/**
 * Creates a bounded_degree_mst object. All default parameters.
 * The returned object can be used to check input validity or to get a lower
* bound on the
 * optimal solution cost.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam SpanningTreeOutputIterator
 * @param g
 * @param deg_bounds
 * @param result_spanning_tree
 * @param oracle
 *
 * @return bounded_degree_mst object
 */
template <typename Oracle = lp::random_violated_separation_oracle,
          typename Graph, typename DegreeBounds, typename SpanningTreeOutputIterator>
auto
make_bounded_degree_mst(const Graph & g, const DegreeBounds & deg_bounds,
                      SpanningTreeOutputIterator result_spanning_tree,
                      Oracle oracle = Oracle()) ->
        decltype(make_bounded_degree_mst(g, deg_bounds, boost::no_named_parameters(), result_spanning_tree, oracle)) {
    return make_bounded_degree_mst(g, deg_bounds, boost::no_named_parameters(), result_spanning_tree, oracle);
}

/**
 * Round Condition of the IR Bounded Degree MST algorithm.
 */
struct bdmst_round_condition {
    /**
     * Constructor. Takes epsilon used in double comparison.
     */
    bdmst_round_condition(double epsilon =
                              bounded_degree_mst_compare_traits::EPSILON)
        : m_round_zero(epsilon) {}

    /**
     * Checks if a given column of the LP can be rounded to 0.
     * If the column is rounded, the corresponding edge is removed from the
     * graph.
     */
    template <typename Problem, typename LP>
    boost::optional<double> operator()(Problem &problem, const LP &lp,
                                       lp::col_id col) {
        auto ret = m_round_zero(problem, lp, col);
        if (ret) {
            problem.remove_column(col);
        }
        return ret;
    }

  private:
    round_condition_equals<0> m_round_zero;
};

/**
 * Relax Condition of the IR Bounded Degree MST algorithm.
 */
struct bdmst_relax_condition {
    /**
     * Checks if a given row of the LP corresponds to a degree bound and can be
     * relaxed.
     * If the row degree is not greater than the corresponding degree bound + 1,
     * it is relaxed
     * and the degree bound is deleted from the problem.
     */
    template <typename Problem, typename LP>
    bool operator()(Problem &problem, const LP &lp, lp::row_id row) {
        auto vertex = problem.row_to_vertex(row);
        if (vertex) {
            auto ret = (lp.get_row_degree(row) <=
                        problem.get_degree_bound(*vertex) + 1);
            if (ret) {
                problem.remove_row(row);
            }
            return ret;
        } else
            return false;
    }
};

/**
 * Initialization of the IR Bounded Degree MST algorithm.
 */
struct bdmst_init {
    /**
     * Initializes the LP: variables for edges, degree bound constraints
     * and constraint for all edges.
     */
    template <typename Problem, typename LP>
    void operator()(Problem &problem, LP &lp) {
        lp.set_lp_name("bounded degree minimum spanning tree");
        lp.set_optimization_type(lp::MINIMIZE);

        add_variables(problem, lp);
        add_degree_bound_constraints(problem, lp);
        add_all_set_equality(problem, lp);
    }

  private:
    /**
     * Adds a variable to the LP for each edge in the input graph.
     * Binds the LP columns to edges.
     */
    template <typename Problem, typename LP>
    void add_variables(Problem & problem, LP & lp) {
        for (auto e : boost::as_array(edges(problem.get_graph()))) {
            auto col = lp.add_column(problem.get_cost(e), 0, 1);
            problem.bind_edge_to_col(e, col);
        }
    }

    /**
     * Adds a degree bound constraint to the LP for each vertex in the input
     * graph
     * and binds vertices to rows.
     */
    template <typename Problem, typename LP>
    void add_degree_bound_constraints(Problem &problem, LP &lp) {
        auto const &g = problem.get_graph();

        for (auto v : boost::as_array(vertices(g))) {
            lp::linear_expression expr;

            for (auto e : boost::as_array(out_edges(v, g))) {
                expr += *(problem.edge_to_col(e));
            }

            auto row =
                lp.add_row(std::move(expr) <= problem.get_degree_bound(v));
            problem.bind_vertex_to_row(v, row);
        }
    }

    /**
     * Adds an equality constraint to the LP for the set of all edges in the
     * input graph.
     */
    template <typename Problem, typename LP>
    void add_all_set_equality(Problem &problem, LP &lp) {
        lp::linear_expression expr;
        for (auto col : lp.get_columns()) {
            expr += col;
        }
        lp.add_row(std::move(expr) == num_vertices(problem.get_graph()) - 1);
    }
};

/**
 * Set Solution component of the IR Bounded Degree MST algorithm.
 */
struct bdmst_set_solution {
    /**
     * Constructor. Takes epsilon used in double comparison.
     */
    bdmst_set_solution(double epsilon =
                           bounded_degree_mst_compare_traits::EPSILON)
        : m_compare(epsilon) {}

    /**
     * Creates the result spanning tree form the LP (all edges corresponding to
     * columns with value 1).
     */
    template <typename Problem, typename GetSolution>
    void operator()(Problem & problem, const GetSolution & solution) {
        for (auto col_and_edge : problem.get_original_edges_map()) {
            if (m_compare.e(solution(col_and_edge.first), 1)) {
                problem.add_to_result_spanning_tree(col_and_edge.second);
            }
        }
    }

private:
    const utils::compare<double>   m_compare;
};

template <typename Init = bdmst_init,
          typename RoundCondition = bdmst_round_condition,
          typename RelaxContition = bdmst_relax_condition,
          typename SetSolution = bdmst_set_solution,
          typename SolveLPToExtremePoint = ir::row_generation_solve_lp<>,
          typename ResolveLpToExtremePoint = ir::row_generation_solve_lp<>>
using bdmst_ir_components =
    IRcomponents<Init, RoundCondition, RelaxContition, SetSolution,
                 SolveLPToExtremePoint, ResolveLpToExtremePoint>;

namespace detail {
/**
 * @brief Solves the Bounded Degree MST problem using Iterative Rounding.
* Non-named version.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam CostMap
 * @tparam VertexIndex
 * @tparam SpanningTreeOutputIterator
 * @tparam IRcomponents
 * @tparam Visitor
 * @param g
 * @param degBoundMap
 * @param cost_map
 * @param vertex_index
 * @param result_spanning_tree
 * @param components
 * @param oracle
 * @param visitor
 *
 * @return solution status
 */
template <typename Oracle = lp::random_violated_separation_oracle,
          typename Graph,
          typename DegreeBounds, typename CostMap, typename VertexIndex,
          typename SpanningTreeOutputIterator,
          typename IRcomponents = bdmst_ir_components<>,
          typename Visitor = trivial_visitor>
IRResult bounded_degree_mst_iterative_rounding(
        const Graph & g,
        const DegreeBounds & deg_bounds,
        CostMap cost_map,
        VertexIndex vertex_index,
        SpanningTreeOutputIterator result_spanning_tree,
        IRcomponents components = IRcomponents(),
        Oracle oracle = Oracle(),
        Visitor visitor = Visitor()) {

    auto bdmst = make_bounded_degree_mst(g, deg_bounds, cost_map, vertex_index, result_spanning_tree, oracle);
    return solve_iterative_rounding(bdmst, std::move(components), std::move(visitor));
}
} // detail

/**
 * @brief Solves the Bounded Degree MST problem using Iterative Rounding. Named
* version.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam SpanningTreeOutputIterator
 * @tparam IRcomponents
 * @tparam Visitor
 * @tparam P
 * @tparam T
 * @tparam R
 * @param g
 * @param deg_bounds
 * @param result_spanning_tree
 * @param params
 * @param components
 * @param oracle
 * @param visitor
 *
 * @return solution status
 */
template <typename Oracle = lp::random_violated_separation_oracle,
          typename Graph,
          typename DegreeBounds, typename SpanningTreeOutputIterator,
          typename IRcomponents = bdmst_ir_components<>,
          typename Visitor = trivial_visitor, typename P, typename T,
          typename R>
IRResult bounded_degree_mst_iterative_rounding(
            const Graph & g,
            const DegreeBounds & deg_bounds,
            const boost::bgl_named_params<P, T, R> & params,
            SpanningTreeOutputIterator result_spanning_tree,
            IRcomponents components = IRcomponents(),
            Oracle oracle = Oracle(),
            Visitor visitor = Visitor()) {

        return detail::bounded_degree_mst_iterative_rounding(g, deg_bounds,
                    choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight),
                    choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index),
                    std::move(result_spanning_tree), std::move(components),
                    std::move(oracle), std::move(visitor));
}

/**
 * @brief Solves the Bounded Degree MST problem using Iterative Rounding. All
* default parameters.
 *
 * @tparam Oracle
 * @tparam Graph
 * @tparam DegreeBounds
 * @tparam SpanningTreeOutputIterator
 * @tparam IRcomponents
 * @tparam Visitor
 * @param g
 * @param deg_bounds
 * @param result_spanning_tree
 * @param components
 * @param oracle
 * @param visitor
 *
 * @return solution status
 */
template <typename Oracle = lp::random_violated_separation_oracle, typename Graph,
          typename DegreeBounds, typename SpanningTreeOutputIterator,
          typename IRcomponents = bdmst_ir_components<>,
          typename Visitor = trivial_visitor>
IRResult bounded_degree_mst_iterative_rounding(
            const Graph & g,
            const DegreeBounds & deg_bounds,
            SpanningTreeOutputIterator result_spanning_tree,
            IRcomponents components = IRcomponents(),
            Oracle oracle = Oracle(),
            Visitor visitor = Visitor()) {

        return bounded_degree_mst_iterative_rounding(g, deg_bounds,
                    boost::no_named_parameters(), std::move(result_spanning_tree),
                    std::move(components), std::move(oracle), std::move(visitor));
}

} //! ir
} //! paal
#endif // PAAL_BOUNDED_DEGREE_MST_HPP

max_stars_repo_name: Kommeren/AA

max_issues_repo_name: Kommeren/AA

max_forks_repo_name: Kommeren/AA


text:
/*!
@file
Defines `boost::hana::on`.

@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FUNCTIONAL_ON_HPP
#define BOOST_HANA_FUNCTIONAL_ON_HPP

#include <boost/hana/detail/create.hpp>
#include <boost/hana/detail/std/forward.hpp>
#include <boost/hana/detail/std/move.hpp>
#include <boost/hana/functional/infix.hpp>

namespace boost { namespace hana {
    //! @ingroup group-functional
    //! Invoke a function with the result of invoking another function on
    //! each argument.
    //!
    //! Specifically, `on(f, g)` is a function such that
    //! @code
    //!     on(f, g)(x...) == f(g(x)...)
    //! @endcode
    //!
    //! For convenience, `on` also supports infix application as provided
    //! by `infix`.
    //! @snippet example/functional/on/infix.cpp main
    //!
    //! @note
    //! `on` is associative, i.e. `on(f, on(g, h))` is equivalent to
    //! `on(on(f, g), h)`.
    //!
    //! @internal
    //! ### Proof of associativity
    //!
    //! @code
    //!     on(f, on(g, h))(xs...) == f(on(g, h)(xs)...)
    //!                            == f(g(h(xs))...)
    //!
    //!     on(on(f, g), h)(xs...) == on(f, g)(h(xs)...)
    //!                            == f(g(h(xs))...)
    //! @endcode
    //! @endinternal
    //!
    //! ### Example
    //! @snippet example/functional/on/multiply.cpp main
    //!
    //! ### Example
    //! @snippet example/functional/on/plus.cpp main
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto on = infix([](auto&& f, auto&& g) {
        return [perfect-capture](auto&& ...x) -> decltype(auto) {
            return forwarded(f)(g(forwarded(x))...);
        };
    });
#else
    template <typename F, typename G>
    struct _on {
        F f; G g;
        template <typename ...X>
        constexpr decltype(auto) operator()(X&& ...x) const& {
            return f(g(detail::std::forward<X>(x))...);
        }

        template <typename ...X>
        constexpr decltype(auto) operator()(X&& ...x) & {
            return f(g(detail::std::forward<X>(x))...);
        }

        template <typename ...X>
        constexpr decltype(auto) operator()(X&& ...x) && {
            return detail::std::move(f)(g(detail::std::forward<X>(x))...);
        }
    };

    constexpr auto on = infix(detail::create<_on>{});
#endif
}} // end namespace boost::hana

#endif // !BOOST_HANA_FUNCTIONAL_ON_HPP

ext: hpp

max_stars_repo_name: josephwinston/hana

max_issues_repo_name: josephwinston/hana

max_forks_repo_name: josephwinston/hana


text:
/*
 * SigmoidTest.hpp
 *
 *  Created on: Dec 29, 2016
 *      Author: ken
 */

#ifndef SIGMOIDTEST_HPP_
#define SIGMOIDTEST_HPP_

#include "cute.h"
#include "ide_listener.h"
#include "xml_listener.h"
#include "cute_runner.h"
#include <armadillo>
#include <iostream>

#include "../src/layer/Sigmoid.hpp"

class SigmoidTest {
public:
	SigmoidTest();
	virtual ~SigmoidTest();

	static void feedForwardTest1();
	static void feedForwardTest2();
	static void backPropTest1();
	static void backPropTest2();
};

#endif /* SIGMOIDTEST_HPP_ */


text:
/**
 * @file PlmLanguageRanker.cpp
 * @author Ian Yang
 * @date Created <2009-09-24 09:47:22>
 * @date Updated <2010-03-24 15:29:22>
 * @brief
 */
#include "PlmLanguageRanker.h"

#include <util/get.h>

#include <boost/assert.hpp>

#include <stdexcept>
#include <cmath>
#include <numeric>

using namespace std;

namespace sf1r {

PlmLanguageRanker::PlmLanguageRanker(
        const TermProximityMeasure* termProximityMeasure,
        float smooth,
        float proximity
)
    : termProximityMeasure_(termProximityMeasure)
    , smoothArg_(smooth)
    , proximityArg_(proximity)
    , termProximityArray_()
{}

PlmLanguageRanker::~PlmLanguageRanker()
{
    delete termProximityMeasure_;
    termProximityMeasure_ = 0;
}

PlmLanguageRanker::PlmLanguageRanker(const PlmLanguageRanker& rhs)
    : termProximityMeasure_(0)
    , smoothArg_(rhs.smoothArg_)
    , proximityArg_(rhs.proximityArg_)
{
    if (rhs.termProximityMeasure_)
    {
        termProximityMeasure_ = rhs.termProximityMeasure_->clone();
    }
}

PlmLanguageRanker& PlmLanguageRanker::operator=(const PlmLanguageRanker& rhs)
{
    if (this != &rhs)
    {
        const TermProximityMeasure* cloned = 0;
        if (rhs.termProximityMeasure_)
        {
            cloned = rhs.termProximityMeasure_->clone();
        }

        termProximityMeasure_ = cloned;
        smoothArg_ = rhs.smoothArg_;
        proximityArg_ = rhs.proximityArg_;
    }

    return *this;
}

void PlmLanguageRanker::setTermProximityMeasure(
        const TermProximityMeasure* termProximityMeasure
)
{
    if (termProximityMeasure != termProximityMeasure_)
    {
        const TermProximityMeasure* orig = termProximityMeasure_;
        termProximityMeasure_ = termProximityMeasure;
        delete orig;
    }
}

float PlmLanguageRanker::getScoreSVD(
        const RankQueryProperty& queryProperty,
        const RankDocumentProperty& documentProperty,
        const vector<double>& queryTF_d,
        const vector<double>& queryTF,
        const vector<double>& collTF
) const
{
    bool USEPROX = true;

    //USEPROX = true;
    float score = 0.0F;
    if (0.0F == queryProperty.getAveragePropertyLength())
        return score;

    std::size_t numTerms = documentProperty.size();
    termProximityArray_.resize(numTerms);

    if (numTerms > 1)
    {
        // calculates term proximity in array parallel to
        // textQuery.termPositions
        termProximityMeasure_->calculate(
                documentProperty,
                termProximityArray_
        );
    }
    else if (numTerms == 1)
    {
        termProximityArray_[0] = 0.0F;
    }

    TermProximityMeasure::array_type::const_iterator termProximity
        = termProximityArray_.begin();
    for (RankDocumentProperty::size_type i = 0;
            i != documentProperty.size(); ++i, ++termProximity)
    {
        float tfInDoc = documentProperty.termFreqAt(i);
        float tfInQuery = queryProperty.termFreqAt(i);

        //if(queryTF.size() > 0)
        //tfInQuery = queryTF[i];

        if (!collTF.empty())
        {
            //cout << "YAY!";
            tfInDoc = collTF[i];
        }

        //double tfInQuery = queryTF[i];

        //double tfInQuery = queryTF_d[i];
        //double tfInQuery = .1;

        if (tfInDoc > 0.0F)
        {
            float proximityFactor = *termProximity;
            //double proximityFactor = termProximityVector[i];

            float collectionMLE =
                    queryProperty.totalTermFreqAt(i) /
                    queryProperty.getTotalPropertyLength();

            //double collectionMLE = queryTF[i];

            float seenDocProb =
                    tfInDoc
                    + smoothArg_ * collectionMLE
                    + proximityArg_ * proximityFactor;
            // / (smoothArg_ + docTokenCount + proxWeight)

            float unseenDocProb = collectionMLE * smoothArg_;
            // / (smoothArg_ + docTokenCount + proxWeight)

            if (USEPROX)
            {
                score += tfInQuery
                        / queryProperty.getQueryLength()
                        * std::log(seenDocProb / unseenDocProb);
            }
            else
            {
                score += tfInQuery / queryProperty.getQueryLength();
            }

        }
    }

    if (score > 0.0F)
    {
        float docTokenCount = documentProperty.docLength();
        float proxWeight =
                proximityArg_
                * std::accumulate(
                        termProximityArray_.begin(),
                        termProximityArray_.begin() + documentProperty.size(),
                        0.0F
                );

        if (USEPROX)
        {
            score += std::log((smoothArg_ ) / (smoothArg_ + docTokenCount + proxWeight));
        }
        else
        {
            score += std::log((smoothArg_ ) / (smoothArg_ + docTokenCount));
        }
    } // end - if

    return score;
} // end PlmLanguageRanker::getScore()

float PlmLanguageRanker::getScore(
        const RankQueryProperty& queryProperty,
        const RankDocumentProperty& documentProperty
) const
{
    //BOOST_ASSERT(termProximityMeasure_);
    if (!termProximityMeasure_)
    {
        throw std::runtime_error(
                "Term Proximity Measure has not been specified"
        );
    }

    float score = 0.0F;
    if (0.0F == queryProperty.getAveragePropertyLength())
    {
        return score;
    }

    std::size_t numTerms = documentProperty.size();
    termProximityArray_.resize(numTerms);

    if (numTerms > 1)
    {
        // calculates term proximity in array parallel to
        // textQuery.termPositions
        termProximityMeasure_->calculate(
                documentProperty,
                termProximityArray_
        );
    }
    else if (numTerms == 1)
    {
        termProximityArray_[0] = 0.0F;
    }

    TermProximityMeasure::array_type::const_iterator termProximity
    = termProximityArray_.begin();
    for (RankDocumentProperty::size_type i = 0;
            i != documentProperty.size(); ++i, ++termProximity)
    {
        float tfInDoc = documentProperty.termFreqAt(i);
        float tfInQuery = queryProperty.termFreqAt(i);
        // cout << "TF: " << i << "," << tfInQuery << "," << tfInDoc << endl;

        if (tfInDoc > 0.0F)
        {
            float proximityFactor = *termProximity;

            float collectionMLE =
                queryProperty.totalTermFreqAt(i) /
                queryProperty.getTotalPropertyLength();

            float seenDocProb =
                tfInDoc
                + smoothArg_ * collectionMLE
                + proximityArg_ * proximityFactor;
            // / (smoothArg_ + docTokenCount + proxWeight)

            float unseenDocProb = collectionMLE * smoothArg_;
            // / (smoothArg_ + docTokenCount + proxWeight)

            score += tfInQuery
                / queryProperty.getQueryLength()
                * std::log(seenDocProb / unseenDocProb);
        }
    }

    if (score > 0.0F)
    {
        float docTokenCount = documentProperty.docLength();
        float proxWeight =
            proximityArg_
            * std::accumulate(
                    termProximityArray_.begin(),
                    termProximityArray_.begin() + documentProperty.size(),
                    0.0F
                    );

        score += std::log(
                (smoothArg_ )
                / (smoothArg_ + docTokenCount + proxWeight)
        );
    } // end - if

    return score;
} // end PlmLanguageRanker::getScore()

PlmLanguageRanker* PlmLanguageRanker::clone() const
{
    return new PlmLanguageRanker(*this);
}

} // namespace sf1r

ext: cpp


text:
//  (C) Copyright Gennadiy Rozental 2001.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision: 74248 $
//
//  Description : defines level of indiration facilitating workarounds for non
//  printable types
// ***************************************************************************

#ifndef BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER
#define BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER

// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/workaround.hpp>

// Boost
#include <boost/mpl/or.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/has_left_shift.hpp>
#include <boost/type_traits/is_abstract.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_function.hpp>
#include <ios>
#include <iostream>
#include <limits>

#if !defined(BOOST_NO_CXX11_NULLPTR)
#include <cstddef>
#endif

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost
{
namespace test_tools
{
namespace tt_detail
{

// ************************************************************************** //
// **************          boost_test_print_type               ************** //
// ************************************************************************** //

namespace impl
{
template <class T>
std::ostream& boost_test_print_type(std::ostream& ostr, T const& t)
{
    BOOST_STATIC_ASSERT_MSG((boost::has_left_shift<std::ostream, T>::value),
                            "Type has to implement operator<< to be printable");
    ostr << t;
    return ostr;
}

struct boost_test_print_type_impl
{
    template <class R>
    std::ostream& operator()(std::ostream& ostr, R const& r) const
    {
        return boost_test_print_type(ostr, r);
    }
};
} // namespace impl

// To avoid ODR violations, see N4381
template <class T>
struct static_const
{
    static const T value;
};
template <class T>
const T static_const<T>::value = T();

namespace
{
static const impl::boost_test_print_type_impl& boost_test_print_type =
    static_const<impl::boost_test_print_type_impl>::value;
}

// ************************************************************************** //
// **************                print_log_value               ************** //
// ************************************************************************** //

template <typename T>
struct print_log_value
{
    void operator()(std::ostream& ostr, T const& t)
    {
        typedef
            typename mpl::or_<is_array<T>, is_function<T>, is_abstract<T>>::type
                cant_use_nl;

        std::streamsize old_precision = set_precision(ostr, cant_use_nl());

        // ostr << t;
        using boost::test_tools::tt_detail::boost_test_print_type;
        boost_test_print_type(ostr, t);

        if (old_precision != (std::streamsize)-1)
            ostr.precision(old_precision);
    }

    std::streamsize set_precision(std::ostream& ostr, mpl::false_)
    {
        if (std::numeric_limits<T>::is_specialized &&
            std::numeric_limits<T>::radix == 2)
            return ostr.precision(2 +
                                  std::numeric_limits<T>::digits * 301 / 1000);
        else if (std::numeric_limits<T>::is_specialized &&
                 std::numeric_limits<T>::radix == 10)
        {
#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
            // (was BOOST_NO_NUMERIC_LIMITS_LOWEST but now deprecated).
            // No support for std::numeric_limits<double>::max_digits10,
            // so guess that a couple of guard digits more than digits10 will
            // display any difference.
            return ostr.precision(2 + std::numeric_limits<T>::digits10);
#else
            // std::numeric_limits<double>::max_digits10; IS supported.
            // Any noisy or guard digits needed to display any difference are
            // included in max_digits10.
            return ostr.precision(std::numeric_limits<T>::max_digits10);
#endif
        }
        // else if T is not specialized for std::numeric_limits<>,
        // then will just get the default precision of 6 digits.
        return (std::streamsize)-1;
    }

    std::streamsize set_precision(std::ostream&, mpl::true_)
    {
        return (std::streamsize)-1;
    }
};

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template <typename T, std::size_t N>
struct print_log_value<T[N]>
{
    void operator()(std::ostream& ostr, T const* t)
    {
        ostr << t;
    }
};
#endif

//____________________________________________________________________________//

template <>
struct BOOST_TEST_DECL print_log_value<bool>
{
    void operator()(std::ostream& ostr, bool t);
};

//____________________________________________________________________________//

template <>
struct BOOST_TEST_DECL print_log_value<char>
{
    void operator()(std::ostream& ostr, char t);
};

//____________________________________________________________________________//

template <>
struct BOOST_TEST_DECL print_log_value<unsigned char>
{
    void operator()(std::ostream& ostr, unsigned char t);
};

//____________________________________________________________________________//

template <>
struct BOOST_TEST_DECL print_log_value<char const*>
{
    void operator()(std::ostream& ostr, char const* t);
};

//____________________________________________________________________________//

template <>
struct BOOST_TEST_DECL print_log_value<wchar_t const*>
{
    void operator()(std::ostream& ostr, wchar_t const* t);
};

#if !defined(BOOST_NO_CXX11_NULLPTR)
template <>
struct print_log_value<std::nullptr_t>
{
    // declaration and definition is here because of #12969
    // https://svn.boost.org/trac10/ticket/12969
    void operator()(std::ostream& ostr, std::nullptr_t /*t*/)
    {
        ostr << "nullptr";
    }
};
#endif

//____________________________________________________________________________//

// ************************************************************************** //
// **************                 print_helper                 ************** //
// ************************************************************************** //
// Adds level of indirection to the output operation, allowing us to customize
// it for types that do not support operator << directly or for any other reason

template <typename T>
struct print_helper_t
{
    explicit print_helper_t(T const& t) : m_t(t)
    {
    }

    T const& m_t;
};

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// Borland suffers premature pointer decay passing arrays by reference
template <typename T, std::size_t N>
struct print_helper_t<T[N]>
{
    explicit print_helper_t(T const* t) : m_t(t)
    {
    }

    T const* m_t;
};
#endif

//____________________________________________________________________________//

template <typename T>
inline print_helper_t<T> print_helper(T const& t)
{
    return print_helper_t<T>(t);
}

//____________________________________________________________________________//

template <typename T>
inline std::ostream& operator<<(std::ostream& ostr, print_helper_t<T> const& ph)
{
    print_log_value<T>()(ostr, ph.m_t);

    return ostr;
}

//____________________________________________________________________________//

} // namespace tt_detail

// ************************************************************************** //
// **************       BOOST_TEST_DONT_PRINT_LOG_VALUE        ************** //
// ************************************************************************** //

#define BOOST_TEST_DONT_PRINT_LOG_VALUE(the_type)                              \
    namespace boost                                                            \
    {                                                                          \
    namespace test_tools                                                       \
    {                                                                          \
    namespace tt_detail                                                        \
    {                                                                          \
    template <>                                                                \
    struct print_log_value<the_type>                                           \
    {                                                                          \
        void operator()(std::ostream&, the_type const&)                        \
        {                                                                      \
        }                                                                      \
    };                                                                         \
    }                                                                          \
    }                                                                          \
    }                                                                          \
    /**/

} // namespace test_tools
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER

max_stars_repo_name: sotaoverride/backup

max_issues_repo_name: sotaoverride/backup

max_forks_repo_name: sotaoverride/backup


text:
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "HttpServer.h"
#include "Constants.h"
#include "Util.h"
#include "Transcoder.h"
#include "TranscodingAudioDataStream.h"

#include <core/sdk/ITrack.h>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include <websocketpp/base64/base64.hpp>

#include <iostream>
#include <unordered_map>
#include <string>
#include <cstdlib>

#include <fcntl.h>
#include <stdio.h>

#ifdef WIN32
#include <io.h>
#endif

#include <vector>

#define HTTP_416_DISABLED true

static const char* ENVIRONMENT_DISABLE_HTTP_SERVER_AUTH = "MUSIKCUBE_DISABLE_HTTP_SERVER_AUTH";

using namespace musik::core::sdk;

std::unordered_map<std::string, std::string> CONTENT_TYPE_MAP = {
    { ".mp3", "audio/mpeg" },
    { ".ogg", "audio/ogg" },
    { ".opus", "audio/ogg" },
    { ".oga", "audio/ogg" },
    { ".spx", "audio/ogg" },
    { ".flac", "audio/flac" },
    { ".aac", "audio/aac" },
    { ".mp4", "audio/mp4" },
    { ".m4a", "audio/mp4" },
    { ".wav", "audio/wav" },
    { ".mpc", "audio/x-musepack" },
    { ".mp+", "audio/x-musepack" },
    { ".mpp", "audio/x-musepack" },
    { ".ape", "audio/monkeys-audio" },
    { ".wma", "audio/x-ms-wma" },
    { ".jpg", "image/jpeg" }
};

struct Range {
    size_t from;
    size_t to;
    size_t total;
    IDataStream* file;

    std::string HeaderValue() {
        return "bytes " + std::to_string(from) + "-" + std::to_string(to) + "/" + std::to_string(total);
    }
};

static std::string contentType(const std::string& fn) {
    try {
        boost::filesystem::path p(fn);
        std::string ext = boost::trim_copy(p.extension().string());
        boost::to_lower(ext);

        auto it = CONTENT_TYPE_MAP.find(ext);
        if (it != CONTENT_TYPE_MAP.end()) {
            return it->second;
        }
    }
    catch (...) {
    }

    return "application/octet-stream";
}

static ssize_t fileReadCallback(void *cls, uint64_t pos, char *buf, size_t max) {
    Range* range = static_cast<Range*>(cls);

    size_t offset = (size_t) pos + range->from;
    offset = std::min(range->to ? range->to : (size_t) SIZE_MAX, offset);

    size_t avail = range->total ? (range->total - offset) : SIZE_MAX;
    size_t count = std::min(avail, max);

    if (range->file->Seekable()) {
        if (!range->file->SetPosition(offset)) {
            return MHD_CONTENT_READER_END_OF_STREAM;
        }
    }

    count = range->file->Read(buf, count);
    if (count > 0) {
        return count;
    }

    return MHD_CONTENT_READER_END_OF_STREAM;
}

static void fileFreeCallback(void *cls) {
    Range* range = static_cast<Range*>(cls);
    if (range->file) {
#ifdef ENABLE_DEBUG
        std::cerr << "******** REQUEST CLOSE: " << range->file << " ********\n\n";
#endif

        range->file->Close(); /* lazy destroy */
        range->file = nullptr;
    }
    delete range;
}

static Range* parseRange(IDataStream* file, const char* range) {
    Range* result = new Range();

    size_t size = file ? file->Length() : 0;

    result->file = file;
    result->total = size;
    result->from = 0;
    result->to = (size <= 0) ? 0 : size - 1;

    if (range) {
        std::string str(range);

        if (str.substr(0, 6) == "bytes=") {
            str = str.substr(6);

            std::vector<std::string> parts;
            boost::split(parts, str, boost::is_any_of("-"));

            if (parts.size() == 2) {
                try {
                    size_t from = (size_t) std::max(0, std::stoi(boost::algorithm::trim_copy(parts[0])));
                    size_t to = size;

                    if (parts.at(1).size()) {
                        to = (size_t) std::min((int) size, std::stoi(boost::algorithm::trim_copy(parts[1])));
                    }

                    if (to > from) {
                        result->from = from;
                        if (to == 0) {
                            result->to = 0;
                        }
                        else if (to >= size) {
                            result->to = (size == 0) ? 0 : size - 1;
                        }
                        else {
                            result->to = (to == 0) ? 0 : to - 1;
                        }
                    }
                }
                catch (...) {
                    /* return false below */
                }
            }
        }
    }

    return result;
}

static size_t getUnsignedUrlParam(
    struct MHD_Connection *connection,
    const std::string& argument,
    size_t defaultValue)
{
    const char* stringValue =
        MHD_lookup_connection_value(
            connection,
            MHD_GET_ARGUMENT_KIND,
            argument.c_str());

    if (stringValue != 0) {
        try {
            return std::stoul(urlDecode(stringValue));
        }
        catch (...) {
            /* invalid bitrate */
        }
    }

    return defaultValue;
}

static std::string getStringUrlParam(
    struct MHD_Connection *connection,
    const std::string& argument,
    std::string defaultValue)
{
    const char* stringValue =
        MHD_lookup_connection_value(
            connection,
            MHD_GET_ARGUMENT_KIND,
            argument.c_str());

    return stringValue ? std::string(stringValue) : defaultValue;
}

static bool isAuthenticated(MHD_Connection *connection, Context& context) {
    const char* disableAuth = std::getenv(ENVIRONMENT_DISABLE_HTTP_SERVER_AUTH);
    if (disableAuth && std::string(disableAuth) == "1") {
        return true;
    }

    const char* authPtr = MHD_lookup_connection_value(
        connection, MHD_HEADER_KIND, "Authorization");

    if (authPtr && strlen(authPtr)) {
        std::string auth(authPtr);
        if (auth.find("Basic ") == 0) {
            std::string encoded = auth.substr(6);
            if (encoded.size()) {
                std::string decoded = websocketpp::base64_decode(encoded);

                std::vector<std::string> userPass;
                boost::split(userPass, decoded, boost::is_any_of(":"));

                if (userPass.size() == 2) {
                    std::string password = GetPreferenceString(context.prefs, key::password, defaults::password);
                    return userPass[0] == "default" && userPass[1] == password;
                }
            }
        }
    }

    return false;
}

HttpServer::HttpServer(Context& context)
: context(context)
, running(false) {
    this->httpServer = nullptr;
}

HttpServer::~HttpServer() {
    this->Stop();
}

void HttpServer::Wait() {
    std::unique_lock<std::mutex> lock(this->exitMutex);
    while (this->running) {
        this->exitCondition.wait(lock);
    }
}

bool HttpServer::Start() {
    if (this->Stop()) {
        Transcoder::RemoveTempTranscodeFiles(this->context);

        MHD_FLAG ipVersion = MHD_NO_FLAG;
        if (context.prefs->GetBool(prefs::use_ipv6.c_str(), defaults::use_ipv6)) {
            ipVersion = MHD_USE_IPv6;
        }

        httpServer = MHD_start_daemon(
#if MHD_VERSION >= 0x00095300
            MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION | ipVersion,
#else
            MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION | ipVersion,
#endif
            context.prefs->GetInt(prefs::http_server_port.c_str(), defaults::http_server_port),
            nullptr,
            nullptr,
            &HttpServer::HandleRequest,
            this,
            MHD_OPTION_UNESCAPE_CALLBACK,
            &HttpServer::HandleUnescape,
            this,
            MHD_OPTION_LISTENING_ADDRESS_REUSE, 1,
            MHD_OPTION_END);

        this->running = (httpServer != nullptr);
        return running;
    }

    return false;
}

bool HttpServer::Stop() {
    if (httpServer) {
        MHD_stop_daemon(this->httpServer);
        this->httpServer = nullptr;
    }

    this->running = false;
    this->exitCondition.notify_all();

    return true;
}

size_t HttpServer::HandleUnescape(void * cls, struct MHD_Connection *c, char *s) {
    /* don't do anything. the default implementation will decode the
    entire path, which breaks if we have individually decoded segments. */
    return strlen(s);
}

int HttpServer::HandleRequest(
    void *cls,
    struct MHD_Connection *connection,
    const char *url,
    const char *method,
    const char *version,
    const char *upload_data,
    size_t *upload_data_size,
    void **con_cls)
{
#ifdef ENABLE_DEBUG
    std::cerr << "******** REQUEST START ********\n";
#endif

    HttpServer* server = static_cast<HttpServer*>(cls);

    struct MHD_Response* response = nullptr;
    int ret = MHD_NO;
    int status = MHD_HTTP_NOT_FOUND;

    try {
        if (method && std::string(method) == "GET") {
            if (!isAuthenticated(connection, server->context)) {
                status = 401; /* unauthorized */
                static const char* error = "unauthorized";
                response = MHD_create_response_from_buffer(strlen(error), (void*)error, MHD_RESPMEM_PERSISTENT);

#ifdef ENABLE_DEBUG
                std::cerr << "unauthorized\n";
#endif
            }
            else {
                /* if we get here we're authenticated */
                std::string urlStr(url);

                if (urlStr[0] == '/') {
                    urlStr = urlStr.substr(1);
                }

                std::vector<std::string> parts;
                boost::split(parts, urlStr, boost::is_any_of("/"));
                if (parts.size() > 0) {
                    /* /audio/id/<id> OR /audio/external_id/<external_id> */
                    if (parts.at(0) == fragment::audio && parts.size() == 3) {
                        status = HandleAudioTrackRequest(server, response, connection, parts);
                    }
                    /* /thumbnail/<id> */
                    else if (parts.at(0) == fragment::thumbnail && parts.size() == 2) {
                        status = HandleThumbnailRequest(server, response, connection, parts);
                    }
                }
            }
        }
    }
    catch (...) {
    }

    if (response) {
#ifdef ENABLE_DEBUG
        std::cerr << "returning with http code: " << status << std::endl;
#endif

        ret = MHD_queue_response(connection, status, response);
        MHD_destroy_response(response);
    }

#ifdef ENABLE_DEBUG
    std::cerr << "*******************************\n\n";
#endif

    return ret;
}

int HttpServer::HandleAudioTrackRequest(
    HttpServer* server,
    MHD_Response*& response,
    MHD_Connection *connection,
    std::vector<std::string>& pathParts)
{
    int status = MHD_HTTP_OK;

    ITrack* track = nullptr;
    bool byExternalId = (pathParts.at(1) == fragment::external_id);

    if (byExternalId) {
        std::string externalId = urlDecode(pathParts.at(2));
        track = server->context.metadataProxy->QueryTrackByExternalId(externalId.c_str());

#ifdef ENABLE_DEBUG
        std::cerr << "externalId: " << externalId << "\n";
        std::cerr << "title: " << GetMetadataString(track, "title") << std::endl;
#endif
    }
    else if (pathParts.at(1) == fragment::id) {
        uint64_t id = std::stoull(urlDecode(pathParts.at(2)));
        track = server->context.metadataProxy->QueryTrackById(id);
    }

    if (track) {
        std::string duration = GetMetadataString(track, key::duration);
        std::string filename = GetMetadataString(track, key::filename);

        track->Release();

        size_t bitrate = getUnsignedUrlParam(connection, "bitrate", 0);
        std::string format = "";

        if (bitrate != 0) {
            format = getStringUrlParam(connection, "format", "mp3");
        }

        IDataStream* file = (bitrate == 0)
            ? server->context.environment->GetDataStream(filename.c_str(), OpenFlags::Read)
            : Transcoder::Transcode(server->context, filename, bitrate, format);

        const char* rangeVal = MHD_lookup_connection_value(
            connection, MHD_HEADER_KIND, "Range");

#ifdef ENABLE_DEBUG
        if (rangeVal) {
            std::cerr << "range header: " << rangeVal << "\n";
        }
#endif

        Range* range = parseRange(file, rangeVal);

#ifdef ENABLE_DEBUG
        std::cerr << "potential response header : " << range->HeaderValue() << std::endl;
#endif

        /* ehh... */
        bool isOnDemandTranscoder = !!dynamic_cast<TranscodingAudioDataStream*>(file);

#ifdef ENABLE_DEBUG
        std::cerr << "on demand? " << isOnDemandTranscoder << std::endl;
#endif

        /* gotta be careful with request ranges if we're transcoding. don't
        allow any custom ranges other than from 0 to end. */
        if (isOnDemandTranscoder && rangeVal && strlen(rangeVal)) {
            if (range->from != 0 || range->to != range->total - 1) {
                delete range;

#ifdef ENABLE_DEBUG
                std::cerr << "removing range header, seek requested with ondemand transcoder\n";
#endif

                if (HTTP_416_DISABLED) {
                    rangeVal = nullptr; /* ignore the header from here on out. */

                    /* lots of clients don't seem to be to deal with 416 properly;
                    instead, ignore the range header and return the whole file,
                    and a 200 (not 206) */
                    if (file) {
                        range = parseRange(file, nullptr);
                    }
                }
                else {
                    if (file) {
                        file->Release();
                        file = nullptr;
                    }

                    if (server->context.prefs->GetBool(
                        prefs::transcoder_synchronous_fallback.c_str(),
                        defaults::transcoder_synchronous_fallback))
                    {
                        /* if we're allowed, fall back to synchronous transcoding. we'll block
                        here until the entire file has been converted and cached */
                        file = Transcoder::TranscodeAndWait(server->context, nullptr, filename, bitrate, format);
                        range = parseRange(file, rangeVal);
                    }
                    else {
                        /* otherwise fail with a "range not satisfiable" status */
                        status = 416;
                        char empty[1];
                        response = MHD_create_response_from_buffer(0, empty, MHD_RESPMEM_PERSISTENT);
                    }
                }
            }
        }

        if (file) {
            size_t length = (range->to - range->from);

            response = MHD_create_response_from_callback(
                length == 0 ? MHD_SIZE_UNKNOWN : length + 1,
                4096,
                &fileReadCallback,
                range,
                &fileFreeCallback);

#ifdef ENABLE_DEBUG
            std::cerr << "response length: " << ((length == 0) ? 0 : length + 1) << "\n";
            std::cerr << "id: " << file << "\n";
#endif

            if (response) {
                if (!isOnDemandTranscoder) {
                    MHD_add_response_header(response, "Accept-Ranges", "bytes");
                }
                else {
                    MHD_add_response_header(response, "X-musikcube-Estimated-Content-Length", "true");
                }

                if (duration.size()) {
                    MHD_add_response_header(response, "X-Content-Duration", duration.c_str());
                    MHD_add_response_header(response, "Content-Duration", duration.c_str());
                }

                if (byExternalId) {
                    /* if we're using an on-demand transcoder, ensure the client does not cache the
                    result because we have to guess the content length. */
                    std::string value = isOnDemandTranscoder ? "no-cache" : "public, max-age=31536000";
                    MHD_add_response_header(response, "Cache-Control", value.c_str());
                }

                std::string type = (isOnDemandTranscoder || format.size())
                    ? contentType("." + format) : contentType(filename);

                MHD_add_response_header(response, "Content-Type", type.c_str());
                MHD_add_response_header(response, "Server", "musikcube server");

                if ((rangeVal && strlen(rangeVal)) || range->from > 0) {
                    if (range->total > 0) {
                        MHD_add_response_header(response, "Content-Range", range->HeaderValue().c_str());
                        status = MHD_HTTP_PARTIAL_CONTENT;
#ifdef ENABLE_DEBUG
                        if (rangeVal) {
                            std::cerr << "actual range header: " << range->HeaderValue() << "\n";
                        }
#endif
                    }
                }
            }
            else {
                file->Release();
                file = nullptr;
            }
        }
    }

    return status;
}

int HttpServer::HandleThumbnailRequest(
    HttpServer* server,
    MHD_Response*& response,
    MHD_Connection* connection,
    std::vector<std::string>& pathParts)
{
    int status = MHD_HTTP_NOT_FOUND;

    char pathBuffer[4096];
    server->context.environment->GetPath(
        PathType::PathLibrary, pathBuffer, sizeof(pathBuffer));

    if (strlen(pathBuffer)) {
        std::string path = std::string(pathBuffer) + "thumbs/" + pathParts.at(1) + ".jpg";
        IDataStream* file = server->context.environment->GetDataStream(path.c_str(), OpenFlags::Read);

        if (file) {
            long length = file->Length();

            response = MHD_create_response_from_callback(
                length == 0 ? MHD_SIZE_UNKNOWN : length + 1,
                4096,
                &fileReadCallback,
                parseRange(file, nullptr),
                &fileFreeCallback);

            if (response) {
                MHD_add_response_header(response, "Cache-Control", "public, max-age=31536000");
                MHD_add_response_header(response, "Content-Type", contentType(path).c_str());
                MHD_add_response_header(response, "Server", "musikcube server");
                status = MHD_HTTP_OK;
            }
            else {
                file->Release();
            }
        }
    }

    return status;
}

max_stars_repo_name: tobbez/musikcube

max_issues_repo_name: doublepeng-Qian/musikcube

max_forks_repo_name: doublepeng-Qian/musikcube


text:
// This file is part of SWGANH which is released under the MIT license.
// See file LICENSE or go to http://swganh.com/LICENSE

#ifndef WIN32
#include <Python.h>
#endif

#include "swganh/app/swganh_app.h"

#include <algorithm>
#include <exception>
#include <fstream>
#include <iostream>

#ifdef WIN32
#include <regex>
#else
#include <boost/regex.hpp>
#endif

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/program_options.hpp>

#include "anh/logger.h"
#include "anh/database/database_manager_interface.h"
#include "anh/event_dispatcher.h"
#include "anh/plugin/plugin_manager.h"
#include "anh/service/datastore.h"
#include "anh/service/service_manager.h"

#include "swganh/app/swganh_kernel.h"

#include "swganh/chat/chat_service_interface.h"
#include "swganh/character/character_service_interface.h"
#include "swganh/connection/connection_service.h"
#include "swganh/login/login_service.h"
#include "swganh/simulation/simulation_service_interface.h"
#include "swganh/galaxy/galaxy_service.h"
#include "swganh/combat/combat_service.h"
#include "swganh/social/social_service.h"
#include "swganh/scripting/utilities.h"

#include "version.h"

using namespace anh;
using namespace anh::app;
using namespace boost::asio;
using namespace boost::program_options;
using namespace std;
using namespace swganh::app;
using namespace swganh::chat;
using namespace swganh::command;
using namespace swganh::login;
using namespace swganh::character;
using namespace swganh::connection;
using namespace swganh::combat;
using namespace swganh::simulation;
using namespace swganh::galaxy;

using anh::plugin::RegistrationMap;

#ifdef WIN32
using std::regex;
using std::smatch;
using std::regex_match;
#else
using boost::regex;
using boost::smatch;
using boost::regex_match;
#endif

options_description AppConfig::BuildConfigDescription() {
    options_description desc;

    desc.add_options()
        ("help,h", "Display help message and config options")

		("server_mode", boost::program_options::value<std::string>(&server_mode)->default_value("all"),
			"Specifies the service configuration mode to run the server in.")

        ("plugin,p", boost::program_options::value<std::vector<std::string>>(&plugins),
            "Only used when single_server_mode is disabled, loads a module of the specified name")
        ("plugin_directory", value<string>(&plugin_directory)->default_value("plugins/"),
            "Directory containing the application plugins")

        ("script_directory", value<string>(&script_directory)->default_value("scripts"),
            "Directory containing the application scripts")

        ("tre_config", boost::program_options::value<std::string>(&tre_config),
            "File containing the tre configuration (live.cfg)")

        ("galaxy_name", boost::program_options::value<std::string>(&galaxy_name),
            "Name of the galaxy (cluster) to this process should run")

        ("resource_cache_size", boost::program_options::value<uint32_t>(&resource_cache_size),
            "Available cache size for the resource manager (in Megabytes)")

        ("db.galaxy_manager.host", boost::program_options::value<std::string>(&galaxy_manager_db.host),
            "Host address for the galaxy_manager datastore")
        ("db.galaxy_manager.schema", boost::program_options::value<std::string>(&galaxy_manager_db.schema),
            "Schema name for the galaxy_manager datastore")
        ("db.galaxy_manager.username", boost::program_options::value<std::string>(&galaxy_manager_db.username),
            "Username for authentication with the galaxy_manager datastore")
        ("db.galaxy_manager.password", boost::program_options::value<std::string>(&galaxy_manager_db.password),
            "Password for authentication with the galaxy_manager datastore")

        ("db.galaxy.host", boost::program_options::value<std::string>(&galaxy_db.host),
            "Host address for the galaxy datastore")
        ("db.galaxy.schema", boost::program_options::value<std::string>(&galaxy_db.schema),
            "Schema name for the galaxy datastore")
        ("db.galaxy.username", boost::program_options::value<std::string>(&galaxy_db.username),
            "Username for authentication with the galaxy datastore")
        ("db.galaxy.password", boost::program_options::value<std::string>(&galaxy_db.password),
            "Password for authentication with the galaxy datastore")

        ("service.login.udp_port",
            boost::program_options::value<uint16_t>(&login_config.listen_port),
            "The port the login service will listen for incoming client connections on")
        ("service.login.address",
            boost::program_options::value<string>(&login_config.listen_address),
            "The public address the login service will listen for incoming client connections on")
        ("service.login.status_check_duration_secs",
            boost::program_options::value<int>(&login_config.galaxy_status_check_duration_secs),
            "The amount of time between checks for updated galaxy status")
        ("service.login.login_error_timeout_secs",
            boost::program_options::value<int>(&login_config.login_error_timeout_secs)->default_value(5),
            "The number of seconds to wait before disconnecting a client after failed login attempt")
        ("service.login.auto_registration",
            boost::program_options::value<bool>(&login_config.login_auto_registration)->default_value(false),
            "Auto Registration flag")

        ("service.connection.ping_port", boost::program_options::value<uint16_t>(&connection_config.ping_port),
            "The port the connection service will listen for incoming client ping requests on")
        ("service.connection.udp_port", boost::program_options::value<uint16_t>(&connection_config.listen_port),
            "The port the connection service will listen for incoming client connections on")
        ("service.connection.address", boost::program_options::value<string>(&connection_config.listen_address),
            "The public address the connection service will listen for incoming client connections on")
    ;

    return desc;
}

SwganhApp::SwganhApp(int argc, char* argv[])
    : io_service_()
    , io_work_(new boost::asio::io_service::work(io_service_))
{
    kernel_ = make_shared<SwganhKernel>(io_service_);
    running_ = false;
    initialized_ = false;

    Initialize(argc, argv);
    Start();
}

SwganhApp::~SwganhApp()
{
    Stop();

    kernel_.reset();
    io_work_.reset();

    // join the threadpool threads until each one has exited.
    for_each(io_threads_.begin(), io_threads_.end(), std::mem_fn(&boost::thread::join));
}

void SwganhApp::Initialize(int argc, char* argv[]) {
    // Init Logging
    SetupLogging_();

    // Load the configuration
    LoadAppConfig_(argc, argv);

    auto app_config = kernel_->GetAppConfig();

    // Initialize kernel resources
    kernel_->GetDatabaseManager()->registerStorageType(
        "galaxy_manager",
        app_config.galaxy_manager_db.schema,
        app_config.galaxy_manager_db.host,
        app_config.galaxy_manager_db.username,
        app_config.galaxy_manager_db.password);

    kernel_->GetDatabaseManager()->registerStorageType(
        "galaxy",
        app_config.galaxy_db.schema,
        app_config.galaxy_db.host,
        app_config.galaxy_db.username,
        app_config.galaxy_db.password);

    CleanupServices_();

    // append command dir
    std::string py_path = "import sys; sys.path.append('.'); sys.path.append('" + app_config.script_directory + "');";
    {
        swganh::scripting::ScopedGilLock lock;
        PyRun_SimpleString(py_path.c_str());
    }

    // Load the plugin configuration.
    LoadPlugins_(app_config.plugins);

    // Load core services
    LoadCoreServices_();

    initialized_ = true;
}

void SwganhApp::Start() {
    if (!initialized_) {
        throw std::runtime_error("Called application Start before Initialize");
    }

    running_ = true;

    // Start up a threadpool for running io_service based tasks/active objects
    // The increment starts at 2 because the main thread of execution already counts
    // as thread in use as does the console thread.
    for (uint32_t i = 1; i < boost::thread::hardware_concurrency(); ++i) {
        boost::thread t([this] () {
            io_service_.run();
        });

#ifdef _WIN32
        SetPriorityClass(t.native_handle(), REALTIME_PRIORITY_CLASS);
#endif

        io_threads_.push_back(move(t));
    }

    kernel_->GetServiceManager()->Start();
}

void SwganhApp::Stop() {
    running_ = false;
}

bool SwganhApp::IsRunning() {
    return running_;
}

SwganhKernel* SwganhApp::GetAppKernel() const {
    return kernel_.get();
}

void SwganhApp::StartInteractiveConsole()
{
    swganh::scripting::ScopedGilLock lock;
    anh::Logger::getInstance().DisableConsoleLogging();

#ifdef WIN32
    std::system("cls");
#else
    if (std::system("clear") != 0)
    {
        LOG(::error) << "Error clearing screen, ignoring console mode";
        return;
    }
#endif

    std::cout << "swgpy console " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH << std::endl;

    boost::python::object main = boost::python::object (boost::python::handle<>(boost::python::borrowed(
        PyImport_AddModule("__main__")
    )));
    auto global_dict = main.attr("__dict__");
    global_dict["kernel"] = boost::python::ptr(GetAppKernel());

    PyRun_InteractiveLoop(stdin, "<stdin>");

    anh::Logger::getInstance().EnableConsoleLogging();
}

void SwganhApp::LoadAppConfig_(int argc, char* argv[]) {
    auto config_description = kernel_->GetAppConfig().BuildConfigDescription();

    variables_map vm;
    store(parse_command_line(argc, argv, config_description), vm);

    ifstream config_file("config/swganh.cfg");

    if (!config_file.is_open()) {
        throw runtime_error("Unable to open the configuration file at: config/swganh.cfg");
    }

    try {
        store(parse_config_file(config_file, config_description, true), vm);
    } catch(...) {
        throw runtime_error("Unable to parse the configuration file at: config/swganh.cfg");
    }

    notify(vm);
    config_file.close();

    if (vm.count("help")) {
        std::cout << config_description << "\n\n";
        exit(0);
    }
}

void SwganhApp::LoadPlugins_(vector<string> plugins) {
    LOG(info) << "Loading plugins...";

    if (!plugins.empty()) {
        auto plugin_manager = kernel_->GetPluginManager();
        auto plugin_directory = kernel_->GetAppConfig().plugin_directory;

        for_each(plugins.begin(), plugins.end(), [plugin_manager, plugin_directory] (const string& plugin) {
			LOG(info) << "Loading plugin " << plugin;
            plugin_manager->LoadPlugin(plugin, plugin_directory);
        });
    }
	LOG(info) << "Finished Loading plugins...";
}

void SwganhApp::CleanupServices_() {

    auto service_directory = kernel_->GetServiceDirectory();

    auto services = service_directory->getServiceSnapshot(service_directory->galaxy());

    if (services.empty()) {
        return;
    }

    LOG(warning) << "Services were not shutdown properly";

    for_each(services.begin(), services.end(), [this, &service_directory] (anh::service::ServiceDescription& service) {
        service_directory->removeService(service);
    });
}

void SwganhApp::LoadCoreServices_()
{

    auto plugin_manager = kernel_->GetPluginManager();
    auto registration_map = plugin_manager->registration_map();

    regex rx("(?:.*\\:\\:)(.*Service)");
    smatch m;

    for_each(registration_map.begin(), registration_map.end(), [this, &rx, &m] (RegistrationMap::value_type& entry) {
        std::string name = entry.first;

        if (entry.first.length() > 7 && regex_match(name, m, rx)) {
            auto service_name = m[1].str();
			LOG(info) << "Loading Service " << name << "...";
            auto service = kernel_->GetPluginManager()->CreateObject<anh::service::ServiceInterface>(name);

            kernel_->GetServiceManager()->AddService(service_name, service);
			LOG(info) << "Loaded Service " << name;
        }
    });

    auto app_config = kernel_->GetAppConfig();

	if(strcmp("login", app_config.server_mode.c_str()) == 0 || strcmp("all", app_config.server_mode.c_str()) == 0)
	{
        auto login_service = std::make_shared<LoginService>(
		    app_config.login_config.listen_address,
		    app_config.login_config.listen_port,
		    kernel_.get());

		login_service->galaxy_status_check_duration_secs(app_config.login_config.galaxy_status_check_duration_secs);
		login_service->login_error_timeout_secs(app_config.login_config.login_error_timeout_secs);
        login_service->login_auto_registration(app_config.login_config.login_auto_registration);

		kernel_->GetServiceManager()->AddService("LoginService", login_service);
	}

	if(strcmp("connection", app_config.server_mode.c_str()) == 0 || strcmp("all", app_config.server_mode.c_str()) == 0)
	{
		auto connection_service = std::make_shared<ConnectionService>(
			app_config.connection_config.listen_address,
			app_config.connection_config.listen_port,
			app_config.connection_config.ping_port,
			kernel_.get());

		kernel_->GetServiceManager()->AddService("ConnectionService", connection_service);
	}

	if(strcmp("simulation", app_config.server_mode.c_str()) == 0 || strcmp("all", app_config.server_mode.c_str()) == 0)
	{
		// These will be loaded in alphabetical order because of how std::map generates its keys
		kernel_->GetServiceManager()->AddService(
			"CombatService",
			std::make_shared<CombatService>(kernel_.get()));

		kernel_->GetServiceManager()->AddService(
            "SocialService",
            std::make_shared<social::SocialService>(kernel_.get()));

		auto simulation_service = kernel_->GetServiceManager()->GetService<SimulationServiceInterface>("SimulationService");
		simulation_service->StartScene("corellia");
		simulation_service->StartScene("naboo");
	}

	// always need a galaxy service running
	kernel_->GetServiceManager()->AddService("GalaxyService",
        std::make_shared<GalaxyService>(kernel_.get()));
}

void SwganhApp::SetupLogging_()
{
    anh::Logger::getInstance().init("swganh");
}

ext: cc

max_stars_repo_name: JohnShandy/swganh

max_issues_repo_name: JohnShandy/swganh

max_forks_repo_name: JohnShandy/swganh


text:
// Copyright (c) 2015-2018 Daniel Cooke
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

#ifndef phylogeny_hpp
#define phylogeny_hpp

#include <unordered_map>
#include <memory>
#include <cstddef>
#include <stack>

#include <boost/optional.hpp>

namespace octopus {

template <typename Label, typename T = boost::optional<int>>
class Phylogeny
{
public:
    struct Group
    {
        Label id;
        T value = boost::none;
    };

    Phylogeny() = default;

    Phylogeny(Group founder);

    Phylogeny(const Phylogeny&);
    Phylogeny& operator=(Phylogeny);
    Phylogeny(Phylogeny&&)                 = default;
    Phylogeny& operator=(Phylogeny&&)      = default;

    ~Phylogeny() = default;

    std::size_t size() const noexcept;
    bool empty() const noexcept;

    void clear() noexcept;
    void clear(const Label& id);

    Group& set_founder(Group founder);
    Group& add_descendant(Group group, const Label& ancestor_id);

    const Group& group(const Label& id) const;
    Group& group(const Label& id);

    const Group& founder() const noexcept;
    const Group& ancestor(const Label& id) const;

    unsigned num_descendants(const Label& id) const noexcept;
    const Group& descendant1(const Label& id) const;
    const Group& descendant2(const Label& id) const;

private:
    struct TreeNode
    {
        Group group;
        TreeNode* ancestor = nullptr;
        std::unique_ptr<TreeNode> descendant1 = nullptr, descendant2 = nullptr;
    };

    std::unique_ptr<TreeNode> tree_;
    std::unordered_map<Label, TreeNode*> nodes_;
};

template <typename Label, typename T>
Phylogeny<Label, T>::Phylogeny(Group founder)
{
    set_founder(std::move(founder));
}

template <typename Label, typename T>
Phylogeny<Label, T>::Phylogeny(const Phylogeny& other)
{
    if (other.tree_) {
        std::stack<TreeNode*> to_visit {};
        to_visit.push(other.tree_->descendant2.get());
        to_visit.push(other.tree_->descendant1.get());
        set_founder(other.tree_->group);
        while (!to_visit.empty()) {
            if (to_visit.top() != nullptr) {
                const TreeNode* visted {to_visit.top()};
                to_visit.pop();
                add_descendant(visted->group, visted->ancestor->group.id);
                to_visit.push(visted->descendant2.get());
                to_visit.push(visted->descendant1.get());
            } else {
                to_visit.pop();
            }
        }
    }
}

template <typename Label, typename T>
Phylogeny<Label, T>& Phylogeny<Label, T>::operator=(Phylogeny other)
{
    std::swap(*this, other);
    return *this;
}

template <typename Label, typename T>
std::size_t Phylogeny<Label, T>::size() const noexcept
{
    return nodes_.size();
}

template <typename Label, typename T>
bool Phylogeny<Label, T>::empty() const noexcept
{
    return tree_ == nullptr;
}

template <typename Label, typename T>
void Phylogeny<Label, T>::clear() noexcept
{
    nodes_.clear();
    tree_.reset();
}

template <typename Label, typename T>
void Phylogeny<Label, T>::clear(const Label& id)
{
    if (tree_) {
        if (tree_->group.id == id) {
            clear();
        } else {
            TreeNode* descendant {nodes_.at(id)};
            const TreeNode& ancestor {descendant->ancestor};
            // Remove nodes from cache
            while (descendant != ancestor) {
                if (descendant->descendant1 && nodes_.count(descendant->descendant1->group.id) == 1) {
                    if (descendant->descendant2 && nodes_.count(descendant->descendant2->group.id) == 1) {
                        descendant = descendant->descendant2;
                    } else {
                        descendant = descendant->descendant1;
                    }
                } else {
                    nodes_.erase(descendant->group.id);
                    descendant = descendant->ancestor;
                }
            }
            // Remove descendants from tree
            if (ancestor.descendant1->group.id == id) {
                ancestor.descendant1.reset();
            } else {
                ancestor.descendant2.reset();
            }
        }
    }
}

template <typename Label, typename T>
typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::set_founder(Group founder)
{
    if (!tree_) {
        TreeNode node {std::move(founder), nullptr, nullptr, nullptr};
        tree_ = std::make_unique<TreeNode>(std::move(node));
    } else {
        nodes_.erase(founder.id);
        tree_->group = std::move(founder);
    }
    return nodes_.emplace(founder.id, std::addressof(*tree_)).first->second->group;
}

template <typename Label, typename T>
typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::add_descendant(Group group, const Label& ancestor_id)
{
    TreeNode* ancestor {nodes_.at(ancestor_id)};
    if (ancestor->descendant1) {
        TreeNode node {std::move(group), ancestor, nullptr, nullptr};
        ancestor->descendant2 = std::make_unique<TreeNode>(std::move(node));
        return nodes_.emplace(ancestor->descendant2->group.id, std::addressof(*ancestor->descendant2)).first->second->group;
    } else {
        TreeNode node {std::move(group), ancestor, nullptr, nullptr};
        ancestor->descendant1 = std::make_unique<TreeNode>(std::move(node));
        return nodes_.emplace(ancestor->descendant1->group.id, std::addressof(*ancestor->descendant1)).first->second->group;
    }
}

template <typename Label, typename T>
const typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::group(const Label& id) const
{
    return nodes_.at(id)->group;
}

template <typename Label, typename T>
typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::group(const Label& id)
{
    return nodes_.at(id)->group;
}

template <typename Label, typename T>
const typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::founder() const noexcept
{
    return tree_->group;
}

template <typename Label, typename T>
const typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::ancestor(const Label& id) const
{
    return nodes_.at(id)->ancestor->group;
}

template <typename Label, typename T>
unsigned Phylogeny<Label, T>::num_descendants(const Label& id) const noexcept
{
    const TreeNode* ancestor {nodes_.at(id)};
    if (ancestor->descendant2) {
        return 2;
    } else if (ancestor->descendant1) {
        return 1;
    } else {
        return 0;
    }
}

template <typename Label, typename T>
const typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::descendant1(const Label& id) const
{
    return nodes_.at(id)->descendant1.group;
}

template <typename Label, typename T>
const typename Phylogeny<Label, T>::Group& Phylogeny<Label, T>::descendant2(const Label& id) const
{
    return nodes_.at(id)->descendant2.group;
}

} // namespace octopus

#endif

max_stars_repo_name: gmagoon/octopus

max_issues_repo_name: gmagoon/octopus

max_forks_repo_name: gmagoon/octopus


text:
// Copyright (c) 2019 Graphcore Ltd. All rights reserved.
#define BOOST_TEST_MODULE RemoveUnusedInputTest0

#include <boost/test/unit_test.hpp>
#include <filereader.hpp>
#include <onnx/onnx_pb.h>
#include <popart/builder.hpp>
#include <popart/graphtransformer.hpp>
#include <popart/tensordata.hpp>

using namespace popart;

// confirm that when prepareNodesFroTraining,
// batch-normalization has 5 outputs
BOOST_AUTO_TEST_CASE(Transformation_PrepareTrain0) {

  auto test = [](bool prepareTraining) {
    auto builder = Builder::create();
    auto aiOnnx  = builder->aiOnnxOpset9();

    TensorInfo info_d{"FLOAT", std::vector<int64_t>{4, 3, 32, 32}};
    TensorInfo info_c{"FLOAT", std::vector<int64_t>{3}};

    auto in0 = builder->addInputTensor(info_d);

    auto a0 = builder->addInputTensor(info_c);
    auto a1 = builder->addInputTensor(info_c);
    auto a2 = builder->addInputTensor(info_c);
    auto a3 = builder->addInputTensor(info_c);

    // in both cases, we set the number of outputs to 1
    unsigned num_outputs = 1;
    float eps            = 0.2;
    float momen          = 0.3;
    auto outs            = aiOnnx.batchnormalization(
        {in0, a0, a1, a2, a3}, num_outputs, eps, momen);
    builder->addOutputTensor(outs[0]);

    std::string proto = builder->getModelProto();

    GraphTransformer gt(proto);

    if (prepareTraining) {
      gt.prepareNodesForTraining();
    }
    auto postProto = io::getModelFromString(gt.getModelProto());

    // cofirm that the batch normalization has 5
    // outputs when the transformation has been run
    int visited = 0;
    for (auto node : postProto.graph().node()) {
      if (node.op_type() == "BatchNormalization") {
        BOOST_CHECK(node.output_size() == prepareTraining ? 5 : 1);
        ++visited;
      }
    }
    BOOST_CHECK(visited == 1);
  };

  test(true);
  test(false);
}


text:
/* Copyright (C) 2012-2019 IBM Corp.
 * This program is 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. See accompanying LICENSE file.
 */

#include <NTL/ZZ.h>
#include <helib/polyEval.h>
#include <helib/EncryptedArray.h>
#include <helib/debugging.h>

#include "gtest/gtest.h"
#include "test_common.h"

#ifdef DEBUG_PRINTOUT
extern helib::SecKey* dbgKey;
extern helib::EncryptedArray* dbgEa;
#endif

namespace {
struct Parameters {
    Parameters(long p, long r, long m, long d, long k, long max_d, long L, bool isMonic) :
        p(p),
        r(r),
        m(m),
        d(d),
        k(k),
        max_d(max_d),
        L(L),
        isMonic(isMonic)
    {};

  const long p;       //   p is the plaintext base
  const long r;       //   r is the lifting
  const long m;       //   m is a specific cyclotomic ring
  const long d;       //   d is the polynomial degree
  const long k;       //   k is the baby-step parameter
  const long max_d;
  const long L;
  const bool isMonic;

    friend std::ostream& operator<<(std::ostream& os, const Parameters& params)
    {
        return os << "{"
            << "p=" << params.p << ","
            << "r=" << params.r << ","
            << "m=" << params.m << ","
            << "d=" << params.d << ","
            << "k=" << params.k << ","
            << "max_d=" << params.max_d << ","
            << "L=" << params.L << ","
            << "isMonic=" << params.isMonic
            << "}";
    };
};

class GTestPolyEval : public ::testing::TestWithParam<Parameters>
{
    protected:
        long p;
        long r;
        long d;
        long max_d;
        long L;
        bool isMonic;
        long m;
        long k;
        helib::Context context;
        long p2r;
        helib::EncryptedArray ea;
        helib::SecKey secretKey;
        const helib::PubKey &publicKey;

        GTestPolyEval() :
            p(GetParam().p),
            r(GetParam().r),
            d(GetParam().d),
            max_d(GetParam().max_d),
            L(GetParam().L),
            isMonic(GetParam().isMonic),
            m(GetParam().m),
            k(GetParam().k),
            context((helib::setDryRun(helib_test::dry), m), p, r),
            p2r(context.alMod.getPPowR()),
            ea((helib::buildModChain(context, L, /*c=*/3), context)),
            secretKey(context),
            publicKey((secretKey.GenSecKey(), secretKey))
            //  addSome1DMatrices(secretKey); // compute key-switching matrices
    {};

    virtual void SetUp() override {
#ifdef DEBUG_PRINTOUT
        helib::dbgEa = &ea;        // for debugging purposes
        helib::dbgKey = &secretKey;
#endif
        if (!helib_test::noPrint) std::cout << (helib::isDryRun()? "* dry run, " : "* ")
        << "degree-"<<d<<", m="<<m<<", L="<<L<<", p^r="<<p2r<<std::endl;
    };

    virtual void TearDown() override
    {
      helib::cleanupGlobals();
    }
};

TEST_P(GTestPolyEval, encryptedPolynomialsEvaluateAtEncryptedPointCorrectly)
{
  NTL::zz_pBak bak; bak.save(); NTL::zz_p::init(p);
  NTL::zz_pXModulus phimX = NTL::conv<NTL::zz_pX>(ea.getPAlgebra().getPhimX());

  // Choose random plaintext polynomials
  NTL::zz_pX pX = NTL::random_zz_pX(deg(phimX)-1);
  NTL::Vec<NTL::zz_pX> ppoly(NTL::INIT_SIZE, d);
  for (long i=0; i<ppoly.length(); i++) random(ppoly[i], deg(phimX)-1);

  // Evaluate the non-encrypted polynomial
  NTL::zz_pX pres = (ppoly.length()>0)? ppoly[ppoly.length()-1] : NTL::zz_pX::zero();
  for (long i=ppoly.length()-2; i>=0; i--) {
    MulMod(pres, pres, pX, phimX);
    pres += ppoly[i];
  }

  // Encrypt the random polynomials
  helib::Ctxt cX(publicKey);
  NTL::Vec<helib::Ctxt> cpoly(NTL::INIT_SIZE, d, cX);

  secretKey.Encrypt(cX, NTL::conv<NTL::ZZX>(pX));

  for (long i=0; i<ppoly.length(); i++)
    secretKey.Encrypt(cpoly[i], NTL::conv<NTL::ZZX>(ppoly[i]));

  // Evaluate the encrypted polynomial
  helib::polyEval(cX, cpoly, cX);

  // Compare the results
  NTL::ZZX ret;
  secretKey.Decrypt(ret, cX);
  NTL::zz_pX cres = NTL::conv<NTL::zz_pX>(ret);
  EXPECT_EQ(cres, pres) << "encrypted poly MISMATCH";
};

TEST_P(GTestPolyEval, evaluatePolynomialOnCiphertext)
{
  // evaluate at random points (at least one co-prime with p)
    std::vector<long> x;
  ea.random(x);
  while (NTL::GCD(x[0],p)!=1) { x[0] = NTL::RandomBnd(p2r); }
  helib::Ctxt inCtxt(publicKey), outCtxt(publicKey);
  ea.encrypt(inCtxt, publicKey, x);

  NTL::ZZX poly;
  for (long i=d; i>=0; i--)
    SetCoeff(poly, i, NTL::RandomBnd(p2r)); // coefficients are random
  if (isMonic) SetCoeff(poly, d);    // set top coefficient to 1

  // Evaluate poly on the ciphertext
  helib::polyEval(outCtxt, poly, inCtxt, k);

  // Check the result
  std::vector<long> y;
  ea.decrypt(outCtxt, secretKey, y);
  for (long i=0; i<ea.size(); i++) {
    EXPECT_EQ(helib::polyEvalMod(poly, x[i], p2r), y[i])
        << "plaintext poly MISMATCH\n";
  }
};

std::vector<Parameters> getParameters()
{
    std::vector<Parameters> allParams;

    //SLOW
    const long p = 7;
    const long r = 2;
          long m = 0;
    const long k = 0;
    long d = 34;

    //FAST
    //const long p = 3;
    //const long r = 2;
    //      long m = 91;
    //const long k = 0;
    //long d = -1;

    const long max_d = (d<=0)? 35 : d;
    const long L = (7+NTL::NextPowerOfTwo(max_d))*30;

    if(m < 2) {
        m = helib::FindM(/*secprm=*/80, L, /*c=*/3, p, 1, 0, m, !helib_test::noPrint);
    }

    // Test both monic and non-monic polynomials of this degree
    if(d >= 0) {
        allParams.push_back(Parameters{p, r, m, d, k, max_d, L, false});
        allParams.push_back(Parameters{p, r, m, d, k, max_d, L,  true});
    } else {
      // Test degrees 1 to 3 and 25 through 35
      for(d = 1; d <= 3; d += 2)
        allParams.push_back(Parameters{p, r, m, d, k, max_d, L, true});
      for(d = 25; d <= 33; d += 2)
        allParams.push_back(Parameters{p, r, m, d, k, max_d, L, true});
    }
    return allParams;
};

INSTANTIATE_TEST_SUITE_P(manyDegrees, GTestPolyEval, ::testing::ValuesIn(getParameters()));

} // namespace

max_stars_repo_name: lparth/homeenc-HElib

max_issues_repo_name: lparth/homeenc-HElib

max_forks_repo_name: lparth/homeenc-HElib