text:
#ifndef BOOST_SERIALIZATION_TEST_TOOLS_HPP
#define BOOST_SERIALIZATION_TEST_TOOLS_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif

#define BOOST_FILESYSTEM_VERSION 3
#include <boost/filesystem/operations.hpp> // unique_path

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_tools.hpp
//
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to 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 for updates, documentation, and revision history.

#include <boost/config.hpp>
#ifndef BOOST_NO_EXCEPTION_STD_NAMESPACE
    #include <exception>
#endif
#include <boost/detail/no_exceptions_support.hpp>

#if defined(UNDER_CE)

// Windows CE does not supply the tmpnam function in its CRT.
// Substitute a primitive implementation here.
namespace boost {
namespace archive {
    const char * tmpnam(char * buffer){
        static char ibuffer [512];
        if(NULL == buffer)
            buffer = ibuffer;

        static unsigned short index = 0;
        std::sprintf(buffer, "\\tmpfile%05X.tmp", index++);
        return buffer;
    }
} // archive
} // boost

#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// win32 has a brain-dead tmpnam implementation.
// which leaves temp files in root directory
// regardless of environmental settings

#include <cstdlib>
#include <cstring>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
    using ::remove;
    using ::strcpy;
    using ::strcat;
    using ::tmpnam;
}
#endif // defined(BOOST_NO_STDC_NAMESPACE)

#include <direct.h>
#include <boost/archive/tmpdir.hpp>

//#if defined(__COMO__)
    #define chdir _chdir
//#endif  // defined win32

#if defined(NDEBUG) && defined(__BORLANDC__)
    #define STRCPY strcpy
#else
    #define STRCPY std::strcpy
#endif

namespace boost {
namespace archive {
    const char * test_filename(const char * dir = NULL, char *fname = NULL){
        static char ibuffer [512];
        ibuffer[0] = '\0';
        if(NULL == dir){
            dir = boost::archive::tmpdir();
        }
        STRCPY(ibuffer, dir);
        std::strcat(ibuffer, "/");
        if(NULL == fname){
            char old_dir[256];
            _getcwd(old_dir, sizeof(old_dir) - 1);
            chdir(dir);
            // (C) Copyright 2010 Dean Michael Berris. <mikhailberis@gmail.com>
            // Instead of using std::tmpnam, we use Boost.Filesystem's unique_path
            boost::filesystem::path tmp_path =
                boost::filesystem::unique_path("%%%%%");
            std::strcat(ibuffer, tmp_path.string().c_str());
            chdir(old_dir);
        }
        else{
            std::strcat(ibuffer, fname);
        }
        return ibuffer;
    }
    const char * tmpnam(char * buffer){
        const char * name = test_filename(NULL, NULL);
        if(NULL != buffer){
            STRCPY(buffer, name);
        }
        return name;
    }
} // archive
} // boost

#else // defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#if defined(__hpux)
// (C) Copyright 2006 Boris Gubenko.
// HP-UX has a restriction that for multi-thread applications, (i.e.
// the ones compiled -mt) if argument to tmpnam is a NULL pointer, then,
// citing the tmpnam(3S) manpage, "the operation is not performed and a
// NULL pointer is returned". tempnam does not have this restriction, so,
// let's use tempnam instead.

#define tmpnam(X) tempnam(NULL,X)

namespace boost {
namespace archive {
    using ::tmpnam;
} // archive
} // boost

#else // defined(__hpux)

// (C) Copyright 2010 Dean Michael Berris.
// Instead of using the potentially dangrous tempnam function that's part
// of the C standard library, on Unix/Linux we use the more portable and
// "safe" unique_path function provided in the Boost.Filesystem library.

#include <boost/archive/tmpdir.hpp>

namespace boost {
namespace archive {
    char const * tmpnam(char * buffer) {
        static char name[512] = {0};
        if (name[0] == 0) {
            boost::filesystem::path tempdir(tmpdir());
            boost::filesystem::path tempfilename =
                boost::filesystem::unique_path("serialization-%%%%");
            boost::filesystem::path temp = tempdir / tempfilename;
            std::strcat(name, temp.string().c_str());
        }
        if (buffer != 0) std::strcpy(buffer, name);
        return name;
    }
} // archive
} // boost

#endif // defined(__hpux)
#endif // defined(_WIN32) || defined(__WIN32__) || defined(WIN32)

#include <boost/core/lightweight_test.hpp>

#define BOOST_CHECK( P ) \
    BOOST_TEST( (P) )
#define BOOST_REQUIRE( P )  \
    BOOST_TEST( (P) )
#define BOOST_CHECK_MESSAGE( P, M )  \
    ((P)? (void)0 : ::boost::detail::error_impl( (M) , __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
#define BOOST_REQUIRE_MESSAGE( P, M ) \
    BOOST_CHECK_MESSAGE( (P), (M) )
#define BOOST_CHECK_EQUAL( A , B ) \
    BOOST_TEST( (A) == (B) )

namespace boost { namespace detail {
inline void msg_impl(char const * msg, char const * file, int line, char const * function)
{
    std::cerr << file << "(" << line << "): " << msg << " in function '" << function << "'" << std::endl;
}
} } // boost::detail

#define BOOST_WARN_MESSAGE( P, M )  \
    ((P)? (void)0 : ::boost::detail::msg_impl( (M) , __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
#define BOOST_MESSAGE( M ) \
    BOOST_WARN_MESSAGE( true , (M) )

#define BOOST_CHECKPOINT( M ) \
    BOOST_WARN_MESSAGE( true , (M) )

//#define BOOST_TEST_DONT_PRINT_LOG_VALUE( T )

#define BOOST_FAIL( M ) BOOST_REQUIRE_MESSAGE( false, (M) )
#define EXIT_SUCCESS 0

int test_main(int argc, char * argv[]);

#include <boost/serialization/singleton.hpp>

int
main(int argc, char * argv[]){
    boost::serialization::singleton_module::lock();

    int retval = 1;
    BOOST_TRY{
        retval = test_main(argc, argv);
    }
    #ifndef BOOST_NO_EXCEPTION_STD_NAMESPACE
        BOOST_CATCH(const std::exception & e){
            BOOST_ERROR(e.what());
        }
    #endif
    BOOST_CATCH(...){
        BOOST_ERROR("failed with uncaught exception:");
    }
    BOOST_CATCH_END

    boost::serialization::singleton_module::unlock();

    int error_count = boost::report_errors();
    if(error_count > 0)
        retval = error_count;
    return retval;
}

// the following is to ensure that when one of the libraries changes
// BJAM rebuilds and relinks the test.
/*
#include "text_archive.hpp"
#include "text_warchive.hpp"
#include "binary_archive.hpp"
#include "xml_archive.hpp"
#include "xml_warchive.hpp"
*/

/////////////////////////////////////////////
// invoke header for a custom archive test.

/////////////////////////////////////////////
// invoke header for a custom archive test.
#if ! defined(BOOST_ARCHIVE_TEST)
#define BOOST_ARCHIVE_TEST text_archive.hpp
#endif

#include <boost/preprocessor/stringize.hpp>
#include BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST)

#ifndef TEST_STREAM_FLAGS
    #define TEST_STREAM_FLAGS (std::ios_base::openmode)0
#endif

#ifndef TEST_ARCHIVE_FLAGS
    #define TEST_ARCHIVE_FLAGS 0
#endif

#ifndef TEST_DIRECTORY
#define TEST_DIRECTORY
#else
#define __x__ TEST_DIRECTORY
#undef TEST_DIRECTORY
#define TEST_DIRECTORY BOOST_PP_STRINGIZE(__x__)
#endif

#endif // BOOST_SERIALIZATION_TEST_TOOLS_HPP


text:
#define BOOST_TEST_DYN_LINK
#include <canard/net/ofp/v13/utility/oxm_match_field_set.hpp>
#include <boost/test/unit_test.hpp>

#include "../../test_utility.hpp"

namespace ofp = canard::net::ofp;
namespace v13 = ofp::v13;
namespace match = v13::oxm_match_fields;

namespace {
  namespace proto = v13::protocol;
  using list_type = v13::oxm_match_field_set::list_type;

  struct parameters
  {
    match::in_port in_port{proto::OFPP_MAX}; // 8
    match::eth_dst eth_dst{"\x01\x02\x03\x04\x05\x06"_mac}; // 10
    match::eth_src eth_src{"\x01\x02\x03\x04\x05\x06"_mac}; // 10
    match::eth_type eth_type{0x0800}; // 6
    match::vlan_vid vlan_vid{proto::OFPVID_PRESENT, proto::OFPVID_PRESENT}; // 8
    match::vlan_pcp vlan_pcp{1};
    match::ip_proto ip_proto{6}; // 5
    match::ipv4_src ipv4_src{"192.168.10.0"_ipv4, 24}; // 12
    match::ipv4_dst ipv4_dst{"192.168.10.0"_ipv4, 24}; // 12
  };
}

BOOST_AUTO_TEST_SUITE(utility_test)
BOOST_AUTO_TEST_SUITE(oxm_match_field_set)

  BOOST_AUTO_TEST_SUITE(is_valid_set)
    BOOST_AUTO_TEST_CASE(true_if_match_is_empty)
    {
      auto const list = list_type{};

      BOOST_TEST(v13::oxm_match_field_set::is_valid_set(list));
    }
    BOOST_AUTO_TEST_CASE(true_if_match_containes_single_field)
    {
      auto const list = list_type{ match::eth_type{0x0800} };

      BOOST_TEST(v13::oxm_match_field_set::is_valid_set(list));
    }
    BOOST_AUTO_TEST_CASE(true_if_match_containes_different_multiple_fields)
    {
      auto const list
        = list_type{ match::eth_type{0x0800}, match::ip_proto{6} };

      BOOST_TEST(v13::oxm_match_field_set::is_valid_set(list));
    }
    BOOST_AUTO_TEST_CASE(false_if_match_containes_same_fields)
    {
      auto const list = list_type{ match::in_port{3}, match::in_port{4} };

      BOOST_TEST(!v13::oxm_match_field_set::is_valid_set(list));
    }
  BOOST_AUTO_TEST_SUITE_END() // is_valid_set

  BOOST_FIXTURE_TEST_SUITE(equivalent_as_set, parameters)
    BOOST_AUTO_TEST_CASE(true_if_same_object)
    {
      auto const list = list_type{ eth_type, vlan_vid };

      BOOST_TEST(v13::oxm_match_field_set::equivalent_as_set(list, list));
    }
    BOOST_AUTO_TEST_CASE(true_if_both_matchs_are_empty)
    {

      BOOST_TEST(
          v13::oxm_match_field_set::equivalent_as_set(
              list_type{}
            , list_type{}));
    }
    BOOST_AUTO_TEST_CASE(true_if_both_field_values_are_equal)
    {
      BOOST_TEST(
          v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, vlan_vid }
            , list_type{ in_port, vlan_vid }));
    }
    BOOST_AUTO_TEST_CASE(false_if_field_values_is_not_equal)
    {
      BOOST_TEST(
          !v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, match::eth_type{0x0800} }
            , list_type{ in_port, match::eth_type{0x8100} }));
    }
    BOOST_AUTO_TEST_CASE(true_if_field_value_is_not_equal_but_equivalent)
    {
      BOOST_TEST(
          v13::oxm_match_field_set::equivalent_as_set(
              list_type{ vlan_vid, match::vlan_pcp{4} }
            , list_type{ vlan_vid, match::vlan_pcp{4, 0xff} }));
    }
    BOOST_AUTO_TEST_CASE(false_if_fiel_type_is_not_equal)
    {
      BOOST_TEST(
          !v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, eth_dst }
            , list_type{ in_port, eth_src }));
    }
    BOOST_AUTO_TEST_CASE(true_if_field_order_is_not_equal)
    {
      BOOST_TEST(
          v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, eth_type, eth_dst }
            , list_type{ eth_type, in_port, eth_dst }));
    }
    BOOST_AUTO_TEST_CASE(false_if_number_of_field_is_not_equal)
    {
      BOOST_TEST(
          !v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, vlan_vid }
            , list_type{ in_port }));
    }
    BOOST_AUTO_TEST_CASE(
      true_if_number_of_field_is_not_equal_but_one_is_wildcard)
    {
      BOOST_TEST(
          v13::oxm_match_field_set::equivalent_as_set(
              list_type{ in_port, match::vlan_vid{0, 0} }
            , list_type{ in_port }));
    }
  BOOST_AUTO_TEST_SUITE_END() // equivalent_as_set

BOOST_AUTO_TEST_SUITE_END() // oxm_match_field_set
BOOST_AUTO_TEST_SUITE_END() // utility_test

ext: cpp


text:
/***************************************************************************
   Copyright 2015 Ufora Inc.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/
#include "../native/module.hpp"
#include "Platform.hpp"
#include "Logging.hpp"

#include <fstream>
#include <utility>
#include <stdint.h>
#include <boost/python.hpp>
#include "../native/Registrar.hpp"
#include "python/CPPMLWrapper.hpp"

class LoggingConfigWrapper :
	public native::module::Exporter<LoggingConfigWrapper> {
public:
	std::string		getModuleName(void)
		{
		return "Logging";
		}

	static LogLevel convertLevelFromPy(int logLevel)
		{
		return static_cast<LogLevel>((logLevel / 10) - 1);
		}

	static bool shouldLog(int logLevel)
		{
		LogLevel level = convertLevelFromPy(logLevel);
		switch (level)
			{
			case LOG_LEVEL_DEBUG:
				return SHOULD_LOG_DEBUG();
			case LOG_LEVEL_INFO:
				return SHOULD_LOG_INFO();
			case LOG_LEVEL_WARN:
				return SHOULD_LOG_WARN();
			case LOG_LEVEL_ERROR:
				return SHOULD_LOG_ERROR();
			case LOG_LEVEL_CRITICAL:
				return SHOULD_LOG_CRITICAL();
			default:
				lassert_dump(false, "Invalid log level:" << logLevel);
			}
		}
	static void logPy(int logLevel, std::string message)
		{
		// convert from python log levels
		int level = convertLevelFromPy(logLevel);
		switch (level)
			{
			case LOG_LEVEL_DEBUG:
				LOG_DEBUG << message;
				return;
			case LOG_LEVEL_INFO:
				LOG_INFO << message;
				return;
			case LOG_LEVEL_WARN:
				LOG_WARN << message;
				return;
			case LOG_LEVEL_ERROR:
				LOG_ERROR << message;
				return;
			case LOG_LEVEL_CRITICAL:
				LOG_CRITICAL << message;
				return;
			default:
				assert(false);
			}
		}

	static void logInfo(std::string i)
		{
		LOG_INFO << i;
		}

	static void logDebug(std::string i)
		{
		LOG_DEBUG << i;
		}

	static void setLogLevelPy(int logLevel)
		{
		Ufora::Logging::setLogLevel(convertLevelFromPy(logLevel));
		}

	static void setScopedLoggingLevel(std::string scopeRegex, std::string fileRegex, int logLevel)
		{
		Ufora::Logging::setScopedLoggingLevel(scopeRegex, fileRegex, convertLevelFromPy(logLevel));
		}

	static void resetScopedLoggingLevelToDefault(std::string scopeRegex, std::string fileRegex)
		{
		Ufora::Logging::resetScopedLoggingLevelToDefault(scopeRegex, fileRegex);
		}

	static void setFileLogger(const std::string& filename)
		{
		static ofstream filestream;
		filestream.open(filename, ios_base::app);
		Ufora::Logging::Logger::setLogWriter(
				std::bind(
					Ufora::Logging::Logger::logToStream,
					std::ref(filestream),
					std::placeholders::_1,
					std::placeholders::_2,
					std::placeholders::_3,
					std::placeholders::_4
					)
				);
		}

	void exportPythonWrapper()
		{
		using namespace boost::python;
		def("setLogLevel", setLogLevelPy);
		def("setFileLogger", setFileLogger);
		def("shouldLog", shouldLog);
		def("log", logPy);
		def("logInfo", logInfo);
		def("logDebug", logDebug);
		def("setScopedLoggingLevel", setScopedLoggingLevel);
		def("resetScopedLoggingLevelToDefault", resetScopedLoggingLevelToDefault);
		}
};

//explicitly instantiating the registration element causes the linker to need
//this file
template<>
char native::module::Exporter<LoggingConfigWrapper>::mEnforceRegistration =
	native::module::ExportRegistrar<LoggingConfigWrapper>::registerWrapper();

max_stars_repo_name: ufora/ufora


text:
// pkt4_send.cc
#include "log/macros.h"
#include "remopts_callouts.h"
#include "remopts_common.h"
#include "remopts_log.h"
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <dhcp/option.h>
#include <dhcp/pkt4.h>
#include <exceptions/exceptions.h>
#include <hooks/hooks.h>
#include <iostream>
#include <stdbool.h>
#include <string>

using namespace std;
using namespace isc;
using namespace isc::hooks;
using namespace isc::remopts;
using namespace isc::log;
using namespace isc::dhcp;
using namespace boost::system;

namespace pt = boost::property_tree;

extern "C" {
int pkt4_send(CalloutHandle &handle) {
  Pkt4Ptr response4_ptr;
  handle.getArgument("response4", response4_ptr);

  string user_class_id;
  bool userclass_match = false;
  try {
    handle.getContext("user_class_id", user_class_id);
    if (user_class_id.compare(conf_user_class) == 0)
      userclass_match = true;
    LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_PARAM_VALUE)
        .arg("userclass_match: ")
        .arg(userclass_match);
  } catch (const std::exception &ex) {
    LOG_INFO(remopts_logger, REMOPTS_MSG).arg("user_class_id is missing");
  }

  string guid_id;
  bool guid_match = false;
  try {
    handle.getContext("guid_id", guid_id);
    if (boost::algorithm::contains(guid_id, conf_machine_guid))
      guid_match = true;
    LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_PARAM_VALUE)
        .arg("guid_match: ")
        .arg(guid_match);
  } catch (const std::exception &ex) {
    LOG_INFO(remopts_logger, REMOPTS_MSG).arg("guid_id is missing");
  }

  OptionPtr option82;
  option82 = response4_ptr->getOption(82);

  string final_url;
  if (option82 and (userclass_match or guid_match)) {
    OptionPtr option82sub1_ptr = option82->getOption(1);
    OptionPtr option82sub2_ptr = option82->getOption(2);
    OptionPtr option82sub9_ptr = option82->getOption(9);

    if (option82sub1_ptr) {
      final_url = final_url + "?sub82_1=" + gethexOptionPtr(option82sub1_ptr);
      LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_URL)
          .arg("final_url: " + final_url);
    }

    if (option82sub2_ptr) {
      final_url = final_url + "&sub82_2=" + gethexOptionPtr(option82sub2_ptr);
      LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_URL)
          .arg("final_url: " + final_url);
    }

    if (option82sub9_ptr) {
      final_url = final_url + "&sub82_9=" + gethexOptionPtr(option82sub9_ptr);
      LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_URL)
          .arg("final_url: " + final_url);
    }

    final_url = conf_url + final_url;
    LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_URL)
        .arg("final_url: " + final_url);
  } else {
    LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_URL)
        .arg("No option82 or user_class/guid_id match");
    return (0); // we already can't get data from opt82
  }

  // get response from curl request
  stringstream ss;
  if (make_curl_request(final_url, ss)) {
    LOG_INFO(remopts_logger, REMOPTS_MSG)
        .arg("curl OK response: \"" + sstrim(ss) + "\"");
    // parse json response
    pt::ptree root;
    try {
      pt::read_json(ss, root);
    } catch (const exception &ex) {
      LOG_ERROR(remopts_logger, REMOPTS_MSG)
          .arg("curl ERR invalid json response: \"" + sstrim(ss) + "\"");
    }

    for (auto &node : root) {
      string first_ = node.first;          // json key
      string second_ = node.second.data(); // json value
      LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_MSG)
          .arg("json_parser: first->" + first_ + "; second->" + second_);

      OptionPtr option = response4_ptr->getOption(stoi(first_));

      // check if option exists and update or create it
      if (option) {
        LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_MSG)
            .arg("Updating existing option " + first_);

        option->setData(second_.cbegin(), second_.cend());
      } else {
        LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_MSG)
            .arg("No preexisting option " + first_ + ", adding..");

        // create option and add it to response
        OptionBuffer buffer;
        // TODO: pack suboptions of option, now only string directly
        buffer.assign(second_.cbegin(), second_.cend());
        option.reset(new Option(Option::V4, stoi(first_), buffer));
        response4_ptr->addOption(option);
        response4_ptr->pack();
      }
      LOG_DEBUG(remopts_logger, DBGLVL_TRACE_BASIC, REMOPTS_MSG)
          .arg(response4_ptr->toText());
    }
    return (0);

  } else {
    LOG_ERROR(remopts_logger, REMOPTS_MSG)
        .arg("ERR response: " + ss.str());
    return (1);
  };
}
}

ext: cc


text:
//[ Vec3
///////////////////////////////////////////////////////////////////////////////
//  Copyright 2008 Eric Niebler. 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)
//
// This is a simple example using proto::extends to extend a terminal type with
// additional behaviors, and using custom contexts and proto::eval for
// evaluating expressions. It is a port of the Vec3 example
// from PETE (http://www.codesourcery.com/pooma/download.html).

#include <iostream>
#include <functional>
#include <boost/assert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/proto/proto_typeof.hpp>
#include <boost/proto/transform.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
using proto::_;

// Here is an evaluation context that indexes into a Vec3
// expression, and combines the result.
struct Vec3SubscriptCtx
  : proto::callable_context< Vec3SubscriptCtx const >
{
    typedef int result_type;

    Vec3SubscriptCtx(int i)
      : i_(i)
    {}

    // Index array terminals with our subscript. Everything
    // else will be handled by the default evaluation context.
    int operator ()(proto::tag::terminal, int const (&arr)[3]) const
    {
        return arr[this->i_];
    }

    int i_;
};

// Here is an evaluation context that counts the number
// of Vec3 terminals in an expression.
struct CountLeavesCtx
  : proto::callable_context< CountLeavesCtx, proto::null_context >
{
    CountLeavesCtx()
      : count(0)
      {}

      typedef void result_type;

      void operator ()(proto::tag::terminal, int const(&)[3])
      {
          ++this->count;
      }

      int count;
};

struct iplus : std::plus<int>, proto::callable {};

// Here is a transform that does the same thing as the above context.
// It demonstrates the use of the std::plus<> function object
// with the fold transform. With minor modifications, this
// transform could be used to calculate the leaf count at compile
// time, rather than at runtime.
struct CountLeaves
  : proto::or_<
        // match a Vec3 terminal, return 1
        proto::when<proto::terminal<int[3]>, mpl::int_<1>() >
        // match a terminal, return int() (which is 0)
      , proto::when<proto::terminal<_>, int() >
        // fold everything else, using std::plus<> to add
        // the leaf count of each child to the accumulated state.
      , proto::otherwise< proto::fold<_, int(), iplus(CountLeaves, proto::_state) > >
    >
{};

// Here is the Vec3 struct, which is a vector of 3 integers.
struct Vec3
  : proto::extends<proto::terminal<int[3]>::type, Vec3>
{
    explicit Vec3(int i=0, int j=0, int k=0)
    {
        (*this)[0] = i;
        (*this)[1] = j;
        (*this)[2] = k;
    }

    int &operator [](int i)
    {
        return proto::value(*this)[i];
    }

    int const &operator [](int i) const
    {
        return proto::value(*this)[i];
    }

    // Here we define a operator = for Vec3 terminals that
    // takes a Vec3 expression.
    template< typename Expr >
    Vec3 &operator =(Expr const & expr)
    {
        typedef Vec3SubscriptCtx const CVec3SubscriptCtx;
        (*this)[0] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(0));
        (*this)[1] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(1));
        (*this)[2] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(2));
        return *this;
    }

    void print() const
    {
        std::cout << '{' << (*this)[0]
                  << ", " << (*this)[1]
                  << ", " << (*this)[2]
                  << '}' << std::endl;
    }
};

// The count_leaves() function uses the CountLeaves transform and
// to count the number of leaves in an expression.
template<typename Expr>
int count_leaves(Expr const &expr)
{
    // Count the number of Vec3 terminals using the
    // CountLeavesCtx evaluation context.
    CountLeavesCtx ctx;
    proto::eval(expr, ctx);

    // This is another way to count the leaves using a transform.
    int i = 0;
    BOOST_ASSERT( CountLeaves()(expr, i, i) == ctx.count );

    return ctx.count;
}

int main()
{
    Vec3 a, b, c;

    c = 4;

    b[0] = -1;
    b[1] = -2;
    b[2] = -3;

    a = b + c;

    a.print();

    Vec3 d;
    BOOST_PROTO_AUTO(expr1, b + c);
    d = expr1;
    d.print();

    int num = count_leaves(expr1);
    std::cout << num << std::endl;

    BOOST_PROTO_AUTO(expr2, b + 3 * c);
    num = count_leaves(expr2);
    std::cout << num << std::endl;

    BOOST_PROTO_AUTO(expr3, b + c * d);
    num = count_leaves(expr3);
    std::cout << num << std::endl;

    return 0;
}
//]

max_stars_repo_name: zyiacas/boost-doc-zh

max_issues_repo_name: sdfict/boost-doc-zh

max_forks_repo_name: sdfict/boost-doc-zh


text:
// Copyright (c) 2019 Klemens D. Morgenstern
//
// 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_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_

#include <vector>
#include <system_error>
#include <boost/process/detail/windows/handle_workaround.hpp>
#include <boost/process/detail/windows/handler.hpp>
#include <boost/winapi/get_current_process_id.hpp>

namespace boost { namespace process { namespace detail {

template<typename Executor, typename Function>
void foreach_used_handle(Executor &exec, Function &&func);

namespace windows {

using native_handle_type = ::boost::winapi::HANDLE_ ;

inline std::vector<native_handle_type> get_handles(std::error_code & ec)
{
    auto pid = ::boost::winapi::GetCurrentProcessId();

    std::vector<char> buffer(2048);
    constexpr static auto STATUS_INFO_LENGTH_MISMATCH_ = static_cast<::boost::winapi::NTSTATUS_>(0xC0000004l);
    auto info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());

    ::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;

    for (;
           nt_status == STATUS_INFO_LENGTH_MISMATCH_;
           nt_status = workaround::nt_system_query_information(
                            workaround::SystemHandleInformation_,
                            info_pointer, static_cast<::boost::winapi::ULONG_>(buffer.size()),
                            nullptr))
    {
        buffer.resize(buffer.size() * 2);
        info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
    }

    if (nt_status < 0 || nt_status > 0x7FFFFFFF)
    {
        ec = ::boost::process::detail::get_last_error();
        return {};
    }
    else
        ec.clear();

    std::vector<native_handle_type> res;
    for (auto itr = info_pointer->Handle; itr != (info_pointer->Handle + info_pointer->Count); itr++)
    {
        if (itr->OwnerPid == pid)
            res.push_back(reinterpret_cast<native_handle_type>(static_cast<std::uintptr_t>(itr->HandleValue)));
    }

    return res;
}

inline std::vector<native_handle_type> get_handles()
{
    std::error_code ec;

    auto res = get_handles(ec);
    if (ec)
        boost::process::detail::throw_error(ec, "NtQuerySystemInformation failed");

    return res;
}

inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
{
    ::boost::winapi::ULONG_ actual_size;
    auto nt_status = workaround::nt_query_object(
            handle,
            workaround::ObjectTypeInformation,
            NULL,
            0, &actual_size);

    std::vector<char> vec;
    vec.resize(actual_size);

    workaround::OBJECT_TYPE_INFORMATION_ * type_info_p = reinterpret_cast<workaround::OBJECT_TYPE_INFORMATION_*>(vec.data());
    nt_status = workaround::nt_query_object(
            handle,
            workaround::ObjectTypeInformation,
            type_info_p,
            actual_size, &actual_size);

    if (nt_status < 0 || nt_status > 0x7FFFFFFF)
    {
        ec = ::boost::process::detail::get_last_error();
        return false;
    }
    else
        ec.clear();

    auto &nm = type_info_p->TypeName.Buffer;
    return type_info_p->TypeName.Length >= 5 &&
            nm[0] == L'F' &&
            nm[1] == L'i' &&
            nm[2] == L'l' &&
            nm[3] == L'e' &&
            nm[4] == L'\0';
}

inline bool is_stream_handle(native_handle_type handle)
{
    std::error_code ec;
    auto res = is_stream_handle(handle, ec);
    if (ec)
        boost::process::detail::throw_error(ec, "NtQueryObject failed");

    return res;
}

struct limit_handles_ : handler_base_ext
{
    mutable std::vector<::boost::winapi::HANDLE_> handles_with_inherit_flag;

    template<typename Executor>
    void on_setup(Executor & exec) const
    {
        auto all_handles = get_handles();
        foreach_used_handle(exec,
                [&](::boost::winapi::HANDLE_ handle)
                {
                    auto itr = std::find(all_handles.begin(), all_handles .end(), handle);
                    DWORD flags = 0u;
                    if (itr != all_handles.end())
                        *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
                    else if ((::boost::winapi::GetHandleInformation(*itr, &flags) != 0)
                            &&((flags & ::boost::winapi::HANDLE_FLAG_INHERIT_) == 0)) //it is NOT inherited anyhow, so ignore too
                        *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
                });

        auto part_itr = std::partition(all_handles.begin(), all_handles.end(),
                                       [](::boost::winapi::HANDLE_ handle) {return handle != ::boost::winapi::INVALID_HANDLE_VALUE_;});

        all_handles.erase(part_itr, all_handles.end()); //remove invalid handles
        handles_with_inherit_flag = std::move(all_handles);

        for (auto handle : handles_with_inherit_flag)
            ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, 0);
    }

    template<typename Executor>
    void on_error(Executor & exec, const std::error_code & ec) const
    {
        for (auto handle : handles_with_inherit_flag)
            ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
    }

    template<typename Executor>
    void on_sucess(Executor & exec) const
    {
        for (auto handle : handles_with_inherit_flag)
            ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
    }

};

}}}}

#endif //PROCESS_HANDLES_HPP

ext: hpp

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
// test_geometric.cpp

// Copyright Paul A. Bristow 2010.
// Copyright John Maddock 2010.

// Use, modification and distribution are subject to 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)

// Tests for Geometric Distribution.

// Note that these defines must be placed BEFORE #includes.
#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error
// because several tests overflow & underflow by design.
#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real

#ifdef _MSC_VER
#  pragma warning(disable: 4127) // conditional expression is constant.
#endif

#if !defined(TEST_FLOAT) && !defined(TEST_DOUBLE) && !defined(TEST_LDOUBLE) && !defined(TEST_REAL_CONCEPT)
#  define TEST_FLOAT
#  define TEST_DOUBLE
#  define TEST_LDOUBLE
#  define TEST_REAL_CONCEPT
#endif

#include <boost/math/tools/test.hpp>
#include <boost/math/concepts/real_concept.hpp> // for real_concept
using ::boost::math::concepts::real_concept;

#include <boost/math/distributions/geometric.hpp> // for geometric_distribution
using boost::math::geometric_distribution;
using boost::math::geometric; // using typedef for geometric_distribution<double>

#include <boost/math/distributions/negative_binomial.hpp> // for some comparisons.

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> // for test_main
#include <boost/test/tools/floating_point_comparison.hpp> // for BOOST_CHECK_CLOSE_FRACTION
#include "test_out_of_range.hpp"

#include <iostream>
using std::cout;
using std::endl;
using std::setprecision;
using std::showpoint;
#include <limits>
using std::numeric_limits;

template <class RealType>
void test_spot( // Test a single spot value against 'known good' values.
               RealType k,    // Number of failures.
               RealType p,    // Probability of success_fraction.
               RealType P,    // CDF probability.
               RealType Q,    // Complement of CDF.
               RealType tol)  // Test tolerance.
{
   boost::math::geometric_distribution<RealType> g(p);
   BOOST_CHECK_EQUAL(p, g.success_fraction());
   BOOST_CHECK_CLOSE_FRACTION(cdf(g, k), P, tol);

  if((P < 0.99) && (Q < 0.99))
  {
    // We can only check this if P is not too close to 1,
    // so that we can guarantee that Q is free of error:
    //
    BOOST_CHECK_CLOSE_FRACTION(
      cdf(complement(g, k)), Q, tol);
    if(k != 0)
    {
      BOOST_CHECK_CLOSE_FRACTION(
        quantile(g, P), k, tol);
    }
    else
    {
      // Just check quantile is very small:
      if((std::numeric_limits<RealType>::max_exponent <= std::numeric_limits<double>::max_exponent)
        && (boost::is_floating_point<RealType>::value))
      {
        // Limit where this is checked: if exponent range is very large we may
        // run out of iterations in our root finding algorithm.
        BOOST_CHECK(quantile(g, P) < boost::math::tools::epsilon<RealType>() * 10);
      }
    }
    if(k != 0)
    {
      BOOST_CHECK_CLOSE_FRACTION(
        quantile(complement(g, Q)), k, tol);
    }
    else
    {
      // Just check quantile is very small:
      if((std::numeric_limits<RealType>::max_exponent <= std::numeric_limits<double>::max_exponent)
        && (boost::is_floating_point<RealType>::value))
      {
        // Limit where this is checked: if exponent range is very large we may
        // run out of iterations in our root finding algorithm.
        BOOST_CHECK(quantile(complement(g, Q)) < boost::math::tools::epsilon<RealType>() * 10);
      }
    }
  } //   if((P < 0.99) && (Q < 0.99))

    // Parameter estimation test:  estimate success ratio:
    BOOST_CHECK_CLOSE_FRACTION(
      geometric_distribution<RealType>::find_lower_bound_on_p(
      1+k, P),
      p, 0.02); // Wide tolerance needed for some tests.
   // Note we bump up the sample size here, purely for the sake of the test,
    // internally the function has to adjust the sample size so that we get
    // the right upper bound, our test undoes this, so we can verify the result.
    BOOST_CHECK_CLOSE_FRACTION(
      geometric_distribution<RealType>::find_upper_bound_on_p(
      1+k+1, Q),
      p, 0.02);

    if(Q < P)
    {
       //
       // We check two things here, that the upper and lower bounds
       // are the right way around, and that they do actually bracket
       // the naive estimate of p = successes / (sample size)
       //
      BOOST_CHECK(
        geometric_distribution<RealType>::find_lower_bound_on_p(
        1+k, Q)
        <=
        geometric_distribution<RealType>::find_upper_bound_on_p(
        1+k, Q)
        );
      BOOST_CHECK(
        geometric_distribution<RealType>::find_lower_bound_on_p(
        1+k, Q)
        <=
        1 / (1+k)
        );
      BOOST_CHECK(
        1 / (1+k)
        <=
        geometric_distribution<RealType>::find_upper_bound_on_p(
        1+k, Q)
        );
    }
    else
    {
       // As above but when P is small.
      BOOST_CHECK(
        geometric_distribution<RealType>::find_lower_bound_on_p(
        1+k, P)
        <=
        geometric_distribution<RealType>::find_upper_bound_on_p(
        1+k, P)
        );
      BOOST_CHECK(
        geometric_distribution<RealType>::find_lower_bound_on_p(
        1+k,  P)
        <=
        1 / (1+k)
        );
      BOOST_CHECK(
        1 / (1+k)
        <=
        geometric_distribution<RealType>::find_upper_bound_on_p(
        1+k, P)
        );
    }

    // Estimate sample size:
    BOOST_CHECK_CLOSE_FRACTION(
      geometric_distribution<RealType>::find_minimum_number_of_trials(
      k, p, P),
      1+k, 0.02); // Can differ 50 to 51 for small p
    BOOST_CHECK_CLOSE_FRACTION(
      geometric_distribution<RealType>::find_maximum_number_of_trials(
         k, p, Q),
      1+k, 0.02);

} // test_spot

template <class RealType> // Any floating-point type RealType.
void test_spots(RealType)
{
  // Basic sanity checks.
  // Most test data is to double precision (17 decimal digits) only,

  cout << "Floating point Type is " << typeid(RealType).name() << endl;

  // so set tolerance to 1000 eps expressed as a fraction,
  // or 1000 eps of type double expressed as a fraction,
  // whichever is the larger.

  RealType tolerance = (std::max)
    (boost::math::tools::epsilon<RealType>(),
    static_cast<RealType>(std::numeric_limits<double>::epsilon()));
  tolerance *= 10; // 10 eps

  cout << "Tolerance = " << tolerance << "." << endl;

  RealType tol1eps = boost::math::tools::epsilon<RealType>(); // Very tight, suit exact values.
  //RealType tol2eps = boost::math::tools::epsilon<RealType>() * 2; // Tight,  values.
  RealType tol5eps = boost::math::tools::epsilon<RealType>() * 5; // Wider 5 epsilon.
  cout << "Tolerance 5 eps = " << tol5eps << "." << endl;

  // Sources of spot test values are mainly R.

  using boost::math::geometric_distribution;
  using boost::math::geometric;
  using boost::math::cdf;
  using boost::math::pdf;
  using boost::math::quantile;
  using boost::math::complement;

  BOOST_MATH_STD_USING // for std math functions

  // Test geometric using cdf spot values R
  // These test quantiles and complements as well.

  test_spot(  //
  static_cast<RealType>(2),   // Number of failures, k
  static_cast<RealType>(0.5), // Probability of success as fraction, p
  static_cast<RealType>(0.875L), // Probability of result (CDF), P
  static_cast<RealType>(0.125L),  // complement CCDF Q = 1 - P
  tolerance);

  test_spot( //
  static_cast<RealType>(0),    // Number of failures, k
  static_cast<RealType>(0.25), // Probability of success as fraction, p
  static_cast<RealType>(0.25),   // Probability of result (CDF), P
  static_cast<RealType>(0.75),   // Q = 1 - P
  tolerance);

  test_spot(
    // R formatC(pgeom(10,0.25), digits=17) [1] "0.95776486396789551"
    // formatC(pgeom(10,0.25, FALSE), digits=17) [1] "0.042235136032104499"

  static_cast<RealType>(10),  // Number of failures, k
  static_cast<RealType>(0.25),  // Probability of success, p
  static_cast<RealType>(0.95776486396789551L),  // Probability of result (CDF), P
  static_cast<RealType>(0.042235136032104499L), // Q = 1 - P
  tolerance);

  test_spot(  //
  // > R formatC(pgeom(50,0.25, TRUE), digits=17) [1] "0.99999957525875771"
  // > R formatC(pgeom(50,0.25, FALSE), digits=17) [1] "4.2474124232020353e-07"
  static_cast<RealType>(50),     // Number of failures, k
  static_cast<RealType>(0.25),     // Probability of success, p
  static_cast<RealType>(0.99999957525875771),  // Probability of result (CDF), P
  static_cast<RealType>(4.2474124232020353e-07),   // Q = 1 - P
  tolerance);
  /*
  // This causes failures in find_upper_bound_on_p p is small branch.
  test_spot(  // formatC(pgeom(50,0.01, TRUE), digits=17)[1] "0.40104399353383874"
    // > formatC(pgeom(50,0.01, FALSE), digits=17) [1] "0.59895600646616121"
  static_cast<RealType>(50), // Number of failures, k
  static_cast<RealType>(0.01),   // Probability of success, p
  static_cast<RealType>(0.40104399353383874),   // Probability of result (CDF), P
  static_cast<RealType>(0.59895600646616121),   // Q = 1 - P
  tolerance);
  */

  test_spot( // > formatC(pgeom(50,0.99, TRUE), digits=17) [1] "                 1"
    // formatC(pgeom(50,0.99, FALSE), digits=17) [1] "1.0000000000000364e-102"
  static_cast<RealType>(50),     // Number of failures, k
  static_cast<RealType>(0.99),    // Probability of success, p
  static_cast<RealType>(1), // Probability of result (CDF), P
  static_cast<RealType>(1.0000000000000364e-102),   // Q = 1 - P
  tolerance);

  test_spot(  // > formatC(pgeom(1,0.99, TRUE), digits=17) [1] "0.99990000000000001"
    // > formatC(pgeom(1,0.99, FALSE), digits=17) [1] "0.00010000000000000009"
  static_cast<RealType>(1),     // Number of failures, k
  static_cast<RealType>(0.99),                    // Probability of success, p
  static_cast<RealType>(0.9999),     // Probability of result (CDF), P
  static_cast<RealType>(0.0001),   // Q = 1 - P
  tolerance);

if(std::numeric_limits<RealType>::is_specialized)
{ // An extreme value test that is more accurate than using negative binomial.
  // Since geometric only uses exp and log functions.
  test_spot(  // > formatC(pgeom(10000, 0.001, TRUE), digits=17) [1] "0.99995487182736897"
// > formatC(pgeom(10000,0.001, FALSE), digits=17) [1] "4.5128172631071587e-05"
  static_cast<RealType>(10000L), // Number of failures, k
  static_cast<RealType>(0.001L),                    // Probability of success, p
  static_cast<RealType>(0.99995487182736897L),     // Probability of result (CDF), P
  static_cast<RealType>(4.5128172631071587e-05L),   // Q = 1 - P
  tolerance); //
  } // numeric_limit is specialized
 // End of single spot tests using RealType

  // Tests on PDF:

  BOOST_CHECK_CLOSE_FRACTION( //> formatC(dgeom(0,0.5), digits=17)[1] " 0.5"
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(0.0) ),  // Number of failures, k is very small but not integral,
  static_cast<RealType>(0.5), // nearly success probability.
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( //> formatC(dgeom(0,0.5), digits=17)[1] "    0.5"
    //  R treates geom as a discrete distribution.
    // > formatC(dgeom(1.999999,0.5, FALSE), digits=17) [1] "   0"
    // Warning message:
    // In dgeom(1.999999, 0.5, FALSE) : non-integer x = 1.999999
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(0.0001L) ),  // Number of failures, k is very small but not integral,
  static_cast<RealType>(0.4999653438420768L), // nearly success probability.
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( // > formatC(pgeom(0.0001,0.5, TRUE), digits=17)[1] " 0.5"
    // > formatC(pgeom(0.0001,0.5, FALSE), digits=17) [1] "               0.5"
    //  R treates geom as a discrete distribution.
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(0.0001L) ),  // Number of failures, k is very small but not integral,
  static_cast<RealType>(0.4999653438420768L), // nearly success probability.
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( // formatC(dgeom(1,0.01), digits=17)[1] "0.0099000000000000008"
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.01L)),
  static_cast<RealType>(1) ),  // Number of failures, k
  static_cast<RealType>(0.0099000000000000008), //
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( //> formatC(dgeom(1,0.99), digits=17)[1] "0.0099000000000000043"
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.99L)),
  static_cast<RealType>(1) ),  // Number of failures, k
  static_cast<RealType>(0.00990000000000000043L), //
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( //> > formatC(dgeom(0,0.99), digits=17)[1] "0.98999999999999999"
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.99L)),
  static_cast<RealType>(0) ),  // Number of failures, k
  static_cast<RealType>(0.98999999999999999L), //
  tolerance);

  // p  near unity.
  BOOST_CHECK_CLOSE_FRACTION( // > formatC(dgeom(100,0.99), digits=17)[1] "9.9000000000003448e-201"
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.99L)),
  static_cast<RealType>(100) ),  // Number of failures, k
  static_cast<RealType>(9.9000000000003448e-201L), //
  100 * tolerance); // Note difference

    // p nearer unity.
  BOOST_CHECK_CLOSE_FRACTION( //
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.9999)),
  static_cast<RealType>(10) ),  // Number of failures, k
  // static_cast<double>(9.9989999999889024e-41), // Boost.Math
  // static_cast<float>(1.00156406e-040)
  static_cast<RealType>(9.999e-41), // exact from 100 digit calculator.
  2e3 * tolerance); // Note bigger tolerance needed.

  // Moshier Cephes 100 digits calculator says 9.999e-41
  //0.9999*pow(1-0.9999,10)
  // 9.9990000000000000000000000000000000000000000000000000000000000000000000E-41
  // 9.998999999988988e-041
  // > formatC(dgeom(10, 0.9999), digits=17) [1] "9.9989999999889024e-41"
  // p *  pow(q, k)         9.9989999999889880e-041
  // exp(p * k * log1p(-p)) 9.9989999999889024e-041

  // 0.9999999999 * pow(1-0.9999999999,10)=  9.9999999990E-101
  // > formatC(dgeom(10,0.9999999999), digits=17)  [1] "1.0000008273040127e-100"
  BOOST_CHECK_CLOSE_FRACTION( //
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.9999999999L)),
  static_cast<RealType>(10) ),  //
  static_cast<RealType>(9.9999999990E-101L), // 1.0000008273040179e-100
  1e9 * tolerance); // Note big tolerance needed.
  // 1.0000008273040179e-100  Boost.Math
  // 1.0000008273040127e-100  R
  // 0.9999999990000004e-100  100 digit calculator 'exact'

  BOOST_CHECK_CLOSE_FRACTION( //
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.00000000001L)),
  static_cast<RealType>(10) ),  //
  static_cast<RealType>(9.999999999e-12L), // get 9.9999999989999994e-012
  1 * tolerance); // Note small tolerance needed.

    BOOST_CHECK_CLOSE_FRACTION( //
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.00000000001L)),
  static_cast<RealType>(1000) ),  //
  static_cast<RealType>(9.9999999e-12L), // get 9.9999998999999913e-012
  tolerance); // Note small tolerance needed.

  ///////////////////////////////////////////////////
  BOOST_CHECK_CLOSE_FRACTION( //
    // > formatC(dgeom(0.0001,0.5, FALSE), digits=17) [1] "               0.5"
    //  R treates geom as a discrete distribution.
    // But Boost.Math is continuous, so if you want R behaviour,
    // make number of failures, k into an integer with the floor function.
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(floor(0.0001L)) ),  // Number of failures, k is very small but MADE integral,
  static_cast<RealType>(0.5), // nearly success probability.
  tolerance);

  // R switches over at about 1e7 from k = 0, returning 0.5,  to k = 1, returning 0.25.
  // Boost.Math does not do this, even for 0.9999999999999999
  // > formatC(pgeom(0.999999,0.5, FALSE), digits=17) [1] "               0.5"
  // > formatC(pgeom(0.9999999,0.5, FALSE), digits=17) [1] "              0.25"

  BOOST_CHECK_CLOSE_FRACTION( // > formatC(pgeom(0.0001,0.5, TRUE), digits=17)[1] "               0.5"
    // > formatC(pgeom(0.0001,0.5, FALSE), digits=17) [1] "               0.5"
    //  R treates geom as a discrete distribution.
    // But Boost.Math is continuous, so if you want R behaviour,
    // make number of failures, k into an integer with the floor function.
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(floor(0.9999999999999999L)) ),  // Number of failures, k is very small but MADE integral,
  static_cast<RealType>(0.5), // nearly success probability.
  tolerance);

  BOOST_CHECK_CLOSE_FRACTION( // > formatC(pgeom(0.0001,0.5, TRUE), digits=17)[1] "               0.5"
    // > formatC(pgeom(0.0001,0.5, FALSE), digits=17) [1] "               0.5"
    //  R treates geom as a discrete distribution.
    // But Boost.Math is continuous, so if you want R behaviour,
    // make number of failures, k into an integer with the floor function.
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
  static_cast<RealType>(floor(1. - tolerance)) ),
  // Number of failures, k is very small but MADE integral,
  // Need to use tolerance here,
  // as epsilon is ill-defined for Real concept:
  // numeric_limits<RealType>::epsilon()  0
  static_cast<RealType>(0.5), // nearly success probability.
  tolerance * 10);

  BOOST_CHECK_CLOSE_FRACTION(
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.0001L)),
  static_cast<RealType>(2)),  // k = 2.
  static_cast<RealType>(9.99800010e-5L), // 'exact '
  tolerance);

  //> formatC(dgeom(2, 0.9999), digits=17) [1] "9.9989999999977806e-09"
  BOOST_CHECK_CLOSE_FRACTION(
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.9999L)),
  static_cast<RealType>(2)),  // k = 0
  static_cast<RealType>(9.999e-9L), // 'exact'
  1000*tolerance);

  BOOST_CHECK_CLOSE_FRACTION(
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.9999L)),
  static_cast<RealType>(3)),  // k = 3
  static_cast<RealType>(9.999e-13L), // get
  1000*tolerance);

  BOOST_CHECK_CLOSE_FRACTION(
  pdf(geometric_distribution<RealType>(static_cast<RealType>(0.9999L)),
  static_cast<RealType>(5)),  // k = 5
  static_cast<RealType>(9.999e-21L), //  9.9989999999944947e-021
  1000*tolerance);

  BOOST_CHECK_CLOSE_FRACTION(
  pdf(geometric_distribution<RealType>( static_cast<RealType>(0.0001L)),
  static_cast<RealType>(3)),  // k = 0.
  static_cast<RealType>(9.99700029999e-5L), //
  tolerance);
   // Tests on cdf:
  // MathCAD pgeom k, r, p) == failures, successes, probability.

  BOOST_CHECK_CLOSE_FRACTION(cdf(
    geometric_distribution<RealType>(static_cast<RealType>(0.5)), // prob 0.5
    static_cast<RealType>(0) ), // k = 0
    static_cast<RealType>(0.5), // probability =p
    tolerance);

  BOOST_CHECK_CLOSE_FRACTION(cdf(complement(
    geometric_distribution<RealType>(static_cast<RealType>(0.5)), //
    static_cast<RealType>(0) )), // k = 0
    static_cast<RealType>(0.5), // probability =
    tolerance);

  BOOST_CHECK_CLOSE_FRACTION(cdf(
    geometric_distribution<RealType>(static_cast<RealType>(0.25)), // prob 0.5
    static_cast<RealType>(1) ), // k = 0
    static_cast<RealType>(0.4375L), // probability =p
    tolerance);

  BOOST_CHECK_CLOSE_FRACTION(cdf(complement(
    geometric_distribution<RealType>(static_cast<RealType>(0.25)), //
    static_cast<RealType>(1) )), // k = 0
    static_cast<RealType>(1-0.4375L), // probability =
    tolerance);

  BOOST_CHECK_CLOSE_FRACTION(cdf(complement(
    geometric_distribution<RealType>(static_cast<RealType>(0.5)), //
    static_cast<RealType>(1) )), // k = 0
    static_cast<RealType>(0.25), // probability = exact 0.25
    tolerance);

  BOOST_CHECK_CLOSE_FRACTION( //
    cdf(geometric_distribution<RealType>(static_cast<RealType>(0.5)),
    static_cast<RealType>(4)),  // k =4.
    static_cast<RealType>(0.96875L), // exact
    tolerance);

  // Tests of other functions, mean and other moments ...

  geometric_distribution<RealType> dist(static_cast<RealType>(0.25));
  // mean:
  BOOST_CHECK_CLOSE_FRACTION(
    mean(dist), static_cast<RealType>((1 - 0.25) /0.25), tol5eps);
  BOOST_CHECK_CLOSE_FRACTION(
    mode(dist), static_cast<RealType>(0), tol1eps);
  // variance:
  BOOST_CHECK_CLOSE_FRACTION(
    variance(dist), static_cast<RealType>((1 - 0.25) / (0.25 * 0.25)), tol5eps);

  // std deviation:
  // sqrt(0.75/0.125)

  BOOST_CHECK_CLOSE_FRACTION(
    standard_deviation(dist), //
    static_cast<RealType>(sqrt((1.0L - 0.25L) / (0.25L * 0.25L))), // using 100 digit calc
    tol5eps);

  BOOST_CHECK_CLOSE_FRACTION(
    skewness(dist), //
    static_cast<RealType>((2-0.25L) /sqrt(0.75L)),
    // using calculator
    tol5eps);
  BOOST_CHECK_CLOSE_FRACTION(
    kurtosis_excess(dist), //
    static_cast<RealType>(6 + 0.0625L/0.75L), //
    tol5eps);
  // 6.083333333333333  6.166666666666667
  BOOST_CHECK_CLOSE_FRACTION(
    kurtosis(dist), // true
    static_cast<RealType>(9 + 0.0625L/0.75L), //
    tol5eps);
  // hazard:
  RealType x = static_cast<RealType>(0.125);
  BOOST_CHECK_CLOSE_FRACTION(
  hazard(dist, x)
  , pdf(dist, x) / cdf(complement(dist, x)), tol5eps);
  // cumulative hazard:
  BOOST_CHECK_CLOSE_FRACTION(
  chf(dist, x), -log(cdf(complement(dist, x))), tol5eps);
  // coefficient_of_variation:
  BOOST_CHECK_CLOSE_FRACTION(
  coefficient_of_variation(dist)
  , standard_deviation(dist) / mean(dist), tol5eps);

  // Special cases for PDF:
  BOOST_CHECK_EQUAL(
  pdf(
  geometric_distribution<RealType>(static_cast<RealType>(0)), //
  static_cast<RealType>(0)),
  static_cast<RealType>(0) );

  BOOST_CHECK_EQUAL(
  pdf(
  geometric_distribution<RealType>(static_cast<RealType>(0)),
  static_cast<RealType>(0.0001)),
  static_cast<RealType>(0) );

  BOOST_CHECK_EQUAL(
  pdf(
  geometric_distribution<RealType>(static_cast<RealType>(1)),
  static_cast<RealType>(0.001)),
  static_cast<RealType>(0) );

  BOOST_CHECK_EQUAL(
  pdf(
  geometric_distribution<RealType>(static_cast<RealType>(1)),
  static_cast<RealType>(8)),
  static_cast<RealType>(0) );

  BOOST_CHECK_SMALL(
  pdf(
   geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(0))-
  static_cast<RealType>(0.25),
  2 * boost::math::tools::epsilon<RealType>() ); // Expect exact, but not quite.
  // numeric_limits<RealType>::epsilon()); // Not suitable for real concept!

  // Quantile boundary cases checks:
  BOOST_CHECK_EQUAL(
  quantile(  // zero P < cdf(0) so should be exactly zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(0)),
  static_cast<RealType>(0));

  BOOST_CHECK_EQUAL(
  quantile(  // min P < cdf(0) so should be exactly zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(boost::math::tools::min_value<RealType>())),
  static_cast<RealType>(0));

  BOOST_CHECK_CLOSE_FRACTION(
  quantile(  // Small P < cdf(0) so should be near zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(boost::math::tools::epsilon<RealType>())), //
  static_cast<RealType>(0),
    tol5eps);

  BOOST_CHECK_CLOSE_FRACTION(
  quantile(  // Small P < cdf(0) so should be exactly zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(0.0001)),
  static_cast<RealType>(0),
    tolerance);

  //BOOST_CHECK(  // Fails with overflow for real_concept
  //quantile(  // Small P near 1 so k failures should be big.
  //geometric_distribution<RealType>(static_cast<RealType>(8), static_cast<RealType>(0.25)),
  //static_cast<RealType>(1 - boost::math::tools::epsilon<RealType>())) <=
  //static_cast<RealType>(189.56999032670058)  // 106.462769 for float
  //);

  if(std::numeric_limits<RealType>::has_infinity)
  { // BOOST_CHECK tests for infinity using std::numeric_limits<>::infinity()
    // Note that infinity is not implemented for real_concept, so these tests
    // are only done for types, like built-in float, double.. that have infinity.
    // Note that these assume that  BOOST_MATH_OVERFLOW_ERROR_POLICY is NOT throw_on_error.
    // #define BOOST_MATH_THROW_ON_OVERFLOW_POLICY ==  throw_on_error would throw here.
    // #define BOOST_MAT_DOMAIN_ERROR_POLICY IS defined throw_on_error,
    //  so the throw path of error handling is tested below with BOOST_MATH_CHECK_THROW tests.

    BOOST_CHECK(
    quantile(  // At P == 1 so k failures should be infinite.
    geometric_distribution<RealType>(static_cast<RealType>(0.25)),
    static_cast<RealType>(1)) ==
    //static_cast<RealType>(boost::math::tools::infinity<RealType>())
    static_cast<RealType>(std::numeric_limits<RealType>::infinity()) );

    BOOST_CHECK_EQUAL(
    quantile(  // At 1 == P  so should be infinite.
    geometric_distribution<RealType>( static_cast<RealType>(0.25)),
    static_cast<RealType>(1)), //
    std::numeric_limits<RealType>::infinity() );

    BOOST_CHECK_EQUAL(
    quantile(complement(  // Q zero 1 so P == 1 < cdf(0) so should be exactly infinity.
    geometric_distribution<RealType>(static_cast<RealType>(0.25)),
    static_cast<RealType>(0))),
    std::numeric_limits<RealType>::infinity() );
   } // test for infinity using std::numeric_limits<>::infinity()
  else
  { // real_concept case, so check it throws rather than returning infinity.
    BOOST_CHECK_EQUAL(
    quantile(  // At P == 1 so k failures should be infinite.
    geometric_distribution<RealType>(static_cast<RealType>(0.25)),
    static_cast<RealType>(1)),
    boost::math::tools::max_value<RealType>() );

    BOOST_CHECK_EQUAL(
    quantile(complement(  // Q zero 1 so P == 1 < cdf(0) so should be exactly infinity.
    geometric_distribution<RealType>(static_cast<RealType>(0.25)),
    static_cast<RealType>(0))),
    boost::math::tools::max_value<RealType>());
  } // has infinity

  BOOST_CHECK( // Should work for built-in and real_concept.
  quantile(complement(  // Q near to 1 so P nearly 1, so should be large > 300.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(boost::math::tools::min_value<RealType>())))
   >= static_cast<RealType>(300) );

  BOOST_CHECK_EQUAL(
  quantile(  //  P ==  0 < cdf(0) so should be zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(0)),
  static_cast<RealType>(0));

  // Quantile Complement boundary cases:

  BOOST_CHECK_EQUAL(
  quantile(complement(  // Q = 1 so P = 0 < cdf(0) so should be exactly zero.
  geometric_distribution<RealType>( static_cast<RealType>(0.25)),
  static_cast<RealType>(1))),
  static_cast<RealType>(0)
  );

  BOOST_CHECK_EQUAL(
  quantile(complement(  // Q very near 1 so P == epsilon < cdf(0) so should be exactly zero.
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(1 - boost::math::tools::epsilon<RealType>()))),
  static_cast<RealType>(0)
  );

  // Check that duff arguments throw domain_error:

  BOOST_MATH_CHECK_THROW(
  pdf( // Negative success_fraction!
  geometric_distribution<RealType>(static_cast<RealType>(-0.25)),
  static_cast<RealType>(0)), std::domain_error);
  BOOST_MATH_CHECK_THROW(
  pdf( // Success_fraction > 1!
  geometric_distribution<RealType>(static_cast<RealType>(1.25)),
  static_cast<RealType>(0)),
  std::domain_error);
  BOOST_MATH_CHECK_THROW(
  pdf( // Negative k argument !
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(-1)),
  std::domain_error);
  //BOOST_MATH_CHECK_THROW(
  //pdf( // check limit on k (failures)
  //geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  //std::numeric_limits<RealType>infinity()),
  //std::domain_error);
  BOOST_MATH_CHECK_THROW(
  cdf(  // Negative k argument !
  geometric_distribution<RealType>(static_cast<RealType>(0.25)),
  static_cast<RealType>(-1)),
  std::domain_error);
  BOOST_MATH_CHECK_THROW(
  cdf( // Negative success_fraction!
  geometric_distribution<RealType>(static_cast<RealType>(-0.25)),
  static_cast<RealType>(0)), std::domain_error);
  BOOST_MATH_CHECK_THROW(
  cdf( // Success_fraction > 1!
  geometric_distribution<RealType>(static_cast<RealType>(1.25)),
  static_cast<RealType>(0)), std::domain_error);
  BOOST_MATH_CHECK_THROW(
  quantile(  // Negative success_fraction!
  geometric_distribution<RealType>(static_cast<RealType>(-0.25)),
  static_cast<RealType>(0)), std::domain_error);
  BOOST_MATH_CHECK_THROW(
  quantile( // Success_fraction > 1!
  geometric_distribution<RealType>(static_cast<RealType>(1.25)),
  static_cast<RealType>(0)), std::domain_error);
   check_out_of_range<geometric_distribution<RealType> >(0.5);
  // End of check throwing 'duff' out-of-domain values.

  { // Compare geometric and negative binomial functions.
    using boost::math::negative_binomial_distribution;
    using boost::math::geometric_distribution;

    RealType k = static_cast<RealType>(2.L);
    RealType alpha = static_cast<RealType>(0.05L);
    RealType p = static_cast<RealType>(0.5L);

    BOOST_CHECK_CLOSE_FRACTION( // Successes parameter in negative binomial is 1 for geometric.
      geometric_distribution<RealType>::find_lower_bound_on_p(k, alpha),
      negative_binomial_distribution<RealType>::find_lower_bound_on_p(k, static_cast<RealType>(1), alpha),
      tolerance);
    BOOST_CHECK_CLOSE_FRACTION( // Successes parameter in negative binomial is 1 for geometric.
      geometric_distribution<RealType>::find_upper_bound_on_p(k, alpha),
      negative_binomial_distribution<RealType>::find_upper_bound_on_p(k, static_cast<RealType>(1), alpha),
      tolerance);
    BOOST_CHECK_CLOSE_FRACTION( // Should be identical - successes parameter is not used.
       geometric_distribution<RealType>::find_maximum_number_of_trials(k, p, alpha),
      negative_binomial_distribution<RealType>::find_maximum_number_of_trials(k, p, alpha),
    tolerance);
  }
    //geometric::find_upper_bound_on_p(k, alpha);
   return;
} // template <class RealType> void test_spots(RealType) // Any floating-point type RealType.

BOOST_AUTO_TEST_CASE( test_main )
{
  // Check that can generate geometric distribution using the two convenience methods:
   using namespace boost::math;
   geometric g05d(0.5); // Using typedef - default type is double.
   geometric_distribution<> g05dd(0.5); // Using default RealType double.

  // Basic sanity-check spot values.

  // Test some simple double only examples.
  geometric_distribution<double> mydist(0.25);
  // success fraction == 0.25 == 25% or 1 in 4 successes.
  // Note: double values (matching the distribution definition) avoid the need for any casting.

  // Check accessor functions return exact values for double at least.
  BOOST_CHECK_EQUAL(mydist.success_fraction(), static_cast<double>(1./4.));

  //cout << numeric_limits<RealType>::epsilon() << endl;

  // (Parameter value, arbitrarily zero, only communicates the floating point type).
#ifdef TEST_FLOAT
  test_spots(0.0F); // Test float.
#endif
#ifdef TEST_DOUBLE
  test_spots(0.0); // Test double.
#endif
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
#ifdef TEST_LDOUBLE
  test_spots(0.0L); // Test long double.
#endif
  #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
#ifdef TEST_REAL_CONCEPT
    test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
#endif
  #endif
#else
   std::cout << "<note>The long double tests have been disabled on this platform "
      "either because the long double overloads of the usual math functions are "
      "not available at all, or because they are too inaccurate for these tests "
      "to pass.</note>" << std::endl;
#endif

} // BOOST_AUTO_TEST_CASE( test_main )

/*

*/


text:
#include <boost/filesystem.hpp>
#include "OutputMethods.h"

#include <fstream>
#include <MAFilter.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/video.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/videoio/videoio_c.h>

#include <opencv2/highgui/highgui.hpp>

#include <kalman.h>

#ifdef _MSC_VER
#pragma warning(push, 0)
#endif
#include <QDebug>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "constants.h"
#include "DetectorCode.h"

bool writeUserVideoFile(const std::string& filename, const VideoFrame2Timestamp& userVideoAssociation)
{
	// Write UservideoFile
	std::ofstream userVideoFile;
	userVideoFile.open(filename);

	if (!userVideoFile.is_open())
	{
		return false;
	}

	userVideoFile << "Start: " << userVideoAssociation.start_time << "\n";

	for (const auto value : userVideoAssociation.frame2time)
	{
		userVideoFile << "Frame " << value.first << ": " << value.second << "\n";
	}

	userVideoFile << "End: " << userVideoAssociation.end_time;

	userVideoFile.close();

	return true;
}

VideoFrame2Gaze estimateAndSaveEyeVideoFile(const std::string& eye_video,
	const std::string& output_filename,
	const VideoFrame2Timestamp& eyeVideoDictionary,
	DetectionToGazeEstimation estimation,
	PupilDetection* pupil_detection,
	int first_eye_threshold)
{
	VideoFrame2Gaze result;
	std::ofstream eyeFile(output_filename);

	// ==================================
	MAFilter pupilR_maFilter(MAFilter(20, true, 1));
	MAFilter pupilL_maFilter(MAFilter(20, true, 1));
	// ==================================

	// analyze eye video
	// detect Glints and Pupil for each frame of eye video
	cv::VideoCapture eyeVid = cv::VideoCapture::VideoCapture(eye_video);
	long frameCount = 0;
	cv::Mat frame1, frame2;
	qDebug() << "Processing saved EyeVideos... this may take some minutes.";

	eyeFile << "Start: " << eyeVideoDictionary.start_time << std::endl;
	qDebug() << "Total amount of frames saved: " << eyeVid.get(CV_CAP_PROP_FRAME_COUNT);
	qDebug() << "Average detection FPS: " << (eyeVideoDictionary.end_time - eyeVideoDictionary.start_time) / eyeVid.get(CV_CAP_PROP_FRAME_COUNT);
	qDebug() << "Eyevideo START-Timestamp: " << eyeVideoDictionary.start_time;
	qDebug() << "Creating eyefeature detection file.";

	// write header for eyeFile
	eyeFile << "timestamp " << "pupil_right " << "pupil_left " << "glint1_right " << "glint2_right " << "glint3_right "
		<< "glint1_left " << "glint2_left " << "glint3_left " << "gaze_x " << "gaze_y " << std::endl;

	// walk though each frame find glints and pupil.
	// estimate gaze and save gaze in eyeVideoDictionary at right position according to frame number
	//while (eyeVid.get(CV_CAP_PROP_POS_FRAMES) < eyeVid.get(CV_CAP_PROP_FRAME_COUNT) - 1)
	while (1)
	{
		qDebug() << "FrameCount: " << frameCount;
		eyeVid.read(frame1);

		if (frame1.empty())
			break;

		eyeVid.set(CV_CAP_PROP_POS_FRAMES, frameCount + 1);

		frameCount += 1;

		PupilGlintCombiInstance pgci = detectGlintAndPupilNEW(frame1, first_eye_threshold, pupil_detection);

		// ================================
		// GLINTS: Kalman Filter
		// PUPIL:  MAFilter

		PupilGlintCombiInstance ergebnis = pgci;

		// right Pupil
		if (pgci.pupilRight.x > 0 && pgci.pupilRight.y > 0)
		{
			ergebnis.pupilRight = pupilR_maFilter.movingAveragesFilter(pgci.pupilRight);
		}

		if (ergebnis.glintRight_1.x > 0 && ergebnis.glintRight_1.y)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::RIGHT_0, ergebnis.glintRight_1.x, ergebnis.glintRight_1.y);
		}

		if (ergebnis.glintRight_2.x > 0 && ergebnis.glintRight_2.y > 0)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::RIGHT_1, ergebnis.glintRight_2.x, ergebnis.glintRight_2.y);

		}

		if (ergebnis.glintRight_3.x > 0 && ergebnis.glintRight_3.y > 0)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::RIGHT_2, ergebnis.glintRight_3.x, ergebnis.glintRight_3.y);

		}

		// left Pupil
		if (pgci.pupilLeft.x > 0 && pgci.pupilLeft.y > 0)
		{
			ergebnis.pupilLeft = pupilL_maFilter.movingAveragesFilter(pgci.pupilLeft);
			//qDebug() << "New Pupilleft: " << ergebnis.pupilLeft.x << " " << ergebnis.pupilLeft.y;
		}

		if (ergebnis.glintLeft_1.x > 0 && ergebnis.glintLeft_1.y > 0)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::LEFT_0, ergebnis.glintLeft_1.x, ergebnis.glintLeft_1.y);

		}

		if (ergebnis.glintLeft_2.x > 0 && ergebnis.glintLeft_2.y > 0)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::LEFT_1, ergebnis.glintLeft_2.x, ergebnis.glintLeft_2.y);

		}

		if (ergebnis.glintLeft_3.x > 0 && ergebnis.glintLeft_3.y > 0)
		{
			KALMAN::GlintFilter::correct(KALMAN::GlintFilter::LEFT_2, ergebnis.glintLeft_3.x, ergebnis.glintLeft_3.y);

		}

		auto gaze = estimation(DetectedFeatures(pgci));
		// TO-DO //auto gaze = estimation(DetectedFeatures(ergebnis));

		//qDebug() << "FilteredGaze: " << gaze.position.x << " " << gaze.position.y;
		// ================================
		//auto gaze = estimation(DetectedFeatures(pgci));
		// ================================

		// ================================
		// GAZE: Kalman Filter
		cv::Point2f gazePostition = gaze.position;
		// TO-DO KALMAN::GlintFilter::correct(KALMAN::GlintFilter::GAZE, gazePostition.x, gazePostition.y, 100.0, 100.0, 40.0);

		ScreenspaceGazeResult filteredGaze(gazePostition);

		qDebug() << "Gaze:" << gaze.position.x << "/" << gaze.position.y;
		if (filteredGaze.valid)
			// TO-DO //result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), filteredGaze.position);
			result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), gaze.position);
		if (!filteredGaze.valid)
			result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), cv::Point2f(1,1));
		// TO-DO //result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), cv::Point2f(-1e6, -1e6));
		// ================================

		/*if(gaze.valid)
			result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), gaze.position);
		if (gaze.valid)
			result.frame2gaze.emplace(eyeVid.get(CV_CAP_PROP_POS_FRAMES), cv::Point2f(-1e6,-1e6));
			*/

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

		// save infos to file
		double time = eyeVideoDictionary.frame2time.at(frameCount);

		eyeFile << time << " " << pgci.pupilRight << " " << pgci.pupilLeft << "  " << pgci.glintRight_1 << " "
		<< pgci.glintRight_2 << " " << pgci.glintRight_3 << " " << pgci.glintLeft_1 <<
		" " << pgci.glintLeft_2 << " " << pgci.glintLeft_3 << gaze.position.x << " " << gaze.position.y << std::endl;
	}

	eyeFile << "End: " << eyeVideoDictionary.end_time << std::endl;

	qDebug() << "Eyevideo END-Timestamp: " << eyeVideoDictionary.end_time;

	// close file
	if (eyeFile.is_open())
	{
		eyeFile.close();
	}

	qDebug() << "Finished processing EyeVideos.";

	return result;
}

bool drawGaze(const std::string& source_video, const std::string& output_file,
	const VideoFrame2Timestamp& stimulus_meta,
	const VideoFrame2Timestamp& eye_meta,
	const VideoFrame2Gaze& gaze_meta,
	const cv::Rect& stimulus_playback_rect)
{
	qDebug() << "Creating output video file...";
	cv::VideoCapture stimulus = cv::VideoCapture::VideoCapture(source_video);

	if (!stimulus.isOpened())
	{
		qWarning() << "drawGaze: Couldn't open reader from " << source_video.c_str();
		//qWarning() << "drawGaze: Couldn't open reader from " << stimulus.c_str();
		return false;
	}

	int stimulus_width = stimulus.get(CV_CAP_PROP_FRAME_WIDTH);
	int stimulus_height = stimulus.get(CV_CAP_PROP_FRAME_HEIGHT);
	cv::Size stimulus_size = cv::Size(stimulus_width, stimulus_height);

	int userVideoFPS = stimulus.get(CV_CAP_PROP_FPS);

	// Original
	//cv::VideoWriter output_writer(output_file, lossy_video_codec, userVideoFPS, stimulus_size);

	//Works
	//cv::VideoWriter output_writer("output.avi", -1, 30, cv::Size(1904,1004));

	cv::VideoWriter output_writer(output_file, -1, userVideoFPS, stimulus_size, true);

	if (!output_writer.isOpened())
	{

		qWarning() << "drawGaze: Couldn't open outwards writer to " << output_file.c_str();
		qWarning() << "output_file: " << output_file.c_str() << ", lossy_video_codec: " << lossy_video_codec << ", FPS: " << userVideoFPS << ", stimulus Size: width: " << stimulus_width << " height: " << stimulus_height;
		stimulus.release();
		return false;
	}

	qDebug() << "Synchronizing estimated gaze points timestamps with stimulus... ";
	qDebug() << "Drawing gaze points...";
	drawGaze(&stimulus, &output_writer, stimulus_meta, eye_meta, gaze_meta, stimulus_playback_rect);
	qDebug() << "Finished drawing gaze points";

	stimulus.release();
	output_writer.release();   // not needed as the destructor of the videowriter already calls that function
	return true;
}

void drawGaze(cv::VideoCapture* stimulus, cv::VideoWriter* output_writer,
	const VideoFrame2Timestamp& stimulus_meta,
	const VideoFrame2Timestamp& eye_meta,
	const VideoFrame2Gaze& gaze_meta,
	const cv::Rect& stimulus_playback_rect)
{
	int userVideoWidth = stimulus->get(CV_CAP_PROP_FRAME_WIDTH);
	int userVideoHeight = stimulus->get(CV_CAP_PROP_FRAME_HEIGHT);
	const double scalex = userVideoWidth / static_cast<double>(stimulus_playback_rect.width);
	const double scaley = userVideoHeight / static_cast<double>(stimulus_playback_rect.height);

	cv::Size output_size = cv::Size(userVideoWidth, userVideoHeight);

	stimulus->set(CV_CAP_PROP_POS_FRAMES, 0);

	while (stimulus->get(CV_CAP_PROP_POS_FRAMES) < stimulus->get(CV_CAP_PROP_FRAME_COUNT) - 1)
	{
		// 1. read frame from user video
		cv::Mat img;
		stimulus->read(img);

		if (stimulus_meta.frame2time.find(stimulus->get(CV_CAP_PROP_POS_FRAMES)) == stimulus_meta.frame2time.end()
			|| stimulus_meta.frame2time.find(stimulus->get(CV_CAP_PROP_POS_FRAMES) + 1) == stimulus_meta.frame2time.end())
		{
			cv::putText(img, "Stimulus Frame2Time Data missing.", cv::Point2f(20, 100), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255, 0, 0), 3);
			(*output_writer) << img;
			continue;
		}

		long currentUserFrameTime = stimulus_meta.frame2time.at(stimulus->get(CV_CAP_PROP_POS_FRAMES));
		long nextUserFrameTime = stimulus_meta.frame2time.at(stimulus->get(CV_CAP_PROP_POS_FRAMES) + 1);

		// 2. get corresponding gaze find all frames which timestamp is greater than the one from the user video but smaller than the NEXT timestamp of the uservideo frame timestamp

		//for (int i = 0; i < eye_meta.frame2time.size(); i++)
		// test
		for (int i = 0; i < eye_meta.frame2time.size(); i++)
		{
			if (eye_meta.frame2time.at(i) >= currentUserFrameTime && eye_meta.frame2time.at(i) < nextUserFrameTime)
			{
				// 3. draw gaze on it
				// check if index i is valid by checking count(). Count returns 1 if mapping from key i exists
				if(gaze_meta.frame2gaze.count(i))
				{

					const cv::Point2f pog_screenspace = gaze_meta.frame2gaze.at(i);
					const cv::Point2f pog_translated = cv::Point2f(pog_screenspace.x - stimulus_playback_rect.tl().x,
						pog_screenspace.y - stimulus_playback_rect.tl().y);
					const cv::Point2f point_of_gaze(pog_translated.x * scalex, pog_translated.y * scaley);

					if (point_of_gaze.x < 0 || point_of_gaze.y < 0 || std::isnan(point_of_gaze.x) || std::isnan(point_of_gaze.y))
					{
						cv::putText(img, "No detection.", cv::Point2f(20, 100), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255, 0, 0), 3);
						//cv::drawMarker(img, Point(10,10), cv::Scalar(255, 0, 255), MARKER_CROSS, 40, 2);
					}
					else if (point_of_gaze.x > output_size.width || point_of_gaze.y > output_size.height)
					{
						cv::putText(img, "Outside bounds.", cv::Point2f(20, 100), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255, 0, 0), 3);
					}
					else
					{
						//cv::drawMarker(img, gaze2frame[i], cv::Scalar(255, 255, 0), MARKER_CROSS, 40, 2);
						qDebug() << "drawing gaze at " << gaze_meta.frame2gaze.at(i).x << " / " << gaze_meta.frame2gaze.at(i).y;
						cv::circle(img, gaze_meta.frame2gaze.at(i), 10, cv::Scalar(0, 0, 255), CV_FILLED, 8, 0);
					}

					// 4. save frame in new file
					(*output_writer) << img;

					qDebug() << "drawing gaze" << i;
					cv::imshow("Frame1", img);
					cv::waitKey(1);

				}
				else
				{
					break;
				}
			}
		}
	}

}

void drawFeatures(cv::Mat& frame, const DetectedFeatures& features, EyePosition eye)
{
	SingleEyeFeatures our_features = features.eye(eye);

	// glints
	for (size_t i = 0; i < SingleEyeFeatures::num_glints; i++)
	{
		if (!our_features.glintValid(i))
			continue;

		// first glint gets special drawing
		cv::Scalar color = i == 0 ? cv::Scalar(0, 255, 0) : cv::Scalar(0, 0, 255);
		cv::circle(frame, our_features.glint(i), 2, color, 1, 8, 0);
		cv::drawMarker(frame, our_features.glint(i), color, cv::MARKER_CROSS, 5, 1);
	}

	if(our_features.pupilValid())
	{
		cv::drawMarker(frame, our_features.pupil_center(), cv::Scalar(0, 255, 0), cv::MARKER_CROSS, 10, 1);
	}

}

void drawFeatures(cv::Mat& frame, const DetectedFeatures& instance)
{
	drawFeatures(frame, instance, EyePosition::RIGHT);
	drawFeatures(frame, instance, EyePosition::LEFT);
}

max_stars_repo_name: dmikushin/RemoteEye

max_issues_repo_name: dmikushin/RemoteEye

max_forks_repo_name: dmikushin/RemoteEye