text:
// Copyright (c) 2011 by BBNT Solutions LLC
// All Rights Reserved.

#include "Generic/common/leak_detection.h" // This must be the first #include
#include "Generic/patterns/Pattern.h"
#include "Generic/patterns/PatternSet.h"
#include "Generic/patterns/EntityLabelPattern.h"
#include "Generic/patterns/ShortcutPattern.h"
#include "Generic/patterns/PatternTypes.h"
#include "Generic/patterns/RegexPattern.h"
#include "Generic/patterns/features/PatternFeatureSet.h"
#include "Generic/patterns/features/TopLevelPFeature.h"
#include "Generic/common/ParamReader.h"
#include "Generic/theories/SentenceTheory.h"
#include "Generic/theories/TokenSequence.h"
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <algorithm>
#include "Generic/common/Sexp.h"

namespace { // private symbols
	const Symbol WORDSETS_SYM(L"wordsets");
	const Symbol ENTITYLABELS_SYM(L"entitylabels");
	const Symbol REFERENCE_SYM(L"reference");
	const Symbol TOPLEVEL_SYM(L"toplevel");
	const Symbol DOCLEVEL_SYM(L"doclevel");
	const Symbol BACKOFF_SYM(L"backoff");
	const Symbol OPTIONS_SYM(L"options");
}

PatternSet::PatternSet(): _keep_all_features(false), _entityLabels(4), _do_not_block_patterns(false)
{
	_single_match_for_ment_prop = ParamReader::getOptionalTrueFalseParamWithDefaultVal("independent_props_ments_sentence_snippets", false);
}

PatternSet::PatternSet(Pattern_ptr pattern) : _keep_all_features(false), _entityLabels(4), _do_not_block_patterns(false)
{
    _single_match_for_ment_prop = ParamReader::getOptionalTrueFalseParamWithDefaultVal("independent_props_ments_sentence_snippets", false);
    _topLevelPatterns.push_back(pattern);
}

PatternSet::PatternSet(const char* filename, bool encrypted): _keep_all_features(false), _entityLabels(4), _do_not_block_patterns(false)
{
	Sexp sexp(filename, true, true, true, true, std::vector<std::string>(), encrypted);
	initializeFromSexp(&sexp);
}

PatternSet::PatternSet(Sexp *sexp): _keep_all_features(false), _entityLabels(4), _do_not_block_patterns(false)
{
	initializeFromSexp(sexp);
}

void PatternSet::initializeFromSexp(Sexp *callers_sexp) {
	_single_match_for_ment_prop = ParamReader::getOptionalTrueFalseParamWithDefaultVal("independent_props_ments_sentence_snippets", false);

	Sexp *sexp = callers_sexp;
	if (sexp->getNumChildren() == 1 && sexp->getFirstChild()->isList()){
		// peel off the extra wrapper layer; it may have held includes or sets or other macros
		sexp = sexp->getFirstChild();
	}
	// Get the name.
	if (!sexp->getFirstChild()->isAtom()) {
		throw UnexpectedInputException("PatternSet::PatternSet",
			"PatternSet Sexp should begin with a pattern set name.");
	}
	_patternSetName = sexp->getFirstChild()->getValue();

	// Process the remaining children, and collect them into lists.
	// We no longer require a strict ordering for these children,
	// and we now allow children to be repeated.
	int num_children = sexp->getNumChildren();
	std::vector<Sexp*> wordsetsSexps;
	std::vector<Sexp*> entitylabelsSexps;
	std::vector<Sexp*> referenceSexps;
	std::vector<Sexp*> toplevelSexps;
	std::vector<Sexp*> doclevelSexps;
	std::vector<Sexp*> backoffSexps;
	std::vector<Sexp*> optionsSexps;
	for (int i=1; i<num_children; ++i) {
		Sexp *child = sexp->getNthChild(i);
		if ((!child->isList()) || (child->getNumChildren()==0) ||
			(!child->getFirstChild()->isAtom())) {
			std::stringstream error;
			error << "Unexpected child of pattern set: " << child->to_debug_string();
			throw UnexpectedInputException("PatternSet::PatternSet()", error.str().c_str());
		}
		Symbol childType = child->getFirstChild()->getValue();
		if (childType == WORDSETS_SYM)
			wordsetsSexps.push_back(child);
		else if (childType == ENTITYLABELS_SYM)
			entitylabelsSexps.push_back(child);
		else if (childType == REFERENCE_SYM)
			referenceSexps.push_back(child);
		else if (childType == TOPLEVEL_SYM)
			toplevelSexps.push_back(child);
		else if (childType == DOCLEVEL_SYM)
			doclevelSexps.push_back(child);
		else if (childType == BACKOFF_SYM)
			backoffSexps.push_back(child);
		else if (childType == OPTIONS_SYM)
			optionsSexps.push_back(child);
		else {
			std::stringstream error;
			error << "Unexpected child of pattern set: " << child->to_debug_string();
			throw UnexpectedInputException("PatternSet::PatternSet()", error.str().c_str());
		}
	}

	// Create the word set map.
	BOOST_FOREACH(Sexp *wordSetSexp, wordsetsSexps) {
		int n_wordsets = wordSetSexp->getNumChildren() - 1;
		for (int j = 0; j < n_wordsets; j++) {
			PatternWordSet_ptr wordSet = boost::make_shared<PatternWordSet>(wordSetSexp->getNthChild(j+1), _wordSets);
			if (_wordSets.find(wordSet->getLabel()) != _wordSets.end()) {
				std::stringstream error;
				error << "Duplicate wordset label: " << wordSet->getLabel();
				throw UnexpectedInputException("PatternSet::PatternSet()", error.str().c_str());
			}
			_wordSets[wordSet->getLabel()] = wordSet;
		}
	}

	// Create the entity label patterns.
	BOOST_FOREACH(Sexp *entityLabelSexp, entitylabelsSexps) {
		int n_entity_label_patterns = entityLabelSexp->getNumChildren() - 1;
		for (int j = 0; j < n_entity_label_patterns; j++) {
			EntityLabelPattern_ptr entityLabelPattern = boost::make_shared<EntityLabelPattern>(
				entityLabelSexp->getNthChild(j+1), _entityLabels, _wordSets);

			// Even though we don't have any reference patterns yet, we call replaceShortcuts
			// because we need CombinationPatterns to update their type correctly.
			if (entityLabelPattern->hasPattern()) {
				entityLabelPattern->replaceShortcuts(_referencePatterns);
			}
			_entityLabelPatterns.push_back(entityLabelPattern);
			_entityLabels.insert(entityLabelPattern->getLabel());
		}
	}

	// Create the reference patterns (shortcuts).  Note that this is the only
	// place where we allow patterns to contain shortcut labels.
	BOOST_FOREACH(Sexp *refSexp, referenceSexps) {
		int n_ref_patterns = refSexp->getNumChildren() - 1;
		for (int j = 0; j < n_ref_patterns; j++) {
			Sexp* refPatSexp = refSexp->getNthChild(j+1);
			// Create the reference pattern.
			Pattern_ptr refPattern = Pattern::parseSexp(
				refPatSexp, _entityLabels, _wordSets, true);
			// Get the shortcut name and make sure it's valid.
			Symbol shortcut = refPattern->getShortcut();
			if (shortcut.is_null())
				throwParseError(refPatSexp, "Reference patterns must have shortcut names");
			if (_referencePatterns.find(shortcut) != _referencePatterns.end())
				throwParseError(refPatSexp, "Duplicate shortcut name");
			// Resolve any shortcuts in the reference pattern.  Reference patterns
			// are only allowed to reference patterns that precede them in the list.
			try {
				refPattern = refPattern->replaceShortcuts(_referencePatterns);
			} catch (UnexpectedInputException& e) {
				std::ostringstream err;
				err << "\n\nIn reference pattern: " << refPatSexp->to_debug_string() << "\n\n";
				err << e.getMessage();
				throw UnexpectedInputException("PatternSet::initializeFromSexp", err.str().c_str());
			}
			// Add the reference pattern to _referencePatterns.  Note that we do this
			// after we replace shortcuts in refPattern -- no self-reference allowed!
			_referencePatterns[shortcut] = refPattern;
		}
	}

	// Create the top-level patterns.
	BOOST_FOREACH(Sexp *topLevelSexp, toplevelSexps)
		loadPatterns(topLevelSexp, _topLevelPatterns);

	// Create the document patterns.
	BOOST_FOREACH(Sexp *docPatternsSexp, doclevelSexps)
		loadPatterns(docPatternsSexp, _docPatterns);

	// Create the backoff level vector.
	BOOST_FOREACH(Sexp* backoffSexp, backoffSexps) {
		int n_backoff_levels = backoffSexp->getNumChildren() - 1;
		for (int j = 0; j < n_backoff_levels; j++) {
			_backoffLevels.push_back(backoffSexp->getNthChild(j+1)->getValue());
		}
	}

	// Process options.
	BOOST_FOREACH(Sexp* optionsSexp, optionsSexps) {
		for (int i = 1; i < optionsSexp->getNumChildren(); ++i) {
			Sexp *childSexp = optionsSexp->getNthChild(i);
			if (childSexp->isAtom()) {
				if (childSexp->getValue() == Symbol(L"KEEP_ALL_FEATURES")) {
					// This should only be set to true if the patterns are engineered to have
					// all the features kept (talk to Liz if you don't know what this means)
					_keep_all_features = true;
				} else {
					throwParseError(childSexp, "Unrecognized atom element in option list");
				}
			} else if (childSexp->isList()) {
				Symbol optionType = childSexp->getFirstChild()->getValue();
				if (optionType == Symbol(L"blocked_proposition_types")) {
					for (int j=0; j<childSexp->getNumChildren()-1; ++j) {
						Symbol blockedType = childSexp->getNthChild(j+1)->getValue();
						if (blockedType == Symbol(L"null")  || blockedType == Symbol(L"none")) {
							;
						} else {
							_blockedPropositionStatuses.insert(PropositionStatusAttribute::getFromString(blockedType.to_string()));
						}
					}
				} else {
					throwParseError(childSexp, "Unrecognized option in option list");
				}
			} else {
				throwParseError(childSexp, "Unrecognized option in option list");
			}
		}
	}
}

void PatternSet::loadPatterns(Sexp *sexp, std::vector<Pattern_ptr> &patterns) {
	if (sexp == 0) { return; }
	int num_patterns = sexp->getNumChildren() - 1;
	for (int j = 0; j < num_patterns; j++) {
		// Parse the pattern.
		Sexp* childSexp = sexp->getNthChild(j+1);
		Pattern_ptr pattern = Pattern::parseSexp(childSexp, _entityLabels, _wordSets);

		// Replace shortcuts with the patterns they point to.
		try {
			pattern = pattern->replaceShortcuts(_referencePatterns);
		} catch (UnexpectedInputException& e) {
			std::ostringstream err;
			err << "\n\nIn pattern: " << childSexp->to_debug_string() << "\n\n";
			err << e.getMessage();
			throw UnexpectedInputException("PatternSet::loadPatterns", err.str().c_str());
		}

		// Add the pattern to the list of patterns.
		patterns.push_back(pattern);
	}
}

void PatternSet::throwParseError(const Sexp *sexp, const char *reason) {
	std::stringstream error;
	error << "Parser Error: " << reason << ": " << sexp->to_debug_string();
	throw UnexpectedInputException("Pattern::throwError()", error.str().c_str());
}

Symbol PatternSet::getPatternSetName() const {
	return _patternSetName;
}
size_t PatternSet::getNTopLevelPatterns() const {
	return _topLevelPatterns.size();
}
Pattern_ptr PatternSet::getNthTopLevelPattern(size_t n) const {
	return _topLevelPatterns[n];
}
size_t PatternSet::getNEntityLabelPatterns() const {
	return _entityLabelPatterns.size();
}
EntityLabelPattern_ptr PatternSet::getNthEntityLabelPattern(size_t n) {
	return _entityLabelPatterns[n];
}
size_t PatternSet::getNDocPatterns() const {
	return _docPatterns.size();
}
Pattern_ptr PatternSet::getNthDocPattern(size_t n) const {
	return _docPatterns[n];
}
int PatternSet::getNBackoffLevels() const {
	return static_cast<int>(_backoffLevels.size());
}

const Symbol::HashSet& PatternSet::getEntityLabelSet() {
	return _entityLabels;
}

Symbol PatternSet::getNthBackoffLevel(int n) const {
	if (n >= 0 && n < static_cast<int>(_backoffLevels.size()))
		return _backoffLevels[n];
	else
		return Symbol();
}

void PatternSet::addBlockedPropositionStatus(PropositionStatusAttribute status) {
	_blockedPropositionStatuses.insert(status);
}

bool PatternSet::isBlockedPropositionStatus(PropositionStatusAttribute status) const {
	if (_do_not_block_patterns)
		return false;
	if (_blockedPropositionStatuses.empty()) {
		const std::set<PropositionStatusAttribute> &defaultBlockedPropositionStatuses = getDefaultBlockedPropositionStatuses();
		return defaultBlockedPropositionStatuses.find(status) != defaultBlockedPropositionStatuses.end();
	} else {
		return _blockedPropositionStatuses.find(status) != _blockedPropositionStatuses.end();
	}
}

const std::set<PropositionStatusAttribute> &PatternSet::getDefaultBlockedPropositionStatuses() {
	static bool initialized = false;
	static std::set<PropositionStatusAttribute> blockedTypes;
	if (!initialized) {
		initialized = true;
		std::vector<std::wstring> types = ParamReader::getWStringVectorParam("blocked_proposition_types");
		if (types.empty()) {
			ParamReader::getRequiredParam("blocked_proposition_types"); // Make sure it was defined.
		}
		BOOST_FOREACH(std::wstring type, types) {
			if (boost::iequals(type, L"none") || boost::iequals(type, L"null")) {
				;
			} else {
				blockedTypes.insert(PropositionStatusAttribute::getFromString(type.c_str()));
			}
		}
	}
	return blockedTypes;
}

/**
 * Uses a PatternSet to build an IDToPatternReturnVecSeqMap,
 * which maps a pattern id name to a PatternReturnVecSeqMap, which stores
 * any of the possible bundles of information used to represent all the args
 * for a given top-level pattern. Usually, there is only one such bundle, but
 * if the pattern contains an any-of, there will be more. If it contains multiple
 * any-ofs, there could be many more.
 *
 * @param output_map IDToPatternReturnVecSeqMap to be filled with non-tbd PatternReturns if no tbd pattern
 * is encountered.
 * @param output_tbd_predicates Names of tbd predicates
 * derived from the "tbd" ReturnPatterns encountered (other than "tbd agent" and "tbd patient").
 * @param dump Determines whether pattern output (which is verbose)
 * should be dumped.
 *
 * @see http://wiki.d4m.bbn.com/wiki/PatternReturn_Hierarchy
 *
 * @author afrankel@bbn.com
 * @date 2010.10.18
 **/

void PatternSet::getPatternReturns(IDToPatternReturnVecSeqMap & output_map, bool dump) const
{
	if (dump) {
		SessionLogger::info("ps_0") << "PATTERN: " << getPatternSetName().to_debug_string();
	}
	size_t n_toplevel_patterns = _topLevelPatterns.size();
	for (size_t n = 0; n < n_toplevel_patterns; ++n) {
		if (_topLevelPatterns[n]) {
			if (_topLevelPatterns[n]->getFirstValidID().is_null()) {
				// We're probably dealing with a pattern that produces an individual
				// and hence doesn't need an ID. Just skip the pattern.
				continue;
			}
			if (dump) {
				std::ostringstream ostr;
				ostr << "  ID: " << _topLevelPatterns[n]->getFirstValidID().to_debug_string() << std::endl;
				_topLevelPatterns[n]->dump(ostr, 0);
				SessionLogger::info("ps_1") << ostr.str();
			}
			PatternReturnVecSeq pattern_return_vec_seq;
			_topLevelPatterns[n]->getReturns(pattern_return_vec_seq);
			output_map.insert(make_pair(_topLevelPatterns[n]->getFirstValidID(), pattern_return_vec_seq));
			int size_after(static_cast<int>(output_map.size()));
			if (dump) {
				std::ostringstream ostr;
				dumpPatternReturnVecSeq(pattern_return_vec_seq, ostr, 0);
				SessionLogger::info("ps_2") << ostr.str();
			}
		}
	}
	return;
}

bool PatternSet::validForPreParseMatching() const {
	for (size_t i = 0; i < _topLevelPatterns.size(); i++) {
		Pattern_ptr pattern = _topLevelPatterns[i];
		RegexPattern_ptr rp = boost::dynamic_pointer_cast<RegexPattern>(pattern);
		if (!rp || !rp->containsOnlyTextSubpatterns())
			return false;
	}
	return true;
}

ext: cpp

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
/*!
 * Title ---- km/PropertyContainer.hpp
 * Author --- Giacomo Trudu aka `Wicker25` - wicker25[at]gmail[dot]com
 *
 * Copyright (C) 2017 by Giacomo Trudu.
 * All rights reserved.
 *
 * This file is part of KeyMaker software.
 */

#ifndef __KM_PROPERTY_CONTAINER_HPP__
#define __KM_PROPERTY_CONTAINER_HPP__

#include <km.hpp>
#include <km/Exception.hpp>
#include <km/Buffer.hpp>
#include <km/PropertyNode.hpp>

#include <algorithm>
#include <map>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

using namespace boost;

namespace km { // Begin main namespace

/*!
 * The property map.
 */
typedef std::map<Buffer, PropertyNode> PropertyMap;

/*!
 * The property container.
 */
template <typename T>
class PropertyContainer
{

public:

    /*!
     * Creates a property container from a property tree.
     *
     * @param[in] container The property container.
     * @param[in] config    The property tree.
     *
     * @return The property container.
     */
    static PropertyContainer fromConfig(PropertyContainer<T> &container, property_tree::ptree &config);

    /*!
     * Converts a property container into a property tree.
     *
     * @param[in] container The property container.
     *
     * @return The configuration node.
     */
    static property_tree::ptree toConfig(const PropertyContainer &container);

    /*!
     * Destructor method.
     */
	virtual ~PropertyContainer();

    /*!
     * Sets a property in the container.
     *
     * @param[in] name     The property name.
     * @param[in] property The property instance.
     *
     * @return The entry node.
     */
    T &setProperty(const Buffer &name, const PropertyNode &property);

    /*!
     * Sets a property in the container.
     *
     * @param[in] name  The property name.
     * @param[in] value The property value.
     *
     * @return The entry node.
     */
    T &setProperty(const Buffer &name, const Buffer &value);

    /*!
     * Returns a property in the container.
     *
     * @param[in] name The property name.
     *
     * @return The property node.
     */
    const PropertyNode &getProperty(const Buffer &name) const;

    /*!
     * Removes a property from the container.
     *
     * @param[in] name The property name.
     *
     * @return The property container.
     */
    T &removeProperty(const Buffer &name);

    /*!
     * Iterates over the properties in the container.
     *
     * @param[in] callback The callback function.
     *
     * @return The property container.
     */
    T &eachProperty(std::function<void (const Buffer &, PropertyNode &)> callback);

    /*!
     * Iterates over the properties in the container.
     *
     * @param[in] callback The callback function.
     *
     * @return The property container.
     */
    const T &eachProperty(std::function<void (const Buffer &, const PropertyNode &)> callback) const;

    /*!
     * Iterates over the properties in the container and produce a new property container.
     *
     * @param[in] callback The callback function.
     *
     * @return The property container.
     */
    T mapProperty(std::function<PropertyNode (const Buffer &, const PropertyNode &)> callback) const;

protected:

    /*!
     * Constructor method.
     */
    PropertyContainer();

    /*!
     * The properties.
     */
    PropertyMap mProperties;
};

/*!
 * The property not found exception.
 */
class PropertyNotFoundException : public Exception
{
    using Exception::Exception;
};

} // End of main namespace

#endif /* __KM_PROPERTY_CONTAINER_HPP__ */

// Include inline methods
#include <km/PropertyContainer-inl.hpp>

ext: hpp

max_stars_repo_name: keymaker-io/keymaker-alpha

max_issues_repo_name: keymaker-io/keymaker-alpha

max_forks_repo_name: keymaker-io/keymaker-alpha


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2011-2014 Renato Tegon Forti
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// 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
//---------------------------------------------------------------------------//

#ifndef BOOST_APPLICATION_ARGS_ASPECT_HPP
#define BOOST_APPLICATION_ARGS_ASPECT_HPP

#include <boost/application/config.hpp>
#include <boost/application/base_type.hpp>

namespace boost {
    namespace application {

        /*!
         * @brief This aspect class handle application args in more friedly way.
         *
         * An aspect that will hold args, and provide a easy way to access they
         * or user can extrat args from it to use with Program_options,
         * getopts or argp and so on.
         *
         */
        template<typename CharType>
        class args_ {
        public:
            // string types to be used internaly to handle unicode on windows
            typedef CharType char_type;
            typedef std::basic_string<char_type> string_type;

            /*!
             * Constructs an args_.
             *
             * \param argc An argc from main.
             * \param argc An argv from main.
             */
            args_(int argc, char_type *argv[]) {
                for (int i = 0; i < argc; i++) {
                    arguments_.push_back(argv[i]);
                }
            }

            /*!
             * Get a argc as provided by main.
             *
             * \return an argc variable.
             *
             */
            int argc() const {
                return (int)arguments_.size();
            }

            /*!
             * Get a argv as provided by main.
             *
             * \return an argv variable.
             *
             */
            char_type **argv() {
                return &arguments_[0];
            }

            /*!
             * Get a vector of args.
             *
             * \return an vector of args.
             *
             */
            std::vector<string_type> arg_vector() {
                std::vector<string_type> args;
                for (int i = 0; i < argc(); ++i) {
                    args.push_back(argv()[i]);
                }

                return args;
            }

        private:
            std::vector<char_type *> arguments_;
        };

        /////////////////////////////////////////////////////////////////////////////
        // args
        //

        // args versions for Multi-Byte string and Unicode string
        typedef args_<character_types::char_type> args;
        // wchar_t / char

    }    // namespace application
}    // namespace boost

#endif    // BOOST_APPLICATION_ARGS_ASPECT_HPP

max_stars_repo_name: NilFoundation/application

max_issues_repo_name: NilFoundation/application

max_forks_repo_name: NilFoundation/application


text:
//==============================================================================
//         Copyright 2003 - 2013   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2013   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#include <nt2/include/functions/expi.hpp>

#include <boost/dispatch/functor/meta/call.hpp>
#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <boost/simd/sdk/simd/native.hpp>
#include <boost/simd/sdk/simd/io.hpp>
#include <complex>
#include <nt2/sdk/complex/complex.hpp>
#include <nt2/sdk/unit/tests/ulp.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <boost/simd/sdk/config.hpp>

#include <nt2/include/constants/mone.hpp>
#include <nt2/include/constants/one.hpp>
#include <nt2/include/constants/pi.hpp>
#include <nt2/include/constants/zero.hpp>
#include <nt2/include/constants/inf.hpp>
#include <nt2/include/constants/minf.hpp>
#include <nt2/include/constants/nan.hpp>
#include <nt2/include/constants/i.hpp>
#include <nt2/include/functions/mul_i.hpp>
#include <nt2/include/functions/exp.hpp>

NT2_TEST_CASE_TPL ( expi_real,  NT2_SIMD_REAL_TYPES)
{
  using nt2::expi;
  using nt2::tag::expi_;
  typedef typename std::complex<T> cT;
  using boost::simd::native;
  typedef BOOST_SIMD_DEFAULT_EXTENSION  ext_t;
  typedef native<T,ext_t>                  vT;
  typedef native<cT,ext_t>                vcT;
  NT2_TEST_TYPE_IS( typename nt2::meta::call<expi_(vcT)>::type, vcT );

  // specific values tests
#ifndef BOOST_SIMD_NO_INVALIDS
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Inf<vcT>())   , nt2::exp(nt2::mul_i(nt2::Inf<vcT>()))  , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Minf<vcT>())  , nt2::exp(nt2::mul_i(nt2::Minf<vcT>()) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Nan<vcT>())   , nt2::exp(nt2::mul_i(nt2::Nan<vcT>())  ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Inf<vT>())    , nt2::exp(nt2::mul_i(nt2::Inf<vcT>()))  , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi((nt2::Minf<vT>())) , nt2::exp(nt2::mul_i(nt2::Minf<vcT>()) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi((nt2::Nan<vT>()))  , nt2::exp(nt2::mul_i(nt2::Nan<vcT>())  ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Inf<vT>()))  , nt2::Zero<vcT>()  , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Minf<vT>())) , nt2::Inf<vcT>() , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Nan<vT>()))  , nt2::Nan<vcT>(), 1);
#endif
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Mone<vcT>()) , nt2::exp(nt2::mul_i(vcT(nt2::Mone<vT>())) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::One<vcT>())  , nt2::exp(nt2::mul_i(vcT(nt2::One<vT>()))  ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Zero<vcT>()) , nt2::exp(nt2::mul_i(vcT(nt2::Zero<vT>())) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Pi<vT>())    , nt2::exp(nt2::mul_i(nt2::Pi<vcT>())), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Mone<vT>())  , nt2::exp(nt2::mul_i(vcT(nt2::Mone<vT>())) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::One<vT>())   , nt2::exp(nt2::mul_i(vcT(nt2::One<vT>()))  ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Zero<vT>())  , nt2::exp(nt2::mul_i(vcT(nt2::Zero<vT>())) ), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::Pi<vT>())    , nt2::exp(nt2::mul_i(vcT(nt2::Pi<vT>()))), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Mone<vT>())) , nt2::exp( nt2::One<vcT>()) , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::One<vT>()))  , nt2::exp( nt2::Mone<vcT>()) , 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Zero<vT>())) , nt2::exp( nt2::Zero<vcT>()), 1);
  NT2_TEST_ULP_EQUAL(nt2::expi(nt2::mul_i(nt2::Pi<vT>()))   , nt2::exp( -nt2::Pi<vcT>()), 1);
}


text: #include <boost/beast/http/span_body.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#ifndef RandomDescriptorCreatorVisitor_HPP
#define RandomDescriptorCreatorVisitor_HPP

#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>

/**
 * This is a simplified visitor type that models with the InpaintingVisitorConcept and does
 * nothing but create random descriptors to initialize nodes.
 */
template <typename TDescriptorMap>
struct RandomDescriptorCreatorVisitor
{
  TDescriptorMap& DescriptorMap;
  unsigned int Dimension;

  RandomDescriptorCreatorVisitor(TDescriptorMap& descriptorMap, const unsigned int dimension) :
  DescriptorMap(descriptorMap), Dimension(dimension)
  {

  }

  template <typename VertexType, typename Graph>
  void InitializeVertex(VertexType v, Graph& g) const
  {
    typedef typename boost::property_traits<TDescriptorMap>::value_type DescriptorType;
    DescriptorType descriptor;
    for(unsigned int i = 0; i < dimension; ++i)
    {
      descriptor[i] = drand48();
    }
    put(this->DescriptorMap, v, descriptor);
  }

};

#endif

max_stars_repo_name: jingtangliao/ff

max_issues_repo_name: jingtangliao/ff

max_forks_repo_name: jingtangliao/ff


text:
#include <dlfcn.h>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <fstream>
#include <iostream>

#include "alpha.h"
#include "common.h"
#include "data.h"
#include "logger.h"
#include "python.h"

namespace bpo = boost::program_options;

int main(int argc, char *argv[]) {
  std::string config_file_path;
  std::string log_config_file_path;
  std::string data_path;
  try {
    bpo::options_description config("Configuration");
    config.add_options()("help,h", "produce help message")(
        "config_file,c",
        bpo::value<std::string>(&config_file_path)
            ->default_value("openalpha.conf"),
        "config file path")("log_config_file,l",
                            bpo::value<std::string>(&log_config_file_path)
                                ->default_value("log.conf"),
                            "log4cxx config file path")(
        "data_path,C",
        bpo::value<std::string>(&data_path)
            ->default_value(openalpha::kDataPath.string()),
        "directory path where data files are located");

    bpo::options_description config_file_options;
    config_file_options.add(config);
    bpo::variables_map vm;

    bpo::store(bpo::parse_command_line(argc, argv, config), vm);
    bpo::notify(vm);
    if (vm.count("help")) {
      std::cerr << config << std::endl;
      return 1;
    }

    std::ifstream ifs(config_file_path.c_str());
    if (ifs) {
      bpo::store(parse_config_file(ifs, config_file_options, true), vm);
    } else {
      std::cerr << config_file_path << " not found" << std::endl;
      return 1;
    }

    bpo::store(bpo::parse_command_line(argc, argv, config), vm);
    bpo::notify(vm);  // make command line option higher priority
  } catch (bpo::error &e) {
    std::cerr << "Bad Options: " << e.what() << std::endl;
    return 1;
  }

  if (!std::ifstream(log_config_file_path.c_str()).good()) {
    std::ofstream(log_config_file_path)
        .write(openalpha::kDefaultLogConf, strlen(openalpha::kDefaultLogConf));
  }

  if (!openalpha::fs::exists(openalpha::kStorePath))
    openalpha::fs::create_directory(openalpha::kStorePath);
  openalpha::kDataPath = data_path;
  openalpha::Logger::Initialize("openalpha", log_config_file_path);
  openalpha::InitalizePy();
  openalpha::DataRegistry::Instance().Initialize();

  auto &ar = openalpha::AlphaRegistry::Instance();
  boost::property_tree::ptree prop_tree;
  boost::property_tree::ini_parser::read_ini(config_file_path, prop_tree);
  for (auto &section : prop_tree) {
    if (!section.second.size()) continue;
    openalpha::Alpha::ParamMap params;
    for (auto &item : section.second) {
      auto name = item.first;
      boost::to_lower(name);
      params[name] = item.second.data();
    }
    auto path = params["alpha"];
    if (!path.empty()) {
      if (boost::algorithm::ends_with(path, ".py")) {
        ar.Add((new openalpha::PyAlpha)
                   ->Initialize(section.first, std::move(params)));
      } else if (boost::algorithm::ends_with(path, ".so")) {
        auto handle = dlopen(path.c_str(), RTLD_NOW);
        if (!handle) {
          LOG_FATAL("Alpha: failed to load '" << path + "': " << dlerror());
        }
        typedef openalpha::Alpha *(*CFunc)();
        auto create_func = (CFunc)dlsym(handle, "create");
        if (!create_func) {
          LOG_FATAL("Alpha: failed to load '" << path + "': " << dlerror());
        }
        auto out = create_func();
        auto alpha = dynamic_cast<openalpha::Alpha *>(out);
        if (!alpha) {
          LOG_FATAL("Alpha: failed to load '"
                    << path + "', create() does not return Alpha object");
        }
        if (alpha->GetVersion() != openalpha::kApiVersion) {
          LOG_FATAL("Alpah: failed to load '" << path + "': version mismatch, "
                                              << "got " << alpha->GetVersion()
                                              << ", expect "
                                              << openalpha::kApiVersion);
        }
        ar.Add(alpha->Initialize(section.first, std::move(params)));
      } else {
        LOG_FATAL("Alpha: invalid path file '"
                  << path << "', expected '.py' or '.so' file")
      }
    }
  }
  ar.Run();

  return 0;
}

ext: cc

max_stars_repo_name: caoruicn/openalpha

max_issues_repo_name: caoruicn/openalpha

max_forks_repo_name: caoruicn/openalpha


text:
#include <algorithm>
#include <boost/optional.hpp>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <limits>
#include <list>
#include <numeric>
#include <queue>
#include <sstream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#define REP(i, n) for(int i = 0, i##_MACRO = (n); i < i##_MACRO; i++)
#define RANGE(i, a, b) for(int i = (a), i##_MACRO = (b); i < i##_MACRO; i++)
#define EACH(e, a) for(auto&& e : a)
#define ALL(a) (a).begin(), (a).end()
#define AALL(a, n) (a), ((a) + (n))
#define FILL(a, n) memset((a), n, sizeof(a))
#define FILLZ(a) FILL(a, 0)
#define MODNUM (static_cast<int>(1e9 + 7))
#define MOD(x) ((x) % MODNUM)

using namespace std;

using ll = long long;
using VI = vector<int>;
using VI2D = vector<vector<int>>;

const int INF = 2e9;
const double EPS = 1e-10;
const double PI = acos(-1.0);

const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};

inline int toInt(string s) {
	int v;
	istringstream sin(s);
	sin >> v;
	return v;
}

int sign(ll n) {
	if(n > 0) {
		return 1;
	}
	if(n < 0) {
		return -1;
	}
	return 0;
}

int main() {
	ll t[2];
	ll a[2];
	ll b[2];
	scanf("%lld %lld", &t[0], &t[1]);
	scanf("%lld %lld", &a[0], &a[1]);
	scanf("%lld %lld", &b[0], &b[1]);
	ll ab[2];
	ab[0] = b[0] - a[0];
	ab[1] = b[1] - a[1];
	if(sign(ab[0]) == sign(ab[1])) {
		puts("0");
		return 0;
	}
	ll abt[2];
	abt[0] = ab[0] * t[0];
	abt[1] = ab[1] * t[1];
	if(abt[0] + abt[1] == 0) {
		puts("infinity");
		return 0;
	}
	if(abs(abt[0]) > abs(abt[1])) {
		puts("0");
		return 0;
	}
	ll abti = abs(abt[0] + abt[1]);
	abt[0] = abs(abt[0]);

	ll result = (abt[0] + (abti - 1)) / abti;
	printf("%lld\n", result * 2 - (abt[0] % abti ? 1 : 0));
	return 0;
}

max_stars_repo_name: arlechann/atcoder

max_issues_repo_name: arlechann/atcoder

max_forks_repo_name: arlechann/atcoder


text:
#include <boost/program_options.hpp>
#include <cstdint>
#include <iostream>
#include <queue>
#include <random>
#include <string>
#include <vector>

#include "config.h"
#include "midgard/logging.h"
#include "midgard/util.h"
#include "sif/edgelabel.h"

#include "baldr/double_bucket_queue.h"

using namespace valhalla::midgard;
using namespace valhalla::baldr;
using namespace valhalla::sif;

namespace bpo = boost::program_options;

/**
 * Benchmark of adjacency list. Constructs a large number of random numbers,
 * adds EdgeLabels to the AdjacencyList with those as the sortcost. Then
 * removes them from the list. This compares performance of an STL
 * priority_queue with the custom approximate double bucket sorting used
 * in adjacencylist.cc.
 */
int Benchmark(const uint32_t n, const float maxcost, const float bucketsize) {
  // Create a set of random costs
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_real_distribution<> dis(0, 1);
  std::vector<uint32_t> costs(n);
  for (uint32_t i = 0; i < n; i++) {
    costs[i] = static_cast<uint32_t>(dis(gen) * maxcost);
  }

  // Test performance of STL priority queue. Construct labels
  // and add to the priority queue
  std::clock_t start = std::clock();
  std::priority_queue<EdgeLabel> pqueue;
  for (uint32_t i = 0; i < n; i++) {
    EdgeLabel el;
    el.SetSortCost(costs[i]);
    pqueue.push(std::move(el));
  }

  uint32_t count = 0;
  std::vector<uint32_t> ordered_cost1;
  while (!pqueue.empty()) {
    EdgeLabel el = pqueue.top();
    ordered_cost1.push_back(el.sortcost());
    pqueue.pop();
    count++;
  }
  uint32_t ms = (std::clock() - start) / static_cast<double>(CLOCKS_PER_SEC / 1000);
  LOG_INFO("Priority Queue: Added and removed " + std::to_string(count) + " edgelabels in " +
           std::to_string(ms) + " ms");

  // Didn't alter the sort order of priority queue, so reverse the vector
  std::reverse(ordered_cost1.begin(), ordered_cost1.end());

  // Test performance of double bucket adjacency list. Set the bucket maxcost
  // such that EmptyOverflow is called once
  std::vector<EdgeLabel> edgelabels;
  // Set up lambda to get sort costs
  const auto edgecost = [&edgelabels](const uint32_t label) { return edgelabels[label].sortcost(); };
  start = std::clock();
  DoubleBucketQueue adjlist(0, maxcost / 2, bucketsize, edgecost);

  // Construct EdgeLabels and add to adjacency list

  for (uint32_t i = 0; i < n; i++) {
    EdgeLabel el;
    el.SetSortCost(costs[i]);
    edgelabels.push_back(std::move(el));
    adjlist.add(i);
  }

  // Get edge label indexes from the adj list. Accumulate total cost to make
  // sure compiler doesn't optimize too much.
  count = 0;
  std::vector<uint32_t> ordered_cost2;
  while (true) {
    uint32_t idx = adjlist.pop();
    if (idx == kInvalidLabel) {
      break;
    }

    // Copy the edge label - simulates what is done in PathAlgorithm
    EdgeLabel el = edgelabels[idx];
    ordered_cost2.push_back(el.sortcost());
    count++;
  }
  ms = (std::clock() - start) / static_cast<double>(CLOCKS_PER_SEC / 1000);
  LOG_INFO("Bucketed Adj. List: Added and removed " + std::to_string(count) + " edgelabels in " +
           std::to_string(ms) + " ms");

  // Verify order
  for (uint32_t i = 0; i < count; i++) {
    if (ordered_cost1[i] != ordered_cost2[i]) {
      LOG_INFO("Costs: " + std::to_string(ordered_cost1[i]) + "," + std::to_string(ordered_cost2[i]));
    }
  }
  return 0;
}

int main(int argc, char* argv[]) {

  bpo::options_description options(
      "valhalla " VALHALLA_VERSION "\n"
      "\n"
      " Usage: adjlistbenchmark [options]\n"
      "\n"
      "adjlistbenchmark is benchmark comparing performance of an STL priority_queue"
      "to the approximate double bucket adjacency list class supplied with Valhalla."
      "\n"
      "\n");

  options.add_options()("help,h", "Print this help message.")("version,v",
                                                              "Print the version of this software.");

  bpo::variables_map vm;
  try {
    bpo::store(bpo::command_line_parser(argc, argv).options(options).run(), vm);
    bpo::notify(vm);

  } catch (std::exception& e) {
    std::cerr << "Unable to parse command line options because: " << e.what() << "\n"
              << "This is a bug, please report it at " PACKAGE_BUGREPORT << "\n";
    return EXIT_FAILURE;
  }

  if (vm.count("help")) {
    std::cout << options << "\n";
    return EXIT_SUCCESS;
  }

  if (vm.count("version")) {
    std::cout << "AdjacencyListBenchmark " << VALHALLA_VERSION << "\n";
    return EXIT_SUCCESS;
  }

  // Benchmark with count, maxcost, and bucketsize
  Benchmark(1000000, 50000, 1);
  LOG_INFO("Done Benchmark!");

  return EXIT_SUCCESS;
}

max_stars_repo_name: mixvit/valhalla

max_issues_repo_name: Bolaxax/valhalla

max_forks_repo_name: Bolaxax/valhalla


text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE OcrLineTest

#include "core/Line.hpp"
#include <boost/test/unit_test.hpp>
#include <functional>
#include <iostream>
#include <vector>

using namespace pcw;

struct Fixture
{
  static const char* ocr;
  static const Box box;

  Fixture()
    : line(std::make_shared<Line>(1, box))
  {
    line->append(ocr, 0, 100, 0.8);
    BOOST_REQUIRE(not line->empty());
    BOOST_CHECK_EQUAL(line->box, box);
  }
  LinePtr line;
};

const char* Fixture::ocr = "pectũeſt: quioo te mp";
const Box Fixture::box{ 0, 0, 100, 20 };

////////////////////////////////////////////////////////////////////////////////
BOOST_FIXTURE_TEST_SUITE(OcrLineTest, Fixture)

////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Line)
{
  BOOST_CHECK_EQUAL(line->ocr(), ocr);
  BOOST_CHECK_EQUAL(line->cor(), ocr); // cor and ocr must be the same
  BOOST_CHECK_CLOSE(line->average_conf(), .8,
                    .001); // it's not rocket sience
  BOOST_CHECK_EQUAL(line->chars().back().cut, 100);
  BOOST_CHECK(not line->is_fully_corrected());
}

////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Tokens)
{
  auto tokens = line->tokens();
  BOOST_REQUIRE(tokens.size() == 7);

  BOOST_CHECK(tokens[0].is_normal());
  BOOST_CHECK_EQUAL(tokens[0].ocr(), "pectũeſt");
  BOOST_CHECK_EQUAL(tokens[0].cor(), "pectũeſt");
  BOOST_CHECK_EQUAL(tokens[0].cor(), "pectũeſt");
  BOOST_CHECK(not tokens[0].is_fully_corrected());

  BOOST_CHECK(not tokens[1].is_normal());
  BOOST_CHECK_EQUAL(tokens[1].ocr(), ": ");
  BOOST_CHECK_EQUAL(tokens[1].cor(), ": ");
  BOOST_CHECK(not tokens[1].is_fully_corrected());

  BOOST_CHECK(tokens[2].is_normal());
  BOOST_CHECK_EQUAL(tokens[2].ocr(), "quioo");
  BOOST_CHECK_EQUAL(tokens[2].cor(), "quioo");
  BOOST_CHECK(not tokens[2].is_fully_corrected());

  BOOST_CHECK(not tokens[3].is_normal());
  BOOST_CHECK_EQUAL(tokens[3].ocr(), " ");
  BOOST_CHECK_EQUAL(tokens[3].cor(), " ");
  BOOST_CHECK(not tokens[3].is_fully_corrected());

  BOOST_CHECK(tokens[4].is_normal());
  BOOST_CHECK_EQUAL(tokens[4].ocr(), "te");
  BOOST_CHECK_EQUAL(tokens[4].cor(), "te");
  BOOST_CHECK(not tokens[4].is_fully_corrected());

  BOOST_CHECK(not tokens[5].is_normal());
  BOOST_CHECK_EQUAL(tokens[5].ocr(), " ");
  BOOST_CHECK_EQUAL(tokens[5].cor(), " ");
  BOOST_CHECK(not tokens[5].is_fully_corrected());

  BOOST_CHECK(tokens[6].is_normal());
  BOOST_CHECK_EQUAL(tokens[6].ocr(), "mp");
  BOOST_CHECK_EQUAL(tokens[6].cor(), "mp");
  BOOST_CHECK(not tokens[6].is_fully_corrected());
}

////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Words)
{
  auto words = line->words();
  BOOST_CHECK_EQUAL(words.size(), 4);
  BOOST_CHECK(std::all_of(
    begin(words), end(words), [](const auto& c) { return c.is_normal(); }));
  BOOST_CHECK_EQUAL(words[0].ocr(), "pectũeſt");
  BOOST_CHECK_EQUAL(words[0].cor(), "pectũeſt");
  BOOST_CHECK(not words[0].is_fully_corrected());
  BOOST_CHECK_EQUAL(words[1].ocr(), "quioo");
  BOOST_CHECK_EQUAL(words[1].cor(), "quioo");
  BOOST_CHECK(not words[1].is_fully_corrected());
  BOOST_CHECK_EQUAL(words[2].ocr(), "te");
  BOOST_CHECK_EQUAL(words[2].cor(), "te");
  BOOST_CHECK(not words[2].is_fully_corrected());
  BOOST_CHECK_EQUAL(words[3].ocr(), "mp");
  BOOST_CHECK_EQUAL(words[3].cor(), "mp");
  BOOST_CHECK(not words[3].is_fully_corrected());
}

////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(WordBoundinBoxes)
{
  auto words = line->words();
  BOOST_CHECK_EQUAL(words.size(), 4);

  BOOST_CHECK_EQUAL(words[0].box.top(), 0);
  BOOST_CHECK_EQUAL(words[0].box.bottom(), 20);
  BOOST_CHECK_EQUAL(words[0].box.height(), 20);
  BOOST_CHECK(words[0].box.width() > 0);

  BOOST_CHECK_EQUAL(words[1].box.top(), 0);
  BOOST_CHECK_EQUAL(words[1].box.bottom(), 20);
  BOOST_CHECK_EQUAL(words[1].box.height(), 20);
  BOOST_CHECK(words[1].box.width() > 0);

  BOOST_CHECK_EQUAL(words[2].box.top(), 0);
  BOOST_CHECK_EQUAL(words[2].box.bottom(), 20);
  BOOST_CHECK_EQUAL(words[2].box.height(), 20);
  BOOST_CHECK(words[2].box.width() > 0);

  BOOST_CHECK_EQUAL(words[3].box.top(), 0);
  BOOST_CHECK_EQUAL(words[3].box.bottom(), 20);
  BOOST_CHECK_EQUAL(words[3].box.right(), 100);
  BOOST_CHECK_EQUAL(words[3].box.height(), 20);
  BOOST_CHECK(words[3].box.width() > 0);
}

////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: cisocrgroup/pocoweb

max_issues_repo_name: cisocrgroup/pocoweb

max_forks_repo_name: cisocrgroup/pocoweb


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

#include <data_tools/std_data.h>

#define BOOST_NO_CXX11_SCOPED_ENUMS
#include <boost/date_time.hpp>
#undef BOOST_NO_CXX11_SCOPED_ENUMS

using namespace std;

namespace std_data {

// instantiate all versions needed to read the structs
template nav_entry::EntriesT read_data<nav_entry::EntriesT>(const boost::filesystem::path& path);
template mbes_ping::PingsT read_data<mbes_ping::PingsT>(const boost::filesystem::path& path);
template sss_ping::PingsT read_data<sss_ping::PingsT>(const boost::filesystem::path& path);
template pt_submaps read_data<pt_submaps>(const boost::filesystem::path& path);

// instantiate all versions needed to write the structs
template void write_data<nav_entry::EntriesT>(nav_entry::EntriesT& data, const boost::filesystem::path& path);
template void write_data<mbes_ping::PingsT>(mbes_ping::PingsT& data, const boost::filesystem::path& path);
template void write_data<sss_ping::PingsT>(sss_ping::PingsT& data, const boost::filesystem::path& path);
template void write_data<pt_submaps>(pt_submaps& data, const boost::filesystem::path& path);

std::string time_string_from_time_stamp(long long time_stamp_)
{
    // TODO: can this be a static variable instead? we could also use that in other libraries
    const boost::posix_time::ptime epoch = boost::posix_time::time_from_string("1970-01-01 00:00:00.000");
    boost::posix_time::ptime t = epoch + boost::posix_time::milliseconds(time_stamp_);
    stringstream time_ss;
    time_ss << t;
    string time_string_ = time_ss.str();
    return time_string_;
}

} // namespace std_data


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  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_SIMD_FUNCTION_CEIL_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_CEIL_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!
  @ingroup group-arithmetic
    Function object implementing ceil capabilities

   Computes the ceil of its parameter.

    @par semantic:
    For any given value @c x of type @c T:

    @code
    T r = ceil(x);
    @endcode

    computes the smallest integral value of type @c T greater or equal to @c x.

    @par Decorators

    std_ for floating entries

    @see  floor, round, round2even, trunc, iceil

  **/
{
} }
#endif

#include <boost/simd/function/scalar/ceil.hpp>
#include <boost/simd/function/simd/ceil.hpp>

#endif


text:
//  To use the simple FFT implementation
//  g++ -o demofft -I.. -Wall -O3 FFT.cpp

//  To use the FFTW implementation
//  g++ -o demofft -I.. -DUSE_FFTW -Wall -O3 FFT.cpp -lfftw3 -lfftw3f -lfftw3l

#ifdef USE_FFTW
#include <fftw3.h>
#endif

#include <vector>
#include <complex>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/FFT>

using namespace std;
using namespace Eigen;

template <typename T>
T mag2(T a)
{
    return a*a;
}
template <typename T>
T mag2(std::complex<T> a)
{
    return norm(a);
}

template <typename T>
T mag2(const std::vector<T> & vec)
{
    T out=0;
    for (size_t k=0;k<vec.size();++k)
        out += mag2(vec[k]);
    return out;
}

template <typename T>
T mag2(const std::vector<std::complex<T> > & vec)
{
    T out=0;
    for (size_t k=0;k<vec.size();++k)
        out += mag2(vec[k]);
    return out;
}

template <typename T>
vector<T> operator-(const vector<T> & a,const vector<T> & b )
{
    vector<T> c(a);
    for (size_t k=0;k<b.size();++k)
        c[k] -= b[k];
    return c;
}

template <typename T>
void RandomFill(std::vector<T> & vec)
{
    for (size_t k=0;k<vec.size();++k)
        vec[k] = T( rand() )/T(RAND_MAX) - .5;
}

template <typename T>
void RandomFill(std::vector<std::complex<T> > & vec)
{
    for (size_t k=0;k<vec.size();++k)
        vec[k] = std::complex<T> ( T( rand() )/T(RAND_MAX) - .5, T( rand() )/T(RAND_MAX) - .5);
}

template <typename T_time,typename T_freq>
void fwd_inv(size_t nfft)
{
    typedef typename NumTraits<T_freq>::Real Scalar;
    vector<T_time> timebuf(nfft);
    RandomFill(timebuf);

    vector<T_freq> freqbuf;
    static FFT<Scalar> fft;
    fft.fwd(freqbuf,timebuf);

    vector<T_time> timebuf2;
    fft.inv(timebuf2,freqbuf);

    long double rmse = mag2(timebuf - timebuf2) / mag2(timebuf);
    cout << "roundtrip rmse: " << rmse << endl;
}

template <typename T_scalar>
void two_demos(int nfft)
{
    cout << "     scalar ";
    fwd_inv<T_scalar,std::complex<T_scalar> >(nfft);
    cout << "    complex ";
    fwd_inv<std::complex<T_scalar>,std::complex<T_scalar> >(nfft);
}

void demo_all_types(int nfft)
{
    cout << "nfft=" << nfft << endl;
    cout << "   float" << endl;
    two_demos<float>(nfft);
    cout << "   double" << endl;
    two_demos<double>(nfft);
    cout << "   long double" << endl;
    two_demos<long double>(nfft);
}

int main()
{
    demo_all_types( 2*3*4*5*7 );
    demo_all_types( 2*9*16*25 );
    demo_all_types( 1024 );
    return 0;
}


text:
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
// Copyright (c) 2015-2018 The Blocknet developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "servicenodeman.h"
#include "activeservicenode.h"
#include "addrman.h"
#include "servicenode.h"
#include "obfuscation.h"
#include "spork.h"
#include "util.h"
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>

/** Servicenode manager */
CServicenodeMan mnodeman;

struct CompareLastPaid {
    bool operator()(const pair<int64_t, CTxIn>& t1,
        const pair<int64_t, CTxIn>& t2) const
    {
        return t1.first < t2.first;
    }
};

struct CompareScoreTxIn {
    bool operator()(const pair<int64_t, CTxIn>& t1,
        const pair<int64_t, CTxIn>& t2) const
    {
        return t1.first < t2.first;
    }
};

struct CompareScoreMN {
    bool operator()(const pair<int64_t, CServicenode>& t1,
        const pair<int64_t, CServicenode>& t2) const
    {
        return t1.first < t2.first;
    }
};

//
// CServicenodeDB
//

CServicenodeDB::CServicenodeDB()
{
    pathMN = GetDataDir() / "mncache.dat";
    strMagicMessage = "ServicenodeCache";
}

bool CServicenodeDB::Write(const CServicenodeMan& mnodemanToSave)
{
    int64_t nStart = GetTimeMillis();

    // serialize, checksum data up to that point, then append checksum
    CDataStream ssServicenodes(SER_DISK, CLIENT_VERSION);
    ssServicenodes << strMagicMessage;                   // servicenode cache file specific magic message
    ssServicenodes << FLATDATA(Params().MessageStart()); // network specific magic number
    ssServicenodes << mnodemanToSave;
    uint256 hash = Hash(ssServicenodes.begin(), ssServicenodes.end());
    ssServicenodes << hash;

    // open output file, and associate with CAutoFile
    FILE* file = fopen(pathMN.string().c_str(), "wb");
    CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
    if (fileout.IsNull())
        return error("%s : Failed to open file %s", __func__, pathMN.string());

    // Write and commit header, data
    try {
        fileout << ssServicenodes;
    } catch (std::exception& e) {
        return error("%s : Serialize or I/O error - %s", __func__, e.what());
    }
    //    FileCommit(fileout);
    fileout.fclose();

    LogPrintf("Written info to mncache.dat  %dms\n", GetTimeMillis() - nStart);
    LogPrintf("  %s\n", mnodemanToSave.ToString());

    return true;
}

CServicenodeDB::ReadResult CServicenodeDB::Read(CServicenodeMan& mnodemanToLoad, bool fDryRun)
{
    int64_t nStart = GetTimeMillis();
    // open input file, and associate with CAutoFile
    FILE* file = fopen(pathMN.string().c_str(), "rb");
    CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
    if (filein.IsNull()) {
        error("%s : Failed to open file %s", __func__, pathMN.string());
        return FileError;
    }

    // use file size to size memory buffer
    int fileSize = boost::filesystem::file_size(pathMN);
    int dataSize = fileSize - sizeof(uint256);
    // Don't try to resize to a negative number if file is small
    if (dataSize < 0)
        dataSize = 0;
    vector<unsigned char> vchData;
    vchData.resize(dataSize);
    uint256 hashIn;

    // read data and checksum from file
    try {
        filein.read((char*)&vchData[0], dataSize);
        filein >> hashIn;
    } catch (std::exception& e) {
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return HashReadError;
    }
    filein.fclose();

    CDataStream ssServicenodes(vchData, SER_DISK, CLIENT_VERSION);

    // verify stored checksum matches input data
    uint256 hashTmp = Hash(ssServicenodes.begin(), ssServicenodes.end());
    if (hashIn != hashTmp) {
        error("%s : Checksum mismatch, data corrupted", __func__);
        return IncorrectHash;
    }

    unsigned char pchMsgTmp[4];
    std::string strMagicMessageTmp;
    try {
        // de-serialize file header (servicenode cache file specific magic message) and ..

        ssServicenodes >> strMagicMessageTmp;

        // ... verify the message matches predefined one
        if (strMagicMessage != strMagicMessageTmp) {
            error("%s : Invalid servicenode cache magic message", __func__);
            return IncorrectMagicMessage;
        }

        // de-serialize file header (network specific magic number) and ..
        ssServicenodes >> FLATDATA(pchMsgTmp);

        // ... verify the network matches ours
        if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
            error("%s : Invalid network magic number", __func__);
            return IncorrectMagicNumber;
        }
        // de-serialize data into CServicenodeMan object
        ssServicenodes >> mnodemanToLoad;
    } catch (std::exception& e) {
        mnodemanToLoad.Clear();
        error("%s : Deserialize or I/O error - %s", __func__, e.what());
        return IncorrectFormat;
    }

    LogPrintf("Loaded info from mncache.dat  %dms\n", GetTimeMillis() - nStart);
    LogPrintf("  %s\n", mnodemanToLoad.ToString());
    if (!fDryRun) {
        LogPrintf("Servicenode manager - cleaning....\n");
        mnodemanToLoad.CheckAndRemove(true);
        LogPrintf("Servicenode manager - result:\n");
        LogPrintf("  %s\n", mnodemanToLoad.ToString());
    }

    return Ok;
}

void DumpServicenodes()
{
    int64_t nStart = GetTimeMillis();

    CServicenodeDB mndb;
    CServicenodeMan tempMnodeman;

    LogPrintf("Verifying mncache.dat format...\n");
    CServicenodeDB::ReadResult readResult = mndb.Read(tempMnodeman, true);
    // there was an error and it was not an error on file opening => do not proceed
    if (readResult == CServicenodeDB::FileError)
        LogPrintf("Missing servicenode cache file - mncache.dat, will try to recreate\n");
    else if (readResult != CServicenodeDB::Ok) {
        LogPrintf("Error reading mncache.dat: ");
        if (readResult == CServicenodeDB::IncorrectFormat)
            LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
        else {
            LogPrintf("file format is unknown or invalid, please fix it manually\n");
            return;
        }
    }
    LogPrintf("Writting info to mncache.dat...\n");
    mndb.Write(mnodeman);

    LogPrintf("Servicenode dump finished  %dms\n", GetTimeMillis() - nStart);
}

CServicenodeMan::CServicenodeMan()
{
    nDsqCount = 0;
}

bool CServicenodeMan::Add(CServicenode& mn)
{
    LOCK(cs);

    if (!mn.IsEnabled())
        return false;

    CServicenode* pmn = Find(mn.vin);
    if (pmn == NULL) {
        LogPrint("servicenode", "CServicenodeMan: Adding new Servicenode %s - %i now\n", mn.vin.prevout.hash.ToString(), size() + 1);
        vServicenodes.push_back(mn);
        return true;
    }

    return false;
}

void CServicenodeMan::AskForMN(CNode* pnode, CTxIn& vin)
{
    std::map<COutPoint, int64_t>::iterator i = mWeAskedForServicenodeListEntry.find(vin.prevout);
    if (i != mWeAskedForServicenodeListEntry.end()) {
        int64_t t = (*i).second;
        if (GetTime() < t) return; // we've asked recently
    }

    // ask for the mnb info once from the node that sent mnp

    LogPrint("servicenode", "CServicenodeMan::AskForMN - Asking node for missing entry, vin: %s\n", vin.prevout.hash.ToString());
    pnode->PushMessage("dseg", vin);
    int64_t askAgain = GetTime() + SERVICENODE_MIN_MNP_SECONDS;
    mWeAskedForServicenodeListEntry[vin.prevout] = askAgain;
}

void CServicenodeMan::Check()
{
    LOCK(cs);

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        mn.Check();
    }
}

void CServicenodeMan::CheckAndRemove(bool forceExpiredRemoval)
{
    Check();

    LOCK(cs);

    //remove inactive and outdated
    vector<CServicenode>::iterator it = vServicenodes.begin();
    while (it != vServicenodes.end()) {
        if ((*it).activeState == CServicenode::SERVICENODE_REMOVE ||
            (*it).activeState == CServicenode::SERVICENODE_VIN_SPENT ||
            (forceExpiredRemoval && (*it).activeState == CServicenode::SERVICENODE_EXPIRED) ||
            (*it).protocolVersion < servicenodePayments.GetMinServicenodePaymentsProto()) {
            LogPrint("servicenode", "CServicenodeMan: Removing inactive Servicenode %s - %i now\n", (*it).vin.prevout.hash.ToString(), size() - 1);

            //erase all of the broadcasts we've seen from this vin
            // -- if we missed a few pings and the node was removed, this will allow is to get it back without them
            //    sending a brand new mnb
            map<uint256, CServicenodeBroadcast>::iterator it3 = mapSeenServicenodeBroadcast.begin();
            while (it3 != mapSeenServicenodeBroadcast.end()) {
                if ((*it3).second.vin == (*it).vin) {
                    servicenodeSync.mapSeenSyncMNB.erase((*it3).first);
                    mapSeenServicenodeBroadcast.erase(it3++);
                } else {
                    ++it3;
                }
            }

            // allow us to ask for this servicenode again if we see another ping
            map<COutPoint, int64_t>::iterator it2 = mWeAskedForServicenodeListEntry.begin();
            while (it2 != mWeAskedForServicenodeListEntry.end()) {
                if ((*it2).first == (*it).vin.prevout) {
                    mWeAskedForServicenodeListEntry.erase(it2++);
                } else {
                    ++it2;
                }
            }

            it = vServicenodes.erase(it);
        } else {
            ++it;
        }
    }

    // check who's asked for the Servicenode list
    map<CNetAddr, int64_t>::iterator it1 = mAskedUsForServicenodeList.begin();
    while (it1 != mAskedUsForServicenodeList.end()) {
        if ((*it1).second < GetTime()) {
            mAskedUsForServicenodeList.erase(it1++);
        } else {
            ++it1;
        }
    }

    // check who we asked for the Servicenode list
    it1 = mWeAskedForServicenodeList.begin();
    while (it1 != mWeAskedForServicenodeList.end()) {
        if ((*it1).second < GetTime()) {
            mWeAskedForServicenodeList.erase(it1++);
        } else {
            ++it1;
        }
    }

    // check which Servicenodes we've asked for
    map<COutPoint, int64_t>::iterator it2 = mWeAskedForServicenodeListEntry.begin();
    while (it2 != mWeAskedForServicenodeListEntry.end()) {
        if ((*it2).second < GetTime()) {
            mWeAskedForServicenodeListEntry.erase(it2++);
        } else {
            ++it2;
        }
    }

    // remove expired mapSeenServicenodeBroadcast
    map<uint256, CServicenodeBroadcast>::iterator it3 = mapSeenServicenodeBroadcast.begin();
    while (it3 != mapSeenServicenodeBroadcast.end()) {
        if ((*it3).second.lastPing.sigTime < GetTime() - (SERVICENODE_REMOVAL_SECONDS * 2)) {
            mapSeenServicenodeBroadcast.erase(it3++);
            servicenodeSync.mapSeenSyncMNB.erase((*it3).second.GetHash());
        } else {
            ++it3;
        }
    }

    // remove expired mapSeenServicenodePing
    map<uint256, CServicenodePing>::iterator it4 = mapSeenServicenodePing.begin();
    while (it4 != mapSeenServicenodePing.end()) {
        if ((*it4).second.sigTime < GetTime() - (SERVICENODE_REMOVAL_SECONDS * 2)) {
            mapSeenServicenodePing.erase(it4++);
        } else {
            ++it4;
        }
    }
}

void CServicenodeMan::Clear()
{
    LOCK(cs);
    vServicenodes.clear();
    mAskedUsForServicenodeList.clear();
    mWeAskedForServicenodeList.clear();
    mWeAskedForServicenodeListEntry.clear();
    mapSeenServicenodeBroadcast.clear();
    mapSeenServicenodePing.clear();
    nDsqCount = 0;
}

int CServicenodeMan::CountEnabled(int protocolVersion)
{
    int i = 0;
    protocolVersion = protocolVersion == -1 ? servicenodePayments.GetMinServicenodePaymentsProto() : protocolVersion;

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        mn.Check();
        if (mn.protocolVersion < protocolVersion || !mn.IsEnabled()) continue;
        i++;
    }

    return i;
}

void CServicenodeMan::DsegUpdate(CNode* pnode)
{
    LOCK(cs);

    if (Params().NetworkID() == CBaseChainParams::MAIN) {
        if (!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
            std::map<CNetAddr, int64_t>::iterator it = mWeAskedForServicenodeList.find(pnode->addr);
            if (it != mWeAskedForServicenodeList.end()) {
                if (GetTime() < (*it).second) {
                    LogPrint("servicenode", "dseg - we already asked peer %i for the list; skipping...\n", pnode->GetId());
                    return;
                }
            }
        }
    }

    pnode->PushMessage("dseg", CTxIn());
    int64_t askAgain = GetTime() + SERVICENODES_DSEG_SECONDS;
    mWeAskedForServicenodeList[pnode->addr] = askAgain;
}

CServicenode* CServicenodeMan::Find(const CScript& payee)
{
    LOCK(cs);
    CScript payee2;

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        payee2 = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
        if (payee2 == payee)
            return &mn;
    }
    return NULL;
}

CServicenode* CServicenodeMan::Find(const CTxIn& vin)
{
    LOCK(cs);

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (mn.vin.prevout == vin.prevout)
            return &mn;
    }
    return NULL;
}

CServicenode* CServicenodeMan::Find(const CPubKey& pubKeyServicenode)
{
    LOCK(cs);

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (mn.pubKeyServicenode == pubKeyServicenode)
            return &mn;
    }
    return NULL;
}

CServicenode* CServicenodeMan::Find(const std::string & nodeAddr)
{
    LOCK(cs);

    for (CServicenode & mn : vServicenodes) {
        if (mn.addr.ToString() == nodeAddr)
            return &mn;
    }
    return nullptr;
}

//
// Deterministically select the oldest/best servicenode to pay on the network
//
CServicenode* CServicenodeMan::GetNextServicenodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount)
{
    LOCK(cs);

    CServicenode* pBestServicenode = NULL;
    std::vector<pair<int64_t, CTxIn> > vecServicenodeLastPaid;

    /*
        Make a vector with all of the last paid times
    */

    int nMnCount = CountEnabled();
    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (!servicenodePayments.ValidNode(mn, fFilterSigTime, nMnCount))
            continue;

        //it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
        if (servicenodePayments.IsScheduled(mn, nBlockHeight)) continue;

        vecServicenodeLastPaid.push_back(make_pair(mn.SecondsSincePayment(), mn.vin));
    }

    nCount = (int)vecServicenodeLastPaid.size();

    //when the network is in the process of upgrading, don't penalize nodes that recently restarted
    if (fFilterSigTime && nCount < nMnCount / 3) return GetNextServicenodeInQueueForPayment(nBlockHeight, false, nCount);

    // Sort them high to low
    sort(vecServicenodeLastPaid.rbegin(), vecServicenodeLastPaid.rend(), CompareLastPaid());

    // Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
    //  -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
    //  -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
    //  -- (chance per block * chances before IsScheduled will fire)
    int nTenthNetwork = CountEnabled() / 10;
    int nCountTenth = 0;
    uint256 nHigh = 0;
    BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn) & s, vecServicenodeLastPaid) {
        CServicenode* pmn = Find(s.second);
        if (!pmn) break;

        uint256 n = pmn->CalculateScore(1, nBlockHeight - 100);
        if (n > nHigh) {
            nHigh = n;
            pBestServicenode = pmn;
        }
        nCountTenth++;
        if (nCountTenth >= nTenthNetwork) break;
    }
    return pBestServicenode;
}

CServicenode* CServicenodeMan::FindRandomNotInVec(std::vector<CTxIn>& vecToExclude, int protocolVersion)
{
    LOCK(cs);

    protocolVersion = protocolVersion == -1 ? servicenodePayments.GetMinServicenodePaymentsProto() : protocolVersion;

    int nCountEnabled = CountEnabled(protocolVersion);
    LogPrint("servicenode", "CServicenodeMan::FindRandomNotInVec - nCountEnabled - vecToExclude.size() %d\n", nCountEnabled - vecToExclude.size());
    if (nCountEnabled - vecToExclude.size() < 1) return NULL;

    int rand = GetRandInt(nCountEnabled - vecToExclude.size());
    LogPrint("servicenode", "CServicenodeMan::FindRandomNotInVec - rand %d\n", rand);
    bool found;

    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (mn.protocolVersion < protocolVersion || !mn.IsEnabled()) continue;
        found = false;
        BOOST_FOREACH (CTxIn& usedVin, vecToExclude) {
            if (mn.vin.prevout == usedVin.prevout) {
                found = true;
                break;
            }
        }
        if (found) continue;
        if (--rand < 1) {
            return &mn;
        }
    }

    return NULL;
}

CServicenode* CServicenodeMan::GetCurrentServiceNode(int mod, int64_t nBlockHeight, int minProtocol)
{
    int64_t score = 0;
    CServicenode* winner = NULL;

    // scan for winner
    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        mn.Check();
        if (mn.protocolVersion < minProtocol || !mn.IsEnabled()) continue;

        // calculate the score for each Servicenode
        uint256 n = mn.CalculateScore(mod, nBlockHeight);
        int64_t n2 = n.GetCompact(false);

        // determine the winner
        if (n2 > score) {
            score = n2;
            winner = &mn;
        }
    }

    return winner;
}

int CServicenodeMan::GetServicenodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol, bool fOnlyActive)
{
    std::vector<pair<int64_t, CTxIn> > vecServicenodeScores;

    //make sure we know about this block
    uint256 hash = 0;
    if (!GetBlockHash(hash, nBlockHeight)) return -1;

    // scan for winner
    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (mn.protocolVersion < minProtocol) {
            if (fDebug)
                LogPrintf("Skipping Servicenode %s with obsolete version: %d)\n", mn.vin.prevout.hash.ToString(), mn.protocolVersion);
            continue;
        }
        if (fOnlyActive) {
            mn.Check();

            if (mn.GetServicenodeInputAge() < vServicenodes.size())
                continue;

            auto snodeAge = GetAdjustedTime() - mn.sigTime;
            if (snodeAge < SERVICENODE_DELAY_SECONDS) {
                if (fDebug)
                    LogPrintf("Skipping recently activated Servicenode %s with age: %ld\n", mn.vin.prevout.hash.ToString(), snodeAge);
                continue;
            }

            if (!mn.IsEnabled()) continue;
        }
        uint256 n = mn.CalculateScore(1, nBlockHeight);
        int64_t n2 = n.GetCompact(false);

        vecServicenodeScores.push_back(make_pair(n2, mn.vin));
    }

    sort(vecServicenodeScores.rbegin(), vecServicenodeScores.rend(), CompareScoreTxIn());

    int rank = 0;
    BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn) & s, vecServicenodeScores) {
        rank++;
        if (s.second.prevout == vin.prevout) {
            return rank;
        }
    }

    return -1;
}

std::vector<pair<int, CServicenode> > CServicenodeMan::GetServicenodeRanks(int64_t nBlockHeight, int minProtocol)
{
    std::vector<pair<int64_t, CServicenode> > vecServicenodeScores;
    std::vector<pair<int, CServicenode> > vecServicenodeRanks;

    //make sure we know about this block
    uint256 hash = 0;
    if (!GetBlockHash(hash, nBlockHeight)) return vecServicenodeRanks;

    // scan for winner
    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        mn.Check();

        if (mn.protocolVersion < minProtocol) continue;

        if (!mn.IsEnabled()) {
            vecServicenodeScores.push_back(make_pair(9999, mn));
            continue;
        }

        uint256 n = mn.CalculateScore(1, nBlockHeight);
        int64_t n2 = n.GetCompact(false);

        vecServicenodeScores.push_back(make_pair(n2, mn));
    }

    sort(vecServicenodeScores.rbegin(), vecServicenodeScores.rend(), CompareScoreMN());

    int rank = 0;
    BOOST_FOREACH (PAIRTYPE(int64_t, CServicenode) & s, vecServicenodeScores) {
        rank++;
        vecServicenodeRanks.push_back(make_pair(rank, s.second));
    }

    return vecServicenodeRanks;
}

CServicenode* CServicenodeMan::GetServicenodeByRank(int nRank, int64_t nBlockHeight, int minProtocol, bool fOnlyActive)
{
    std::vector<pair<int64_t, CTxIn> > vecServicenodeScores;

    // scan for winner
    BOOST_FOREACH (CServicenode& mn, vServicenodes) {
        if (mn.protocolVersion < minProtocol) continue;
        if (fOnlyActive) {
            mn.Check();
            if (!mn.IsEnabled()) continue;
        }

        uint256 n = mn.CalculateScore(1, nBlockHeight);
        int64_t n2 = n.GetCompact(false);

        vecServicenodeScores.push_back(make_pair(n2, mn.vin));
    }

    sort(vecServicenodeScores.rbegin(), vecServicenodeScores.rend(), CompareScoreTxIn());

    int rank = 0;
    BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn) & s, vecServicenodeScores) {
        rank++;
        if (rank == nRank) {
            return Find(s.second);
        }
    }

    return NULL;
}

void CServicenodeMan::ProcessServicenodeConnections()
{
    //we don't care about this for regtest
    if (Params().NetworkID() == CBaseChainParams::REGTEST) return;

    LOCK(cs_vNodes);
    BOOST_FOREACH (CNode* pnode, vNodes) {
        if (pnode->fObfuScationMaster) {
            if (obfuScationPool.pSubmittedToServicenode != NULL && pnode->addr == obfuScationPool.pSubmittedToServicenode->addr) continue;
            LogPrintf("Closing Servicenode connection peer=%i \n", pnode->GetId());
            pnode->fObfuScationMaster = false;
            pnode->Release();
        }
    }
}

void CServicenodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
    if (fLiteMode) return; //disable all Obfuscation/Servicenode related functionality
    if (!servicenodeSync.IsBlockchainSynced()) return;

    LOCK(cs_process_message);

    if (strCommand == "mnb") { //Servicenode Broadcast
        CServicenodeBroadcast mnb;
        vRecv >> mnb;

        if (mapSeenServicenodeBroadcast.count(mnb.GetHash())) { //seen
            servicenodeSync.AddedServicenodeList(mnb.GetHash());
            return;
        }
        mapSeenServicenodeBroadcast.insert(make_pair(mnb.GetHash(), mnb));

        int nDoS = 0;
        if (!mnb.CheckAndUpdate(nDoS)) {
            if (nDoS > 0)
                Misbehaving(pfrom->GetId(), nDoS);

            //failed
            return;
        }

        // make sure the vout that was signed is related to the transaction that spawned the Servicenode
        //  - this is expensive, so it's only done once per Servicenode
        if (!obfuScationSigner.IsVinAssociatedWithPubkey(mnb.vin, mnb.pubKeyCollateralAddress)) {
            LogPrintf("mnb - Got mismatched pubkey and vin\n");
            Misbehaving(pfrom->GetId(), 33);
            return;
        }

        // make sure it's still unspent
        //  - this is checked later by .check() in many places and by ThreadCheckObfuScationPool()
        if (mnb.CheckInputsAndAdd(nDoS)) {
            // use this as a peer
            addrman.Add(CAddress(mnb.addr), pfrom->addr, 2 * 60 * 60);
            servicenodeSync.AddedServicenodeList(mnb.GetHash());
        } else {
            LogPrintf("mnb - Rejected Servicenode entry %s\n", mnb.vin.prevout.hash.ToString());

            if (nDoS > 0)
                Misbehaving(pfrom->GetId(), nDoS);
        }
    }

    else if (strCommand == "mnp") { //Servicenode Ping
        CServicenodePing mnp;
        vRecv >> mnp;

        LogPrint("servicenode", "mnp - Servicenode ping, vin: %s\n", mnp.vin.prevout.hash.ToString());

        if (mapSeenServicenodePing.count(mnp.GetHash())) return; //seen
        mapSeenServicenodePing.insert(make_pair(mnp.GetHash(), mnp));

        int nDoS = 0;
        if (mnp.CheckAndUpdate(nDoS)) return;

        if (nDoS > 0) {
            // if anything significant failed, mark that node
            Misbehaving(pfrom->GetId(), nDoS);
        } else {
            // if nothing significant failed, search existing Servicenode list
            CServicenode* pmn = Find(mnp.vin);
            // if it's known, don't ask for the mnb, just return
            if (pmn != NULL) return;
        }

        // something significant is broken or mn is unknown,
        // we might have to ask for a servicenode entry once
        AskForMN(pfrom, mnp.vin);

    } else if (strCommand == "dseg") { //Get Servicenode list or specific entry

        CTxIn vin;
        vRecv >> vin;

        if (vin == CTxIn()) { //only should ask for this once
            //local network
            bool isLocal = (pfrom->addr.IsRFC1918() || pfrom->addr.IsLocal());

            if (!isLocal && Params().NetworkID() == CBaseChainParams::MAIN) {
                std::map<CNetAddr, int64_t>::iterator i = mAskedUsForServicenodeList.find(pfrom->addr);
                if (i != mAskedUsForServicenodeList.end()) {
                    int64_t t = (*i).second;
                    if (GetTime() < t) {
                        Misbehaving(pfrom->GetId(), 34);
                        LogPrintf("dseg - peer already asked me for the list\n");
                        return;
                    }
                }
                int64_t askAgain = GetTime() + SERVICENODES_DSEG_SECONDS;
                mAskedUsForServicenodeList[pfrom->addr] = askAgain;
            }
        } //else, asking for a specific node which is ok

        int nInvCount = 0;

        BOOST_FOREACH (CServicenode& mn, vServicenodes) {
            if (mn.addr.IsRFC1918()) continue; //local network

            if (mn.IsEnabled()) {
                LogPrint("servicenode", "dseg - Sending Servicenode entry - %s \n", mn.vin.prevout.hash.ToString());
                if (vin == CTxIn() || vin == mn.vin) {
                    CServicenodeBroadcast mnb = CServicenodeBroadcast(mn);
                    uint256 hash = mnb.GetHash();
                    pfrom->PushInventory(CInv(MSG_SERVICENODE_ANNOUNCE, hash));
                    nInvCount++;

                    if (!mapSeenServicenodeBroadcast.count(hash)) mapSeenServicenodeBroadcast.insert(make_pair(hash, mnb));

                    if (vin == mn.vin) {
                        LogPrint("servicenode", "dseg - Sent 1 Servicenode entry to peer %i\n", pfrom->GetId());
                        return;
                    }
                }
            }
        }

        if (vin == CTxIn()) {
            pfrom->PushMessage("ssc", SERVICENODE_SYNC_LIST, nInvCount);
            LogPrint("servicenode", "dseg - Sent %d Servicenode entries to peer %i\n", nInvCount, pfrom->GetId());
        }
    }
}

void CServicenodeMan::Remove(CTxIn vin)
{
    LOCK(cs);

    vector<CServicenode>::iterator it = vServicenodes.begin();
    while (it != vServicenodes.end()) {
        if ((*it).vin == vin) {
            LogPrint("servicenode", "CServicenodeMan: Removing Servicenode %s - %i now\n", (*it).vin.prevout.hash.ToString(), size() - 1);
            vServicenodes.erase(it);
            break;
        }
        ++it;
    }
}

void CServicenodeMan::UpdateServicenodeList(CServicenodeBroadcast mnb)
{
    LOCK(cs);
    mapSeenServicenodePing.insert(std::make_pair(mnb.lastPing.GetHash(), mnb.lastPing));
    mapSeenServicenodeBroadcast.insert(std::make_pair(mnb.GetHash(), mnb));

    LogPrintf("CServicenodeMan::UpdateServicenodeList -- servicenode=%s\n", mnb.vin.prevout.ToStringShort());

    CServicenode* pmn = Find(mnb.vin);
    if (pmn == NULL) {
        CServicenode mn(mnb);
        if (Add(mn)) {
            servicenodeSync.AddedServicenodeList(mnb.GetHash());
        }
    } else if (pmn->UpdateFromNewBroadcast(mnb)) {
        servicenodeSync.AddedServicenodeList(mnb.GetHash());
    }
}

std::string CServicenodeMan::ToString() const
{
    std::ostringstream info;

    info << "Servicenodes: " << (int)vServicenodes.size() << ", peers who asked us for Servicenode list: " << (int)mAskedUsForServicenodeList.size() << ", peers we asked for Servicenode list: " << (int)mWeAskedForServicenodeList.size() << ", entries in Servicenode list we asked for: " << (int)mWeAskedForServicenodeListEntry.size() << ", nDsqCount: " << (int)nDsqCount;

    return info.str();
}


text:
#include <NTL/LLL.h>

#include <NTL/new.h>

NTL_START_IMPL

static void ExactDiv(ZZ& qq, const ZZ& a, const ZZ& b)
{
   NTL_ZZRegister(q);
   NTL_ZZRegister(r);

   DivRem(q, r, a, b);
   if (!IsZero(r)) {
      cerr << "a = " << a << "\n";
      cerr << "b = " << b << "\n";
      LogicError("ExactDiv: nonzero remainder");
   }
   qq = q;
}

static void BalDiv(ZZ& q, const ZZ& a, const ZZ& d)

//  rounds a/d to nearest integer, breaking ties
//    by rounding towards zero.  Assumes d > 0.

{
   NTL_ZZRegister(r);
   DivRem(q, r, a, d);

   add(r, r, r);

   long cmp = compare(r, d);
   if (cmp > 0 || (cmp == 0 && q < 0))
      add(q, q, 1);
}

static void MulAddDiv(ZZ& c, const ZZ& c1, const ZZ& c2,
                      const ZZ& x, const ZZ& y, const ZZ& z)

// c = (x*c1 + y*c2)/z

{
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);

   mul(t1, x, c1);
   mul(t2, y, c2);
   add(t1, t1, t2);
   ExactDiv(c, t1, z);
}

static void MulSubDiv(ZZ& c, const ZZ& c1, const ZZ& c2,
                      const ZZ& x, const ZZ& y, const ZZ& z)

// c = (x*c1 - y*c2)/z

{
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);

   mul(t1, x, c1);
   mul(t2, y, c2);
   sub(t1, t1, t2);
   ExactDiv(c, t1, z);
}

#if 0

static void MulSubDiv(vec_ZZ& c, const vec_ZZ& c1, const vec_ZZ& c2,
                      const ZZ& x, const ZZ& y, const ZZ& z)

// c = (x*c1 + y*c2)/z

{
   long n = c1.length();
   if (c2.length() != n) LogicError("MulSubDiv: length mismatch");
   c.SetLength(n);

   long i;
   for (i = 1; i <= n; i++)
      MulSubDiv(c(i), c1(i), c2(i), x, y, z);
}

#endif

static void RowTransform(vec_ZZ& c1, vec_ZZ& c2,
                         const ZZ& x, const ZZ& y, const ZZ& u, const ZZ& v)

// (c1, c2) = (x*c1 + y*c2, u*c1 + v*c2)

{
   long n = c1.length();
   if (c2.length() != n) LogicError("MulSubDiv: length mismatch");
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);
   NTL_ZZRegister(t3);
   NTL_ZZRegister(t4);

   long i;
   for (i = 1; i <= n; i++) {
      mul(t1, x, c1(i));
      mul(t2, y, c2(i));
      add(t1, t1, t2);

      mul(t3, u, c1(i));
      mul(t4, v, c2(i));
      add(t3, t3, t4);

      c1(i) = t1;
      c2(i) = t3;
   }
}

static void RowTransform(ZZ& c1, ZZ& c2,
                         const ZZ& x, const ZZ& y, const ZZ& u, const ZZ& v)

// (c1, c2) = (x*c1 + y*c2, u*c1 + v*c2)

{
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);
   NTL_ZZRegister(t3);
   NTL_ZZRegister(t4);

   mul(t1, x, c1);
   mul(t2, y, c2);
   add(t1, t1, t2);

   mul(t3, u, c1);
   mul(t4, v, c2);
   add(t3, t3, t4);

   c1 = t1;
   c2 = t3;
}

static void MulSubFrom(vec_ZZ& c, const vec_ZZ& c2, const ZZ& x)

// c = c - x*c2

{
   long n = c.length();
   if (c2.length() != n) LogicError("MulSubFrom: length mismatch");

   long i;
   for (i = 1; i <= n; i++)
      MulSubFrom(c(i), c2(i), x);
}

static void MulSubFrom(vec_ZZ& c, const vec_ZZ& c2, long x)

// c = c - x*c2

{
   long n = c.length();
   if (c2.length() != n) LogicError("MulSubFrom: length mismatch");

   long i;
   for (i = 1; i <= n; i++)
      MulSubFrom(c(i), c2(i), x);
}

static long SwapTest(const ZZ& d0, const ZZ& d1, const ZZ& d2, const ZZ& lam,
                     long a, long b)

// test if a*d1^2 > b*(d0*d2 + lam^2)

{
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);

   mul(t1, d0, d2);
   sqr(t2, lam);
   add(t1, t1, t2);
   mul(t1, t1, b);

   sqr(t2, d1);
   mul(t2, t2, a);

   return t2 > t1;
}

static
void reduce(long k, long l,
            mat_ZZ& B, vec_long& P, vec_ZZ& D,
            vec_vec_ZZ& lam, mat_ZZ* U)
{
   NTL_ZZRegister(t1);
   NTL_ZZRegister(r);

   if (P(l) == 0) return;
   add(t1, lam(k)(P(l)), lam(k)(P(l)));
   abs(t1, t1);
   if (t1 <= D[P(l)]) return;

   long j;
   long rr, small_r;

   BalDiv(r, lam(k)(P(l)), D[P(l)]);

   if (r.WideSinglePrecision()) {
      small_r = 1;
      rr = to_long(r);
   }
   else {
      small_r = 0;
   }

   if (small_r) {
      MulSubFrom(B(k), B(l), rr);

      if (U) MulSubFrom((*U)(k), (*U)(l), rr);

      for (j = 1; j <= l-1; j++)
         if (P(j) != 0)
            MulSubFrom(lam(k)(P(j)), lam(l)(P(j)), rr);
      MulSubFrom(lam(k)(P(l)), D[P(l)], rr);
   }
   else {
      MulSubFrom(B(k), B(l), r);

      if (U) MulSubFrom((*U)(k), (*U)(l), r);

      for (j = 1; j <= l-1; j++)
         if (P(j) != 0)
            MulSubFrom(lam(k)(P(j)), lam(l)(P(j)), r);
      MulSubFrom(lam(k)(P(l)), D[P(l)], r);
   }

}

static
long swap(long k, mat_ZZ& B, vec_long& P, vec_ZZ& D,
          vec_vec_ZZ& lam, mat_ZZ* U, long m, long verbose)

// swaps vectors k-1 and k;  assumes P(k-1) != 0
// returns 1 if vector k-1 need to be reduced after the swap...
//    this only occurs in 'case 2' when there are linear dependencies

{
   long i, j;
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);
   NTL_ZZRegister(t3);
   NTL_ZZRegister(e);
   NTL_ZZRegister(x);
   NTL_ZZRegister(y);

   if (P(k) != 0) {
      if (verbose) cerr << "swap case 1: " << k << "\n";

      swap(B(k-1), B(k));
      if (U) swap((*U)(k-1), (*U)(k));

      for (j = 1; j <= k-2; j++)
         if (P(j) != 0)
            swap(lam(k-1)(P(j)), lam(k)(P(j)));

      for (i = k+1; i <= m; i++) {
         MulAddDiv(t1, lam(i)(P(k)-1), lam(i)(P(k)),
                   lam(k)(P(k)-1), D[P(k)-2], D[P(k)-1]);
         MulSubDiv(t2, lam(i)(P(k)-1), lam(i)(P(k)),
                   D[P(k)], lam(k)(P(k)-1), D[P(k)-1]);
         lam(i)(P(k)-1) = t1;
         lam(i)(P(k)) = t2;
      }

      MulAddDiv(D[P(k)-1], D[P(k)], lam(k)(P(k)-1),
                D[P(k)-2], lam(k)(P(k)-1), D[P(k)-1]);

      return 0;
   }
   else if (!IsZero(lam(k)(P(k-1)))) {
      if (verbose) cerr << "swap case 2: " << k << "\n";
      XGCD(e, x, y, lam(k)(P(k-1)), D[P(k-1)]);

      ExactDiv(t1, lam(k)(P(k-1)), e);
      ExactDiv(t2, D[P(k-1)], e);

      t3 = t2;
      negate(t2, t2);
      RowTransform(B(k-1), B(k), t1, t2, y, x);
      if (U) RowTransform((*U)(k-1), (*U)(k), t1, t2, y, x);
      for (j = 1; j <= k-2; j++)
         if (P(j) != 0)
            RowTransform(lam(k-1)(P(j)), lam(k)(P(j)), t1, t2, y, x);

      sqr(t2, t2);
      ExactDiv(D[P(k-1)], D[P(k-1)], t2);

      for (i = k+1; i <= m; i++)
         if (P(i) != 0) {
            ExactDiv(D[P(i)], D[P(i)], t2);
            for (j = i+1; j <= m; j++) {
               ExactDiv(lam(j)(P(i)), lam(j)(P(i)), t2);
            }
         }

      for (i = k+1; i <= m; i++) {
         ExactDiv(lam(i)(P(k-1)), lam(i)(P(k-1)), t3);
      }

      swap(P(k-1), P(k));

      return 1;
   }
   else {
      if (verbose) cerr << "swap case 3: " << k << "\n";

      swap(B(k-1), B(k));
      if (U) swap((*U)(k-1), (*U)(k));

      for (j = 1; j <= k-2; j++)
         if (P(j) != 0)
            swap(lam(k-1)(P(j)), lam(k)(P(j)));

      swap(P(k-1), P(k));

      return 0;
   }
}

static
void IncrementalGS(mat_ZZ& B, vec_long& P, vec_ZZ& D, vec_vec_ZZ& lam,
                   long& s, long k)
{
   long n = B.NumCols();
   long m = B.NumRows();

   NTL_ZZRegister(u);
   NTL_ZZRegister(t1);
   NTL_ZZRegister(t2);

   long i, j;

   for (j = 1; j <= k-1; j++) {
      long posj = P(j);
      if (posj == 0) continue;

      InnerProduct(u, B(k), B(j));
      for (i = 1; i <= posj-1; i++) {
         mul(t1, D[i], u);
         mul(t2, lam(k)(i), lam(j)(i));
         sub(t1, t1, t2);
         div(t1, t1, D[i-1]);
         u = t1;
      }

      lam(k)(posj) = u;
   }

   InnerProduct(u, B(k), B(k));
   for (i = 1; i <= s; i++) {
      mul(t1, D[i], u);
      mul(t2, lam(k)(i), lam(k)(i));
      sub(t1, t1, t2);
      div(t1, t1, D[i-1]);
      u = t1;
   }

   if (u == 0) {
      P(k) = 0;
   }
   else {
      s++;
      P(k) = s;
      D[s] = u;
   }
}

static
long LLL(vec_ZZ& D, mat_ZZ& B, mat_ZZ* U, long a, long b, long verbose)
{
   long m = B.NumRows();
   long n = B.NumCols();

   long force_reduce = 1;

   vec_long P;
   P.SetLength(m);

   D.SetLength(m+1);
   D[0] = 1;

   vec_vec_ZZ lam;

   lam.SetLength(m);

   long j;
   for (j = 1; j <= m; j++)
      lam(j).SetLength(m);

   if (U) ident(*U, m);

   long s = 0;

   long k = 1;
   long max_k = 0;

   while (k <= m) {
      if (k > max_k) {
         IncrementalGS(B, P, D, lam, s, k);
         max_k = k;
      }

      if (k == 1) {
         force_reduce = 1;
         k++;
         continue;
      }

      if (force_reduce)
         for (j = k-1; j >= 1; j--)
            reduce(k, j, B, P, D, lam, U);

      if (P(k-1) != 0 &&
          (P(k) == 0 ||
           SwapTest(D[P(k)], D[P(k)-1], D[P(k)-2], lam(k)(P(k)-1), a, b))) {
         force_reduce = swap(k, B, P, D, lam, U, max_k, verbose);
         k--;
      }
      else {
         force_reduce = 1;
         k++;
      }
   }

   D.SetLength(s+1);
   return s;
}

static
long image(ZZ& det, mat_ZZ& B, mat_ZZ* U, long verbose)
{
   long m = B.NumRows();
   long n = B.NumCols();

   long force_reduce = 1;

   vec_long P;
   P.SetLength(m);

   vec_ZZ D;
   D.SetLength(m+1);
   D[0] = 1;

   vec_vec_ZZ lam;

   lam.SetLength(m);

   long j;
   for (j = 1; j <= m; j++)
      lam(j).SetLength(m);

   if (U) ident(*U, m);

   long s = 0;

   long k = 1;
   long max_k = 0;

   while (k <= m) {
      if (k > max_k) {
         IncrementalGS(B, P, D, lam, s, k);
         max_k = k;
      }

      if (k == 1) {
         force_reduce = 1;
         k++;
         continue;
      }

      if (force_reduce)
         for (j = k-1; j >= 1; j--)
            reduce(k, j, B, P, D, lam, U);

      if (P(k-1) != 0 && P(k) == 0) {
         force_reduce = swap(k, B, P, D, lam, U, max_k, verbose);
         k--;
      }
      else {
         force_reduce = 1;
         k++;
      }
   }

   det = D[s];
   return s;
}

long LLL(ZZ& det, mat_ZZ& B, mat_ZZ& U, long verbose)
{
   vec_ZZ D;
   long s;
   s = LLL(D, B, &U, 3, 4, verbose);
   det = D[s];
   return s;
}

long LLL(ZZ& det, mat_ZZ& B, long verbose)
{
   vec_ZZ D;
   long s;
   s = LLL(D, B, 0, 3, 4, verbose);
   det = D[s];
   return s;
}

long LLL(ZZ& det, mat_ZZ& B, mat_ZZ& U, long a, long b, long verbose)
{
   if (a <= 0 || b <= 0 || a > b || b/4 >= a) LogicError("LLL: bad args");

   vec_ZZ D;
   long s;
   s = LLL(D, B, &U, a, b, verbose);
   det = D[s];
   return s;
}

long LLL(ZZ& det, mat_ZZ& B, long a, long b, long verbose)
{
   if (a <= 0 || b <= 0 || a > b || b/4 >= a) LogicError("LLL: bad args");

   vec_ZZ D;
   long s;
   s = LLL(D, B, 0, a, b, verbose);
   det = D[s];
   return s;
}

long LLL_plus(vec_ZZ& D_out, mat_ZZ& B, mat_ZZ& U, long verbose)
{
   vec_ZZ D;
   long s;
   s = LLL(D, B, &U, 3, 4, verbose);
   D_out = D;
   return s;
}

long LLL_plus(vec_ZZ& D_out, mat_ZZ& B, long verbose)
{
   vec_ZZ D;
   long s;
   s = LLL(D, B, 0, 3, 4, verbose);
   D_out = D;
   return s;
}

long LLL_plus(vec_ZZ& D_out, mat_ZZ& B, mat_ZZ& U, long a, long b, long verbose)
{
   if (a <= 0 || b <= 0 || a > b || b/4 >= a) LogicError("LLL_plus: bad args");

   vec_ZZ D;
   long s;
   s = LLL(D, B, &U, a, b, verbose);
   D_out = D;
   return s;
}

long LLL_plus(vec_ZZ& D_out, mat_ZZ& B, long a, long b, long verbose)
{
   if (a <= 0 || b <= 0 || a > b || b/4 >= a) LogicError("LLL_plus: bad args");

   vec_ZZ D;
   long s;
   s = LLL(D, B, 0, a, b, verbose);
   D_out = D;
   return s;
}

long image(ZZ& det, mat_ZZ& B, mat_ZZ& U, long verbose)
{
   return image(det, B, &U, verbose);
}

long image(ZZ& det, mat_ZZ& B, long verbose)
{
   return image(det, B, 0, verbose);
}

long LatticeSolve(vec_ZZ& x, const mat_ZZ& A, const vec_ZZ& y, long reduce)
{
   long n = A.NumRows();
   long m = A.NumCols();

   if (y.length() != m)
      LogicError("LatticeSolve: dimension mismatch");

   if (reduce < 0 || reduce > 2)
      LogicError("LatticeSolve: bad reduce parameter");

   if (IsZero(y)) {
      x.SetLength(n);
      clear(x);
      return 1;
   }

   mat_ZZ A1, U1;
   ZZ det2;
   long im_rank, ker_rank;

   A1 = A;

   im_rank = image(det2, A1, U1);
   ker_rank = n - im_rank;

   mat_ZZ A2, U2;
   long new_rank;
   long i;

   A2.SetDims(im_rank + 1, m);
   for (i = 1; i <= im_rank; i++)
      A2(i) = A1(ker_rank + i);

   A2(im_rank + 1) = y;

   new_rank = image(det2, A2, U2);

   if (new_rank != im_rank ||
      (U2(1)(im_rank+1) != 1  && U2(1)(im_rank+1) != -1))
      return 0;

   vec_ZZ x1;
   x1.SetLength(im_rank);

   for (i = 1; i <= im_rank; i++)
      x1(i) = U2(1)(i);

   if (U2(1)(im_rank+1) == 1)
      negate(x1, x1);

   vec_ZZ x2, tmp;
   x2.SetLength(n);
   clear(x2);
   tmp.SetLength(n);

   for (i = 1; i <= im_rank; i++) {
      mul(tmp, U1(ker_rank+i), x1(i));
      add(x2, x2, tmp);
   }

   if (reduce == 0) {
      x = x2;
      return 1;
   }
   else if (reduce == 1) {
      U1.SetDims(ker_rank+1, n);
      U1(ker_rank+1) = x2;
      image(det2, U1);

      x = U1(ker_rank + 1);
      return 1;
   }
   else if (reduce == 2) {
      U1.SetDims(ker_rank, n);
      LLL(det2, U1);
      U1.SetDims(ker_rank+1, n);
      U1(ker_rank+1) = x2;
      image(det2, U1);

      x = U1(ker_rank + 1);
      return 1;
   }

   return 0;
}

NTL_END_IMPL

max_stars_repo_name: Brainloop-Security/secret-sharing

max_issues_repo_name: Brainloop-Security/secret-sharing

max_forks_repo_name: Brainloop-Security/secret-sharing