text:
/*
 *  Copyright 2013 Aurelian Melinte.
 *
 *  Use, modification and distribution are subject to the Boost Software License,
 *  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt).
 */

#if !defined(BOOST_CALL_STACK_GNU_SYMBOL_HPP)
#define BOOST_CALL_STACK_GNU_SYMBOL_HPP

#if !defined(BOOST_CALL_STACK_HPP)
#  error "This header cannot be included directly. Include <boost/call_stack/call_stack.hpp>"
#endif

#include <boost/call_stack/detail/config.hpp>

#include <boost/call_stack/detail/unique.hpp>
#include <boost/call_stack/detail/singleton.hpp>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/assert.hpp>

#include <elf.h>
#include <execinfo.h>
#include <cxxabi.h>
#include <dlfcn.h>

#include <signal.h>

#if !defined(BOOST_CALL_STACK_GNU_NO_LIBBFD)
#  pragma message("Note: Link with optional library libbfd.")
#  include <bfd.h>
#else
#  pragma message("Note: Excluding libbfd. Some symbols might not resolve properly. Line numbers are not available.")
#endif

#include <unistd.h>

#include <cstring>
#include <cstdlib>

#include <memory>
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <sstream>
#include <algorithm>

/*
 *
 */

namespace boost { namespace call_stack { namespace detail {

/*
 *
 */

typedef void*                address_type;
static const address_type    null_address = nullptr;

typedef long                 delta_type;
static delta_type            null_delta = delta_type(0);

/*
 *
 */
template <typename T>
struct free_wrapper
{
    void operator() (T*& ptr)
    {
        if (ptr)
        {
            std::free(ptr);
            ptr = nullptr;
        }
    }
};

class null_symbol_resolver
{
public:

    null_symbol_resolver(const address_type& addr = null_address) noexcept
    {
        resolve(addr);
    }

    null_symbol_resolver(null_symbol_resolver const& other) noexcept
    {
        resolve(other._addr);
    }
    null_symbol_resolver& operator=(null_symbol_resolver other) noexcept
    {
        swap(other);
        return *this;
    }

#if (__cplusplus >= 201103L)
#pragma message ("**** C++11 FIXME delete this pragma")
    null_symbol_resolver(null_symbol_resolver&& other) noexcept : null_symbol_resolver()
    {
        swap(other);
    }
    null_symbol_resolver& operator=(null_symbol_resolver&& other) noexcept
    {
        BOOST_ASSERT(this != &other);
        swap(other);
        return *this;
    }
#endif

    void resolve(const address_type& addr) noexcept
    {
        _addr = addr;
        _binary_name = nullptr;
        _sym_name = nullptr;
        _demangled_sym_name.reset(static_cast<char*>(0), free_wrapper<char>());
        _delta = null_delta;
        _source_file_name = nullptr;
        _line_number = 0;

        _dladdr_ret = false;
    }

    address_type addr() const noexcept              { return _addr; }
    const char*  binary_file() const noexcept       { return safe(_binary_name); }
    const char*  raw_name() const noexcept          { return safe(_sym_name); }
    const char*  demangled_name() const noexcept
    {
        if (_demangled_sym_name) {
            return safe(const_cast<const char*>(_demangled_sym_name.get()));
        }
        else {
            return raw_name();
        }
    }
    delta_type   delta() const noexcept             { return _delta; }
    const char*  source_file() const noexcept       { return safe(_source_file_name); }
    unsigned int line_number() const noexcept       { return  _line_number; }

    void swap(null_symbol_resolver& other) noexcept
    {
        std::swap(_addr,                 other._addr);
        std::swap(_binary_name,          other._binary_name);
        std::swap(_sym_name,             other._sym_name);
        std::swap(_demangled_sym_name,   other._demangled_sym_name);
        std::swap(_delta,                other._delta);
        std::swap(_source_file_name,     other._source_file_name);
        std::swap(_line_number,          other._line_number);
        std::swap(_dladdr_ret,           other._dladdr_ret);
    }

protected:

    const char* safe(const char* p) const { return (p && *p) ? p : "??"; }

protected:

    address_type  _addr;
    const char*   _binary_name;
    const char*   _sym_name;
    boost::shared_ptr<char>  _demangled_sym_name; // Demangler uses malloc()
    delta_type    _delta;

    const char*   _source_file_name;
    unsigned int  _line_number;

    bool          _dladdr_ret;
}; //null_symbol_resolver

inline void swap(null_symbol_resolver& left, null_symbol_resolver& right) noexcept
{
    BOOST_ASSERT(&left != &right);
    left.swap(right);
}

/*
 *
 */

class basic_symbol_resolver : public null_symbol_resolver
{
public:

    typedef null_symbol_resolver  base_type;

    basic_symbol_resolver(const address_type& addr = nullptr) noexcept : base_type(addr)
    {
        resolve(addr);
    }

    basic_symbol_resolver(basic_symbol_resolver const& other) noexcept : base_type(other._addr)
    {
        resolve(other._addr);
    }
    basic_symbol_resolver& operator=(basic_symbol_resolver other) noexcept
    {
        swap(other);
        return *this;
    }

#if (__cplusplus >= 201103L)
    basic_symbol_resolver(basic_symbol_resolver&& other) noexcept : basic_symbol_resolver()
    {
        swap(other);
    }
    basic_symbol_resolver& operator=(basic_symbol_resolver&& other) noexcept
    {
        BOOST_ASSERT(this != &other);
        swap(other);
        return *this;
    }
#endif

    void resolve(const address_type& addr) noexcept
    {
        _resolve(addr);
    }

    void swap(basic_symbol_resolver& other) noexcept
    {
        base_type::swap(other);
        std::swap(_info, other._info);
    }

protected:

    void _demangle() noexcept
    {
        int status = 0;
        _demangled_sym_name.reset(abi::__cxa_demangle(_sym_name, 0, 0, &status),
                                  free_wrapper<char>());
    }

    void _resolve(const address_type& addr) noexcept
    {
        base_type::resolve(addr);

        if (addr == null_address)
            return;

        _dladdr_ret = (::dladdr(_addr, &_info) != 0);
        if (_dladdr_ret)
        {
            _binary_name = _info.dli_fname;
            _sym_name   = _info.dli_sname;
            _delta = static_cast<const char *>(_addr) - static_cast<const char *>(_info.dli_saddr);

            _demangle();
        }
    }

protected:

    Dl_info     _info;
}; //basic_symbol_resolver

inline void swap(basic_symbol_resolver& left, basic_symbol_resolver& right) noexcept
{
    BOOST_ASSERT(&left != &right);
    left.swap(right);
}

/*
 *
 */

#if !defined(BOOST_CALL_STACK_GNU_NO_LIBBFD)
namespace bfd {

typedef struct ::bfd cbfd;
struct sym_tab_type
{
    boost::shared_ptr< cbfd >       abfd;
    unsigned                        storage_needed;
    boost::shared_ptr< asymbol* >   syms;
    long                            cSymbols;
    asection *                      text;
    bool                            dynamic;
    boost::shared_ptr< asymbol >    ptr;
    bfd_vma                         base; ///< module base address

    sym_tab_type()
        : storage_needed(0)
        , cSymbols(0)
        , text(nullptr)
        , dynamic(false)
        , base(0)
    {}
};

typedef std::map<std::string, sym_tab_type> sym_map_type;

// Map modules to their base addresses
typedef std::map<std::string, bfd_vma> bfd_vma_map_type;

struct bfd_close_wrapper
{
    bool operator() (cbfd*& abfd)
    {
        bool ret = false;
        if (abfd)
        {
            ret = bfd_close(abfd);
        }
        return ret;
    }
};

class library : public boost::call_stack::detail::unique
{
public:

    library()
        : _init_called(false)
        , _is_pie(false)
    {
        bool ret = init();
        BOOST_ASSERT(ret);
    }

    ~library()
    {
        bool ret = shutdown();
        BOOST_ASSERT(ret);
    }

    bool init()
    {
        boost::mutex::scoped_lock lock(_lib_mutex);
        return _init();
    }

    // This resolver could return stale data with the following scenario:
    // - program loads module dynamically with libdl(3lib) API
    // - check call stack with functions from module on the stack
    // - program unloads module -> stale data in the _vmas map
    // - program loads module again at new base address
    // - check call stack with functions from module on the stack find stale vma
    // Same issue is possible with cached symbol data in _syms.
    // For such situations, use bfd::bfd_lib_type::instance().flush_cached_data();
    void flush_cached_data()
    {
        boost::mutex::scoped_lock lock(_lib_mutex);
        _syms.clear();
        _vmas.clear();
    }

    bool shutdown()
    {
        boost::mutex::scoped_lock lock(_lib_mutex);
        return _shutdown();
    }

    void resolve(const address_type&   addr,
                 const char *   binfile,
                 const char **  source_file_name,
                 const char **  func_name,
                 unsigned int * line_number)
    {
        if (!binfile || !*binfile) {
            return;
        }

        *source_file_name = nullptr;
        *line_number      = 0;
        *func_name        = nullptr;

        boost::mutex::scoped_lock lock(_lib_mutex);

        _init();
        if (!_init_called)
        {
            return;
        }

        sym_map_type::iterator itBfd = _syms.find(binfile);
        if (itBfd == _syms.end()) {
            sym_tab_type fbfd;

            fbfd.base = _compute_maps_base(binfile);

            //FIXME: char *find_separate_debug_file (bfd *abfd);
            fbfd.abfd.reset(bfd_openr(binfile, 0), bfd_close_wrapper());
            if (!fbfd.abfd) {
                return;
            }
#ifdef BFD_DECOMPRESS // Old libbfd?
            fbfd.abfd->flags |= BFD_DECOMPRESS;
#endif

            // Required
            bfd_check_format(fbfd.abfd.get(), bfd_object);

            fbfd.text = bfd_get_section_by_name(fbfd.abfd.get(), ".text");

            fbfd.storage_needed = bfd_get_symtab_upper_bound(fbfd.abfd.get());
            if (0 == fbfd.storage_needed) {
                fbfd.dynamic = true;
                fbfd.storage_needed = bfd_get_dynamic_symtab_upper_bound(fbfd.abfd.get());
            }

            fbfd.syms.reset(static_cast<asymbol**>(::malloc(fbfd.storage_needed)),
                            free_wrapper<asymbol*>());

            if (fbfd.dynamic) {
                fbfd.cSymbols = bfd_canonicalize_dynamic_symtab(fbfd.abfd.get(), fbfd.syms.get());
            }
            else {
                fbfd.cSymbols = bfd_canonicalize_symtab(fbfd.abfd.get(), fbfd.syms.get());
            }
            BOOST_ASSERT(fbfd.cSymbols >= 0);

            _syms[binfile] = fbfd;
            itBfd = _syms.find(binfile);
        }

        if (itBfd != _syms.end()) {
            const sym_tab_type &stab = itBfd->second;

            bfd_vma vma = bfd_get_section_vma(stab.abfd.get(), stab.text);

            long offset = ((long)addr) - stab.base - vma; //stab.text->vma;
            if (offset > 0) {
                if ( !bfd_find_nearest_line(stab.abfd.get(),
                                            stab.text,
                                            stab.syms.get(),
                                            offset,
                                            source_file_name,
                                            func_name,
                                            line_number)
                    ) {
                    //std::cerr << "libbfd: could not find " << std::hex << addr;
                    *source_file_name = nullptr;
                    *line_number      = 0;
                    *func_name        = nullptr;
                }
                //trace it
            }
        }
    }

private:

    bool _init()
    {
        if (_init_called)
        {
            return true;
        }

        bfd_init();
        _init_called = true;

        return _init_called;
    }

    bool _shutdown()
    {
        if (!_init_called)
        {
            return true;
        }

        _syms.clear();
        _vmas.clear();
        //No couterparty to bfd_init()

        _init_called = false;
        return true;
    }

    // Ubuntu 18.04 with PIE-compiled programs
    bool _is_position_independent_executable(std::string const& executable_file_path)
    {
        static bool s_first_time = true;
        static std::string s_executable_file_path;

        if (!s_first_time)
        {
            assert(s_executable_file_path == executable_file_path);
            return _is_pie;
        }

        s_first_time = false;
        s_executable_file_path = executable_file_path;

        std::ifstream executable_file;
        executable_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        executable_file.open(executable_file_path.c_str());

        Elf64_Ehdr elf_header;
        executable_file.read(reinterpret_cast<char*>(&elf_header), sizeof(elf_header));
        // check if it is really an elf file
        if (::memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0)
        {
            throw std::runtime_error(
                "Unsupported non-ELF format found for the executable '" + executable_file_path + "'");
        }

        _is_pie = (elf_header.e_type == ET_DYN);
        return _is_pie;
    }

    // Must run under _lib_mutex because of _vmas
    bfd_vma _compute_maps_base(const char * binfile)
    {
        boost::system::error_code ec;
        std::string executable_file_path =
            boost::filesystem::canonical(binfile, ec).string();
        if (ec)
        {
            executable_file_path = std::string(binfile);
        }

        bfd_vma_map_type::const_iterator itVma = _vmas.find(executable_file_path);
        if (itVma != _vmas.end())
        {
            return itVma->second;
        }

        pid_t pid = ::getpid();
        std::string procFile = "/proc/" + boost::lexical_cast<std::string>(pid) + "/maps";
        std::ifstream proc_maps_file(procFile.c_str());
        std::string line;

        int line_no = 0;
        while (std::getline(proc_maps_file, line))
        {
            if (boost::algorithm::ends_with(line, executable_file_path))
            {
                // this is the executable itself and we don't have a position independent executable
                if (line_no == 0 && !_is_position_independent_executable(executable_file_path))
                {
                    _vmas[executable_file_path] = 0;
                    return 0;
                }

                size_t const loc = line.find("-");
                if (loc == std::string::npos)
                {
                    _vmas[executable_file_path] = 0;
                    return 0;
                }

                std::string const base = "0x" + line.substr(0, loc);
                std::stringstream sstream(base);
                sstream.imbue(std::locale::classic());
                bfd_vma base_decimal = 0;
                sstream >> std::hex >> base_decimal;
                _vmas[executable_file_path] = base_decimal;
                return base_decimal;
            }
            line_no++;
        }
        return 0;
    }

private:

    boost::mutex     _lib_mutex;
    bool             _init_called;
    bool             _is_pie; // Ubuntu 18.04 with PIE-compiled programs
    sym_map_type     _syms;
    bfd_vma_map_type _vmas;
};

typedef lpt::singleton<bfd::library> bfd_lib_type;

class source_resolver
{
public:

    const char*  name() const          { return _sym_name; }
    const char*  source_file() const   { return _source_file_name; }
    unsigned int line_number() const   { return  _line_number; }

    source_resolver(const address_type& addr, const char * binfile)
        : _source_file_name(nullptr)
        , _sym_name(nullptr)
        , _line_number(0)
    {
        resolve(addr, binfile);
    }

    friend void swap(source_resolver& left, source_resolver& right)
    {
        std::swap(left._source_file_name, right._source_file_name);
        std::swap(left._sym_name,         right._sym_name);
        std::swap(left._line_number,      right._line_number);
    }

protected:

    void resolve(const address_type& addr, const char * binfile)
    {
        return bfd::bfd_lib_type::instance().resolve(addr, binfile, &_source_file_name, &_sym_name, &_line_number);
    }

protected:

    const char*    _source_file_name;
    const char*    _sym_name;
    unsigned int   _line_number;
};

} //namespace bfd

class extended_symbol_resolver : public basic_symbol_resolver
{
public:

    typedef basic_symbol_resolver  base_type;

    extended_symbol_resolver(const address_type& addr = nullptr) : base_type(addr)
    {
        resolve(addr);
    }

    extended_symbol_resolver(extended_symbol_resolver const& other) noexcept
        : base_type(other._addr)
    {
        resolve(other._addr);
    }

    extended_symbol_resolver& operator=(extended_symbol_resolver other) noexcept
    {
        swap(other);
        return *this;
    }

#if (__cplusplus >= 201103L)
    extended_symbol_resolver(extended_symbol_resolver&& other) noexcept : extended_symbol_resolver()
    {
        swap(other);
    }
    extended_symbol_resolver& operator=(extended_symbol_resolver&& other) noexcept
    {
        BOOST_ASSERT(this != &other);
        swap(other);
        return *this;
    }
#endif

    void resolve(const address_type& addr)
    {
        base_type::resolve(addr);
        _resolve(addr, _binary_name);
    }

    void swap(extended_symbol_resolver& other) noexcept
    {
        base_type::swap(other);
    }

protected:

    void _resolve(const address_type& addr, const char * binfile)
    {
        detail::bfd::source_resolver sym(addr, binfile);
        _line_number        = sym.line_number();
        _source_file_name   = sym.source_file();
        if (!_sym_name && sym.name()) {
            _sym_name = sym.name();
            _demangle();
        }
    }
}; //extended_symbol_resolver

#else //defined(BOOST_CALL_STACK_GNU_NO_LIBBFD)

class extended_symbol_resolver : public basic_symbol_resolver
{
public:

    typedef basic_symbol_resolver  base_type;

    extended_symbol_resolver(const address_type& addr = nullptr) : base_type(addr)
    {
    }
};

#endif // BOOST_CALL_STACK_GNU_NO_LIBBFD

inline void swap(extended_symbol_resolver& left, extended_symbol_resolver& right) noexcept
{
    BOOST_ASSERT(&left != &right);
    left.swap(right);
}

}}} //namespace boost::call_stack::detail

namespace std {

} //namespace std

#endif //#if !defined(BOOST_CALL_STACK_GNU_SYMBOL_HPP)

ext: hpp


text:
#define BOOST_TEST_MODULE trade_api_test
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
#include <hb/log/log.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <hb/trade_api_plugin/trade_api_plugin_impl.h>
#include <memory>

using namespace std;
using namespace hb::plugin;
namespace bt = boost::unit_test;

struct Env : public trade_api_plugin_impl {
    Env() {
        trade_api_data_type d =  {
                host: "api.huobi.me",
                port: "80",
                access_key: "523333f0-bgbfh5tv3f-f1799835-8982f",
                secret_key: "3e8ea65f-bae19bb3-58ad7d9f-470bd",
                target_pair: "eosusdt",
                expired_seconds: 30,
                cert_pem: "/etc/huobi_cert/cert.pem",
                url_query_pirce: "/market/detail/merged?symbol=",
                url_query_account: "/v1/account/accounts",
                url_query_order: "/v1/order/orders/{order-id}",
                url_query_order_client: "/v1/order/orders/getClientOrder",
                url_cancel_order: "/v1/order/orders/{order-id}/submitcancel",
                url_new_order: "/v1/order/orders/place"
        };
        data(d);
    }
    ~Env() {

    }
};

BOOST_AUTO_TEST_SUITE(trade_api_test)

static shared_ptr<Env> my =make_shared<Env>();
static price_result_type price_result;
static string new_order_id;
static string new_client_order_id = "d4395bb2-4c0d-46c7-b346-b4be7651f6a9";

// get_price
BOOST_AUTO_TEST_CASE(get_price) try {
    log_info<<"get_price>>>>>>>>>>";
    auto result = my->get_price();
    price_result = result;
    log_info<<"close_price:"<<price_result.close_price;
    log_info<<"max_buy_price:"<<price_result.max_buy_price;
    log_info<<"max_buy_num:"<<price_result.max_buy_num;
    log_info<<"max_sale_price:"<<price_result.max_sale_price;
    log_info<<"max_sale_num:"<<price_result.max_sale_num;
    BOOST_CHECK_EQUAL(price_result.status, true);
    boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
} catch (...) {
    log_throw("get_price", nullptr);
    BOOST_FAIL("get_price error!");
};
// get_account
BOOST_AUTO_TEST_CASE(get_account) try {
    log_info<<"get_account>>>>>>>>>>";
    string account_id = my->get_account();
    my->account_id(account_id);
    log_info<<"spot_account_id is:"<<account_id;
    BOOST_CHECK_EQUAL(account_id, "1197869");
    boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
} catch (...) {
    log_throw("get_account", nullptr);
    BOOST_FAIL("get_account error!");
};

// new_sale_order
BOOST_AUTO_TEST_CASE(new_sale_order) try {
    log_info<<"new_sale_order>>>>>>>>>>";
    if(!price_result.status){
        BOOST_FAIL("price_result.status error!");
    }
    double use_sale_price = price_result.close_price + price_result.close_price*0.08;
    //new order
    new_order_id = my->new_sale_order(5,use_sale_price);
    log_info<<"new_order_id:"<<new_order_id;
    boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
} catch (...) {
    log_throw("new_sale_order", nullptr);
    BOOST_FAIL("new_sale_order error!");
};
// // query_order_id_by_client
// BOOST_AUTO_TEST_CASE(query_order_id_by_client) try {
//     log_info<<"query_order_id_by_client>>>>>>>>>>";
//     new_order_id = my->query_order_id_by_client(new_client_order_id);
//     log_info<<"query_order_id_by_client order_id:"<<new_order_id;
//     boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
// } catch (...) {
//     log_throw("query_order_id_by_client");
//     BOOST_FAIL("query_order_id_by_client error!");
// };

// get_order_status
BOOST_AUTO_TEST_CASE(get_order_status) try {
    //query order
    order_result_type order_status = my->get_order_status(new_order_id);
    log_info<<"order_status>>>>>>>>>>";
    log_info<<"status:"<<order_status.status;
    log_info<<"price:"<<order_status.price;
    log_info<<"number:"<<order_status.number;
    log_info<<"amount:"<<order_status.amount;
    log_info<<"fee:"<<order_status.fee;
    boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
} catch (...) {
    log_throw("get_order_status", nullptr);
    BOOST_FAIL("get_order_status error!");
};
// cancell_order
BOOST_AUTO_TEST_CASE(cancell_order) try {
    log_info<<"cancell_order>>>>>>>>>>";
    my->cancell_order(new_order_id);
} catch (...) {
    log_throw("cancell_order", nullptr);
    BOOST_FAIL("cancell_order error!");
};

//tt
// BOOST_AUTO_TEST_CASE(tt) try {

//     my->account_id("1197869");
//     my->cancell_order("84033115186");
// } catch (...) {
//     log_throw("tt");
//     BOOST_FAIL("tt error!");
// };
BOOST_AUTO_TEST_SUITE_END()

ext: cpp


text:
/*
 * Copyright (C) 2012 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/
#include <string>
#include <iostream>
#include <functional>
#include <boost/filesystem.hpp>
#include <sys/types.h>

// Not Apple or Windows
#if not defined(__APPLE__) && not defined(_WIN32)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
#endif

#ifndef _WIN32
#include <dirent.h>
#else
#include "gazebo/common/win_dirent.h"
#endif

#include "gazebo/gazebo_config.h"

#include <ignition/common/Profiler.hh>

#include "gazebo/common/CommonIface.hh"
#include "gazebo/common/Events.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/common/SystemPaths.hh"

#include "gazebo/rendering/ogre_gazebo.h"
#include "gazebo/rendering/Material.hh"
#include "gazebo/rendering/RenderEvents.hh"
#include "gazebo/rendering/RTShaderSystem.hh"
#include "gazebo/rendering/WindowManager.hh"
#include "gazebo/rendering/Scene.hh"
#include "gazebo/rendering/RenderTypes.hh"
#include "gazebo/rendering/RenderEngine.hh"
#include "gazebo/rendering/RenderEnginePrivate.hh"

using namespace gazebo;
using namespace rendering;

//////////////////////////////////////////////////
RenderEngine::RenderEngine()
    : dataPtr(new RenderEnginePrivate)
{
  this->dataPtr->logManager = NULL;
  this->dataPtr->root = NULL;

#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
  this->dataPtr->overlaySystem = NULL;
#endif

  this->dummyDisplay = NULL;

  this->dataPtr->initialized = false;

  this->dataPtr->renderPathType = NONE;
  this->dataPtr->windowManager.reset(new WindowManager);
}

//////////////////////////////////////////////////
RenderEngine::~RenderEngine()
{
  // this->Fini();
}

//////////////////////////////////////////////////
void RenderEngine::Load()
{
  if (!this->CreateContext())
  {
    gzwarn << "Unable to create X window. Rendering will be disabled\n";
    return;
  }

  if (!this->dataPtr->root)
  {
    this->dataPtr->connections.push_back(event::Events::ConnectPreRender(
        std::bind(&RenderEngine::PreRender, this)));
    this->dataPtr->connections.push_back(event::Events::ConnectRender(
        std::bind(&RenderEngine::Render, this)));
    this->dataPtr->connections.push_back(event::Events::ConnectPostRender(
        std::bind(&RenderEngine::PostRender, this)));

    // Create a new log manager and prevent output from going to stdout
    this->dataPtr->logManager = new Ogre::LogManager();

    std::string logPath = common::SystemPaths::Instance()->GetLogPath();
    logPath += "/ogre.log";

    this->dataPtr->logManager->createLog(logPath, true, false, false);

    // Make the root
    try
    {
      // empty strings for config filenames (plugins.cfg and ogre.cfg)
      // so ogre doesn't try to look for them.
      this->dataPtr->root = new Ogre::Root("", "");
    }
    catch (Ogre::Exception &e)
    {
      gzthrow("Unable to create an Ogre rendering environment, no Root ");
    }

#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
    // OgreOverlay is a component on its own in ogre 1.9 so must manually
    // initialize it. Must be created after this->dataPtr->root,
    // but before this->dataPtr->root is initialized.
    if (!this->dataPtr->overlaySystem)
      this->dataPtr->overlaySystem = new Ogre::OverlaySystem();
#endif

    // Load all the plugins
    this->LoadPlugins();

    // Setup the rendering system, and create the context
    this->SetupRenderSystem();

    // Initialize the root node, and don't create a window
    this->dataPtr->root->initialise(false);

    // Setup the available resources
    this->SetupResources();
  }

  // Create a 1x1 render window so that we can grab a GL context. Based on
  // testing, this is a hard requirement by Apple. We also need it to
  // properly initialize GLWidget and UserCameras. See the GLWidget
  // constructor.
  this->dataPtr->windowManager->CreateWindow(
      std::to_string(this->dummyWindowId), 1, 1);

  this->CheckSystemCapabilities();
}

//////////////////////////////////////////////////
ScenePtr RenderEngine::CreateScene(const std::string &_name,
                                   bool _enableVisualizations,
                                   bool _isServer)
{
  if (this->dataPtr->renderPathType == NONE)
    return ScenePtr();

  if (!this->dataPtr->initialized)
  {
    gzerr << "RenderEngine is not initialized\n";
    return ScenePtr();
  }

  ScenePtr scene;

  try
  {
    scene.reset(new Scene(_name, _enableVisualizations, _isServer));
  }
  catch (...)
  {
    gzerr << "Failed to instantiate a scene\n";
    scene.reset();
    return scene;
  }

  try
  {
    scene->Load();
  }
  catch (...)
  {
    gzerr << "Failed to load scene\n";
    scene.reset();
    return scene;
  }

  try
  {
    scene->Init();
  }
  catch (...)
  {
    gzerr << "Failed to initialize scene\n";
    scene.reset();
    return scene;
  }

  this->dataPtr->scenes.push_back(scene);

  rendering::Events::createScene(_name);

  return scene;
}

//////////////////////////////////////////////////
void RenderEngine::RemoveScene(const std::string &_name)
{
  if (this->dataPtr->renderPathType == NONE)
    return;

  for (auto iter = this->dataPtr->scenes.begin();
       iter != this->dataPtr->scenes.end(); ++iter)
  {
    if ((*iter)->Name() == _name)
    {
      rendering::Events::removeScene(_name);

      (*iter)->Clear();
      (*iter).reset();
      this->dataPtr->scenes.erase(iter);
      return;
    }
  }
}

//////////////////////////////////////////////////
ScenePtr RenderEngine::GetScene(const std::string &_name)
{
  if (this->dataPtr->renderPathType == NONE)
    return ScenePtr();

  for (const auto &scene : this->dataPtr->scenes)
  {
    if (_name.empty() || scene->Name() == _name)
      return scene;
  }

  return ScenePtr();
}

//////////////////////////////////////////////////
ScenePtr RenderEngine::GetScene(unsigned int index)
{
  if (index < this->dataPtr->scenes.size())
    return this->dataPtr->scenes[index];
  else
  {
    gzerr << "Invalid Scene Index[" << index << "]\n";
    return ScenePtr();
  }
}

//////////////////////////////////////////////////
unsigned int RenderEngine::SceneCount() const
{
  return this->dataPtr->scenes.size();
}

//////////////////////////////////////////////////
void RenderEngine::PreRender()
{
  IGN_PROFILE("rendering::RenderEngine::PreRender");
  this->dataPtr->root->_fireFrameStarted();
}

//////////////////////////////////////////////////
void RenderEngine::Render()
{
  IGN_PROFILE("rendering::RenderEngine::Render");
}

//////////////////////////////////////////////////
void RenderEngine::PostRender()
{
  IGN_PROFILE("rendering::RenderEngine::PostRender");
  // _fireFrameRenderingQueued was here for CEGUI to work. Leaving because
  // it shouldn't harm anything, and we don't want to introduce
  // a regression.
  this->dataPtr->root->_fireFrameRenderingQueued();
  this->dataPtr->root->_fireFrameEnded();
}

//////////////////////////////////////////////////
void RenderEngine::Init()
{
  if (this->dataPtr->renderPathType == NONE)
  {
    gzwarn << "Cannot initialize render engine since "
           << "render path type is NONE. Ignore this warning if"
           << "rendering has been turned off on purpose.\n";
    return;
  }

  this->dataPtr->initialized = false;

  Ogre::ColourValue ambient;

  /// Create a dummy rendering context.
  /// This will allow gazebo to run headless. And it also allows OGRE to
  /// initialize properly

  // Set default mipmap level (NB some APIs ignore this)
  Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);

  // init the resources
  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(
      Ogre::TFO_ANISOTROPIC);

  RTShaderSystem::Instance()->Init();
  rendering::Material::CreateMaterials();

  for (unsigned int i = 0; i < this->dataPtr->scenes.size(); i++)
    this->dataPtr->scenes[i]->Init();

  this->dataPtr->initialized = true;
}

//////////////////////////////////////////////////
void RenderEngine::Fini()
{
  // TODO: this was causing a segfault on shutdown
  // Windows are created on load so clear them even
  // if render engine is not initialized
  this->dataPtr->windowManager->Fini();

  if (!this->dataPtr->initialized)
    return;

  this->dataPtr->connections.clear();

  RTShaderSystem::Instance()->Fini();

  // Deallocate memory for every scene
  while (!this->dataPtr->scenes.empty())
  {
    this->RemoveScene(this->dataPtr->scenes.front()->Name());
  }

#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
  delete this->dataPtr->overlaySystem;
  this->dataPtr->overlaySystem = NULL;
#endif

  // TODO: this was causing a segfault. Need to debug, and put back in
  if (this->dataPtr->root)
  {
    /*const Ogre::Root::PluginInstanceList ll =
     this->dataPtr->root->getInstalledPlugins();

    for (Ogre::Root::PluginInstanceList::const_iterator iter = ll.begin();
         iter != ll.end(); iter++)
    {
      this->dataPtr->root->unloadPlugin((*iter)->getName());
      this->dataPtr->root->uninstallPlugin(*iter);
    }
    */

    try
    {
      delete this->dataPtr->root;
    }
    catch (...)
    {
    }
  }
  this->dataPtr->root = NULL;

  delete this->dataPtr->logManager;
  this->dataPtr->logManager = NULL;

  for (unsigned int i = 0; i < this->dataPtr->scenes.size(); ++i)
    this->dataPtr->scenes[i].reset();
  this->dataPtr->scenes.clear();

  // Not Apple or Windows
#if not defined(__APPLE__) && not defined(_WIN32)
  if (this->dummyDisplay)
  {
    glXDestroyContext(static_cast<Display *>(this->dummyDisplay),
                      static_cast<GLXContext>(this->dummyContext));
    XDestroyWindow(static_cast<Display *>(this->dummyDisplay),
                   this->dummyWindowId);
    XCloseDisplay(static_cast<Display *>(this->dummyDisplay));
    this->dummyDisplay = NULL;
  }
#endif

  this->dataPtr->initialized = false;
}

//////////////////////////////////////////////////
void RenderEngine::LoadPlugins()
{
  std::list<std::string>::iterator iter;
  std::list<std::string> ogrePaths =
      common::SystemPaths::Instance()->GetOgrePaths();

  for (iter = ogrePaths.begin();
       iter != ogrePaths.end(); ++iter)
  {
    std::string path(*iter);
    DIR *dir = opendir(path.c_str());

    if (dir == NULL)
    {
      continue;
    }
    closedir(dir);

    std::vector<std::string> plugins;
    std::vector<std::string>::iterator piter;

#ifdef __APPLE__
    std::string extension = ".dylib";
#elif defined(_WIN32)
    std::string extension = ".dll";
#else
    std::string extension = ".so";
#endif

    plugins.push_back(path + "/RenderSystem_GL");
    plugins.push_back(path + "/Plugin_ParticleFX");
    plugins.push_back(path + "/Plugin_BSPSceneManager");
    plugins.push_back(path + "/Plugin_OctreeSceneManager");

#if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR >= 11
    // OGRE 1.11 moved FreeImage codec support to a plugin
    // See: https://github.com/OGRECave/ogre/blob/master/Docs/1.11-Notes.md
    plugins.push_back(path + "/Codec_FreeImage");
#endif

#ifdef HAVE_OCULUS
    plugins.push_back(path + "/Plugin_CgProgramManager");
#endif

    for (piter = plugins.begin(); piter != plugins.end(); ++piter)
    {
      try
      {
#if _DEBUG
        // Load the debug plugin into OGRE
        this->dataPtr->root->loadPlugin(*piter + "_d" + extension);
#else
        // Load the plugin into OGRE
        this->dataPtr->root->loadPlugin(*piter + extension);
#endif
      }
      catch (Ogre::Exception &e)
      {
        gzerr << "Exception: " + e.getFullDescription();
        gzerr << "Unable to load Ogre Plugin[" << *piter
              << "]. Rendering will not be possible."
              << "Make sure you have installed OGRE and Gazebo properly.\n";
      }
    }
  }
}

/////////////////////////////////////////////////
void RenderEngine::AddResourcePath(const std::string &_uri)
{
  if (_uri.find("__default__") != std::string::npos || _uri.empty())
    return;

  std::string path = common::find_file_path(_uri);

  if (path.empty())
  {
    gzerr << "URI doesn't exist[" << _uri << "]\n";
    return;
  }

  try
  {
    path = boost::filesystem::path(path).make_preferred().string();
    if (!Ogre::ResourceGroupManager::getSingleton().resourceLocationExists(
            path, "General"))
    {
      Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
          path, "FileSystem", "General", true);
      Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup(
          "General");

      // Parse all material files in the path if any exist
      boost::filesystem::path dir(path);

      if (boost::filesystem::exists(dir) &&
          boost::filesystem::is_directory(dir))
      {
        std::vector<boost::filesystem::path> paths;
        std::copy(boost::filesystem::directory_iterator(dir),
                  boost::filesystem::directory_iterator(),
                  std::back_inserter(paths));
        std::sort(paths.begin(), paths.end());

        // Iterate over all the models in the current gazebo path
        for (std::vector<boost::filesystem::path>::iterator dIter =
                 paths.begin();
             dIter != paths.end(); ++dIter)
        {
          if (dIter->filename().extension() == ".material")
          {
            boost::filesystem::path fullPath = path / dIter->filename();
            fullPath = dIter->filename();

            Ogre::DataStreamPtr stream =
                Ogre::ResourceGroupManager::getSingleton().openResource(
                    fullPath.string(), "General");

            // There is a material file under there somewhere, read the thing in
            try
            {
              Ogre::MaterialManager::getSingleton().parseScript(
                  stream, "General");
              Ogre::MaterialPtr matPtr =
                  Ogre::MaterialManager::getSingleton().getByName(
                      fullPath.string());

              if (!matPtr.isNull())
              {
                // is this necessary to do here? Someday try it without
                matPtr->compile();
                matPtr->load();
              }
            }
            catch (Ogre::Exception &e)
            {
              gzerr << "Unable to parse material file[" << fullPath << "]\n";
            }
            stream->close();
          }
        }
      }
    }
  }
  catch (Ogre::Exception &_e)
  {
    gzerr << _e.getFullDescription();
    gzthrow("Unable to load Ogre Resources.\nMake sure the"
            "resources path in the world file is set correctly.");
  }
}

//////////////////////////////////////////////////
RenderEngine::RenderPathType RenderEngine::GetRenderPathType() const
{
  return this->dataPtr->renderPathType;
}

//////////////////////////////////////////////////
void RenderEngine::SetupResources()
{
  std::vector<std::pair<std::string, std::string>> archNames;
  std::vector<std::pair<std::string, std::string>>::iterator aiter;
  std::list<std::string>::const_iterator iter;
  std::list<std::string> paths =
      common::SystemPaths::Instance()->GetGazeboPaths();

  std::list<std::string> mediaDirs;
  mediaDirs.push_back("media");

  for (iter = paths.begin(); iter != paths.end(); ++iter)
  {
    DIR *dir;
    if ((dir = opendir((*iter).c_str())) == NULL)
    {
      continue;
    }
    closedir(dir);

    archNames.push_back(
        std::make_pair((*iter) + "/", "General"));

    for (std::list<std::string>::iterator mediaIter = mediaDirs.begin();
         mediaIter != mediaDirs.end(); ++mediaIter)
    {
      std::string prefix = (*iter) + "/" + (*mediaIter);

      archNames.push_back(
          std::make_pair(prefix, "General"));
      archNames.push_back(
          std::make_pair(prefix + "/skyx", "SkyX"));
#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0) && !defined(__APPLE__))
      archNames.push_back(
          std::make_pair(prefix + "/rtshaderlib150", "General"));
#endif
      archNames.push_back(
          std::make_pair(prefix + "/rtshaderlib", "General"));
#if (OGRE_RESOURCEMANAGER_STRICT == 0)
      archNames.push_back(
          std::make_pair(prefix + "/materials/programs", "General"));
#endif
      archNames.push_back(
          std::make_pair(prefix + "/materials/scripts", "General"));
      archNames.push_back(
          std::make_pair(prefix + "/materials/textures", "General"));
      archNames.push_back(
          std::make_pair(prefix + "/media/models", "General"));
      archNames.push_back(
          std::make_pair(prefix + "/fonts", "Fonts"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/looknfeel", "LookNFeel"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/schemes", "Schemes"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/imagesets", "Imagesets"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/fonts", "Fonts"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/layouts", "Layouts"));
      archNames.push_back(
          std::make_pair(prefix + "/gui/animations", "Animations"));
#if (OGRE_RESOURCEMANAGER_STRICT != 0)
      try
      {
        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
            boost::filesystem::path(
                prefix + "/materials/programs")
                .make_preferred()
                .string(),
            "FileSystem", "General", true);
      }
      catch (Ogre::Exception & /*_e*/)
      {
        gzerr << "Unable to load Ogre Resources. Make sure the resources path "
              << "in the world file is set correctly.";
      }
#endif
    }
  }

  for (aiter = archNames.begin(); aiter != archNames.end(); ++aiter)
  {
    try
    {
      Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
          boost::filesystem::path(aiter->first).make_preferred().string(),
          "FileSystem", aiter->second);
    }
    catch (Ogre::Exception & /*_e*/)
    {
      gzthrow("Unable to load Ogre Resources. Make sure the resources path "
              "in the world file is set correctly.");
    }
  }
}

//////////////////////////////////////////////////
void RenderEngine::SetupRenderSystem()
{
  Ogre::RenderSystem *renderSys;
  const Ogre::RenderSystemList *rsList;

  // Set parameters of render system (window size, etc.)
#if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR == 6
  rsList = this->dataPtr->root->getAvailableRenderers();
#else
  rsList = &(this->dataPtr->root->getAvailableRenderers());
#endif

  int c = 0;

  renderSys = NULL;

  do
  {
    if (c == static_cast<int>(rsList->size()))
      break;

    renderSys = rsList->at(c);
    c++;
  } while (renderSys &&
           renderSys->getName().compare("OpenGL Rendering Subsystem") != 0);

  if (renderSys == NULL)
  {
    gzthrow("unable to find OpenGL rendering system. OGRE is probably "
            "installed incorrectly. Double check the OGRE cmake output, "
            "and make sure OpenGL is enabled.");
  }

  // We operate in windowed mode
  renderSys->setConfigOption("Full Screen", "No");

  /// We used to allow the user to set the RTT mode to PBuffer, FBO, or Copy.
  ///   Copy is slow, and there doesn't seem to be a good reason to use it
  ///   PBuffer limits the size of the renderable area of the RTT to the
  ///           size of the first window created.
  ///   FBO seem to be the only good option
  renderSys->setConfigOption("RTT Preferred Mode", "FBO");

  // get all supported fsaa values
  Ogre::ConfigOptionMap configMap = renderSys->getConfigOptions();
  auto fsaaOoption = configMap.find("FSAA");

  if (fsaaOoption != configMap.end())
  {
    auto values = (*fsaaOoption).second.possibleValues;
    for (auto const &str : values)
    {
      int value = 0;
      try
      {
        value = std::stoi(str);
      }
      catch (...)
      {
        continue;
      }
      this->dataPtr->fsaaLevels.push_back(value);
    }
  }
  std::sort(this->dataPtr->fsaaLevels.begin(), this->dataPtr->fsaaLevels.end());

  // check if target fsaa is supported
  unsigned int fsaa = 0;
  unsigned int targetFSAA = 4;
  auto const it = std::find(this->dataPtr->fsaaLevels.begin(),
                            this->dataPtr->fsaaLevels.end(), targetFSAA);
  if (it != this->dataPtr->fsaaLevels.end())
    fsaa = targetFSAA;

  renderSys->setConfigOption("FSAA", std::to_string(fsaa));

  this->dataPtr->root->setRenderSystem(renderSys);
}

/////////////////////////////////////////////////
bool RenderEngine::CreateContext()
{
  bool result = true;

#if defined __APPLE__ || _WIN32
  this->dummyDisplay = 0;
#else
  try
  {
    this->dummyDisplay = XOpenDisplay(0);
    if (!this->dummyDisplay)
    {
      gzerr << "Can't open display: " << XDisplayName(0) << "\n";
      return false;
    }

    int screen = DefaultScreen(this->dummyDisplay);

    int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16,
                        GLX_STENCIL_SIZE, 8, None};

    XVisualInfo *dummyVisual = glXChooseVisual(
        static_cast<Display *>(this->dummyDisplay),
        screen, static_cast<int *>(attribList));

    if (!dummyVisual)
    {
      gzerr << "Unable to create glx visual\n";
      return false;
    }

    this->dummyWindowId = XCreateSimpleWindow(
        static_cast<Display *>(this->dummyDisplay),
        RootWindow(static_cast<Display *>(this->dummyDisplay), screen),
        0, 0, 1, 1, 0, 0, 0);

    this->dummyContext = glXCreateContext(
        static_cast<Display *>(this->dummyDisplay),
        dummyVisual, NULL, 1);

    if (!this->dummyContext)
    {
      gzerr << "Unable to create glx context\n";
      return false;
    }

    glXMakeCurrent(static_cast<Display *>(this->dummyDisplay),
                   this->dummyWindowId, static_cast<GLXContext>(this->dummyContext));
  }
  catch (...)
  {
    result = false;
  }
#endif

  return result;
}

/////////////////////////////////////////////////
void RenderEngine::CheckSystemCapabilities()
{
  const Ogre::RenderSystemCapabilities *capabilities;
  Ogre::RenderSystemCapabilities::ShaderProfiles profiles;
  Ogre::RenderSystemCapabilities::ShaderProfiles::const_iterator iter;

  capabilities = this->dataPtr->root->getRenderSystem()->getCapabilities();
  if (!capabilities)
  {
    gzerr << "Cannot get render system capabilities" << std::endl;
    return;
  }

  profiles = capabilities->getSupportedShaderProfiles();

  bool hasFragmentPrograms =
      capabilities->hasCapability(Ogre::RSC_FRAGMENT_PROGRAM);

  bool hasVertexPrograms =
      capabilities->hasCapability(Ogre::RSC_VERTEX_PROGRAM);

  // bool hasGeometryPrograms =
  //  capabilities->hasCapability(Ogre::RSC_GEOMETRY_PROGRAM);

  // bool hasRenderToVertexBuffer =
  //  capabilities->hasCapability(Ogre::RSC_HWRENDER_TO_VERTEX_BUFFER);

  // int multiRenderTargetCount = capabilities->getNumMultiRenderTargets();

  bool hasFBO =
#if OGRE_VERSION_MAJOR == 1 && OGRE_VERSION_MINOR >= 11
      // All APIs targeted by OGRE supported this capability,
      // see https://ogrecave.github.io/ogre/api/1.10/group___render_system.html#gga3d2965b7f378ebdcfe8a4a6cf74c3de7a8a0ececdc95122ac3063fc4f27d6402c
      true;
#else
      capabilities->hasCapability(Ogre::RSC_FBO);
#endif

  bool hasGLSL =
      std::find(profiles.begin(), profiles.end(), "glsl") != profiles.end();

  if (!hasFragmentPrograms || !hasVertexPrograms)
    gzwarn << "Vertex and fragment shaders are missing. "
           << "Fixed function rendering will be used.\n";

  if (!hasGLSL)
    gzwarn << "GLSL is missing."
           << "Fixed function rendering will be used.\n";

  if (!hasFBO)
    gzwarn << "Frame Buffer Objects (FBO) is missing. "
           << "Rendering will be disabled.\n";

  this->dataPtr->renderPathType = RenderEngine::NONE;

  if (hasFBO && hasGLSL && hasVertexPrograms && hasFragmentPrograms)
    this->dataPtr->renderPathType = RenderEngine::FORWARD;
  else if (hasFBO)
    this->dataPtr->renderPathType = RenderEngine::VERTEX;

  // Disable deferred rendering for now. Needs more work.
  // if (hasRenderToVertexBuffer && multiRenderTargetCount >= 8)
  //  this->dataPtr->renderPathType = RenderEngine::DEFERRED;
}

/////////////////////////////////////////////////
WindowManagerPtr RenderEngine::GetWindowManager() const
{
  return this->dataPtr->windowManager;
}

/////////////////////////////////////////////////
Ogre::Root *RenderEngine::Root() const
{
  return this->dataPtr->root;
}

/////////////////////////////////////////////////
std::vector<unsigned int> RenderEngine::FSAALevels() const
{
  return this->dataPtr->fsaaLevels;
}

#if (OGRE_VERSION >= ((1 << 16) | (9 << 8) | 0))
/////////////////////////////////////////////////
Ogre::OverlaySystem *RenderEngine::OverlaySystem() const
{
  return this->dataPtr->overlaySystem;
}
#endif

ext: cc

max_stars_repo_name: pedro-salgueiro/gazebo

max_issues_repo_name: pedro-salgueiro/gazebo

max_forks_repo_name: pedro-salgueiro/gazebo


text:
#include <boost/test/auto_unit_test.hpp>
#include "inputs/outliers.h"
#include "inputs/data_for_outliers_ut.h"
#include "libs/sources_handling/input_data.h"
#include "apps/detect_duplicates/outliers_action.h"
#include "apps/detect_duplicates/duplication_task.h"
#include "utils/algorithms.hpp"
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
#include <iostream>

using test_data_outliers = std::vector<input_data>;

template<typename Range>
row_numbers run_detection(policy_action action, const Range& input)
{
    outliers_detector detect_action{action};
    std::for_each(std::begin(input), std::end(input),
                        [&detect_action](auto& data) {
                                ::apply_action(detect_action, data);
                    }
    );
    row_numbers outliers, missings;
    finding(detect_action, outliers, missings);
    return outliers;
}

BOOST_AUTO_TEST_CASE(test_no_outliers)
{
    test_data_outliers not_outliers {
        {1.0, 1}, {1.0, 2}, {1.0, 3}, {1.0, 4},
        {1.0, 5}, {1.0, 6}, {1.0, 7}, {1.0, 8},
    }; // all same, so no outliers
    // build the action that we would apply on this
    row_numbers empty_list;
    auto outliers = run_detection(outlier_predicate {std::begin(empty_list), std::end(empty_list)},
            not_outliers);

    BOOST_TEST(outliers.empty(), "we are not expecting to find any outliers in this input");
}

BOOST_AUTO_TEST_CASE (test_outiers_no_drops)
{
    test_data_outliers input_data;
    auto index = 1u;
    boost::transform(Input_vector, std::back_inserter(input_data), [&index](auto val) {
                                return test_data_outliers::value_type{val, index++};
                            }
                    );
    row_numbers empty_list;
    //boost::copy(input_data, std::ostream_iterator<test_data_outliers::value_type>(std::cout, "\n"));
    auto outliers = run_detection(outlier_predicate{std::begin(empty_list), std::end(empty_list)}, input_data);
    //boost::copy(outliers, std::ostream_iterator<row_numbers::value_type>(std::cout, "\n"));
    BOOST_TEST_REQUIRE(!outliers.empty(), "we must have outliers in this list");
    BOOST_TEST_REQUIRE(outliers.size() == utils::size(identified_outliers_idx),
            "the number of outliers must be "<<utils::size(identified_outliers_idx)<<", but we have "<<outliers.size());

    for (auto outlier : outliers) {
        auto i = std::find(std::begin(identified_outliers_idx), std::end(identified_outliers_idx), outlier);
        BOOST_TEST((i != std::end(identified_outliers_idx)),
                    "outlier index "<<outlier<<" for "<<Input_vector[outlier]<<" must be in the list of outliers");
    }
}

BOOST_AUTO_TEST_CASE (test_outiers_with_drops)
{
    test_data_outliers input_data;
    auto index = 1u;
    boost::transform(Input_vector, std::back_inserter(input_data), [&index](auto val) {
                                return test_data_outliers::value_type{val, index++};
                            }
                    );
    row_numbers drops{identified_outliers_idx[0]};
    //boost::copy(input_data, std::ostream_iterator<test_data_outliers::value_type>(std::cout, "\n"));
    auto outliers = run_detection(outlier_predicate{std::begin(drops), std::end(drops)}, input_data);
    //boost::copy(outliers, std::ostream_iterator<row_numbers::value_type>(std::cout, "\n"));
    BOOST_TEST_REQUIRE(!outliers.empty(), "we must have outliers in this list");
    BOOST_TEST_REQUIRE(outliers.size() == (utils::size(identified_outliers_idx) - 1),
            "the number of outliers must be "<<(utils::size(identified_outliers_idx)-1)<<", but we have "<<outliers.size());

    for (auto outlier : outliers) {
        if (outlier != identified_outliers_idx[0]) {
            auto i = std::find(std::begin(identified_outliers_idx), std::end(identified_outliers_idx), outlier);
            BOOST_TEST((i != std::end(identified_outliers_idx)),
                    "outlier index "<<outlier<<" for "<<Input_vector[outlier]<<" must be in the list of outliers");
        }
    }
}

BOOST_AUTO_TEST_CASE (test_outiers_with_duplications)
{
    const row_numbers::value_type expected_rows[] = {
        123,  449,  499,  982,  993, 1015, 1016, 1031, 1042, 1043, 1045,
        1046, 1149, 1240, 2015, 2313, 2948
    };
    auto outliers = run_detection(outlier_predicate{}, outliers_input_data);
    BOOST_TEST_REQUIRE(outliers.empty() == false);
    std::set<row_numbers::value_type> dups;
    for (auto v : outliers) {
        auto r = dups.insert(v);
        BOOST_TEST(r.second,
                "the value "<<v<<" was already in the list of outliers - we should not have duplications!");
    }
    std::cout<<std::endl;
    BOOST_TEST_REQUIRE(utils::size(expected_rows) == outliers.size());
    std::sort(std::begin(outliers), std::end(outliers));
    for (auto i = 0u; i < outliers.size(); ++i) {
        BOOST_TEST(expected_rows[i] == outliers[i],
                "the value "<<expected_rows[i]<<" was expected to be in outliers list but we have "<<outliers[i]);
    }
}


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

#ifndef read_reader_impl_hpp
#define read_reader_impl_hpp

#include <string>
#include <vector>
#include <cstddef>
#include <unordered_map>
#include <utility>
#include <functional>

#include <boost/optional.hpp>

#include "basics/genomic_region.hpp"
#include "basics/aligned_read.hpp"

namespace octopus { namespace io {

class IReadReaderImpl
{
public:
    using SampleName    = std::string;
    using ReadContainer = std::vector<AlignedRead>;
    using SampleReadMap = std::unordered_map<SampleName, ReadContainer>;
    using PositionList  = std::vector<GenomicRegion::Position>;
    using AlignedReadReadVisitor = std::function<bool(const SampleName&, AlignedRead)>;
    using ContigRegionVisitor = std::function<bool(const SampleName&, ContigRegion)>;

    virtual ~IReadReaderImpl() noexcept = default;

    virtual bool is_open() const noexcept = 0;
    virtual void open() = 0;
    virtual void close() = 0;

    virtual std::vector<SampleName> extract_samples() const = 0;
    virtual std::vector<std::string> extract_read_groups(const SampleName& sample) const = 0;

    virtual bool iterate(const GenomicRegion& region,
                         AlignedReadReadVisitor visitor) const = 0;
    virtual bool iterate(const SampleName& sample,
                         const GenomicRegion& region,
                         AlignedReadReadVisitor visitor) const = 0;
    virtual bool iterate(const std::vector<SampleName>& samples,
                         const GenomicRegion& region,
                         AlignedReadReadVisitor visitor) const = 0;

    virtual bool iterate(const GenomicRegion& region,
                         ContigRegionVisitor visitor) const = 0;
    virtual bool iterate(const SampleName& sample,
                         const GenomicRegion& region,
                         ContigRegionVisitor visitor) const = 0;
    virtual bool iterate(const std::vector<SampleName>& samples,
                         const GenomicRegion& region,
                         ContigRegionVisitor visitor) const = 0;

    virtual bool has_reads(const GenomicRegion& region) const = 0;
    virtual bool has_reads(const SampleName& sample,
                           const GenomicRegion& region) const = 0;
    virtual bool has_reads(const std::vector<SampleName>& samples,
                           const GenomicRegion& region) const = 0;

    virtual std::size_t count_reads(const GenomicRegion& region) const = 0;
    virtual std::size_t count_reads(const SampleName& sample,
                                    const GenomicRegion& region) const = 0;
    virtual std::size_t count_reads(const std::vector<SampleName>& sample,
                                    const GenomicRegion& region) const = 0;

    virtual PositionList extract_read_positions(const GenomicRegion& region,
                                                std::size_t max_reads) const = 0;
    virtual PositionList extract_read_positions(const SampleName& sample,
                                                const GenomicRegion& region,
                                                std::size_t max_reads) const = 0;
    virtual PositionList extract_read_positions(const std::vector<SampleName>& samples,
                                                const GenomicRegion& region,
                                                std::size_t max_reads) const = 0;

    virtual SampleReadMap fetch_reads(const GenomicRegion& region) const = 0;
    virtual ReadContainer fetch_reads(const SampleName& sample,
                                      const GenomicRegion& region) const = 0;
    virtual SampleReadMap fetch_reads(const std::vector<SampleName>& samples,
                                      const GenomicRegion& region) const = 0;

    virtual std::vector<GenomicRegion::ContigName> reference_contigs() const = 0;
    virtual GenomicRegion::Size reference_size(const GenomicRegion::ContigName& contig) const = 0;

    virtual boost::optional<std::vector<GenomicRegion::ContigName>> mapped_contigs() const { return boost::none; };
    virtual boost::optional<std::vector<GenomicRegion>> mapped_regions() const { return boost::none; };
};

} // namespace io
} // namespace octopus

#endif

max_stars_repo_name: roryk/octopus

max_issues_repo_name: roryk/octopus

max_forks_repo_name: roryk/octopus


text:
#include "Vocabulary.h"
#include "Singleton.h"

#define BOOST_TEST_MODULE MertVocabulary
#include <boost/test/unit_test.hpp>

using namespace MosesTuning;

namespace mert {
namespace {

void TearDown() {
  Singleton<Vocabulary>::Delete();
}

} // namespace

BOOST_AUTO_TEST_CASE(vocab_basic) {
  Vocabulary vocab;
  BOOST_REQUIRE(vocab.empty());
  vocab.clear();

  BOOST_CHECK_EQUAL(0, vocab.Encode("hello"));
  BOOST_CHECK_EQUAL(0, vocab.Encode("hello"));
  BOOST_CHECK_EQUAL(1, vocab.Encode("world"));

  BOOST_CHECK_EQUAL(2, vocab.size());

  int v;
  BOOST_CHECK(vocab.Lookup("hello", &v));
  BOOST_CHECK_EQUAL(0, v);
  BOOST_CHECK(vocab.Lookup("world", &v));
  BOOST_CHECK_EQUAL(1, v);

  BOOST_CHECK(!vocab.Lookup("java", &v));

  vocab.clear();
  BOOST_CHECK(!vocab.Lookup("hello", &v));
  BOOST_CHECK(!vocab.Lookup("world", &v));
}

BOOST_AUTO_TEST_CASE(vocab_factory_test) {
  Vocabulary* vocab1 = VocabularyFactory::GetVocabulary();
  Vocabulary* vocab2 = VocabularyFactory::GetVocabulary();
  Vocabulary* vocab3 = VocabularyFactory::GetVocabulary();

  BOOST_REQUIRE(vocab1 != NULL);
  BOOST_CHECK(vocab1 == vocab2);
  BOOST_CHECK(vocab2 == vocab3);

  TearDown();
}
} // namespace mert

max_stars_repo_name: anshsarkar/TailBench

max_issues_repo_name: anshsarkar/TailBench

max_forks_repo_name: anshsarkar/TailBench


text:
// Copyright 2010 Dean Michael Berris.
// Copyright 2016 Google, Inc.
// 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)

#include <gtest/gtest.h>
#include <boost/network/message/directives/header.hpp>
#include <boost/network/protocol/http/algorithms/linearize.hpp>
#include <boost/network/protocol/http/request.hpp>
#include <iostream>
#include <iterator>
#include "tag_types.hpp"

namespace http = boost::network::http;
namespace tags = boost::network::http::tags;
namespace mpl = boost::mpl;
namespace net = boost::network;

template <class T>
class LinearizeTest : public ::testing::Test {};

TYPED_TEST_CASE(LinearizeTest, TagTypes);

TYPED_TEST(LinearizeTest, LinearizeRequest) {
  http::basic_request<TypeParam> request("http://www.boost.org");
  static char http_1_0_output[] =
      "GET / HTTP/1.0\r\n"
      "Host: www.boost.org\r\n"
      "Accept: */*\r\n"
      "Connection: Close\r\n"
      "\r\n";
  static char http_1_1_output[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.boost.org\r\n"
      "Accept: */*\r\n"
      "Accept-Encoding: identity;q=1.0, *;q=0\r\n"
      "Connection: Close\r\n"
      "\r\n";
  typename http::basic_request<TypeParam>::string_type output_1_0;
  linearize(request, "GET", 1, 0, std::back_inserter(output_1_0));
  EXPECT_EQ(http_1_0_output, output_1_0);
  typename http::basic_request<TypeParam>::string_type output_1_1;
  linearize(request, "GET", 1, 1, std::back_inserter(output_1_1));
  EXPECT_EQ(http_1_1_output, output_1_1);
}

TYPED_TEST(LinearizeTest, OverrideHeaders) {
  http::basic_request<TypeParam> request("http://www.boost.org");
  // We can override the defaulted headers and test that here.
  request << net::header("Accept", "");
  static char http_1_0_no_accept_output[] =
      "GET / HTTP/1.0\r\n"
      "Host: www.boost.org\r\n"
      "Connection: Close\r\n"
      "\r\n";
  static char http_1_1_no_accept_output[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.boost.org\r\n"
      "Accept-Encoding: identity;q=1.0, *;q=0\r\n"
      "Connection: Close\r\n"
      "\r\n";
  typename http::basic_request<TypeParam>::string_type output_1_0;
  linearize(request, "GET", 1, 0, std::back_inserter(output_1_0));
  EXPECT_EQ(http_1_0_no_accept_output, output_1_0);
  typename http::basic_request<TypeParam>::string_type output_1_1;
  linearize(request, "GET", 1, 1, std::back_inserter(output_1_1));
  EXPECT_EQ(http_1_1_no_accept_output, output_1_1);
}

max_stars_repo_name: yhager/cpp-netlib

max_issues_repo_name: yhager/cpp-netlib

max_forks_repo_name: yhager/cpp-netlib


text: #include <boost/python/object_call.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
// Copyright (C) 2015, Pawel Tomulik <ptomulik@meil.pw.edu.pl>
//
// 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)
#define BOOST_TEST_MODULE test_txpl_lexer_token_t

#include <txpl/test_config.hpp>
#include <boost/test/unit_test.hpp>

#ifndef TXPL_TEST_SKIP_LEXER_TOKEN_T

#include <txpl/lexer/token_t.hpp>
BOOST_AUTO_TEST_CASE(token_t__values)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::plus_     == static_cast<token_t>('+'));
  BOOST_CHECK(token_t::minus_    == static_cast<token_t>('-'));
  BOOST_CHECK(token_t::mul_      == static_cast<token_t>('*'));
  BOOST_CHECK(token_t::div_      == static_cast<token_t>('/'));
  BOOST_CHECK(token_t::mod_      == static_cast<token_t>('%'));
  BOOST_CHECK(token_t::xor_      == static_cast<token_t>('^'));
  BOOST_CHECK(token_t::bitand_   == static_cast<token_t>('&'));
  BOOST_CHECK(token_t::bitor_    == static_cast<token_t>('|'));
  BOOST_CHECK(token_t::lt_       == static_cast<token_t>('<'));
  BOOST_CHECK(token_t::gt_       == static_cast<token_t>('>'));
  BOOST_CHECK(token_t::not_      == static_cast<token_t>('!'));
  BOOST_CHECK(token_t::neg_      == static_cast<token_t>('~'));
  BOOST_CHECK(token_t::comma_    == static_cast<token_t>(','));
  BOOST_CHECK(token_t::dot_      == static_cast<token_t>('.'));
  BOOST_CHECK(token_t::lparen_   == static_cast<token_t>('('));
  BOOST_CHECK(token_t::rparen_   == static_cast<token_t>(')'));
  BOOST_CHECK(token_t::lbracket_ == static_cast<token_t>('['));
  BOOST_CHECK(token_t::rbracket_ == static_cast<token_t>(']'));
  BOOST_CHECK(token_t::lbrace_   == static_cast<token_t>('{'));
  BOOST_CHECK(token_t::rbrace_   == static_cast<token_t>('}'));

  BOOST_CHECK(token_t::qchar_    == static_cast<token_t>(0x10000));
  BOOST_CHECK(token_t::qstring_  == static_cast<token_t>(0x10001));
  BOOST_CHECK(token_t::qregex_   == static_cast<token_t>(0x10002));
  BOOST_CHECK(token_t::word_     == static_cast<token_t>(0x10003));
  BOOST_CHECK(token_t::real_     == static_cast<token_t>(0x10004));
  BOOST_CHECK(token_t::int_      == static_cast<token_t>(0x10005));
  BOOST_CHECK(token_t::bool_     == static_cast<token_t>(0x10006));
  BOOST_CHECK(token_t::and_      == static_cast<token_t>(0x10100));
  BOOST_CHECK(token_t::or_       == static_cast<token_t>(0x10101));
  BOOST_CHECK(token_t::eq_       == static_cast<token_t>(0x10102));
  BOOST_CHECK(token_t::neq_      == static_cast<token_t>(0x10103));
  BOOST_CHECK(token_t::le_       == static_cast<token_t>(0x10104));
  BOOST_CHECK(token_t::ge_       == static_cast<token_t>(0x10105));
  BOOST_CHECK(token_t::lshift_   == static_cast<token_t>(0x10106));
  BOOST_CHECK(token_t::rshift_   == static_cast<token_t>(0x10107));
  BOOST_CHECK(token_t::match_    == static_cast<token_t>(0x10108));
  BOOST_CHECK(token_t::nmatch_   == static_cast<token_t>(0x10109));
  BOOST_CHECK(token_t::nssep_    == static_cast<token_t>(0x1010A));
  BOOST_CHECK(token_t::spaces_   == static_cast<token_t>(0x1010B));
  BOOST_CHECK(token_t::other_    == static_cast<token_t>(0x1010C));
}
BOOST_AUTO_TEST_CASE(token_t__eq__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ == '(');
  BOOST_CHECK(token_t::rparen_ == ')');
  BOOST_CHECK('(' == token_t::lparen_);
  BOOST_CHECK(')' == token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ == '('));
  BOOST_CHECK(!('(' == token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__eq__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ == L'(');
  BOOST_CHECK(token_t::rparen_ == L')');
  BOOST_CHECK(L'(' == token_t::lparen_);
  BOOST_CHECK(L')' == token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ == L'('));
  BOOST_CHECK(!(L'(' == token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__neq__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ != ')');
  BOOST_CHECK(token_t::rparen_ != '(');
  BOOST_CHECK(')' != token_t::lparen_);
  BOOST_CHECK('(' != token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ != ')'));
  BOOST_CHECK(!(')' != token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__neq__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ != L')');
  BOOST_CHECK(token_t::rparen_ != L'(');
  BOOST_CHECK(L')' != token_t::lparen_);
  BOOST_CHECK(L'(' != token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ != L')'));
  BOOST_CHECK(!(L')' != token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__lt__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ < ')');
  BOOST_CHECK('(' < token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ < '('));
  BOOST_CHECK(!(')' < token_t::lparen_));
}
BOOST_AUTO_TEST_CASE(token_t__lt__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ < L')');
  BOOST_CHECK(L'(' < token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ < L'('));
  BOOST_CHECK(!(L')' < token_t::lparen_));
}
BOOST_AUTO_TEST_CASE(token_t__gt__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::rparen_ > '(');
  BOOST_CHECK(')' > token_t::lparen_);
  BOOST_CHECK(!(token_t::lparen_ > ')'));
  BOOST_CHECK(!('(' > token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__gt__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::rparen_ > L'(');
  BOOST_CHECK(L')' > token_t::lparen_);
  BOOST_CHECK(!(token_t::lparen_ > L')'));
  BOOST_CHECK(!(L'(' > token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__le__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ <= ')');
  BOOST_CHECK(token_t::lparen_ <= '(');
  BOOST_CHECK('(' <= token_t::rparen_);
  BOOST_CHECK(')' <= token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ <= '('));
  BOOST_CHECK(!(')' <= token_t::lparen_));
}
BOOST_AUTO_TEST_CASE(token_t__le__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::lparen_ <= L')');
  BOOST_CHECK(token_t::lparen_ <= L'(');
  BOOST_CHECK(L'(' <= token_t::rparen_);
  BOOST_CHECK(L')' <= token_t::rparen_);
  BOOST_CHECK(!(token_t::rparen_ <= L'('));
  BOOST_CHECK(!(L')' <= token_t::lparen_));
}
BOOST_AUTO_TEST_CASE(token_t__ge__char)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::rparen_ >= '(');
  BOOST_CHECK(token_t::rparen_ >= ')');
  BOOST_CHECK(')' >= token_t::lparen_);
  BOOST_CHECK('(' >= token_t::lparen_);
  BOOST_CHECK(!(token_t::lparen_ >= ')'));
  BOOST_CHECK(!('(' >= token_t::rparen_));
}
BOOST_AUTO_TEST_CASE(token_t__ge__wchar_t)
{
  using namespace txpl::lexer;
  BOOST_CHECK(token_t::rparen_ >= L'(');
  BOOST_CHECK(token_t::rparen_ >= L')');
  BOOST_CHECK(L')' >= token_t::lparen_);
  BOOST_CHECK(L'(' >= token_t::lparen_);
  BOOST_CHECK(!(token_t::lparen_ >= L')'));
  BOOST_CHECK(!(L'(' >= token_t::rparen_));
}
#else
BOOST_AUTO_TEST_CASE(dummy)
{
  BOOST_CHECK(true);
}
#endif

max_stars_repo_name: ptomulik/txpl

max_issues_repo_name: ptomulik/txpl

max_forks_repo_name: ptomulik/txpl


text:
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <cmath>
#include <cstddef>
#include <dcs/debug.hpp>
#include <dcs/math/random/mersenne_twister.hpp>
#include <dcs/math/stats/distribution/mmpp.hpp>
#include <dcs/test.hpp>

static const double tol(1.0e-5);

DCS_TEST_DEF( rand )
{
	DCS_DEBUG_TRACE("Test Case: Random Variate Generation");

	typedef double real_type;
	typedef ::boost::numeric::ublas::matrix<real_type> matrix_type;
	typedef ::boost::numeric::ublas::vector<real_type> vector_type;
	typedef ::std::size_t size_type;

	const size_type n(2);
	const unsigned long seed(5489UL);

	vector_type lambda(n);
	lambda(0) = 20;
	lambda(1) = 2;

	matrix_type Q(n,n);
	Q(0,0) = -2; Q(0,1) =  2;
	Q(1,0) =  1; Q(1,1) = -1;

	::dcs::math::stats::mmpp_distribution<real_type> mmpp(lambda, Q);
	DCS_DEBUG_TRACE("Q: " << mmpp.Q());
	DCS_DEBUG_TRACE("lambda: " << mmpp.lambda());

	::dcs::math::random::mt19937 rng(seed);

	real_type res;
	real_type expect;

	res = ::dcs::math::stats::rand(mmpp, rng);
	expect = 0.107375;
	DCS_DEBUG_TRACE("x[1] " << ::std::fixed << res);
	DCS_TEST_CHECK_CLOSE( res, expect, tol );
}

int main()
{
	DCS_TEST_BEGIN();

	DCS_TEST_DO( rand );

	DCS_TEST_END();
}

max_stars_repo_name: sguazt/dcsxx-commons

max_issues_repo_name: sguazt/dcsxx-commons

max_forks_repo_name: sguazt/dcsxx-commons


text:
#include <algorithm>
#include <boost/ut.hpp>
#include <ranges>

#include "../src/chip8.h"
#include "../src/common.h"

boost::ut::suite functionality = [] {
    using namespace boost::ut;

    Chip8 chip8;
    chip8.set_debug_level(spdlog::level::debug);

    "check load_rom"_test = [&chip8] {
        std::vector<u8> data{0, 1, 2, 3, 4};
        chip8.load_rom(data);
        const auto &memory = chip8.memory();

        auto counter = std::views::iota(0u, data.size());
        for (const auto i : counter) {
            expect(eq(memory[i + chip8.ROM_START], data[i]));
        }

        data.resize(10);
        std::ranges::fill(data, 0xAB);
        chip8.load_rom(data);

        counter = std::views::iota(0u, data.size());
        for (const auto i : counter) {
            expect(eq(memory[i + chip8.ROM_START], data[i]));
        }
    };

    "check fetch"_test = [&chip8] {
        std::vector<u8> data{0x00, 0x0F, 0xA0, 0x00, 0x10,
                             0xDE, 0xBA, 0x1A, 0xAA, 0xAA};
        chip8.load_rom(data);
        auto pc = chip8.ROM_START;

        expect(eq(chip8.pc(), pc));
        auto opcode = chip8.fetch();
        expect(eq(opcode, 0x0000F));
        pc += 2;

        expect(eq(chip8.pc(), pc));
        opcode = chip8.fetch();
        expect(eq(opcode, 0xA000));
        pc += 2;

        expect(eq(chip8.pc(), pc));
        opcode = chip8.fetch();
        expect(eq(opcode, 0x10DE));
        pc += 2;

        expect(eq(chip8.pc(), pc));
        opcode = chip8.fetch();
        expect(eq(opcode, 0xBA1A));
        pc += 2;

        expect(eq(chip8.pc(), pc));
        opcode = chip8.fetch();
        expect(eq(opcode, 0xAAAA));
        pc += 2;
    };
};

// TODO: Add some Emu tests

int main() {}


text:
#pragma once
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <map>
#include <boost/dynamic_bitset.hpp>

#include "../Basis/AbstractBasis1D.hpp"

template<typename UINT>
class TIXXZ
{
private:
	const edlib::AbstractBasis1D<UINT>& basis_;
	double J_;
	double delta_;

public:
	TIXXZ(const edlib::AbstractBasis1D<UINT>& basis, double J, double delta)
		: basis_(basis), J_(J), delta_(delta)
	{

	}

	std::map<int, double> getCol(UINT n) const
	{
		unsigned int N = basis_.getN();

		UINT a = basis_.getNthRep(n);
		const boost::dynamic_bitset<> bs(N, a);

		std::map<int, double> m;
		for(unsigned int i = 0; i < N; i++)
		{
			//Next-nearest
			{
				unsigned int j = (i+1)%N;
				int sgn = (1-2*bs[i])*(1-2*bs[j]);

				m[n] += J_*delta_*sgn;

				UINT s = a;
				s ^= basis_.mask({i,j});

				int bidx;
				double coeff;

				std::tie(bidx, coeff) = basis_.hamiltonianCoeff(s, n);

				if(bidx >= 0)
				{
					m[bidx] += J_*(1.0-sgn)*coeff;
				}
			}
		}
		return m;
	}
};

max_stars_repo_name: chaeyeunpark/ExactDiagonalization

max_issues_repo_name: chaeyeunpark/ExactDiagonalization

max_forks_repo_name: chaeyeunpark/ExactDiagonalization


text:
#include <taichi/lang.h>
#include <taichi/testing.h>
#include <numeric>
#include <taichi/visual/gui.h>
#include <taichi/system/threading.h>
#include <Eigen/Dense>
#include <taichi/math/eigen.h>
#include <Eigen/StdVector>

TLANG_NAMESPACE_BEGIN

static TC_FORCE_INLINE __m128 make_float4(float32 a,
                                          float32 b,
                                          float32 c,
                                          float32 d) {
  return _mm_set_ps(d, c, b, a);
}

TC_FORCE_INLINE __m128 make_float3(float a, float b, float c) {
  return make_float4(a, b, c, 0);
}

// clang-format off
TC_ALIGNED(64) const static __m128 grid_pos_offset_[27] = {
    make_float3(0, 0, 0),
    make_float3(0, 0, 1),
    make_float3(0, 0, 2),
    make_float3(0, 1, 0),
    make_float3(0, 1, 1),
    make_float3(0, 1, 2),
    make_float3(0, 2, 0),
    make_float3(0, 2, 1),
    make_float3(0, 2, 2),
    make_float3(1, 0, 0),
    make_float3(1, 0, 1),
    make_float3(1, 0, 2),
    make_float3(1, 1, 0),
    make_float3(1, 1, 1),
    make_float3(1, 1, 2),
    make_float3(1, 2, 0),
    make_float3(1, 2, 1),
    make_float3(1, 2, 2),
    make_float3(2, 0, 0),
    make_float3(2, 0, 1),
    make_float3(2, 0, 2),
    make_float3(2, 1, 0),
    make_float3(2, 1, 1),
    make_float3(2, 1, 2),
    make_float3(2, 2, 0),
    make_float3(2, 2, 1),
    make_float3(2, 2, 2),
};
// clang-format on

TC_TEST("cast_int") {
  __m128 f = _mm_set_ps(0.1f, 0.4f, 0.6f, 0.7f);
  union {
    __m128i i;
    int v[4];
  };
  i = _mm_cvtps_epi32(f);  // round to nearest, not floor....
  for (int j = 0; j < 4; j++) {
    TC_P(v[j]);
  }
}

struct MPMContext {
 public:
  struct Particle {
    real J;
    Vector3 pos, v;
    Matrix3 C;

    Particle() {
      pos = Vector3::rand() * 0.5_f + Vector3(0.25_f);
      v = Vector3::rand();
      C = Matrix3::rand();
      J = rand<float32>();
    }
  };

  struct ParticleEigen {
    // EIGEN_MAKE_ALIGNED_OPERATOR_NEW

    Eigen::Matrix<real, 3, 3> C;
    Eigen::Matrix<real, 3, 1> pos, v;
    real J;
    ParticleEigen() {
    }

    ParticleEigen(Particle &p) {
      pos = to_eigen(p.pos);
      v = to_eigen(p.v);
      C = to_eigen(p.C);
      J = p.J;
    }
  };

  int n_particles;  // num particles
  static constexpr real mass = 2.0_f;
  static constexpr real vol = 3.0_f;
  static constexpr int n = 7;
  static constexpr real dx = 1.0_f / n;
  static constexpr real inv_dx = 1.0_f / dx;
  static constexpr real dt = 1e-1_f;

  using Grid = Vector4[n][n][n];
  Grid grid;
  using EigenGrid = Eigen::Matrix<real, 4, 1>[n][n][n];
  EigenGrid eigen_grid;

  void clear_grid() {
    std::memset(grid, 0, sizeof(grid));
    std::memset(eigen_grid, 0, sizeof(eigen_grid));
  }

  std::vector<Particle> particles;
  std::vector<ParticleEigen> eigen_particles;

  MPMContext(int n_particles) : n_particles(n_particles) {
    particles.resize(n_particles);
    eigen_particles.resize(n_particles);
    for (int i = 0; i < n_particles; i++) {
      particles[i] = Particle();
      eigen_particles[i] = ParticleEigen(particles[i]);
    }
    clear_grid();
  }

  void p2g() {
    constexpr int T = 3;
    TC_WARN_IF(T != 3, "T is not 3");

    for (int p_i = 0; p_i < n_particles; p_i++) {
      using Vec = Vector3;
      auto &p = particles[p_i];
      Vector3i base_coord = (p.pos * inv_dx - Vector3(0.5_f)).cast<int>();
      auto fx = p.pos * inv_dx - base_coord.cast<real>();
      // Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx,
      // fx-1,fx-2]
      Vec w[3]{Vec(0.5) * sqr(Vec(1.5) - fx), Vec(0.75) - sqr(fx - Vec(1.0)),
               Vec(0.5) * sqr(fx - Vec(0.5))};
      real J = p.J;
      auto stress =  // Cauchy stress times dt and inv_dx
          -4 * inv_dx * inv_dx * dt * vol * Matrix3(J - 1);
      auto affine = stress + mass * p.C;

      // Scatter to grid
      for (int i = 0; i < T; i++) {
        for (int j = 0; j < T; j++) {
          for (int k = 0; k < T; k++) {
            auto dpos = (Vec(i, j, k) - fx) * dx;
            Vector4 mv(p.v * mass, mass);  // translational momentum
            grid[base_coord.x + i][base_coord.y + j][base_coord.z + k] +=
                w[i].x * w[j].y * w[k].z * (mv + Vector4(affine * dpos, 0));
          }
        }
      }
    }
  }

  void p2g_eigen() {
    constexpr int T = 3;
    TC_WARN_IF(T != 3, "T is not 3");

    for (int p_i = 0; p_i < n_particles; p_i++) {
      using Vec = Eigen::Matrix<real, 3, 1>;
      auto sqr = [](const Vec &vec) -> Vec {
        Vec ret;
        for (int i = 0; i < 3; i++) {
          ret(i) = vec(i) * vec(i);
        }
        return ret;
      };
      auto &p = eigen_particles[p_i];
      Eigen::Matrix<int, 3, 1> base_coord =
          (p.pos * inv_dx - Vec::Ones() * 0.5_f).cast<int>();
      Vec fx = p.pos * inv_dx - base_coord.cast<real>();

      Vec w[3]{0.5f * sqr(Vec::Ones() * 1.5f - fx),
               Vec::Ones() * 0.75f - sqr(fx - Vec::Ones()),
               0.5f * sqr(fx - Vec::Ones() * 0.5f)};
      real J = p.J;
      auto stress =  // Cauchy stress times dt and inv_dx
          -4 * inv_dx * inv_dx * dt * vol * (J - 1) *
          Eigen::Matrix<real, 3, 3>::Identity();
      Eigen::Matrix<real, 3, 3> affine = stress + mass * p.C;

      // Scatter to grid
      for (int i = 0; i < T; i++) {
        for (int j = 0; j < T; j++) {
          for (int k = 0; k < T; k++) {
            Vec dpos = (Vec(i, j, k) - fx) * dx;
            Eigen::Matrix<real, 4, 1> contrib;
            for (int d = 0; d < 3; d++) {
              contrib(d) = mass * p.v(d) + (affine * dpos)(d);
            }
            contrib(3) = mass;
            eigen_grid[base_coord(0) + i][base_coord(1) + j]
                      [base_coord(2) + k] +=
                w[i](0) * w[j](1) * w[k](2) * contrib;
          }
        }
      }
    }
  }

  using Vector = Vector3f;
  using Matrix = Matrix3f;
  using Vectori = Vector3i;

  struct MLSMPMFastKernel32 {
    static constexpr int dim = 3;
    TC_ALIGNED(64) __m128 kernels[3][3];

    TC_FORCE_INLINE MLSMPMFastKernel32(const __m128 &pos, real inv_delta_x) {
      __m128 p_fract = _mm_sub_ps(pos, _mm_set1_ps(0.5f));
      TC_ALIGNED(64) __m128 w_cache[dim];
      for (int k = 0; k < dim; k++) {
        __m128 t = _mm_sub_ps(_mm_set1_ps(p_fract[k]),
                              make_float4(-0.5f, 0.5f, 1.5f, 0.0f));
        __m128 tt = _mm_mul_ps(t, t);
        w_cache[k] = _mm_fmadd_ps(
            make_float4(0.5f, -1.0f, 0.5f, 0.0f), tt,
            _mm_fmadd_ps(make_float4(-1.5f, 0.0f, 1.5f, 0.0f), t,
                         make_float4(1.125f, 0.75f, 1.125f, 0.0f)));
      }
      for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
          kernels[i][j] = _mm_mul_ps(_mm_set1_ps(w_cache[0][i] * w_cache[1][j]),
                                     w_cache[2]);
        }
      }
    }
  };

  TC_FORCE_INLINE static int get_stencil_start(real x) {
    return int(x - 0.5f);
  }

#define broadcast(s, i) _mm_shuffle_ps((s), (s), 0x55 * (i))
  void p2g_intrinsics() {
    const auto inv_delta_x = 1.0_f / dx;
    const real delta_t = dt;
    __m128 S = _mm_set1_ps(-4.0_f * inv_delta_x * delta_t);
    for (int p_i = 0; p_i < n_particles; p_i++) {
      Particle &p = particles[p_i];

      // Note, pos is magnified grid pos
      __m128 pos_ = _mm_mul_ps(p.pos.v, _mm_set1_ps(inv_delta_x));

      Vectori grid_base_pos(get_stencil_start(pos_[0]),
                            get_stencil_start(pos_[1]),
                            get_stencil_start(pos_[2]));
      auto base_offset =
          grid_base_pos[0] * n * n + grid_base_pos[1] * n + grid_base_pos[2];
      Vector grid_base_pos_f = Vector(grid_base_pos);

      MLSMPMFastKernel32 kernel(_mm_sub_ps(pos_, grid_base_pos_f), inv_delta_x);
      const __m128(&kernels)[3][3] = kernel.kernels;
      const __m128 v = p.v.v;
      __m128 mass_ = _mm_set1_ps(mass);
      // Note, apic_b has delta_x issue
      const Matrix3f apic_b_inv_d_mass = (-mass * dx) * p.C;
      const __m128 mass_v = _mm_mul_ps(_mm_set1_ps(mass), v);

      auto stress = -vol * Matrix3(p.J - 1);

      __m128 delta_t_tmp_force_[3];
      auto &delta_t_tmp_force = reinterpret_cast<Matrix &>(delta_t_tmp_force_);
      for (int i = 0; i < 3; i++) {
        delta_t_tmp_force_[i] = _mm_mul_ps(_mm_set1_ps(delta_t), stress[i]);
      }

      __m128 rela_pos = _mm_sub_ps(pos_, grid_base_pos_f);
      __m128 affine[3];

      for (int i = 0; i < 3; i++)
        affine[i] = _mm_fmadd_ps(stress[i], S, apic_b_inv_d_mass[i]);
#define LOOP(node_id)                                                       \
  {                                                                         \
    __m128 dpos = _mm_sub_ps(rela_pos, grid_pos_offset_[node_id]);          \
    __m128 weight =                                                         \
        _mm_set1_ps(kernels[node_id / 9][node_id / 3 % 3][node_id % 3]);    \
    __m128 affine_prod = _mm_fmadd_ps(                                      \
        affine[2], broadcast(dpos, 2),                                      \
        _mm_fmadd_ps(affine[1], broadcast(dpos, 1),                         \
                     _mm_fmadd_ps(affine[0], broadcast(dpos, 0), mass_v))); \
    __m128 contrib = _mm_blend_ps(mass_, affine_prod, 0x7);                 \
    __m128 delta = _mm_mul_ps(weight, contrib);                             \
    auto &g = grid[0][0][node_id / 9 * n * n + node_id / 3 % 3 * n +        \
                         node_id % 3 + base_offset];                        \
    g = _mm_add_ps(g, delta);                                               \
  }
      TC_REPEAT27(LOOP);
#undef LOOP
    }
  }
#undef broadcast
};

TC_TEST("simd_mpm_baselines") {
  {
    MPMContext context(128);
    context.p2g();

    MPMContext::Grid grid_gt;
    std::memcpy(&grid_gt[0][0][0], &context.grid[0][0][0],
                sizeof(MPMContext::Grid));
    context.clear_grid();
    context.p2g_intrinsics();
    context.p2g_eigen();

    for (int i = 0; i < context.n; i++) {
      for (int j = 0; j < context.n; j++) {
        for (int k = 0; k < context.n; k++) {
          for (int d = 0; d < 4; d++) {
            // TC_INFO("{} {} {} {} , {}", i, j, k, d, grid_gt[i][j][k][d]);
            TC_CHECK_EQUAL(grid_gt[i][j][k][d], context.grid[i][j][k][d],
                           1e-3_f);
            TC_CHECK_EQUAL(grid_gt[i][j][k][d], context.eigen_grid[i][j][k](d),
                           1e-3_f);
          }
        }
      }
    }
  }

  MPMContext context(4 * 1024 * 1024);
  int N = 4;
  for (int i = 0; i < N; i++) {
    TC_TIME(context.p2g());
  }

  context.clear_grid();
  for (int i = 0; i < N; i++) {
    TC_TIME(context.p2g_intrinsics());
  }

  for (int i = 0; i < N; i++) {
    TC_TIME(context.p2g_eigen());
  }
};

// TODO: shuffled inputs?

TC_TEST("simd_mpm") {
  initialize_benchmark();
  int n_particles = 4 * 1024 * 1024;
  MPMContext context(n_particles);
  int n_grid = context.n;
  context.p2g();

  CoreState::set_trigger_gdb_when_crash(true);
  Program prog(Arch::x86_64);
  prog.config.max_vector_width = 4;
  prog.config.gcc_version = -2;
  prog.config.serial_schedule = true;
  prog.config.force_vectorized_global_load = true;
  prog.config.force_vectorized_global_store = true;
  // prog.config.extra_flags = "-fno-slp-vectorize";

  Global(g_J, f32);
  Global(tmp, i32);
  Global(tmp1, f32);
  auto ind = Index(0);
  constexpr int dim = 3;

  Vector grid(DataType::f32, dim + 1);
  Vector g_pos(DataType::f32, dim);
  Vector g_v(DataType::f32, dim);
  Vector g_C(DataType::f32, dim, dim);

  layout([&]() {
    root.dense(ind, n_particles).place(tmp);
    root.dense(ind, n_particles).place(tmp1);
    root.dense(ind, n_particles).place(g_J);
    for (int i = 0; i < dim; i++) {
      root.dense(ind, n_particles).place(g_pos(i));
      root.dense(ind, n_particles).place(g_v(i));
      for (int j = 0; j < dim; j++) {
        root.dense(ind, n_particles).place(g_C(i, j));
      }
    }
    root.dense(ind, bit::least_pot_bound(n_grid * n_grid * n_grid))
        .place(grid(0), grid(1), grid(2), grid(3));
  });

  auto &p2g = kernel([&]() {
    Declare(p_i);
    Vectorize(4);
    For(p_i, 0, n_particles, [&]() {
      auto mass = context.mass;
      auto vol = context.vol;
      auto dx = context.dx;
      auto inv_dx = context.inv_dx;
      auto dt = context.dt;

      auto v = Eval(g_v[p_i]);
      auto pos = Eval(g_pos[p_i]);
      auto J = Eval(g_J[p_i]);

      Vector v4(4);
      for (int i = 0; i < dim; i++) {
        v4(i) = v(i);
      }
      v4(3) = real(1);

      Vector base_coord = (inv_dx * pos - 0.5_f).cast_elements<int>();
      auto base_offset = Eval(base_coord(0) * (n_grid * n_grid) +
                              base_coord(1) * (n_grid) + base_coord(2));
      Vector fx = inv_dx * pos - base_coord.cast_elements<real>();

      Vector w[3];
      w[0] = 0.5_f * sqr(1.5_f - fx);
      w[1] = 0.75_f - sqr(fx - 1.0_f);
      w[2] = 0.5_f * sqr(fx - 0.5_f);

      Vector fx4(4);
      for (int i = 0; i < dim; i++) {
        fx4(i) = fx(i);
      }
      fx4(3) = real(0);

      Matrix stress(dim, dim);
      for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
          if (i == j) {
            stress(i, j) = J - real(1);
          } else {
            stress(i, j) = real(0);
          }
        }
      }

      auto scaled_stress = Eval((-4 * inv_dx * inv_dx * dt * vol) * stress);

      Matrix affine_ = dx * (scaled_stress + mass * g_C[p_i]);
      Matrix affine__(4, 3);
      for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
          affine__(i, j) = affine_(i, j);
        }
        affine__(dim, i) = real(0);
      }
      Matrix affine(4, 3);
      int slp = 4;
      SLP(slp);
      for (int j = 0; j < dim; j++) {
        for (int i = 0; i < dim + 1; i++) {
          affine(i, j) = Eval(affine__(i, j));
        }
      }

      constexpr int T = 3;
      TC_WARN_IF(T != 3, "T is not 3");

      auto mv = Eval(mass * v4);

      auto contrib0 = Eval(mv - Eval(affine * fx));
      for (int i = 0; i < T; i++) {
        SLP(1);
        auto weight0 = Eval(w[i](0));
        SLP(slp);
        auto contrib1 = Eval(contrib0);
        for (int j = 0; j < T; j++) {
          SLP(1);
          auto weight1 = Eval(weight0 * w[j](1));
          SLP(slp);
          auto contrib2 = Eval(contrib1);
          for (int k = 0; k < T; k++) {
            SLP(1);
            auto weight2 = Eval(weight1 * w[k](2));
            SLP(slp);
            auto contrib2 = Eval(contrib1 + real(k) * affine.col(2));
            grid[base_offset + (i * n_grid * n_grid + j * n_grid + k)] +=
                weight2 * contrib2;
          }
          SLP(slp);
          contrib1.set(Eval(contrib1 + affine.col(1)));
        }
        SLP(slp);
        contrib0.set(Eval(contrib0 + affine.col(0)));
      }
    });
  });

  auto initialize_data = [&] {
    for (int p = 0; p < n_particles; p++) {
      g_J.val<float32>(p) = context.particles[p].J;
      for (int i = 0; i < dim; i++) {
        g_pos(i).val<float32>(p) = context.particles[p].pos[i];
        g_v(i).val<float32>(p) = context.particles[p].v[i];
        for (int j = 0; j < dim; j++) {
          g_C(i, j).val<float32>(p) = context.particles[p].C[j][i];
        }
      }
    }
  };
  TC_TIME(initialize_data());

  TC_P(taichi::PID::get_pid());
  TC_TIME(p2g());

  /*
  for (int i = 0; i < n_particles; i++) {
    TC_P(tmp.val<int32>(i));
  }
  for (int i = 0; i < n_particles; i++) {
    TC_P(tmp1.val<float32>(i));
  }
  return;
  */

  auto tolerance = 1e-4_f * std::sqrt((real)n_particles);
  for (int i = 0; i < context.n; i++) {
    for (int j = 0; j < context.n; j++) {
      for (int k = 0; k < context.n; k++) {
        for (int d = 0; d < 4; d++) {
          if (std::abs(
                  grid(d).val<float32>(i * n_grid * n_grid + j * n_grid + k) -
                  context.grid[i][j][k][d]) > tolerance) {
            TC_WARN("{},{},{} {}", i, j, k, d);
          }
          TC_CHECK_EQUAL(
              grid(d).val<float32>(i * n_grid * n_grid + j * n_grid + k),
              context.grid[i][j][k][d], tolerance);
        }
      }
    }
  }
  for (int i = 0; i < 10; i++)
    TC_TIME(p2g());
};

TLANG_NAMESPACE_END

max_stars_repo_name: AnimatedRNG/taichi

max_issues_repo_name: AnimatedRNG/taichi

max_forks_repo_name: AnimatedRNG/taichi