text: #include <boost/log/expressions/predicates/ends_with.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#pragma once

#include <boost/aura/base/allocation_tracker.hpp>
#include <boost/aura/base/check_initialized.hpp>
#include <boost/aura/base/metal/safecall.hpp>
#include <boost/aura/platform.hpp>

#include <TargetConditionals.h>
#import <Metal/Metal.h>

#include <cstddef>

#if ! __has_feature(objc_arc)
#error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag
#endif

namespace boost
{
namespace aura
{
namespace base_detail
{
namespace metal
{

class device
{
public:
        /// Query the number of devices in the system.
        static std::size_t num()
        {
#if TARGET_IPHONE_SIMULATOR == 1
                return 0;
#elif TARGET_OS_IPHONE == 1
                return 1;
#elif TARGET_OS_MAC == 1
                return [MTLCopyAllDevices() count];
#endif
        }

public:
        /// @copydoc boost::aura::base::cuda::device::device()
        inline explicit device()
                : initialized_(false)
                , ordinal_(-1)
        {
        }

        /// @copydoc boost::aura::base::cuda::device::device(std::size_t)
        inline explicit device(std::size_t ordinal)
                : initialized_(false)
                , ordinal_(ordinal)
        {
                device_ = MTLCreateSystemDefaultDevice();
                AURA_METAL_CHECK_ERROR(device_);
                initialized_ = true;
        }

        /// Prevent copies.
        device(const device&) = delete;
        void operator=(const device&) = delete;

        /// Move construct.
        device(device&& other)
                : initialized_(other.initialized_)
                , ordinal_(other.ordinal_)
                , device_(other.device_)
        {
                other.initialized_ = false;
                other.ordinal_ = -1;
        }

        /// Move assign.
        device& operator=(device&& other)
        {
                reset();

                initialized_ = other.initialized_;
                ordinal_ = other.ordinal_;
                device_ = other.device_;

                other.initialized_ = false;
                other.ordinal_ = -1;
                return *this;
        }

        // Reset.
        inline void reset()
        {
                if (initialized_)
                {
                        device_ = nil;
                        initialized_ = false;
                }
                ordinal_ = -1;
        }

        /// @copydoc boost::aura::base::cuda::device::~device()
        inline ~device() { reset(); }

        /// @copydoc boost::aura::base::cuda::device::get_base_device()
        inline id<MTLDevice> get_base_device()
        {
                AURA_CHECK_INITIALIZED(initialized_);
                return device_;
        }

        /// @copydoc boost::aura::base::cuda::device::get_ordinal()
        inline std::size_t get_ordinal() const
        {
                AURA_CHECK_INITIALIZED(initialized_);
                return ordinal_;
        }

        /// @copydoc boost::aura::base::cuda::device::activate()
        inline void activate() const { AURA_CHECK_INITIALIZED(initialized_); }

        /// @copydoc boost::aura::base::cuda::device::deactivate()
        inline void deactivate() const { AURA_CHECK_INITIALIZED(initialized_); }

        /// Query initialized state.
        inline bool initialized() const { return initialized_; }

        /// Shared memory.
        bool supports_shared_memory() const
        {
                return platform::supports_shared_memory;
        }

        /// Allocation tracker.
        boost::aura::detail::allocation_tracker allocation_tracker;

private:
        /// Initialized flag
        bool initialized_;

        /// Device ordinal
        std::size_t ordinal_;

        /// Device handle
        id<MTLDevice> device_;
};

} // namespace metal
} // namespace base_detail
} // namespace aura
} // namespace boost

max_stars_repo_name: sschaetz/aura

max_issues_repo_name: sschaetz/aura

max_forks_repo_name: sschaetz/aura


text:
#define BOOST_TEST_MODULE "test_datasetManager_REST"

#include "Config.hpp"
#include "Hash.hpp"
#include "restClient.hpp"
#include "restServer.hpp"
#include "visUtil.hpp"

#include "fmt.hpp"
#include "json.hpp"

#include <boost/test/included/unit_test.hpp>
#include <iostream>
#include <string>

// the code to test:
#include "datasetManager.hpp"

using kotekan::connectionInstance;
using kotekan::restServer;

using json = nlohmann::json;

using namespace std::string_literals;

struct TestContext {

    std::atomic<size_t> _dset_id_count;

    void init() {
        _dset_id_count = 0;
        restServer::instance().register_post_callback(
            "/register-state", std::bind(&TestContext::register_state, this, std::placeholders::_1,
                                         std::placeholders::_2));
        restServer::instance().register_post_callback(
            "/send-state", std::bind(&TestContext::send_state, this, std::placeholders::_1,
                                     std::placeholders::_2));
        restServer::instance().register_post_callback(
            "/register-dataset", std::bind(&TestContext::register_dataset, this,
                                           std::placeholders::_1, std::placeholders::_2));
        usleep(1000);
    }

    void register_state(connectionInstance& con, json& js) {
        DEBUG_NON_OO("test: /register-state received:\n{:s}", js.dump(4));
        json reply;
        try {
            js.at("hash");
        } catch (std::exception& e) {
            std::string error =
                fmt::format("Failure parsing register state message from datasetManager: {}\n{}.",
                            js.dump(), e.what());
            reply["result"] = error;
            con.send_json_reply(reply);
            BOOST_CHECK_MESSAGE(false, error);
        }

        BOOST_CHECK(js.at("hash").is_string());
        reply["request"] = "get_state";
        reply["hash"] = js.at("hash");
        reply["result"] = "success";
        con.send_json_reply(reply);
        DEBUG_NON_OO("test: /register-state: replied with:\n{:s}", reply.dump(4));
    }

    void send_state(connectionInstance& con, json& js) {
        DEBUG_NON_OO("test: /send-state received:\n{:s}", js.dump(4));
        json reply;
        try {
            js.at("hash");
            js.at("state");
            js.at("state").at("type");
            js.at("state").at("data");
        } catch (std::exception& e) {
            std::string error = fmt::format(fmt("Failure parsing send-state message from "
                                                "datasetManager:\n{:s}\n{:s}."),
                                            js.dump(4), e.what());
            reply["result"] = error;
            con.send_json_reply(reply);
            BOOST_CHECK_MESSAGE(false, error);
        }

        BOOST_CHECK(js.at("hash").is_string());

        // check the received state
        static std::vector<input_ctype> inputs = {input_ctype(1, "1"), input_ctype(2, "2"),
                                                  input_ctype(3, "3")};
        static std::vector<prod_ctype> prods = {{1, 1}, {2, 2}, {3, 3}};
        static std::vector<std::pair<uint32_t, freq_ctype>> freqs = {
            {1, {1.1, 1}}, {2, {2, 2.2}}, {3, {3, 3}}};

        static state_uptr states[3] = {std::make_unique<inputState>(inputs),
                                       std::make_unique<prodState>(prods),
                                       std::make_unique<freqState>(freqs)};
        static bool pass[3] = {false, false, false};
        state_uptr received_state = datasetState::from_json(js.at("state"));

        for (ushort i = 0; i < 4; i++) {
            BOOST_CHECK(i < 4);
            if (states[i]->to_json() == received_state->to_json()) {
                BOOST_CHECK(pass[i] == false);
                pass[i] = true;
                break;
            }
        }

        reply["result"] = "success";
        con.send_json_reply(reply);
        DEBUG_NON_OO("test: /send-state: replied with\n{:s}", reply.dump(4));
    }

    void register_dataset(connectionInstance& con, json& js) {
        DEBUG_NON_OO("test: /register-dataset received:\n{:s}", js.dump(4));
        json reply;
        json js_ds;
        try {
            js.at("hash");
            js_ds = js.at("ds");
            js_ds.at("is_root");
            js_ds.at("state");
            if (!js_ds.at("is_root"))
                js_ds.at("base_dset");
        } catch (std::exception& e) {
            std::string error = fmt::format("Failure parsing register-dataset message from "
                                            "datasetManager: {}\n{}.",
                                            js.dump(), e.what());
            reply["result"] = error;
            con.send_json_reply(reply);
            BOOST_CHECK_MESSAGE(false, error);
        }

        BOOST_CHECK(js_ds.at("state").is_string());
        if (!js_ds.at("is_root"))
            BOOST_CHECK(js_ds.at("base_dset").is_string());
        BOOST_CHECK(js_ds.at("is_root").is_boolean());
        BOOST_CHECK(js.at("hash").is_string());

        BOOST_CHECK(hash(js_ds.dump()) == Hash::from_string(js.at("hash")));

        reply["result"] = "success";
        con.send_json_reply(reply);
        DEBUG_NON_OO("test: /register-dataset: replied with\n{:s}", reply.dump(4));
    }
};

BOOST_FIXTURE_TEST_CASE(_dataset_manager_general, TestContext) {
    _global_log_level = 4;
    __enable_syslog = 0;

    json json_config;
    json_config["use_dataset_broker"] = true;

    // kotekan restServer endpoints defined above. Start with random free port.
    restServer::instance().start("127.0.0.1", 0);
    usleep(10000);
    json_config["ds_broker_port"] = restServer::instance().port;
    std::cout << "Running RESTserver on port " << json_config["ds_broker_port"] << " for dM test."
              << std::endl;

    TestContext::init();

    kotekan::Config conf;
    conf.update_config(json_config);
    datasetManager& dm = datasetManager::instance(conf);

    // generate datasets:
    std::vector<input_ctype> inputs = {input_ctype(1, "1"), input_ctype(2, "2"),
                                       input_ctype(3, "3")};
    std::vector<prod_ctype> prods = {{1, 1}, {2, 2}, {3, 3}};
    std::vector<std::pair<uint32_t, freq_ctype>> freqs = {
        {1, {1.1, 1}}, {2, {2, 2.2}}, {3, {3, 3}}};

    std::vector<state_id_t> states1;
    states1.push_back(dm.create_state<freqState>(freqs).first);
    states1.push_back(dm.create_state<prodState>(prods).first);
    states1.push_back(dm.create_state<inputState>(inputs).first);

    dset_id_t init_ds_id = dm.add_dataset(states1);

    // register first state again
    std::vector<state_id_t> states2;
    states2.push_back(dm.create_state<freqState>(freqs).first);
    states2.push_back(dm.create_state<prodState>(prods).first);
    states2.push_back(dm.create_state<inputState>(inputs).first);

    // register new dataset with the twin state
    dm.add_dataset(states2, init_ds_id);

    std::cout << dm.summary() << std::endl;

    for (auto s : dm.states())
        std::cout << s.first << " - " << s.second->data_to_json().dump() << std::endl;

    for (auto s : dm.datasets())
        std::cout << s.second.state() << " - " << s.second.base_dset() << std::endl;

    usleep(500000);
}

ext: cpp

max_stars_repo_name: james-s-willis/kotekan

max_issues_repo_name: james-s-willis/kotekan

max_forks_repo_name: james-s-willis/kotekan


text:
#include <Alembic/Util/All.h>
#include <Alembic/AbcCoreAbstract/All.h>
#include <Alembic/AbcCoreOgawa/All.h>
#ifdef SIMBA_ENABLE_ALEMBIC_HDF5
#include <Alembic/AbcCoreHDF5/All.h>
#endif // SIMBA_ENABLE_ALEMBIC_HDF5
#include <Alembic/Abc/All.h>
#include <Alembic/AbcCoreFactory/All.h>
#include <Alembic/AbcGeom/All.h>
#include <Alembic/AbcCollection/All.h>
#include <Alembic/AbcMaterial/All.h>

#include <boost/tokenizer.hpp>
#include <boost/format.hpp>

typedef std::vector<std::string> PathList;

void TokenizePath( const std::string &path, PathList &result )
{
    typedef boost::char_separator<char> Separator;
    typedef boost::tokenizer<Separator> Tokenizer;

    Tokenizer tokenizer( path, Separator( "/" ) );

    for ( Tokenizer::iterator iter = tokenizer.begin() ; iter != tokenizer.end() ;
          ++iter )
    {
        if ( (*iter).empty() ) { continue; }

        result.push_back( *iter );
    }
}

void arbitrary_geometry_attributes(const Alembic::AbcGeom::ICompoundProperty& arbParams)
{
	size_t num_properties = arbParams.getNumProperties();
	std::cout << boost::format(", user_properties(%1%)") % num_properties;
}

void iterate_hierarchy(const Alembic::Abc::IObject& top, size_t level = 0)
{
	size_t numChildren = top.getNumChildren();

	for (size_t i=0;i<numChildren;i++)
	{
		std::string child_name =top.getChildHeader(i).getName();
		for (size_t indent=0;indent<level;indent++)
			std::cout << "  ";
		std::cout << boost::format("name : %1%") % child_name;
		Alembic::Abc::IObject child(top,child_name);
		const Alembic::Abc::MetaData &child_md = child.getMetaData();
		if (Alembic::AbcGeom::IPolyMeshSchema::matches(child_md))
		{
			std::cout << " of type PolyMesh";
	        Alembic::AbcGeom::IPolyMesh mesh(top,child_name);
	        Alembic::AbcGeom::IPolyMeshSchema& schema = mesh.getSchema();

	        arbitrary_geometry_attributes(schema.getArbGeomParams());
	        size_t num_properties = schema.getNumProperties();
	    	std::cout << boost::format(", geometry_properties(%1%)") % num_properties;
	    	Alembic::Abc::IV3fArrayProperty velocities_property = schema.getVelocitiesProperty();
	    	if (velocities_property.valid())
		    	std::cout << ", has velocity";
	    	else
	    		std::cout << ", does NOT have velocity";
		}
		else if (Alembic::AbcGeom::IPointsSchema::matches(child_md))
		{
			std::cout << " of type Points";
	        Alembic::AbcGeom::IPoints points(top,child_name);
	        Alembic::AbcGeom::IPointsSchema& schema = points.getSchema();

	        arbitrary_geometry_attributes(schema.getArbGeomParams());
		}
		else if (Alembic::AbcGeom::IXformSchema::matches(child_md))
		{
			std::cout << " of type Xform";
		}
		else if (Alembic::AbcGeom::ICurvesSchema::matches(child_md))
		{
			std::cout << " of type Curves";
		}
		std::cout << std::endl;
		iterate_hierarchy(child,level+1);
	}
}

int main(int argc, char** argv)
{
    if (argc != 2)
    {
        std::cerr << "Usage : " << argv[0] << " <Alembic Archive>" << std::endl;
        return 1;
    }
    std::string m_fileName(argv[1]);
    Alembic::AbcGeom::IArchive m_archive;
    m_archive = Alembic::AbcGeom::IArchive( Alembic::AbcCoreOgawa::ReadArchive(),
            m_fileName );
    uint32_t numSamplings = m_archive.getNumTimeSamplings();
    std::cout << "archive_num_samples = " << numSamplings << std::endl;
    if (numSamplings > 1)
    {
        Alembic::Abc::chrono_t min = m_archive.getTimeSampling(1)->getSampleTime(0);
        std::cout << "min time = " << min << std::endl;
        Alembic::Abc::chrono_t max = m_archive.getTimeSampling(1)->getSampleTime(1);
        std::cout << "max time = " << max << std::endl;
        size_t numStoredTimes = m_archive.getTimeSampling(1)->getNumStoredTimes();
        std::cout << "numStoredTimes = " << numStoredTimes << std::endl;
        for (Alembic::Util::uint32_t s = 2; s < numSamplings; ++s)
        {
            Alembic::Abc::chrono_t current_min = m_archive.getTimeSampling(s)->getSampleTime(0);
            std::cout << "current_min = " << current_min << std::endl;

        }

    }
    Alembic::Abc::IObject top = m_archive.getTop();
    iterate_hierarchy(top);

    return 0;
}

// == Emacs ================
// -------------------------
// Local variables:
// tab-width: 4
// indent-tabs-mode: t
// c-basic-offset: 4
// end:
//
// == vi ===================
// -------------------------
// Format block
// ex:ts=4:sw=4:expandtab
// -------------------------


text:
//
// Boost.Process
//
// Copyright (c) 2006 Julio M. Merino Vidal.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt.)
//

//!
//! \file boost/process/detail/posix_ops.hpp
//!
//! Provides some convenience functions to start processes under POSIX
//! operating systems.
//!

#if !defined(BOOST_PROCESS_DETAIL_POSIX_OPS_HPP)
/** \cond */
#define BOOST_PROCESS_DETAIL_POSIX_OPS_HPP
/** \endcond */

#include <boost/process/config.hpp>

#if !defined(BOOST_PROCESS_POSIX_API)
#   error "Unsupported platform."
#endif

extern "C" {
#   include <fcntl.h>
#   include <unistd.h>
#   include <semaphore.h>
#   include <signal.h>
}

#include <cerrno>
#include <cstdlib>
#include <map>
#include <set>

#include <boost/optional.hpp>
#include <boost/process/detail/command_line_ops.hpp>
#include <boost/process/detail/environment.hpp>
#include <boost/process/detail/file_handle.hpp>
#include <boost/process/detail/pipe.hpp>
#include <boost/process/detail/stream_info.hpp>
#include <boost/process/exceptions.hpp>
#include <boost/process/stream_behavior.hpp>
#include <boost/scoped_array.hpp>
#include <boost/throw_exception.hpp>

namespace boost {
namespace process {
namespace detail {

// ------------------------------------------------------------------------

//!
//! Holds a mapping between native file descriptors and their corresponding
//! pipes to set up communication between the parent and the %child process.
//!
typedef std::map< int, stream_info > info_map;

//!
//! Maintains a list of file descriptor pairs, aimed at keeping a list of
//! stream merges (source descriptor, target descriptor).
//!
typedef std::set< std::pair< int, int > > merge_set;

// ------------------------------------------------------------------------

//!
//! \brief Helper class to configure a POSIX %child.
//!
//! This helper class is used to hold all the attributes that configure a
//! new POSIX %child process and to centralize all the actions needed to
//! make them effective.
//!
//! All its fields are public for simplicity.  It is only intended for
//! internal use and it is heavily coupled with the Launcher
//! implementations.
//!
struct posix_setup
{
    //!
    //! \brief The work directory.
    //!
    //! This string specifies the directory in which the %child process
    //! starts execution.  It cannot be empty.
    //!
    std::string m_work_directory;

    //!
    //! \brief The user credentials.
    //!
    //! UID that specifies the user credentials to use to run the %child
    //! process.  Defaults to the current UID.
    //!
    uid_t m_uid;

    //!
    //! \brief The effective user credentials.
    //!
    //! EUID that specifies the effective user credentials to use to run
    //! the %child process.  Defaults to the current EUID.
    //!
    uid_t m_euid;

    //!
    //! \brief The group credentials.
    //!
    //! GID that specifies the group credentials to use to run the %child
    //! process.  Defaults to the current GID.
    //!
    uid_t m_gid;

    //!
    //! \brief The effective group credentials.
    //!
    //! EGID that specifies the effective group credentials to use to run
    //! the %child process.  Defaults to the current EGID.
    //!
    uid_t m_egid;

    //!
    //! \brief The chroot directory, if any.
    //!
    //! Specifies the directory in which the %child process is chrooted
    //! before execution.  Empty if this feature is not desired.
    //!
    std::string m_chroot;

    //!
    //! \brief Creates a new properties set.
    //!
    //! Creates a new object that has sensible default values for all the
    //! properties.
    //!
    posix_setup(void);

    //!
    //! \brief Sets up the execution environment.
    //!
    //! Modifies the current execution environment (that of the %child) so
    //! that the properties become effective.
    //!
    //! \throw system_error If any error ocurred during environment
    //!                     configuration.  The child process should abort
    //!                     execution if this happens because its start
    //!                     conditions cannot be met.
    //!
    void operator()(void) const;
};

// ------------------------------------------------------------------------

inline
posix_setup::posix_setup(void) :
    m_uid(::getuid()),
    m_euid(::geteuid()),
    m_gid(::getgid()),
    m_egid(::getegid())
{
}

// ------------------------------------------------------------------------

inline
void
posix_setup::operator()(void)
    const
{
    if (!m_chroot.empty()) {
        if (::chroot(m_chroot.c_str()) == -1)
            boost::throw_exception
                (system_error("boost::process::detail::posix_setup",
                              "chroot(2) failed", errno));
    }

    if (m_gid != ::getgid()) {
        if (::setgid(m_gid) == -1)
            boost::throw_exception
                (system_error("boost::process::detail::posix_setup",
                              "setgid(2) failed", errno));
    }

    if (m_egid != ::getegid()) {
        if (::setegid(m_egid) == -1)
            boost::throw_exception
                (system_error("boost::process::detail::posix_setup",
                              "setegid(2) failed", errno));
    }

    if (m_uid != ::getuid()) {
        if (::setuid(m_uid) == -1)
            boost::throw_exception
                (system_error("boost::process::detail::posix_setup",
                              "setuid(2) failed", errno));
    }

    if (m_euid != ::geteuid()) {
        if (::seteuid(m_euid) == -1)
            boost::throw_exception
                (system_error("boost::process::detail::posix_setup",
                              "seteuid(2) failed", errno));
    }

    BOOST_ASSERT(m_work_directory != "");
    if (chdir(m_work_directory.c_str()) == -1)
        boost::throw_exception
            (system_error("boost::process::detail::posix_setup",
                          "chdir(2) failed", errno));
}

// ------------------------------------------------------------------------

//!
//! \brief Configures child process' input streams.
//!
//! Sets up the current process' input streams to behave according to the
//! information in the \a info map.  \a closeflags is modified to reflect
//! those descriptors that should not be closed because they where modified
//! by the function.
//!
//! Modifies the current execution environment, so this should only be run
//! on the child process after the fork(2) has happened.
//!
//! \throw system_error If any error occurs during the configuration.
//!
inline
void
setup_input(info_map& info, bool closeflags[], int maxdescs)
{
    for (info_map::iterator iter = info.begin(); iter != info.end(); iter++) {
        int d = (*iter).first;
        stream_info& si = (*iter).second;

        BOOST_ASSERT(d < maxdescs);
        closeflags[d] = false;

        if (si.m_type == stream_info::usefile) {
            int fd = ::open(si.m_file.c_str(), O_RDONLY);
            if (fd == -1)
                boost::throw_exception
                    (system_error("boost::process::detail::setup_input",
                                  "open(2) of " + si.m_file + " failed",
                                  errno));
            if (fd != d) {
                file_handle h(fd);
                h.posix_remap(d);
                h.disown();
            }
        } else if (si.m_type == stream_info::usehandle) {
            if (si.m_handle.get() != d)
                si.m_handle.posix_remap(d);
        } else if (si.m_type == stream_info::usepipe) {
            si.m_pipe->wend().close();
            if (d != si.m_pipe->rend().get())
                si.m_pipe->rend().posix_remap(d);
        } else
            BOOST_ASSERT(si.m_type == stream_info::inherit);
    }
}

// ------------------------------------------------------------------------

//!
//! \brief Configures child process' output streams.
//!
//! Sets up the current process' output streams to behave according to the
//! information in the \a info map and in the \a merges set.  \a closeflags
//! is modified to reflect those descriptors that should not be closed
//! because they where modified by the function.
//!
//! Modifies the current execution environment, so this should only be run
//! on the child process after the fork(2) has happened.
//!
//! \throw system_error If any error occurs during the configuration.
//!
inline
void
setup_output(info_map& info, merge_set& merges, bool closeflags[],
             int maxdescs)
{
    for (info_map::iterator iter = info.begin(); iter != info.end(); iter++) {
        int d = (*iter).first;
        stream_info& si = (*iter).second;

        BOOST_ASSERT(d < maxdescs);
        closeflags[d] = false;

        if (si.m_type == stream_info::usefile) {
            int fd = ::open(si.m_file.c_str(), O_WRONLY);
            if (fd == -1)
                boost::throw_exception
                    (system_error("boost::process::detail::setup_output",
                                  "open(2) of " + si.m_file + " failed",
                                  errno));
            if (fd != d) {
                file_handle h(fd);
                h.posix_remap(d);
                h.disown();
            }
        } else if (si.m_type == stream_info::usehandle) {
            if (si.m_handle.get() != d)
                si.m_handle.posix_remap(d);
        } else if (si.m_type == stream_info::usepipe) {
            si.m_pipe->rend().close();
            if (d != si.m_pipe->wend().get())
                si.m_pipe->wend().posix_remap(d);
        } else
            BOOST_ASSERT(si.m_type == stream_info::inherit);
    }

    for (merge_set::const_iterator iter = merges.begin();
         iter != merges.end(); iter++) {
        const std::pair< int, int >& p = (*iter);
        file_handle fh = file_handle::posix_dup(p.second, p.first);
        fh.disown();
        BOOST_ASSERT(p.first < maxdescs);
        closeflags[p.first] = false;
    }
}

// ------------------------------------------------------------------------

#if defined(FD_CLOEXEC) && defined(__AIX__)
inline int
set_cloexec_flag (int desc, bool value = true)
{
    int oldflags = fcntl (desc, F_GETFD, 0);
    // If reading the flags failed, return error indication now.
    if (oldflags < 0)
        return oldflags;
    // Set just the flag we want to set.
    if (value)
        oldflags |= FD_CLOEXEC;
    else
        oldflags &= ~FD_CLOEXEC;
    // Store modified flag word in the descriptor.
    return fcntl (desc, F_SETFD, oldflags);
}
#endif

//!
//! \brief Starts a new child process in a POSIX operating system.
//!
//! This helper functions is provided to simplify the Launcher's task when
//! it comes to starting up a new process in a POSIX operating system.
//! The function hides all the details of the fork/exec pair of calls as
//! well as all the setup of communication pipes and execution environment.
//!
//! \param cl The command line used to execute the child process.
//! \param env The environment variables that the new child process
//!            receives.
//! \param infoin A map describing all input file descriptors to be
//!               redirected.
//! \param infoout A map describing all output file descriptors to be
//!                redirected.
//! \param merges A list of output file descriptors to be merged.
//! \param setup A helper object used to configure the child's execution
//!              environment.
//! \return The new process' PID.  The caller is responsible of creating
//!         an appropriate Child representation for it.
//!
template< class Command_Line >
inline
pid_t
posix_start(const Command_Line& cl,
            const environment& env,
            info_map& infoin,
            info_map& infoout,
            merge_set& merges,
            const posix_setup& setup)
{

    // before we fork, we create a semaphore.  That semaphore is shared between
    // both processes - we use it for synching parent and child.
    char buf[64];
    snprintf (buf, 64, "%d%c", int (::getpid ()), '\0');

    std::string sem_name;
    sem_name  = "/tmp.boost.process";
    sem_name += buf;

    sem_t * sem = ::sem_open (sem_name.c_str (), O_CREAT,
                            S_IRUSR | S_IWUSR, 0);

    if ( ((sem_t*)SEM_FAILED) == sem )
    {
        boost::throw_exception
            (system_error("boost::process::detail::posix_start",
                          "sem_open (3) failed", errno));
    }

    // also, we ignore SIGPIPE: there is no (good) way to know when to stop
    // writing to the childs stdin in the case of premature death of that
    // child...
    if ( SIG_ERR == ::signal (SIGPIPE, SIG_IGN) )
    {
        boost::throw_exception
            (system_error("boost::process::detail::posix_start",
                          "signal (2) failed (tried to ignore SIGPIPE)", errno));
    }

    pid_t pid = ::fork();
    if (pid == -1) {
        boost::throw_exception
            (system_error("boost::process::detail::posix_start",
                          "fork(2) failed", errno));
    } else if (pid == 0) {

#if defined(F_MAXFD)
        int maxdescs = std::max(::fcntl(0, F_MAXFD), 128); // XXX
#else
        int maxdescs = 128; // XXX
#endif
        try {
            boost::scoped_array<bool> closeflags(new bool[maxdescs]);

            for (int i = 0; i < maxdescs; i++)
                closeflags[i] = true;

            setup_input(infoin, closeflags.get(), maxdescs);
            setup_output(infoout, merges, closeflags.get(), maxdescs);

            for (int i = 0; i < maxdescs; i++) {
                if (closeflags[i]) {
#if defined(FD_CLOEXEC) && defined(__AIX__)
                    set_cloexec_flag(i);
#else
                    ::close(i);
#endif
                }
            }

            setup();
        }
        catch (const system_error& e) {
            ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
            ::write(STDERR_FILENO, "\n", 1);
            // ::exit(EXIT_FAILURE);
            // tell parent that something went REALLY wrong
            ::abort();
        }

        std::pair< std::size_t, char** > args = command_line_to_posix_argv(cl);
        char** envp = env.envp();

        // before calling exec, make sure the parent has all io
        // channels set up, so that we don't loose any initial io.
        ::sem_wait (sem);

        // clean up the semaphore
        ::sem_close  (sem);
        ::sem_unlink (sem_name.c_str ());

        ::execve(cl.get_executable().c_str(), args.second, envp);

        system_error e("boost::process::detail::posix_start",
                       "execve(2) failed", errno);

        for (std::size_t i = 0; i < args.first; i++)
            delete [] args.second[i];
        delete [] args.second;

        for (std::size_t i = 0; i < env.size(); i++)
            delete [] envp[i];
        delete [] envp;

        ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
        ::write(STDERR_FILENO, "\n", 1);

        // ::exit(EXIT_FAILURE);
        // tell parent that something went REALLY wrong
        ::abort();
    }
    else
    {
        // parent branch

        BOOST_ASSERT(pid > 0);

        for (info_map::iterator iter = infoin.begin();
             iter != infoin.end(); iter++) {
            stream_info& si = (*iter).second;

            if (si.m_type == stream_info::usepipe)
                si.m_pipe->rend().close();
        }

        for (info_map::iterator iter = infoout.begin();
             iter != infoout.end(); iter++) {
            stream_info& si = (*iter).second;

            if (si.m_type == stream_info::usepipe)
                si.m_pipe->wend().close();
        }

        // signal the child that we are done with io setup.
        // child can now call exec.
        ::sem_post (sem);
        ::sem_close (sem);
    }

    return pid;
}

// ------------------------------------------------------------------------

//!
//! \brief Converts a stream_behavior to a info_map entry.
//!
//! Given a stream_behavior \a beh, a file descriptor \a desc and whether
//! it is an input flow on an output one (\a out), inserts the appropriate
//! information representing this stream in the \a info map.
//!
inline
void
posix_behavior_to_info(stream_behavior beh, int desc, bool out,
                       info_map& info, std::string const& filename = "")
{
    if (beh == inherit_stream) {
        stream_info si;
        si.m_type = stream_info::inherit;
        info.insert(info_map::value_type(desc, si));
    } else if (beh == silent_stream) {
        stream_info si;
        si.m_type = stream_info::usefile;
        si.m_file = out ? "/dev/null" : "/dev/zero";
        info.insert(info_map::value_type(desc, si));
    } else if (beh == redirect_file) {
        stream_info si;
        si.m_type = stream_info::usefile;
        si.m_file = filename;
        info.insert(info_map::value_type(desc, si));
    } else if (beh == redirect_stream) {
        stream_info si;
        si.m_type = stream_info::usepipe;
        si.m_pipe = pipe();
        info.insert(info_map::value_type(desc, si));
    } else
        BOOST_ASSERT(beh == close_stream);
}

// ------------------------------------------------------------------------

//!
//! \brief Locates a communication pipe and returns one of its endpoints.
//!
//! Given a \a info map, and a file descriptor \a desc, searches for its
//! communicataion pipe in the map and returns one of its endpoins as
//! indicated by the \a out flag.  This is intended to be used by a
//! parent process after a fork(2) call.
//!
//! \pre If the info map contains the given descriptor, it is configured
//!      to use a pipe.
//! \post The info map does not contain the given descriptor.
//! \return If the file descriptor is found in the map, returns the pipe's
//!         read end if out is true; otherwise its write end.  If the
//!         descriptor is not found returns an invalid file handle.
//!
inline
file_handle
posix_info_locate_pipe(info_map& info, int desc, bool out)
{
    file_handle fh;

    info_map::iterator iter = info.find(desc);
    if (iter != info.end()) {
        BOOST_ASSERT(iter != info.end());
        stream_info& si = (*iter).second;
        BOOST_ASSERT(si.m_type == stream_info::usepipe);
        fh = out ? si.m_pipe->rend().disown() : si.m_pipe->wend().disown();
        BOOST_ASSERT(fh.is_valid());
        info.erase(iter);
    }

    return fh;
}

// ------------------------------------------------------------------------

} // namespace detail
} // namespace process
} // namespace boost

#endif // !defined(BOOST_PROCESS_DETAIL_POSIX_OPS_HPP)

max_stars_repo_name: saga-project/saga-cpp

max_issues_repo_name: saga-project/saga-cpp

max_forks_repo_name: saga-project/saga-cpp


text:
/***********************************************************************
This file is part of the librjmcmc project source files.

Copyright : Institut Geographique National (2008-2012)
Contributors : Mathieu Brédif, Olivier Tournaire, Didier Boldo
email : librjmcmc@ign.fr

This software is a generic C++ library for stochastic optimization.

This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
modify and/or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".

As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors have only limited liability.

In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.

The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.

***********************************************************************/

//[building_footprint_rectangle_gui_parameters
#include "rjmcmc-wx/wx_parameter.hpp"
typedef parameters< wx_parameter > param;
#include "building_footprint_rectangle_parameters_inc.hpp"
//]

//[building_footprint_rectangle_gui_core_include
#include "building_footprint_rectangle.hpp"
//]

//[building_footprint_rectangle_gui_visitors
#include "rjmcmc/simulated_annealing/visitor/composite_visitor.hpp"
#include "rjmcmc-wx/all.hpp"
#include "rjmcmc/simulated_annealing/visitor/any_visitor.hpp"
#include "rjmcmc/rjmcmc/sampler/any_sampler.hpp"
//]

#include "rjmcmc/simulated_annealing/salamon_initial_schedule.hpp"

//[building_footprint_rectangle_gui_specific
#include <boost/thread.hpp>
#include <boost/filesystem/operations.hpp>
#include <wx/app.h>
#include <wx/gdicmn.h>
//]

//[building_footprint_rectangle_gui_gilviewer_and_resources
#include <GilViewer/gui/basic_viewer_frame.hpp>
#include <GilViewer/gui/define_id.hpp>
#include <GilViewer/gui/panel_viewer.hpp>
#include <GilViewer/gui/panel_manager.hpp>
#include <GilViewer/gui/layer_control.hpp>
#include <GilViewer/io/gilviewer_io_factory.hpp>
#include <GilViewer/io/gilviewer_io_factory.hpp>
#include "rjmcmc-wx/gui/resources/IGN.xpm"
//]

#define NEEDS_XINITTHREADS 0// (wxMAJOR_VERSION>=3 && !defined(__WINDOWS__) && !defined(__WXOS2__))
#if NEEDS_XINITTHREADS
#include <X11/Xlib.h>
#endif

//[building_footprint_rectangle_gui_app_declaration
class building_footprint_rectangle_gui : public wxApp, public simulated_annealing::Controler
{
    //]
    //[building_footprint_rectangle_gui_app_typedef_visitor

    typedef simulated_annealing::composite_visitor<
            simulated_annealing::wx::log_visitor*,
            simulated_annealing::wx::configuration_visitor*,
            simulated_annealing::wx::parameters_visitor*,
            simulated_annealing::wx::chart_visitor*,
            simulated_annealing::wx::controler_visitor*
            > visitor;
    //] //_typedef_visitor

private:
    //[building_footprint_rectangle_gui_app_oninit
    bool OnInit()
    {
        /*<< Gilviewer IO factory initialization >>*/
        //register_all_file_formats();
        /*< Parameters processing >*/
        char **my_argv = new char*[argc];
        for (int i=0;i<argc;++i)
        {
            wxString mystr(argv[i]);
            my_argv[i] = new char[mystr.size()+1];
            strcpy(my_argv[i], mystr.To8BitData());
        }
        m_param = new param;
        initialize_parameters(m_param);
        if(!m_param->parse(argc,my_argv)) return false;
        /*< Various gui stuffs >*/
        wxSize frame_size;
        frame_size.x = std::min(800, wxGetClientDisplayRect().GetWidth());
        frame_size.y = std::min(600, wxGetClientDisplayRect().GetHeight());
        m_frame = new basic_viewer_frame((wxFrame *)NULL, wxID_ANY, _("librjmcmc: rectangular building footprint extraction"), wxDefaultPosition, frame_size);
        m_frame->SetIcon(wxICON(IGN));
        wxAuiManager * manager = m_frame->dockManager();
        panel_viewer::Register(m_frame,manager);
        m_panelviewer = panel_manager::instance()->create_object("PanelViewer");
        wxAuiPaneInfo paneInfoDrawPane;
        paneInfoDrawPane.Name( wxT("Viewer panel name") );
        paneInfoDrawPane.Caption( wxT("Viewer panel") );
        paneInfoDrawPane.TopDockable();
        paneInfoDrawPane.Center();
        paneInfoDrawPane.CloseButton(false);
        paneInfoDrawPane.CaptionVisible(false);
        manager->AddPane( m_panelviewer, paneInfoDrawPane );

        //create toolbars
        m_panelviewer->main_toolbar(m_frame,manager); // TODO : buttons do nothing
        m_panelviewer->mode_and_geometry_toolbar(m_frame,manager); // TODO : buttons do nothing

        m_frame->SetMenuBar( m_panelviewer->menubar() );
        m_frame->SetStatusText(wxT("GilViewer - Adrien Chauve & Olivier Tournaire"));

        m_confg_visitor = new simulated_annealing::wx::configuration_visitor(m_panelviewer);
        /*< Visitors initialization >*/

        m_param_visitor = new simulated_annealing::wx::parameters_visitor(m_panelviewer,m_param,m_frame);
        m_chart_visitor = new simulated_annealing::wx::chart_visitor(m_frame);
        m_contr_visitor = new simulated_annealing::wx::controler_visitor(this,m_frame);
        m_visitor = new visitor(&m_log_visitor,m_confg_visitor,m_param_visitor,m_chart_visitor,m_contr_visitor);

        m_contr_visitor->add_pane(manager);
        manager->Update();
        m_frame->Show();
        return true;
    }
    //]

public:

    void load_image(const std::string& file)
    {
        if(file=="") return;
        layer_control *lc = m_confg_visitor->panelviewer()->layercontrol();
        layer_control::const_iterator it  = lc->begin();
        layer_control::const_iterator end = lc->end();
        for(;it!=end;++it)
        {
            using namespace boost::filesystem;
            if((*it)->filename()==path(system_complete(file)).string())
            {
                return; // it;
            }
        }
        // return
                lc->add_layer_from_file(wxString(file.c_str(), *wxConvCurrent));
    }

    //[building_footprint_rectangle_gui_go
    virtual void go()
    {
        release();
        update_values(m_param);

        Iso_rectangle_2 bbox = get_bbox(m_param);
        std::string  dsm_file = m_param->get<boost::filesystem::path>("dsm").string();
        clip_bbox(bbox,dsm_file );

        gradient_functor gf(m_param->get<double>("sigmaD"));
        oriented_gradient_image grad_image(dsm_file,  bbox, gf);
        m_grad = grad_image.img();

        std::string  mask_file = m_param->get<boost::filesystem::path>("mask").string();

        load_image(dsm_file );
        load_image(mask_file);

        set_bbox(m_param,bbox);
        wxPoint p0(wxCoord(bbox.min().x()),wxCoord(bbox.min().y()));
        wxPoint p1(wxCoord(bbox.max().x()),wxCoord(bbox.max().y()));
        m_confg_visitor->set_bbox(wxRect(p0,p1));

        init_visitor        (m_param,*m_visitor);
        create_configuration(m_param,grad_image,m_config);
        //<-
        //    estimate_initial_temperature(p,100,*m_config);
        //->
        create_sampler      (m_param,m_sampler);
        create_schedule     (m_param,m_schedule);
        create_end_test     (m_param,m_end_test);

      //  std::cout << "Salamon initial schedule : " << salamon_initial_schedule(m_sampler->density(),*m_config,1000) << std::endl;
        m_config->clear();

        typedef rjmcmc::mt19937_generator Engine;
        Engine& e = rjmcmc::random();
        typedef rjmcmc::any_sampler<Engine,configuration> any_sampler;

        typedef rjmcmc::any_sampler<Engine,configuration> any_sampler;
        typedef simulated_annealing::any_visitor<configuration,any_sampler> any_visitor;

        any_sampler *sampler = new any_sampler(*m_sampler);
        any_visitor *visitor = new any_visitor(*m_visitor);

        m_thread = new boost::thread(
                simulated_annealing::optimize<Engine,configuration,any_sampler,schedule,end_test,any_visitor>,
                e, boost::ref(*m_config), boost::ref(*sampler),
                boost::ref(*m_schedule),   boost::ref(*m_end_test),
                boost::ref(*visitor) );
    }
    //]

    //[building_footprint_rectangle_gui_controller_overload
    virtual void stop() { m_end_test->stop(); }

    virtual void param_visibility(bool b) { m_param_visitor->Show(b); }
    virtual void chart_visibility(bool b) { m_chart_visitor->Show(b); }
    virtual bool param_visibility() const { return m_param_visitor->IsShown(); }
    virtual bool chart_visibility() const { return m_chart_visitor->IsShown(); }
    //]

    //[building_footprint_rectangle_gui_cons_des
    building_footprint_rectangle_gui() :
            m_config(NULL), m_sampler(NULL), m_schedule(NULL), m_end_test(NULL),
            m_visitor(NULL), m_thread(NULL), m_param(NULL),
            m_confg_visitor(NULL), m_param_visitor(NULL), m_chart_visitor(NULL)
    {
#if NEEDS_XINITTHREADS
	XInitThreads ();
#endif
    }

    virtual ~building_footprint_rectangle_gui() {
        release();
        //<-
        /*
        if(m_confg_visitor) { m_confg_visitor->Close(); }
        if(m_param_visitor) { m_param_visitor->Close(); }
        if(m_chart_visitor) { m_chart_visitor->Close(); }
        */
        //->
        if(m_visitor    ) { delete m_visitor; }
        if(m_param      ) { delete m_param; }
    }
    //]
private:
    //[building_footprint_rectangle_gui_release
    void release()
    {
        if(m_end_test){ m_end_test->stop(); }
        if(m_thread)  { m_thread->join(); delete m_thread; m_thread=NULL; }
        if(m_end_test){ delete m_end_test;m_end_test=NULL; }
        if(m_config)  { delete m_config;  m_config  =NULL; }
        if(m_schedule){ delete m_schedule;m_schedule=NULL; }
        if(m_sampler) { delete m_sampler; m_sampler =NULL; }
    }
    //]

    //[building_footprint_rectangle_gui_members
    configuration *m_config;
    sampler       *m_sampler;
    schedule      *m_schedule;
    end_test      *m_end_test;
    visitor       *m_visitor;
    boost::thread *m_thread;
    basic_viewer_frame *m_frame;
    panel_viewer *m_panelviewer;
    param        *m_param;

    simulated_annealing::wx::configuration_visitor *m_confg_visitor;
    simulated_annealing::wx::parameters_visitor    *m_param_visitor;
    simulated_annealing::wx::chart_visitor         *m_chart_visitor;
    simulated_annealing::wx::log_visitor            m_log_visitor;
    simulated_annealing::wx::controler_visitor     *m_contr_visitor;
    boost::shared_ptr<gradient_image_t>     m_grad;

    DECLARE_GILVIEWER_METHODS_FOR_EVENTS_TABLE();
    DECLARE_EVENT_TABLE();
};
//]

BEGIN_EVENT_TABLE(building_footprint_rectangle_gui,wxApp)
ADD_GILVIEWER_EVENTS_TO_TABLE(building_footprint_rectangle_gui)
END_EVENT_TABLE()

IMPLEMENTS_GILVIEWER_METHODS_FOR_EVENTS_TABLE(building_footprint_rectangle_gui,m_panelviewer);

//[building_footprint_rectangle_gui_implement
IMPLEMENT_APP(building_footprint_rectangle_gui);
//]

max_stars_repo_name: StOriJimmy/librjmcmc

max_issues_repo_name: StOriJimmy/librjmcmc

max_forks_repo_name: StOriJimmy/librjmcmc


text:
#if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES)

    #include <boost/proto/transform/detail/preprocessed/fold_impl.hpp>

#elif !defined(BOOST_PP_IS_ITERATING)

    #define BOOST_PROTO_CHILD_N_TYPE(N)                                                             \
        BOOST_PP_CAT(proto_child, N)                                                                \
        /**/

    #define BOOST_PROTO_FOLD_STATE_TYPE(Z, N, DATA)                                                 \
        typedef                                                                                \
            typename when<_, Fun>::template impl<                                                   \
                typename result_of::child_c<Expr, N>::type                                          \
              , BOOST_PP_CAT(state, N)                                                              \
              , Data                                                                                \
            >::result_type                                                                          \
        BOOST_PP_CAT(state, BOOST_PP_INC(N));                                                       \
        /**/

    #define BOOST_PROTO_FOLD_STATE(Z, N, DATA)                                                      \
        BOOST_PP_CAT(state, BOOST_PP_INC(N))                                                        \
        BOOST_PP_CAT(s, BOOST_PP_INC(N))                                                            \
          = typename when<_, Fun>::template impl<                                                   \
                typename result_of::child_c<Expr, N>::type                                          \
              , BOOST_PP_CAT(state, N)                                                              \
              , Data                                                                                \
            >()(                                                                                \
                proto::child_c<N>(e)                                                                \
              , BOOST_PP_CAT(s, N)                                                                  \
              , d                                                                                \
            );                                                                                \
        /**/

    #define BOOST_PROTO_REVERSE_FOLD_STATE_TYPE(Z, N, DATA)                                         \
        typedef                                                                                \
            typename when<_, Fun>::template impl<                                                   \
                typename result_of::child_c<                                                        \
                    Expr                                                                            \
                  , BOOST_PP_SUB(DATA, BOOST_PP_INC(N))                                             \
                >::type                                                                             \
              , BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, N))                                          \
              , Data                                                                                \
            >::result_type                                                                          \
        BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, BOOST_PP_INC(N)));                                   \
        /**/

    #define BOOST_PROTO_REVERSE_FOLD_STATE(Z, N, DATA)                                              \
        BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, BOOST_PP_INC(N)))                                    \
        BOOST_PP_CAT(s, BOOST_PP_SUB(DATA, BOOST_PP_INC(N)))                                        \
          = typename when<_, Fun>::template impl<                                                   \
                typename result_of::child_c<                                                        \
                    Expr                                                                            \
                  , BOOST_PP_SUB(DATA, BOOST_PP_INC(N))                                             \
                >::type                                                                             \
              , BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, N))                                          \
              , Data                                                                                \
            >()(                                                                                \
                proto::child_c<BOOST_PP_SUB(DATA, BOOST_PP_INC(N))>(e)                              \
              , BOOST_PP_CAT(s, BOOST_PP_SUB(DATA, N))                                              \
              , d                                                                                \
            );                                                                                \
        /**/

    #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
        #pragma wave option(preserve: 2, line: 0, output: "preprocessed/fold_impl.hpp")
    #endif

    ///////////////////////////////////////////////////////////////////////////////
    /// \file fold_impl.hpp
    /// Contains definition of fold_impl<> and reverse_fold_impl<> templates.
    //
    //  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)

    #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
        #pragma wave option(preserve: 1)
    #endif

    #define BOOST_PP_ITERATION_PARAMS_1                                                             \
        (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/detail/fold_impl.hpp>))
    #include BOOST_PP_ITERATE()

    #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
        #pragma wave option(output: null)
    #endif

    #undef BOOST_PROTO_REVERSE_FOLD_STATE
    #undef BOOST_PROTO_REVERSE_FOLD_STATE_TYPE
    #undef BOOST_PROTO_FOLD_STATE
    #undef BOOST_PROTO_FOLD_STATE_TYPE
    #undef BOOST_PROTO_CHILD_N_TYPE

#else

    #define N BOOST_PP_ITERATION()

    template<typename State0, typename Fun, typename Expr, typename State, typename Data>
    struct fold_impl<State0, Fun, Expr, State, Data, N>
      : transform_impl<Expr, State, Data>
    {
        typedef typename when<_, State0>::template impl<Expr, State, Data>::result_type state0;
        BOOST_PP_REPEAT(N, BOOST_PROTO_FOLD_STATE_TYPE, N)
        typedef BOOST_PP_CAT(state, N) result_type;

        result_type operator ()(
            typename fold_impl::expr_param e
          , typename fold_impl::state_param s
          , typename fold_impl::data_param d
        ) const
        {
            state0 s0 =
                typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d);
            BOOST_PP_REPEAT(N, BOOST_PROTO_FOLD_STATE, N)
            return BOOST_PP_CAT(s, N);
        }
    };

    template<typename State0, typename Fun, typename Expr, typename State, typename Data>
    struct reverse_fold_impl<State0, Fun, Expr, State, Data, N>
      : transform_impl<Expr, State, Data>
    {
        typedef typename when<_, State0>::template impl<Expr, State, Data>::result_type BOOST_PP_CAT(state, N);
        BOOST_PP_REPEAT(N, BOOST_PROTO_REVERSE_FOLD_STATE_TYPE, N)
        typedef state0 result_type;

        result_type operator ()(
            typename reverse_fold_impl::expr_param e
          , typename reverse_fold_impl::state_param s
          , typename reverse_fold_impl::data_param d
        ) const
        {
            BOOST_PP_CAT(state, N) BOOST_PP_CAT(s, N) =
                typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d);
            BOOST_PP_REPEAT(N, BOOST_PROTO_REVERSE_FOLD_STATE, N)
            return s0;
        }
    };

    #undef N

#endif

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
#include <chrono>
#include <cstring>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <map>
#include <vector>
#include <cmath>
#include <thread>
#include <boost/tokenizer.hpp>
#include <readline/readline.h>
#include <readline/history.h>

#include "KOnexAPI.hpp"
#include "Command.hpp"
#include "Exception.hpp"
#include "TimeSeries.hpp"

#include "config.hpp"

#define TIME_COMMAND(_command)                                          \
  __start_time = chrono::system_clock::now();                           \
  _command                                                              \
  __end_time = chrono::system_clock::now();                             \
  if (gTimerEnabled)                                                    \
  {                                                                     \
    chrono::duration<float> elapsed_seconds = __end_time - __start_time;\
    cout << "Command executed in ";                                     \
    cout << setprecision(4) << elapsed_seconds.count() << "s" << endl;  \
  }                                                                     \

using namespace std;

konex::KOnexAPI gKOnexAPI;
bool gTimerEnabled = true;
chrono::time_point<chrono::system_clock> __start_time, __end_time;

bool tooFewArgs(const vector<string>& args, int limit)
{
  if (args.size() < limit) {
    cout << "Error! Too few arguments" << endl;
    return true;
  }
  return false;
}

bool tooManyArgs(const vector<string>& args, int limit)
{
  if (args.size() > limit) {
    cout << "Error! Too many arguments" << endl;
    return true;
  }
  return false;
}

/**************************************************************************
 * HOW TO CREATE A NEW COMMAND
 *
 * Step 1: Define a new command using the MAKE_COMMAND macro
 *
 * MAKE_COMMAND(<command_name>, <code>, <help_summary>, <help>)
 *  <command_name> - name of the command
 *  <code>         - the code being executed when this command is called.
 *                   Arguments are put in a vector of string call 'args'.
 *                   This code should return true if the command is carried
 *                   out successfully and false otherwise.
 *  <help_summary> - a short text line describing the command. This is
 *                   showed next to the command name when 'help' is called
 *  <help>         - a long text describe the command in details. This is
 *                   showed when 'help <command_name>' is called
 *
 * This macro creates a class Cmd<command_name> and its object in a variable
 * called cmd<command_name>. This variable is used in step 2.
 **************************************************************************/

MAKE_COMMAND(LoadDataset,
  {
    if (tooFewArgs(args, 2) || tooManyArgs(args, 5))
    {
      return false;
    }

    string filePath = args[1];
    int maxNumRow = args.size() > 2 ? stoi(args[2]) : 0;
    int startCol  = args.size() > 3 ? stoi(args[3]) : 0;
    string separators = args.size() > 4 ? args[4] : " ";

    konex::dataset_info_t info;

    info = gKOnexAPI.loadDataset(filePath, maxNumRow, startCol, separators);

    cout << "Dataset loaded                         " << endl
              << "  Name:        " << info.name       << endl
              << "  ID:          " << info.id         << endl
              << "  Item count:  " << info.itemCount  << endl
              << "  Item length: " << info.itemLength << endl;

    return true;
  },

  "Load a dataset to the memory",

  "Dataset are text files with table-like format, such as comma-separated  \n"
  "values files.                                                           \n"
  "                                                                        \n"
  "Usage: load <filePath> [<maxNumRow> <startCol> <separators>]            \n"
  "  filePath  - Path to a text file containing the dataset                \n"
  "  maxNumRow - Maximum number of rows will be read from the file. If this\n"
  "              number is non-positive or the number of actual line is    \n"
  "              smaller than this number, all lines are read. (default: 0)\n"
  "  startCol  - Omit all columns before this column. (default: 0)         \n"
  "  separators - A list of characters used to separate values in the file \n"
  "              (default: <space>)                                        \n"
  )

MAKE_COMMAND(SaveDataset,
  {
    if (tooFewArgs(args, 3) || tooManyArgs(args, 4))
    {
      return false;
    }

    int index = stoi(args[1]);
    string filePath = args[2];
    char separator = args.size() == 4 && args[3][0] != '\n' ? args[3][0] : ' ';

    gKOnexAPI.saveDataset(index, filePath, separator);

    cout << "Saved dataset " << index << " to " << filePath << endl;

    return true;
  },

  "Save a dataset from memory to disk",

  "Usage: save <dataset_index> <filePath> [<separator>]            \n"
  "  dataset_index - Index of the dataset to be saved              \n"
  "  filePath  - Path to the saved file                            \n"
  "  separator - Separator between values in a series              \n"
  "              (default: <space>)                                \n"
  )

MAKE_COMMAND(UnloadDataset,
  {
    if (tooFewArgs(args, 2) || tooManyArgs(args, 5))
    {
      return false;
    }

    int index = stoi(args[1]);

    gKOnexAPI.unloadDataset(index);

    cout << "Dataset " << index << " is unloaded" << endl;
    return true;
  },

  "Unload a dataset from the memory",

  "Usage: unload <dataset_index>                               \n"
  "  dataset_index  - Index of the dataset being unloaded. Use \n"
  "                   'list dataset' to retrieve the list of   \n"
  "                   loaded datasets.                         \n"
  )

MAKE_COMMAND(List,
  {
    if (tooFewArgs(args, 2) || tooManyArgs(args, 2))
    {
      return false;
    }

    if (args[1] == "dataset")
    {
      vector<konex::dataset_info_t> infos = gKOnexAPI.getAllDatasetInfo();
      cout << "There are " << infos.size() << " loaded datasets" << endl << endl;
      for (const auto& i : infos)
      {
        cout << "  " << setw(4) << i.id << " " << i.name;
        cout << "\t" << setw(10) << (i.isNormalized ? "Normalized" : "");
        cout << "\t" << setw(10) << (i.isGrouped ? "Grouped" : "");
        cout << endl;
      }
    }
    else
    {
      cout << "Error! Unknown object: " << args[1] << endl;
      return false;
    }
    return true;
  },

  "List loaded dataset or available distance",

  "Usage: list dataset|distance"
  )

MAKE_COMMAND(Timer,
  {
    if (tooFewArgs(args, 1) || tooManyArgs(args, 2))
    {
      return false;
    }
    if (args.size() == 1)
    {
      cout << "Timer is " << (gTimerEnabled ? "ON" : "OFF") << endl;
    }
    else
    {
      if (args[1] == "on")
      {
        gTimerEnabled = true;
        cout << "Timer is ON" << endl;
      }
      else if (args[1] == "off")
      {
        gTimerEnabled = false;
        cout << "Timer is OFF" << endl;
      }
      else
      {
        cout << "Error! Argument for timer must be 'on' or 'off'" << endl;
        return false;
      }
    }
    return true;
  },

  "Turn timer on or off",

  "When timer is turned on, each command is timed and reported at  \n"
  "the end of its execution. If this command is called without     \n"
  "an additional argument, the current state of timer is printed.  \n"
  "                                                                \n"
  "Usage: timer [on|off]                                           \n"
  )

MAKE_COMMAND(Distance,
  {
    if (tooFewArgs(args, 9) || tooManyArgs(args, 10))
    {
      return false;
    }

    int ds1 = stoi(args[1]);
    int idx1 = stoi(args[2]);
    int start1 = stoi(args[3]);
    int end1 = stoi(args[4]);
    int ds2 = stoi(args[5]);
    int idx2 = stoi(args[6]);
    int start2 = stoi(args[7]);
    int end2 = stoi(args[8]);
    string distance = "euclidean_dtw";
    if (args.size() == 10)
    {
      distance = args[9];
    }
    konex::data_t dist = gKOnexAPI.distanceBetween(ds1, idx1, start1, end1, ds2, idx2, start2, end2, distance);
    cout << distance << " distance between " << endl
         << idx1 << " [" << start1 << ", " << end1 << "] from dataset " << ds1 << endl
         << idx2 << " [" << start2 << ", " << end2 << "] from dataset " << ds2 << endl
         << "is " << dist << endl;
    return true;
  },

  "Calculate distance between two time series",

  "Usage: distance <dataset1> <index1> <start1> <end1> <dataset2> <index2> <start2> <end2> [<distance>]\n"
  "  dataset1  -  Index of the first dataset.                                                          \n"
  "  index1    -  Index of the first time series.                                                      \n"
  "  start1    -  Starting position of the first time series                                           \n"
  "  end1      -  Ending position of the first tiem series.                                            \n"
  "  dataset2  -  Index of the first dataset.                                                          \n"
  "  index2    -  Index of the first time series.                                                      \n"
  "  start2    -  Starting position of the first time series                                           \n"
  "  end2      -  Ending position of the first tiem series.                                            \n"
  "  distance  -  The string identifier of a distance. Use 'list distance' to retrieve the list of     \n"
  "               loaded distance. Default to euclidean.                                               \n"
  )

MAKE_COMMAND(GroupDataset,
  {
    if (tooFewArgs(args, 3) || tooManyArgs(args, 4))
    {
      return false;
    }

    int index = stoi(args[1]);
    konex::data_t threshold = stod(args[2]);
    string distance_name = args.size() == 4 ? args[3] : "euclidean";

    int count = -1;
    int maxThreads = std::thread::hardware_concurrency();
    cout << "Grouping using " << maxThreads << " threads." << endl;

    TIME_COMMAND(
      count = gKOnexAPI.groupDataset(index, threshold, distance_name, maxThreads);
    )

    cout << "Dataset " << index << " is now grouped" << endl;
    cout << "Number of Groups: " << count << endl;
    return true;
  },

  "Group a dataset in memory",

  "Usage: group <dataset_index> <threshold> [<distance>]          \n"
  "  dataset_index   - Index of the dataset being grouped. Use    \n"
  "                    'list dataset' to retrieve the list of     \n"
  "                    loaded datasets.                           \n"
  "  threshold       - Threshold for grouping.                    \n"
  "  distance        - The string identifier of a distance. This  \n"
  "                    string must not end with '_dtw'. Use       \n"
  "                    'list distance' to retrieve the list of    \n"
  "                    loaded distance. Default to euclidean.     \n"
  )

MAKE_COMMAND(SaveGroup,
  {
    if (tooFewArgs(args, 3) || tooManyArgs(args, 4))
    {
      return false;
    }

    int index = stoi(args[1]);
    bool groupSizeOnly = args.size() == 4 ? stoi(args[3]) : false;

    gKOnexAPI.saveGroup(index, args[2], groupSizeOnly);
    cout << "Saved groups of dataset " << index << " to " << args[2] << endl;

    return true;
  },

  "Save groups of a grouped dataset",

  "Usage: saveGroup <dataset_index> <path> [<groupSizeOnly>]            \n"
  "  dataset_index   - Index of the dataset whose groups will be saved. \n"
  "  path            - Where to save the groups.                        \n"
  "  groupSizeOnly   - If set to 1, only the sizes of groups are saved  \n"
  "                    Default is 0.                                    \n"
  )

MAKE_COMMAND(LoadGroup,
  {
    if (tooFewArgs(args, 3) || tooManyArgs(args, 3))
    {
      return false;
    }

    int index = stoi(args[1]);

    int numGroups = gKOnexAPI.loadGroup(index, args[2]);
    cout << numGroups << " groups loaded for dataset " << index;

    return true;
  },

  "Load saved groups to a compatible dataset",

  "A dataset is compatible with a saved group file is when the item     \n"
  "count and item length is the same.                                   \n"
  "                                                                     \n"
  "Usage: loadGroup <dataset_index> <path>                              \n"
  "  dataset_index   - Index of the dataset whose groups will be loaded.\n"
  "  path            - Where to save the groups.                        \n"
  )

MAKE_COMMAND(NormalizeDataset,
  {
    if (tooFewArgs(args, 2) || tooManyArgs(args, 2))
    {
      return false;
    }

    int index = stoi(args[1]);

    gKOnexAPI.normalizeDataset(index);

    cout << "Dataset " << index << " is now normalized" << endl;
    return true;
  },

  "Normalize a dataset. (Warning: this operation cannot be undone)",

  "Usage: normalize <dataset_index>                           \n"
  "  dataset_index   - Index of the dataset to be normalized  \n"
)

MAKE_COMMAND(PAA,
  {
    if (tooFewArgs(args, 3) || tooManyArgs(args, 3))
    {
      return false;
    }

    int index = stoi(args[1]);
    int blockSize = stoi(args[2]);

    konex::dataset_info_t info = gKOnexAPI.PAA(index, blockSize);

    cout << "Dataset PAA-ed                     " << endl
         << "  Name:        " << info.name       << endl
         << "  ID:          " << info.id         << endl
         << "  Item count:  " << info.itemCount  << endl
         << "  Item length: " << info.itemLength << endl;
    return true;
  },

  "Perform piecewise aggregate approximation (PAA) on a dataset. "
  "(Warning: this operation cannot be undone)",

  "Usage: paa <dataset_index> <block_size>                \n"
  "  dataset_index   - Index of the dataset to be PAA-ed  \n"
  "  block_size      - Size of a block to aggregate         "
)

MAKE_COMMAND(Match,
  {
    if (tooFewArgs(args, 4) || tooManyArgs(args, 6))
    {
      return false;
    }

    int db_index = stoi(args[1]);
    int  q_index = stoi(args[2]);
    int ts_index = stoi(args[3]);
    int start = -1;
    int end = -1;

    if (args.size() > 4)
    {
      start = stoi(args[4]);
      end = stoi(args[5]);
    }

    TIME_COMMAND(
      konex::candidate_time_series_t best =
        gKOnexAPI.getBestMatch(db_index, q_index, ts_index, start, end);
    )

    cout << "Best Match is timeseries "
         << best.data.getIndex() << " [" << best.data.getStart() << ", " << best.data.getEnd() << "] " << endl
         << "Distance = " << best.dist << endl;

    return true;
  },

  "Find the best match of a time series",

  "Usage: match <target_dataset_idx> <q_dataset_idx> <ts_index> [<start> <end>]                    \n"
  "  dataset_index   - Index of loaded dataset to get the result from.                             \n"
  "                    Use 'list dataset' to retrieve the list of                                  \n"
  "                    loaded datasets.                                                            \n"
  "  q_dataset_idx   - Same as dataset_index, except for the query                                 \n"
  "  ts_index        - Index of the query                                                          \n"
  "  start           - The start location of the query in the timeseries                           \n"
  "  end             - The end location of the query in the timeseries (this point is not included)\n"
  )

MAKE_COMMAND(kSim,
  {
    if (tooFewArgs(args, 5) || tooManyArgs(args, 8))
    {
      return false;
    }

    int k = stoi(args[1]);
    int db_index = stoi(args[2]);
    int  q_index = stoi(args[3]);
    int ts_index = stoi(args[4]);
    int start = -1;
    int end = -1;
    int ke = k;

    if (args.size() == 6)
    {
      ke = stoi(args[5]);
    }
    else if (args.size() > 6)
    {
      start = stoi(args[5]);
      end = stoi(args[6]);
    }
    if (args.size() > 7)
    {
      ke = stoi(args[7]);
    }

    TIME_COMMAND(
      vector<konex::candidate_time_series_t> results =
        gKOnexAPI.kSim(k, ke, db_index, q_index, ts_index, start, end);
    )

    for (int i = 0; i < results.size(); i++)
    {
      std::cout << "Timeseries "
                << results[i].data.getIndex() << " [" << results[i].data.getStart() << ", " << results[i].data.getEnd() << "] "
                << "- distance = " << results[i].dist
                << std::endl;
    }

    return true;
  },

  "Find k similar time series to a query. Provides a bound of dist to the query for each result. The distance is <= the dist provided.",

    "Usage: kSim <k> <target_dataset_idx> <q_dataset_idx> <ts_index> [<start> <end>] [<ke>]           \n"
    "  k               - The number of neigbors                                                       \n"
    "  dataset_index   - Index of loaded dataset to get the result from.                              \n"
    "                    Use 'list dataset' to retrieve the list of                                   \n"
    "                    loaded datasets.                                                             \n"
    "  q_dataset_idx   - Same as dataset_index, except for the query                                  \n"
    "  ts_index        - Index of the query                                                           \n"
    "  start           - The start location of the query in the timeseries                            \n"
    "  end             - The end location of the query in the timeseries (this point is not included) \n"
    "  ke              - How far that the database will be explored (Default is equal to k)           \n"
    )

MAKE_COMMAND(kSimRaw,
  {
    if (tooFewArgs(args, 5) || tooManyArgs(args, 8))
    {
      return false;
    }

    int k = stoi(args[1]);
    int db_index = stoi(args[2]);
    int  q_index = stoi(args[3]);
    int ts_index = stoi(args[4]);
    int start = -1;
    int end = -1;
    int PAABlock = 0;

    if (args.size() == 6)
    {
      PAABlock = stoi(args[5]);
    }
    if (args.size() == 7)
    {
      start = stoi(args[5]);
      end = stoi(args[6]);
    }
    if (args.size() == 8)
    {
      PAABlock = stoi(args[7]);
    }

    TIME_COMMAND(
      std::vector<konex::candidate_time_series_t> results =
        gKOnexAPI.kSimRaw(k, db_index, q_index, ts_index, start, end, PAABlock);
    )

    for (int i = 0; i < results.size(); i++)
    {
      std::cout << "Timeseries "
                << results[i].data.getIndex() << " [" << results[i].data.getStart() << ", " << results[i].data.getEnd() << "] "
                << "- distance = " << results[i].dist
                << std::endl;
    }

    return true;
  },

  "Perform knn on a time series exhaustively - exact. This function will return exact distances.",

  "Usage: kSimRaw <k> <target_dataset_idx> <q_dataset_idx> <ts_index> [<start> <end>] [<PAA_block>] \n"
  "  k               - The number of neigbors                                                       \n"
  "  dataset_index   - Index of loaded dataset to get the result from.                              \n"
  "                    Use 'list dataset' to retrieve the list of                                   \n"
  "                    loaded datasets.                                                             \n"
  "  q_dataset_idx   - Same as dataset_index, except for the query                                  \n"
  "  ts_index        - Index of the query                                                           \n"
  "  start           - The start location of the query in the timeseries                            \n"
  "  end             - The end location of the query in the timeseries                              \n"
  "  PAA_block       - Size of PAA block. Set to 0 or negative to disable PAA feature               \n"
  )

  MAKE_COMMAND(PrintTS,
    {
      if (tooFewArgs(args, 5) || tooManyArgs(args, 5))
      {
        return false;
      }

      int ds    = stoi(args[1]);
      int index = stoi(args[2]);
      int start = stoi(args[3]);
      int end   = stoi(args[4]);

      gKOnexAPI.printTS(ds, index, start, end);

      return true;
    },

    "Print a time series.",

    "Usage: printTS <ds> <index> <start> <end>                            \n"
    "  ds              - Index of the dataset containing the time series. \n"
    "  index           - Index of the time series.                        \n"
    "  start           - The start location of the time series.           \n"
    "  end             - The end location of the timeseries.                "
    )

/************************************************************************
 *                      Start Experiment Code                           *
 ************************************************************************/
#define SEP ","
string results_path = "results.txt";

double computeJaccard(const vector<konex::candidate_time_series_t> &a,
                      const vector<konex::candidate_time_series_t> &b)
{
  int overlap = 0;
  for (int i = 0; i < min(a.size(), b.size()); i++) {
    overlap += abs(a[i].dist - b[i].dist) < 1e-9;
  }
  return overlap * 1.0 / (a.size() + b.size() - overlap);
}

double computeWeightedJaccard(const vector<konex::candidate_time_series_t> &a,
                              const vector<konex::candidate_time_series_t> &b)
{
  double minSum = 0;
  double maxSum = 0;
  for (int i = 0; i < max(a.size(), b.size()); i++) {
    if (abs(a[i].dist - b[i].dist) < EPS) {
      minSum += 1;
      maxSum += 1;
    }
    else {
      minSum += min(a[i].data.getIndex(), b[i].data.getIndex())
              + min(a[i].data.getStart(), b[i].data.getStart())
              + min(a[i].data.getLength(), b[i].data.getLength())
              + min(a[i].dist, b[i].dist);
      maxSum += max(a[i].data.getIndex(), b[i].data.getIndex())
              + max(a[i].data.getStart(), b[i].data.getStart())
              + max(a[i].data.getLength(), b[i].data.getLength())
              + max(a[i].dist, b[i].dist);
    }
  }
  return minSum / maxSum;
}

void printResults(ofstream &fout, const vector<konex::candidate_time_series_t> &r)
{
  for (auto i = 0; i < r.size(); i++) {
    int end = r[i].data.getStart() + r[i].data.getLength();
    fout << r[i].dist << SEP << r[i].data.getIndex() << SEP << r[i].data.getStart() << SEP << end;
    if (i < r.size() - 1) {
      fout << SEP;
    }
  }
}

MAKE_COMMAND(TestSim,
  {
    if (args.size() == 2) {
      results_path = args[1];
      cout << "Path for result file set to: " << results_path << endl;
      return true;
    }

    if (tooFewArgs(args, 7) || tooManyArgs(args, 9))
    {
      return false;
    }

    int k = stoi(args[1]);
    int m = stoi(args[2]);
    int block = stoi(args[3]);
    int db_index = stoi(args[4]);
    int  q_index = stoi(args[5]);
    int ts_index = stoi(args[6]);
    int start = -1;
    int end = -1;

    if (args.size() > 7)
    {
      start = stoi(args[7]);
      end = stoi(args[8]);
    }
    chrono::duration<float> kSimRawTime;
    chrono::duration<float> kSimRawPAATime;
    chrono::duration<float> kSimTime;

    TIME_COMMAND(
      std::vector<konex::candidate_time_series_t> rawResults =
        gKOnexAPI.kSimRaw(k, db_index, q_index, ts_index, start, end);
    )
    kSimRawTime = __end_time - __start_time;

    TIME_COMMAND(
      std::vector<konex::candidate_time_series_t> rawPAAResults =
        gKOnexAPI.kSimRaw(k, db_index, q_index, ts_index, start, end, block);
    )
    kSimRawPAATime = __end_time - __start_time;

    double jaccardPAA  = computeJaccard(rawPAAResults, rawResults);
    double wjaccardPAA = computeWeightedJaccard(rawPAAResults, rawResults);

    ofstream fout(results_path, ios_base::out | ios_base::app );

    int steps = m / 100;
    int count = -1;
    for (int h = k; h <= m; h += steps) {
      // EXPERIMENT
      extraTimeSeries = 0;
      TIME_COMMAND(
        std::vector<konex::candidate_time_series_t> results =
          gKOnexAPI.kSim(k, h, db_index, q_index, ts_index, start, end);
      )
      kSimTime = __end_time - __start_time;

      // Compute the metrics
      double jaccardKSim = computeJaccard(results, rawResults);
      double wjaccardKSim = computeWeightedJaccard(results, rawResults);

      std::cout << "k = " << k << " h = " << h
                << " h_extra = " << h + extraTimeSeries
                << " Jaccard_kSim = " << jaccardKSim
                << " WJaccard_KSim = " << wjaccardKSim
                << " Jaccard_kSimRawPAA = " <<  jaccardPAA
                << " WJaccard_kSimRawPAA = " << wjaccardPAA << endl;

      if (fout) {
        fout << k << SEP << h << SEP << h + extraTimeSeries << SEP << block << SEP
             << ts_index << SEP << start << SEP << end << SEP
             << jaccardKSim << SEP << wjaccardKSim << SEP << jaccardPAA << SEP << wjaccardPAA << SEP
             << kSimTime.count() << SEP << kSimRawTime.count() << SEP << kSimRawPAATime.count() << SEP;
        printResults(fout, results); fout << SEP;
        printResults(fout, rawResults); fout << SEP;
        printResults(fout, rawPAAResults);
        fout << endl;
      }
      if (abs(wjaccardKSim - 1.0) < EPS) {
        if (count == -1) {
          count = 4;
        }
        else {
          count--;
          if (count == 0) {
            break;
          }
        }
      }
    }
    if (fout) {
      cout << "Results appended to " << results_path << endl;
    } else {
      cout << "Cannot open " << results_path << ". Nothing has been saved" << endl;
    }
    return true;
  },

  "For science",

  "Usage: testSim <k> <m> <n> <target_dataset_idx> <q_dataset_idx> <ts_index> [<start> <end>] \n"
  "  k               - The number of neigbors                                                 \n"
  "  m               - For i = 1..m, an experiment is run with the number of examined         \n"
  "                    time series (h) to be i*k.                                             \n"
  "  n               - Block size for PAA.                                                    \n"
  "  dataset_index   - Index of loaded dataset to get the result from.                        \n"
  "                    Use 'list dataset' to retrieve the list of                             \n"
  "                    loaded datasets.                                                       \n"
  "  q_dataset_idx   - Same as dataset_index, except for the query                            \n"
  "  ts_index        - Index of the query                                                     \n"
  "  start           - The start location of the query in the timeseries                      \n"
  "  end             - The end location of the query in the timeseries                        \n"
  "                                                                                \n"
  "  Note: use testSim <path> to specify where the experiment output will be save.            \n"
  "  By default, the results will be saved to results.txt in the working directory.             "

  )

/************************************************************************
 *                      End Experiment Code                             *
 ************************************************************************/

/**************************************************************************
 * Step 2: Add the Command object into the commands map
 *
 * The key is a string which is also the string that is used to match with
 * user input. The value is the cmd<command_name> variable created in step 1.
 **************************************************************************/

map<string, Command*> commands = {
  {"load", &cmdLoadDataset},
  {"save", &cmdSaveDataset},
  {"unload", &cmdUnloadDataset},
  {"list", &cmdList},
  {"timer", &cmdTimer},
  {"distance", &cmdDistance},
  {"group", &cmdGroupDataset},
  {"saveGroup", &cmdSaveGroup},
  {"loadGroup", &cmdLoadGroup},
  {"normalize", &cmdNormalizeDataset},
  {"paa", &cmdPAA},
  {"match", &cmdMatch},
  {"kSim", &cmdkSim},
  {"kSimRaw", &cmdkSimRaw},
  {"printTS", &cmdPrintTS},
  {"testSim", &cmdTestSim }
};

/**************************************************************************/
/**************************************************************************/

#define COUT_HELP_ALIGNMENT 15

const string HELP_SUMMARY = "Retrieve a list of commands or get help for a command";
const string HELP_HELP    = "Usage: help [<command_name>]                                \n"
                                 "  command_name - Name of command to retrieve help about. If \n"
                                 "                 not specified, a list of available commands\n"
                                 "                 is shown instead.                            ";
const string EXIT_SUMMARY = "Terminate the program";
const string EXIT_HELP    = "Usage: Can use either 'exit' or 'quit'";

void showHelp(const string& command_name)
{
  if (command_name == "help")
  {
    cout << HELP_SUMMARY << endl << HELP_HELP << endl;
  }
  else if (command_name == "exit" || command_name == "quit")
  {
    cout << EXIT_SUMMARY << endl << EXIT_HELP << endl;
  }
  else if (commands.find(command_name) != commands.end())
  {
    Command* cmd = commands[command_name];
    cout << cmd->getSummary() << endl << cmd->getHelp() << endl;
  }
  else
  {
    cout << "Error! Cannot find help for command: " << command_name << endl;
  }
}

void showAllHelps()
{
  cout << "Use 'help <command>' to see help for a command" << endl << endl;

  cout << setw(COUT_HELP_ALIGNMENT);
  cout << "help" << HELP_SUMMARY << endl;

  cout << setw(COUT_HELP_ALIGNMENT);
  cout << "exit|quit " << EXIT_SUMMARY << endl;

  cout << endl;
  for (const auto& cmd : commands)
  {
    cout << setw(COUT_HELP_ALIGNMENT);
    cout << cmd.first << cmd.second->getSummary() << endl;
  }
}

bool processLine(const string& line)
{
  boost::char_separator<char> sep(" ");
  typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
  tokenizer tokens(line, sep);
  vector<string> args (tokens.begin(), tokens.end());

  if (args.size() == 0 || args[0].find("//") == 0)
  {
    return false;
  }

  if (args[0] == "quit" || args[0] == "exit")
  {
    return true;
  }
  else if (args[0] == "help")
  {
    if (args.size() == 1)
    {
      showAllHelps();
    }
    else if (args.size() == 2)
    {
      showHelp(args[1]);
    }
    else
    {
      cout << "Error! Too many arguments for 'help'" << endl;
    }
  }
  else
  {
    if (commands.find(args[0]) == commands.end())
    {
      cout << "Error! Cannot find command: " << args[0] << endl;
    }
    else {
      commands[args[0]]->doCommand(args);
    }
  }

  return false;
}

bool wantToQuitByEOF()
{
  cout << endl;
  char* raw_line = nullptr;
  do
  {
    delete raw_line;
    raw_line = readline("Do you really want to exit ([y]/n)? ");
    if (raw_line == nullptr || strcmp(raw_line, "y") == 0 || strcmp(raw_line, "") == 0)
    {
      return true;
    }
  }
  while (strcmp(raw_line, "n") != 0);
  return false;
}

int main (int argc, char *argv[])
{
  bool quit = false;
  char* raw_line;

  // Align left
  cout << left;
  cout << "Welcome to GENEX!\n"
               "Use 'help' to see the list of available commands." << endl;

  while (true)
  {
    quit = false;
    raw_line = readline(">> ");

    if (raw_line == nullptr) // Ctrl-D is hit or EOF
    {
      quit = wantToQuitByEOF();
    }
    else
    {
      if (strlen(raw_line) > 0)
      {
        add_history(raw_line);
      }
      string line = string(raw_line);
      delete raw_line;
      try
      {
        quit = processLine(line);
      }
      catch (konex::KOnexException& e)
      {
        cout << "Error! " << e.what() << endl;
      }
      catch (logic_error& e)
      {
        cout << "Error! Cannot convert some value to numeric" << endl;
      }
      catch (...)
      {
        cout << "Error! Unknown error" << endl;
        quit = true;
      }
      cout << endl;
    }

    if (quit)
    {
      break;
    }
  }
  return 0;
}

max_stars_repo_name: ctring/konex

max_issues_repo_name: ctring/konex

max_forks_repo_name: ctring/konex


text:
#include <string>
#include <stdexcept>
#include <cassert>

struct datetime {
    enum zone_offsets_t {
        OFFSET_NOT_SET,
        OFFSET_Z,
        OFFSET_UTC_PLUS,
        OFFSET_UTC_MINUS
    };

private:
    unsigned short year_;
    unsigned short month_;
    unsigned short day_;

    unsigned short hours_;
    unsigned short minutes_;
    unsigned short seconds_;

    zone_offsets_t zone_offset_type_;
    unsigned int zone_offset_in_min_;

    static void dt_assert(bool v, const char* msg) {
        if (!v) {
            throw std::logic_error(
                "Assertion failed in datetime: " + std::string(msg)
            );
        }
    }

public:
    datetime()
        : year_(0), month_(0), day_(0)
        , hours_(0), minutes_(0), seconds_(0)
        , zone_offset_type_(OFFSET_NOT_SET), zone_offset_in_min_(0)
    {}

    // Getters: year(), month(), day(), hours(), minutes(),
    // seconds(), zone_offset_type(), zone_offset_in_min()
    // ...
    unsigned short year() const { return year_; }
    unsigned short month() const { return month_; }
    unsigned short day() const { return day_; }

    unsigned short hours() const { return hours_; }
    unsigned short minutes() const { return minutes_; }
    unsigned short seconds() const { return seconds_; }

    zone_offsets_t zone_offset_type() const { return zone_offset_type_; }
    unsigned int zone_offset_in_min() const { return zone_offset_in_min_; }

    // Setters: set_year(unsigned short), set_day(unsigned short), ...
    //
    // void set_*(unsigned short v) {
    //     Some dt_assert.
    //     Setting the '*_' to 'v'.
    // }
    // ...
    void set_year(unsigned short val) {
        year_ = val;
    }

    void set_month(unsigned short val) {
        dt_assert(val < 13 && val > 0, "month parameter has incorrect value");
        month_ = val;
    }

    void set_day(unsigned short val)  {
        dt_assert(val < 32 && val > 0, "day parameter has incorrect value");
        day_ = val;
    }

    void set_hours(unsigned short val) {
        dt_assert(val < 24, "hours parameter has incorrect value");
        hours_ = val;
    }

    void set_minutes(unsigned short val) {
        dt_assert(val < 24, "minutes parameter has incorrect value");
        minutes_ = val;
    }

    void set_seconds(unsigned short val) {
        dt_assert(val < 60, "seconds parameter has incorrect value");
        seconds_ = val;
    }

    void set_zone_offset(zone_offsets_t val) {
        // We do not get over paranoid, so we won't check val range
        zone_offset_type_ = val;
    }

    void set_zone_offset_in_min(unsigned short val) {
        zone_offset_in_min_ = val;
    }
};

void set_zone_offset(datetime& dt, char sign, unsigned short hours
    , unsigned short minutes)
{
    dt.set_zone_offset(
        sign == '+'
        ? datetime::OFFSET_UTC_PLUS
        : datetime::OFFSET_UTC_MINUS
    );
    dt.set_zone_offset_in_min(hours * 60 + minutes);
}

// Default includes for Boost.Spirit.
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

// We'll use bind() function from Boost.Spirit,
// because it interates better with parsers.
#include <boost/spirit/include/phoenix_bind.hpp>

datetime parse_datetime(const std::string& s) {
    using boost::spirit::qi::_1;
    using boost::spirit::qi::_2;
    using boost::spirit::qi::_3;
    using boost::spirit::qi::uint_parser;
    using boost::spirit::qi::char_;
    using boost::phoenix::bind;
    using boost::phoenix::ref;

    datetime ret;

    // Use unsigned short as output type; require Radix 10 and
    // from 2 to 2 digits.
    uint_parser<unsigned short, 10, 2, 2> u2_;

    // Use unsigned short as output type; require Radix 10 and
    // from 4 to 4 digits.
    uint_parser<unsigned short, 10, 4, 4> u4_;

    boost::spirit::qi::rule<const char*, void()> timezone_parser
        = -(  // unary minus means optional rule

            // Zero offset
            char_('Z')[ bind(
                &datetime::set_zone_offset, &ret, datetime::OFFSET_Z
            ) ]

            |  // OR

            // Specific zone offset
            ((char_('+')|char_('-')) >> u2_ >> ':' >> u2_) [
                bind(&set_zone_offset, ref(ret), _1, _2, _3)
            ]
        );

    boost::spirit::qi::rule<const char*, void()> date_parser =
           u4_ [ bind(&datetime::set_year, &ret, _1) ]  >> '-'
        >> u2_ [ bind(&datetime::set_month, &ret, _1) ] >> '-'
        >> u2_ [ bind(&datetime::set_day, &ret, _1) ];

    boost::spirit::qi::rule<const char*, void()> time_parser =
            u2_ [ bind(&datetime::set_hours, &ret, _1) ] >> ':'
         >> u2_ [ bind(&datetime::set_minutes, &ret, _1) ] >> ':'
         >> u2_ [ bind(&datetime::set_seconds, &ret, _1) ];

    const char* first = s.data();
    const char* const end = first + s.size();
    const bool success = boost::spirit::qi::parse(first, end,
        (
            (date_parser >> 'T' >> time_parser)
            | date_parser
            | time_parser
        )
        >> timezone_parser
    );

    if (!success || first != end) {
        throw std::logic_error("Parsing of '" + s + "' failed");
    }
    return ret;
} // end of parse_datetime() function

#include <boost/spirit/include/qi_rule.hpp>

// Somewhere in header file
class example_1 {
    boost::spirit::qi::rule<const char*, void()> some_rule_;
public:
    example_1();
};

// In source file
example_1::example_1() {
    some_rule_ = /* ... a lot of parser code ... */ boost::spirit::qi::char_('!');
}

#ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS

// WARNING! For the pre-x3 versions of Boost.Spirit you must use
// `boost::proto::deep_copy` for saving a parser into an `auto` variable!
//
// See the description and comments at
// http://boost-spirit.com/home/articles/qi-example/zero-to-60-mph-in-2-seconds/
// for more info.
datetime parse_datetime_cxx11(const std::string& s) {
    using boost::spirit::qi::_1;
    using boost::spirit::qi::_2;
    using boost::spirit::qi::_3;
    using boost::spirit::qi::uint_parser;
    using boost::spirit::qi::char_;
    using boost::phoenix::bind;
    using boost::phoenix::ref;

    datetime ret;

    // Use unsigned short as output type; require Radix 10 and
    // from 2 to 2 digits.
    uint_parser<unsigned short, 10, 2, 2> u2_;

    // Use unsigned short as output type; require Radix 10 and
    // from 4 to 4 digits.
    uint_parser<unsigned short, 10, 4, 4> u4_;

    const auto timezone_parser = boost::proto::deep_copy(
        -(  // unary minus means optional rule

            // Zero offset
            char_('Z')[ bind(
                &datetime::set_zone_offset, &ret, datetime::OFFSET_Z
            ) ]

            |  // OR

            // Specific zone offset
            ((char_('+')|char_('-')) >> u2_ >> ':' >> u2_) [
                bind(&set_zone_offset, ref(ret), _1, _2, _3)
            ]
        )
    );

    const auto date_parser = boost::proto::deep_copy(
           u4_ [ bind(&datetime::set_year, &ret, _1) ]  >> '-'
        >> u2_ [ bind(&datetime::set_month, &ret, _1) ] >> '-'
        >> u2_ [ bind(&datetime::set_day, &ret, _1) ]
    );

    const auto time_parser = boost::proto::deep_copy(
            u2_ [ bind(&datetime::set_hours, &ret, _1) ] >> ':'
         >> u2_ [ bind(&datetime::set_minutes, &ret, _1) ] >> ':'
         >> u2_ [ bind(&datetime::set_seconds, &ret, _1) ]
    );

    const char* first = s.data();
    const char* const end = first + s.size();
    const bool success = boost::spirit::qi::parse(first, end,
        (
            (date_parser >> 'T' >> time_parser)
            | date_parser
            | time_parser
        )
        >> timezone_parser
    );

    if (!success || first != end) {
        throw std::logic_error("Parsing of '" + s + "' failed");
    }
    return ret;
} // end of parse_datetime_cxx11() function

#endif

int main () {
    datetime d1  = parse_datetime("2012-10-20T10:00:00Z");
    assert(d1.year() == 2012);
    assert(d1.month() == 10);
    assert(d1.day() == 20);
    assert(d1.hours() == 10);
    assert(d1.minutes() == 0);
    assert(d1.seconds() == 0);
    assert(d1.zone_offset_type() == datetime::OFFSET_Z);
    assert(d1.zone_offset_in_min() == 0);

    datetime d2  = parse_datetime("2012-10-20T10:00:00");
    assert(d2.year() == 2012);
    assert(d2.month() == 10);
    assert(d2.day() == 20);
    assert(d2.hours() == 10);
    assert(d2.minutes() == 0);
    assert(d2.seconds() == 0);
    assert(d2.zone_offset_type() == datetime::OFFSET_NOT_SET);
    assert(d2.zone_offset_in_min() == 0);

    datetime d3  = parse_datetime("2012-10-20T10:00:00+09:15");
    assert(d3.year() == 2012);
    assert(d3.month() == 10);
    assert(d3.day() == 20);
    assert(d3.hours() == 10);
    assert(d3.minutes() == 0);
    assert(d3.seconds() == 0);
    assert(d3.zone_offset_type() == datetime::OFFSET_UTC_PLUS);
    assert(d3.zone_offset_in_min() == 9 * 60 + 15);

    datetime d4  = parse_datetime("2012-10-20-09:15");
    assert(d4.year() == 2012);
    assert(d4.month() == 10);
    assert(d4.day() == 20);
    assert(d4.hours() == 0);
    assert(d4.minutes() == 0);
    assert(d4.seconds() == 0);
    assert(d4.zone_offset_type() == datetime::OFFSET_UTC_MINUS);
    assert(d4.zone_offset_in_min() == 9 * 60 + 15);

    datetime d5  = parse_datetime("10:00:09+09:15");
    assert(d5.year() == 0);
    assert(d5.month() == 0);
    assert(d5.day() == 0);
    assert(d5.hours() == 10);
    assert(d5.minutes() == 0);
    assert(d5.seconds() == 9);
    assert(d5.zone_offset_type() == datetime::OFFSET_UTC_PLUS);
    assert(d5.zone_offset_in_min() ==  9 * 60 + 15);

#ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS
    datetime d6  = parse_datetime_cxx11("2012-10-20T10:00:00Z");
    assert(d6.year() == 2012);
    assert(d6.month() == 10);
    assert(d6.day() == 20);
    assert(d6.hours() == 10);
    assert(d6.minutes() == 0);
    assert(d6.seconds() == 0);
    assert(d6.zone_offset_type() == datetime::OFFSET_Z);
    assert(d6.zone_offset_in_min() == 0);
#endif
}

max_stars_repo_name: apolukhin/boost-cookbook

max_issues_repo_name: apolukhin/boost-cookbook

max_forks_repo_name: apolukhin/boost-cookbook