text:
#include <QTest>
#include <QObject>

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

#include "uritests.h"

#ifdef SPECTRE_QT_TEST
// This is all you need to run all the tests
int RunQtTests()
{
    bool fInvalid = false;

    URITests test1;
    if (QTest::qExec(&test1) != 0)
        fInvalid = true;

    return fInvalid;
}

BOOST_AUTO_TEST_CASE(universeInOrder) {
    BOOST_CHECK(RunQtTests() == false);
}
#endif

max_stars_repo_name: ptownsimon/spectre

max_issues_repo_name: ptownsimon/spectre

max_forks_repo_name: ptownsimon/spectre


text:
//
// experimental/coro/simple_test.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2021 Klemens D. Morgenstern
//                    (klemens dot morgenstern at gmx dot net)
//
// 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)
//

// Disable autolinking for unit tests.
#if !defined(BOOST_ALL_NO_LIB)
#define BOOST_ALL_NO_LIB 1
#endif // !defined(BOOST_ALL_NO_LIB)

// Test that header file is self-contained.
#include <boost/asio/experimental/coro.hpp>

#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream>
#include <vector>
#include "../../unit_test.hpp"

using namespace boost::asio::experimental;

namespace boost {
namespace asio {
namespace experimental {

template struct coro<void(), void, any_io_executor>;
template struct coro<int(), void, any_io_executor>;
template struct coro<void(), int, any_io_executor>;
template struct coro<int(int), void, any_io_executor>;
template struct coro<int(), int, any_io_executor>;
template struct coro<int(int), int, any_io_executor>;

template struct coro<void() noexcept, void, any_io_executor>;
template struct coro<int() noexcept, void, any_io_executor>;
template struct coro<void() noexcept, int, any_io_executor>;
template struct coro<int(int) noexcept, void, any_io_executor>;
template struct coro<int() noexcept, int, any_io_executor>;
template struct coro<int(int) noexcept, int, any_io_executor>;

} // namespace experimental
} // namespace asio
} // namespace boost

namespace coro {

template <typename Func>
struct on_scope_exit
{
	Func func;

  static_assert(noexcept(func()));

  on_scope_exit(const Func &f)
    : func(static_cast< Func && >(f))
	{
	}

	on_scope_exit(Func &&f)
    : func(f)
	{
	}

  on_scope_exit(const on_scope_exit &) = delete;

	~on_scope_exit()
  {
    func();
  }
};

boost::asio::experimental::coro<int> generator_impl(
    boost::asio::any_io_executor, int& last, bool& destroyed)
{
  on_scope_exit x = [&]() noexcept { destroyed = true; };
  (void)x;

  int i = 0;
  while (true)
    co_yield last = ++i;
}

boost::asio::awaitable<void> generator_test()
{
  int val = 0;
  bool destr = false;
  {
    auto gi = generator_impl(
        co_await boost::asio::this_coro::executor, val, destr);

    for (int i = 0; i < 10; i++)
    {
      BOOST_ASIO_CHECK(val == i);
      const auto next = co_await gi.async_resume(boost::asio::use_awaitable);
      BOOST_ASIO_CHECK(next);
      BOOST_ASIO_CHECK(val == *next);
      BOOST_ASIO_CHECK(val == i + 1);
    }

    BOOST_ASIO_CHECK(!destr);
  }
  BOOST_ASIO_CHECK(destr);
};

void run_generator_test()
{
  boost::asio::io_context ctx;
  boost::asio::co_spawn(ctx, generator_test, boost::asio::detached);
  ctx.run();
}

boost::asio::experimental::coro<void, int> task_test(boost::asio::io_context&)
{
  co_return 42;
}

boost::asio::experimental::coro<void, int> task_throw(boost::asio::io_context&)
{
  throw std::logic_error(__func__);
  co_return 42;
}

void run_task_test()
{
  boost::asio::io_context ctx;

  bool tt1 = false;
  bool tt2 = false;
  bool tt3 = false;
  bool tt4 = false;
  auto tt = task_test(ctx);
  tt.async_resume(
      [&](std::exception_ptr pt, int i)
      {
        tt1 = true;
        BOOST_ASIO_CHECK(!pt);
        BOOST_ASIO_CHECK(i == 42);
        tt.async_resume(
            [&](std::exception_ptr pt, int)
            {
              tt2 = true;
              BOOST_ASIO_CHECK(pt);
            });
      });

  auto tt_2 = task_throw(ctx);

  tt_2.async_resume(
      [&](std::exception_ptr pt, int)
      {
        tt3 = true;
        BOOST_ASIO_CHECK(pt);
        tt.async_resume(
            [&](std::exception_ptr pt, int)
            {
              tt4 = true;
              BOOST_ASIO_CHECK(pt);
            });
      });

  ctx.run();

  BOOST_ASIO_CHECK(tt1);
  BOOST_ASIO_CHECK(tt2);
  BOOST_ASIO_CHECK(tt3);
  BOOST_ASIO_CHECK(tt4);
}

boost::asio::experimental::coro<char> completion_generator_test_impl(
    boost::asio::any_io_executor, int limit)
{
  for (int i = 0; i < limit; i++)
    co_yield i;
}

boost::asio::awaitable<void> completion_generator_test()
{
  std::vector<int> res;
  auto g = completion_generator_test_impl(
      co_await boost::asio::this_coro::executor, 10);

  BOOST_ASIO_CHECK(g.is_open());
  while (auto val = co_await g.async_resume(boost::asio::use_awaitable))
    res.push_back(*val);

  BOOST_ASIO_CHECK(!g.is_open());
  BOOST_ASIO_CHECK((res == std::vector{0,1,2,3,4,5,6,7,8,9}));
};

void run_completion_generator_test()
{
  boost::asio::io_context ctx;
  boost::asio::co_spawn(ctx, completion_generator_test, boost::asio::detached);
  ctx.run();
}

boost::asio::experimental::coro<int(int)>
symmetrical_test_impl(boost::asio::any_io_executor)
{
  int i = 0;
  while (true)
    i = (co_yield i) + i;
}

boost::asio::awaitable<void> symmetrical_test()
{
  auto g = symmetrical_test_impl(co_await boost::asio::this_coro::executor);

  BOOST_ASIO_CHECK(g.is_open());

  BOOST_ASIO_CHECK(0  == (co_await g.async_resume(0,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(1  == (co_await g.async_resume(1,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(3  == (co_await g.async_resume(2,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(6  == (co_await g.async_resume(3,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(10  == (co_await g.async_resume(4,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(15 == (co_await g.async_resume(5,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(21 == (co_await g.async_resume(6,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(28 == (co_await g.async_resume(7,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(36 == (co_await g.async_resume(8,
          boost::asio::use_awaitable)).value_or(-1));

  BOOST_ASIO_CHECK(45 == (co_await g.async_resume(9,
          boost::asio::use_awaitable)).value_or(-1));
};

void run_symmetrical_test()
{
  boost::asio::io_context ctx;
  boost::asio::co_spawn(ctx, symmetrical_test, boost::asio::detached);
  ctx.run();
}

} // namespace coro

BOOST_ASIO_TEST_SUITE
(
  "coro/simple_test",
  BOOST_ASIO_TEST_CASE(::coro::run_generator_test)
  BOOST_ASIO_TEST_CASE(::coro::run_task_test)
  BOOST_ASIO_TEST_CASE(::coro::run_symmetrical_test)
  BOOST_ASIO_TEST_CASE(::coro::run_completion_generator_test)
)

ext: cpp


text:
/**
 * Copyright 2013 JDSU
 * Author: Andy Lai (Andy.Lai@jdsu.com)
 */
#include <netinet/in.h>
#include <boost/regex.hpp>
#include "xtreme/common/pubsub_filter/ipv6address_asterisk_range.h"

namespace xtreme {
namespace filter {

IPv6AddressAsteriskRange::IPv6AddressAsteriskRange(const std::string& value)
throw(InvalidFieldValueException) : IPv6AddressAsterisk(value, kIPV6TYPE_BASIC) {
  Ipv6AddressStringToUINT(value, lst_compare_info_, lst_compare_range_info_);
}
bool IPv6AddressAsteriskRange::operator ==(const uint8_t* b) const {
  std::list<CompareInfo>::const_iterator it;
  for (it = lst_compare_info_.begin(); it != lst_compare_info_.end(); ++it) {
    if (memcmp((*it).p_value_, b + (*it).offset_, (*it).len_) != 0)
      return false;
  }
  std::list<RangeCompareInfo>::const_iterator it_range;
  for (it_range = lst_compare_range_info_.begin(); it_range != lst_compare_range_info_.end(); ++it_range) {
    if ((*it_range).type_ == 0) {
      if (*(b+(*it_range).offset_) < (*it_range).lower_)
        return false;
      if (*(b+(*it_range).offset_) > (*it_range).upper_)
        return false;
    } else {
      if (memcmp((b+(*it_range).offset_), (*it_range).lower_v6, 2) < 0)
        return false;
      if (memcmp((b+(*it_range).offset_), (*it_range).upper_v6, 2) > 0)
         return false;
    }
  }
  return true;
}
}
}

ext: cc


text: #include <boost/numeric/ublas/operation/c_array.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
// OGL TLM on GPU
//
// A program to demo and bench mark the implementation of the TLM Theory on a GPU
// using OpenGL as the renderer and for GPGPU operations
#define NOMINMAX
#include "stdafx.h"
#include <oglwfw/WindowMgr.hpp>
#include "Camera/PerspectiveWorldCamera.hpp"
#include "Camera/PolarOrbitView.hpp"
#include "Maths/mtxlib.h"

#include "TLM Modules/TLMCommon.h"
#include "TLM Modules/ITLMRenderer.h"
#include "TLM Modules/TLMFullShader.h"
#include "TLM Modules/TLMCPUGPUHybrid.h"
#include "TLM Modules/TLMCPUOnly.h"
#include "TLM Modules/TLMMPCPUOnly.h"
#include "TLM Modules/TLMMPCPUGPUHybrid.h"
#include "TLM Modules/TLMCPUOnlyMTTLM.h"

#include "Mesh/IMesh.hpp"
#include "Mesh/PlaneMesh.hpp"

#include <fstream>
#include <boost/format.hpp>	// for output stream data formatting
#include <boost/lexical_cast.hpp>
#include <limits>
#include <string>

#include "libFrameEncoder.hpp"

struct timeDetails
{
	int framenumber;
	LONGLONG updateTime;
	LONGLONG driveTime;
	LONGLONG renderTime;
	LONGLONG totalTime;
};

// Declare the test function
void Test(const size_t MAX_TEST_ITOR, const size_t DELAY, float frequency, int scale, int meshsize, TLM::ITLMRenderer &currentmode, const std::string &filename, OpenGLWFW::WindowManager const &WinMgr);

// Main program function
int _tmain(int argc, _TCHAR* argv[])
{
	OpenGLWFW::WindowManager WinMgr;
	try
	{
		WinMgr.Init();
		if(!WinMgr.FindCompatibleOGLMode())
			return -1;
		if(!WinMgr.FindCompatibleDisplayMode(800,600))
			return -2;

//		WinMgr.SetFullScreen(OpenGLWFW::winprops::fullscreen);
		WinMgr.CreateWin();
		WinMgr.Show();
	}
	catch (std::bad_exception &)
	{
		return -3;
	}

	OpenGLWFW::opengldetails opengldetails;
	WinMgr.GetOpenGLDetails(opengldetails);

	{
		LARGE_INTEGER freq;
		QueryPerformanceFrequency(&freq);
		std::ofstream displaydata("details.txt");
		displaydata << "Information about your graphics card" << std::endl;
		displaydata << "----------------------------------------------------" << std::endl;
		displaydata << "Vendor\t\t\t\t\t:\t" << opengldetails.vendor << std::endl;
		displaydata << "Version\t\t\t\t\t:\t" << opengldetails.version << std::endl;
		displaydata << "Renderer\t\t\t\t\t:\t" << opengldetails.renderer << std::endl;
		displaydata << "\nPerformance counter frequency (counts per second): \t" << freq.QuadPart << std::endl;
	}

	// Standard OpenGL setup stuff
	glClearColor(0.0f, 0.0f, 0.2f, 1.0f);		// This Will Clear The Background Color To kinda blue
	glClearDepth(1.0);							// Enables Clearing Of The Depth Buffer
	glDepthFunc(GL_LEQUAL);						// The Type Of Depth Test To Do
	glEnable(GL_DEPTH_TEST);					// Turn Depth Testing On
	glShadeModel(GL_SMOOTH);					// Enables Smooth Color Shading
	glDisable(GL_BLEND);
	glDisable(GL_CULL_FACE);
	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);

	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);					// Full Brightness.  50% Alpha

	// Constants for all tests
	const float FREQUENCY = 1.0f;
	const int SCALE = 100;
	const size_t MAX_TEST_ITOR = 1000;
	const int NUM_TESTS = 7; // only 7 of the sizes work
	const int MESHSIZES[] = { 40, 50, 100, 128, 256, 512, 1024, 2048, 4096};
	const size_t ITERATIONDELAY = 10;	// Wait 10 iterations before collecting results

	Mesh::PlaneMesh mesh(0);

	// CPU only tests
	{
		TLM::TLMCPUOnly module(mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + ".txt");
			WinMgr.SetWindowTitle("Testing : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY, FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// CPUGPU Hybrid tests @ 32bit per channel
	{
		TLM::TLMCPUGPUHybrid module(GL_RGBA32F_ARB,mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 32bpc.txt");
			WinMgr.SetWindowTitle("Testing @ 32bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}
	// CPUGPU Hybrid tests @ 16bit per channel
	{
		TLM::TLMCPUGPUHybrid module(GL_RGBA16F_ARB,mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 16bpc.txt");
			WinMgr.SetWindowTitle("Testing @ 16bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// CPU Only MT tests
	{
		TLM::TLMMPCPUOnly module(mesh);

		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + ".txt");
			WinMgr.SetWindowTitle("Testing : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// CPU only with MT TLM tests
	{
		TLM::TLMCPUOnlyMTTLM module(mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + ".txt");
			WinMgr.SetWindowTitle("Testing : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY, FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// CPU/GPU MT tests @ 32bpc
	{
		TLM::TLMMPCPUGPUHybrid module(GL_RGBA32F_ARB,mesh);

		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 32bpc.txt");
			WinMgr.SetWindowTitle("Testing @ 32bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// CPU/GPU MT tests @ 16bpc
	{
		TLM::TLMMPCPUGPUHybrid module(GL_RGBA16F_ARB,mesh);

		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 16bpc.txt");
			WinMgr.SetWindowTitle("Testing @ 16bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// GPU only tests @ 32bit per channel
	// We need at least GL2.0, PBO and FP textures to let this method work
	if(GLEE_ARB_pixel_buffer_object && GLEE_ARB_texture_float && GLEE_VERSION_2_0)
	{
		TLM::TLMFullShader module(GL_RGBA32F_ARB,mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 32bpc");
			WinMgr.SetWindowTitle("Testing @ 32bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	// GPU only tests @ 16bit per channel
	// We need at least GL2.0, PBO and FP textures to let this method work
	if(GLEE_ARB_pixel_buffer_object && GLEE_ARB_texture_float && GLEE_VERSION_2_0)
	{
		TLM::TLMFullShader module(GL_RGBA16F_ARB,mesh);
		for(int i = 0; i < NUM_TESTS; i++)
		{
			mesh.createResources(MESHSIZES[i]);
			mesh.generateMesh();
			module.CreateResources(MESHSIZES[i]);
			std::string filename(module.GetFriendlyName() + " " + boost::lexical_cast<std::string>(MESHSIZES[i]) + " 16bpc.txt");
			WinMgr.SetWindowTitle("Testing @ 16bpc : " + module.GetFriendlyName() + " @ " + boost::lexical_cast<std::string>(MESHSIZES[i]));
			Test(MAX_TEST_ITOR,ITERATIONDELAY,FREQUENCY,SCALE,MESHSIZES[i],module,filename,WinMgr);
			module.DestoryResources();
		}
	}

	return 0;
}

void Test(const size_t MAX_TEST_ITOR, const size_t DELAY, float frequency, int scale, int meshsize, TLM::ITLMRenderer &currentmode, const std::string &filename, OpenGLWFW::WindowManager const &WinMgr)
{
	size_t iter = 0;
	LARGE_INTEGER timestart;
	LARGE_INTEGER timeend;

	timeDetails working;
	std::vector<timeDetails> details(MAX_TEST_ITOR);

	Resurrection::CameraSystem::PerspectiveWorldCamera camera(60.0f,800.0f/600.0f,1.0f,100.0f);
	vector3 pos(-4.0f, -1.0f, -4.0f);
	vector3 target(0.0f, 0.0f, 0.0f);
	float angle = 0.0f;
	Resurrection::CameraSystem::PolarOrbitView view(target,pos,DegToRad(angle - 270));
	camera.setView(&view);

	std::string vfilename = filename + ".ogm";
	FrameEncoder::TheoraEncoder *encoder = new FrameEncoder::TheoraEncoder(vfilename,800,600);

	LARGE_INTEGER freq;
	QueryPerformanceFrequency(&freq);
	LARGE_INTEGER fpsstart;
	LARGE_INTEGER fpsend;
	QueryPerformanceCounter(&fpsstart);

	while (iter < MAX_TEST_ITOR + DELAY)
	{
		working.framenumber = iter;

		glDisable(GL_CULL_FACE);
		glDisable(GL_DEPTH_TEST);
		QueryPerformanceCounter(&timestart);
		currentmode.DriveTLMData(TLM::generateDrivingValue(iter,frequency,scale));
		QueryPerformanceCounter(&timeend);
		working.driveTime = timeend.QuadPart - timestart.QuadPart;
		QueryPerformanceCounter(&timestart);
		currentmode.GenerateTLMData();
		QueryPerformanceCounter(&timeend);
		working.updateTime = timeend.QuadPart - timestart.QuadPart;

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		view.setAngle(DegToRad(angle - 270));
		camera.updateViewMatrix();
		camera.setMatricies();
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_CULL_FACE);
		QueryPerformanceCounter(&timestart);
		currentmode.RenderTLM(vector3(0.0f,0.0f,0.0f), vector3(0.0f,0.0f,0.0f));
		QueryPerformanceCounter(&timeend);
		working.renderTime = timeend.QuadPart - timestart.QuadPart;

		// Store details
		if(iter >= DELAY)
			details[iter - DELAY] = working;

		angle += 0.3f;
		if(angle > 360.0f)
			angle = 0.0f;

		//currentmode.VisualiseTextures();
		unsigned char * buffer = encoder->requestBuffer();
		glReadPixels(0,0,800,600,GL_RGB,GL_UNSIGNED_BYTE,buffer);
		encoder->processBuffer(buffer);
		encoder->Process();

		WinMgr.SwapBuffers();
		iter++;
	}
	QueryPerformanceCounter(&fpsend);

	encoder->endEncoding();
	delete encoder;

	LARGE_INTEGER runtime;
	runtime.QuadPart = fpsend.QuadPart - fpsstart.QuadPart;
	float tmp = runtime.QuadPart / freq.QuadPart;
	float fps = float(MAX_TEST_ITOR + DELAY) / tmp;

	// Work out details
	timeDetails average;
	average.driveTime = 0;
	average.renderTime = 0;
	average.updateTime = 0;

	// Collect all details to build average
	for(int i = 0; i < std::min(MAX_TEST_ITOR,details.size()); i++)
	{
		average.driveTime += details[i].driveTime;
		average.renderTime += details[i].renderTime;
		average.updateTime += details[i].updateTime;
	}
	average.driveTime /= std::min(MAX_TEST_ITOR,details.size());
	average.renderTime /= std::min(MAX_TEST_ITOR,details.size());
	average.updateTime /= std::min(MAX_TEST_ITOR,details.size());

	timeDetails min;
	min.driveTime = std::numeric_limits<LONGLONG>::max();
	min.renderTime = std::numeric_limits<LONGLONG>::max();
	min.updateTime = std::numeric_limits<LONGLONG>::max();

	// Collect all details to build min times
	for(int i = 0; i < std::min(MAX_TEST_ITOR,details.size()); i++)
	{
		min.driveTime = std::min(details[i].driveTime, min.driveTime);
		min.renderTime = std::min(details[i].renderTime, min.renderTime);
		min.updateTime = std::min(details[i].updateTime, min.updateTime);
	}

	timeDetails max;
	max.driveTime = 0;
	max.renderTime = 0;
	max.updateTime = 0;

	// Collect all details to build max times
	for(int i = 0; i < std::min(MAX_TEST_ITOR,details.size()); i++)
	{
		max.driveTime = std::max(details[i].driveTime, max.driveTime);
		max.renderTime = std::max(details[i].renderTime, max.renderTime);
		max.updateTime = std::max(details[i].updateTime, max.updateTime);
	}

	std::string ofilename = filename + ".txt";
	std::ofstream results(ofilename.c_str());

	results << boost::format("Name : %1%\nSize : %2%\n") % currentmode.GetFriendlyName() % meshsize;
	results << boost::format("\t\tMax\tMin\tAverage\n");
	results << boost::format("Drive Time\t%1%\t%2%\t%3%\n") % max.driveTime % min.driveTime % average.driveTime;
	results << boost::format("Render Time\t%1%\t%2%\t%3%\n") % max.renderTime % min.renderTime % average.renderTime;
	results << boost::format("Update Time\t%1%\t%2%\t%3%\n") % max.updateTime % min.updateTime % average.updateTime;
	results << boost::format("FPS : %1%\n") % fps;
	results << boost::format("Dumping full results in CSV format (drive,render,update)...\n");
	for(int i = 0; i < std::min(MAX_TEST_ITOR,details.size()); i++)
	{
		results << boost::format("%1%,%2%,%3%\n") % details[i].driveTime % details[i].renderTime % details[i].updateTime;
	}
}

max_stars_repo_path: OGL TLM on GPU/OGL TLM on GPU.cpp

max_issues_repo_path: OGL TLM on GPU/OGL TLM on GPU.cpp

max_forks_repo_path: OGL TLM on GPU/OGL TLM on GPU.cpp


text:
#ifndef OBJECT_HPP
#define OBJECT_HPP

#include <memory>
#include <iostream>

#include <boost/geometry.hpp>

#include "utils.hpp"

class Actor;
class DrawableObject;
class World;

class Object {
    public:

// http://stackoverflow.com/questions/9907160/how-to-convert-enum-names-to-string-in-c
#define OBJECT_TYPE_FOREACH(F) \
        F(DO_NOTHING) \
        F(MOVE_UP) \
        F(MOVE_DOWN) \
        F(RANDOM) \
        F(FOLLOW_HUMAN) \
        F(FLEE_HUMAN) \
        F(HUMAN) \
        F(WALL) \
        F(FRUIT) \
        F(FRUIT_EATER) \
        F(TREE) \
        F(TELEPORT) \

        enum class Type {
            OBJECT_TYPE_FOREACH(UTILS_COMMAFY)
        };

        Object();
        virtual ~Object();
        Object(
            unsigned int x,
            unsigned int y,
            Type type,
            std::unique_ptr<Actor> actor,
            unsigned int fov = 0,
            std::unique_ptr<DrawableObject> drawableObject = nullptr,
            unsigned int id = 0
        );
        Object(
            unsigned int x,
            unsigned int y,
            Type type
        );
        void draw(const World& world, int cameraX = 0, int cameraY = 0) const;
        Actor& getActor() const;
        unsigned int getFov() const;
        unsigned int getId() const;
        int getScore() const;
        unsigned int getX() const;
        unsigned int getY() const;
        auto getType() const -> Type;
        void setDrawableObject(std::unique_ptr<DrawableObject>&& drawableObject);
        void setId(unsigned int id);
        void setScore(int score);
        void setX(unsigned int x);
        void setY(unsigned int y);

        // Types.
        struct PointerCmp {
            // Required for the heterogeneous searches to be found by compiler.
            // Value does not seem to matter, only presence, but std::true_type is a good choice semantically.
            typedef std::true_type is_transparent;
            typedef std::unique_ptr<Object> T;
            bool operator()(const T& l, unsigned int r) const;
            bool operator()(unsigned int l, const T& r) const;
            bool operator()(const T& l, const Object *r) const;
            bool operator()(const Object *l, const T& r) const;
            bool operator()(const T& l, const T& r) const;
        };
    protected:
        std::unique_ptr<Actor> actor;
        std::unique_ptr<DrawableObject> drawableObject;
        Type type;
        int score;
        unsigned int
            /// How much can this object see.
            /// 0 means nothing, not even itself.
            /// 1 means just itself.
            /// 2 means itself + the 8 adjacent squares (infinite norm).
            /// n means sees a rectangle of width 2 * (n - 1) + 1
            fov,
            id,
            x,
            y
        ;
};

std::ostream& operator<<(std::ostream& os, const Object& o);
std::ostream& operator<<(std::ostream& os, const Object::Type& t);

namespace bg = boost::geometry;
namespace bgi = bg::index;

namespace boost { namespace geometry {
    // Adapt to Object to Boost Point.
    namespace traits {
        template<> struct tag<Object>
        { typedef point_tag type; };

        template<> struct coordinate_type<Object>
        { typedef int type; };

        template<> struct coordinate_system<Object>
        { typedef cs::cartesian type; };

        template<> struct dimension<Object> : boost::mpl::int_<2> {};

        template<>
        struct access<Object, 0> {
            static int get(Object const& p) {
                return p.getX();
            }
            static void set(Object& p, int const& value) {
                p.setX(value);
            }
        };

        template<>
        struct access<Object, 1> {
            static int get(Object const& p) {
                return p.getY();
            }
            static void set(Object& p, int const& value) {
                p.setY(value);
            }
        };
    }

    // Adapt Object* to Object.
    namespace index {
        template <typename Box>
        struct indexable<Box*> {
            typedef Box* V;
            typedef Box const& result_type;
            result_type operator()(V const& v) const { return *v; }
        };
    }
}}

// Simplified object for making queries.
typedef bg::model::point<int, 2, bg::cs::cartesian> QueryPoint;
typedef bg::model::box<QueryPoint> QueryBox;

#endif

max_issues_repo_name: cirosantilli/general-game-ai

max_forks_repo_name: cirosantilli/general-game-ai


text:
#include <nano/node/bootstrap/bootstrap_attempt.hpp>
#include <nano/node/bootstrap/bootstrap_frontier.hpp>
#include <nano/node/node.hpp>
#include <nano/node/transport/tcp.hpp>

#include <boost/format.hpp>

constexpr double nano::bootstrap_limits::bootstrap_connection_warmup_time_sec;
constexpr double nano::bootstrap_limits::bootstrap_minimum_elapsed_seconds_blockrate;
constexpr double nano::bootstrap_limits::bootstrap_minimum_frontier_blocks_per_sec;
constexpr unsigned nano::bootstrap_limits::bulk_push_cost_limit;

constexpr size_t nano::frontier_req_client::size_frontier;

void nano::frontier_req_client::run (nano::account const & start_account_a, uint32_t const frontiers_age_a, uint32_t const count_a)
{
	nano::frontier_req request;
	request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits<nano::uint256_t>::max ()) ? start_account_a : start_account_a.number () + 1;
	request.age = frontiers_age_a;
	request.count = count_a;
	current = start_account_a;
	frontiers_age = frontiers_age_a;
	count_limit = count_a;
	next (); // Load accounts from disk
	auto this_l (shared_from_this ());
	connection->channel->send (
	request, [this_l] (boost::system::error_code const & ec, size_t size_a) {
		if (!ec)
		{
			this_l->receive_frontier ();
		}
		else
		{
			if (this_l->connection->node->config.logging.network_logging ())
			{
				this_l->connection->node->logger.try_log (boost::str (boost::format ("Error while sending bootstrap request %1%") % ec.message ()));
			}
		}
	},
	nano::buffer_drop_policy::no_limiter_drop);
}

nano::frontier_req_client::frontier_req_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt> const & attempt_a) :
	connection (connection_a),
	attempt (attempt_a),
	count (0),
	bulk_push_cost (0)
{
}

void nano::frontier_req_client::receive_frontier ()
{
	auto this_l (shared_from_this ());
	connection->socket->async_read (connection->receive_buffer, nano::frontier_req_client::size_frontier, [this_l] (boost::system::error_code const & ec, size_t size_a) {
		// An issue with asio is that sometimes, instead of reporting a bad file descriptor during disconnect,
		// we simply get a size of 0.
		if (size_a == nano::frontier_req_client::size_frontier)
		{
			this_l->received_frontier (ec, size_a);
		}
		else
		{
			if (this_l->connection->node->config.logging.network_message_logging ())
			{
				this_l->connection->node->logger.try_log (boost::str (boost::format ("Invalid size: expected %1%, got %2%") % nano::frontier_req_client::size_frontier % size_a));
			}
		}
	});
}

bool nano::frontier_req_client::bulk_push_available ()
{
	return bulk_push_cost < nano::bootstrap_limits::bulk_push_cost_limit && frontiers_age == std::numeric_limits<decltype (frontiers_age)>::max ();
}

void nano::frontier_req_client::unsynced (nano::block_hash const & head, nano::block_hash const & end)
{
	if (bulk_push_available ())
	{
		attempt->add_bulk_push_target (head, end);
		if (end.is_zero ())
		{
			bulk_push_cost += 2;
		}
		else
		{
			bulk_push_cost += 1;
		}
	}
}

void nano::frontier_req_client::received_frontier (boost::system::error_code const & ec, size_t size_a)
{
	if (!ec)
	{
		debug_assert (size_a == nano::frontier_req_client::size_frontier);
		nano::account account;
		nano::bufferstream account_stream (connection->receive_buffer->data (), sizeof (account));
		auto error1 (nano::try_read (account_stream, account));
		(void)error1;
		debug_assert (!error1);
		nano::block_hash latest;
		nano::bufferstream latest_stream (connection->receive_buffer->data () + sizeof (account), sizeof (latest));
		auto error2 (nano::try_read (latest_stream, latest));
		(void)error2;
		debug_assert (!error2);
		if (count == 0)
		{
			start_time = std::chrono::steady_clock::now ();
		}
		++count;
		std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>> (std::chrono::steady_clock::now () - start_time);

		double elapsed_sec = std::max (time_span.count (), nano::bootstrap_limits::bootstrap_minimum_elapsed_seconds_blockrate);
		double blocks_per_sec = static_cast<double> (count) / elapsed_sec;
		double age_factor = (frontiers_age == std::numeric_limits<decltype (frontiers_age)>::max ()) ? 1.0 : 1.5; // Allow slower frontiers receive for requests with age
		if (elapsed_sec > nano::bootstrap_limits::bootstrap_connection_warmup_time_sec && blocks_per_sec * age_factor < nano::bootstrap_limits::bootstrap_minimum_frontier_blocks_per_sec)
		{
			connection->node->logger.try_log (boost::str (boost::format ("Aborting frontier req because it was too slow: %1% frontiers per second, last %2%") % blocks_per_sec % account.to_account ()));
			promise.set_value (true);
			return;
		}
		if (attempt->should_log ())
		{
			connection->node->logger.always_log (boost::str (boost::format ("Received %1% frontiers from %2%") % std::to_string (count) % connection->channel->to_string ()));
		}
		if (!account.is_zero () && count <= count_limit)
		{
			last_account = account;
			while (!current.is_zero () && current < account)
			{
				// We know about an account they don't.
				unsynced (frontier, 0);
				next ();
			}
			if (!current.is_zero ())
			{
				if (account == current)
				{
					if (latest == frontier)
					{
						// In sync
					}
					else
					{
						if (connection->node->ledger.block_or_pruned_exists (latest))
						{
							// We know about a block they don't.
							unsynced (frontier, latest);
						}
						else
						{
							attempt->add_frontier (nano::pull_info (account, latest, frontier, attempt->incremental_id, 0, connection->node->network_params.bootstrap.frontier_retry_limit));
							// Either we're behind or there's a fork we differ on
							// Either way, bulk pushing will probably not be effective
							bulk_push_cost += 5;
						}
					}
					next ();
				}
				else
				{
					debug_assert (account < current);
					attempt->add_frontier (nano::pull_info (account, latest, nano::block_hash (0), attempt->incremental_id, 0, connection->node->network_params.bootstrap.frontier_retry_limit));
				}
			}
			else
			{
				attempt->add_frontier (nano::pull_info (account, latest, nano::block_hash (0), attempt->incremental_id, 0, connection->node->network_params.bootstrap.frontier_retry_limit));
			}
			receive_frontier ();
		}
		else
		{
			if (count <= count_limit)
			{
				while (!current.is_zero () && bulk_push_available ())
				{
					// We know about an account they don't.
					unsynced (frontier, 0);
					next ();
				}
				// Prevent new frontier_req requests
				attempt->set_start_account (std::numeric_limits<nano::uint256_t>::max ());
				if (connection->node->config.logging.bulk_pull_logging ())
				{
					connection->node->logger.try_log ("Bulk push cost: ", bulk_push_cost);
				}
			}
			else
			{
				// Set last processed account as new start target
				attempt->set_start_account (last_account);
			}
			try
			{
				promise.set_value (false);
			}
			catch (std::future_error &)
			{
			}
			connection->connections->pool_connection (connection);
		}
	}
	else
	{
		if (connection->node->config.logging.network_logging ())
		{
			connection->node->logger.try_log (boost::str (boost::format ("Error while receiving frontier %1%") % ec.message ()));
		}
	}
}

void nano::frontier_req_client::next ()
{
	// Filling accounts deque to prevent often read transactions
	if (accounts.empty ())
	{
		size_t max_size (128);
		auto transaction (connection->node->store.tx_begin_read ());
		for (auto i (connection->node->store.account.begin (transaction, current.number () + 1)), n (connection->node->store.account.end ()); i != n && accounts.size () != max_size; ++i)
		{
			nano::account_info const & info (i->second);
			nano::account const & account (i->first);
			accounts.emplace_back (account, info.head);
		}
		/* If loop breaks before max_size, then accounts_end () is reached
		Add empty record */
		if (accounts.size () != max_size)
		{
			accounts.emplace_back (nano::account (0), nano::block_hash (0));
		}
	}
	// Retrieving accounts from deque
	auto const & account_pair (accounts.front ());
	current = account_pair.first;
	frontier = account_pair.second;
	accounts.pop_front ();
}

nano::frontier_req_server::frontier_req_server (std::shared_ptr<nano::bootstrap_server> const & connection_a, std::unique_ptr<nano::frontier_req> request_a) :
	connection (connection_a),
	current (request_a->start.number () - 1),
	frontier (0),
	request (std::move (request_a)),
	count (0)
{
	next ();
}

void nano::frontier_req_server::send_next ()
{
	if (!current.is_zero () && count < request->count)
	{
		std::vector<uint8_t> send_buffer;
		{
			nano::vectorstream stream (send_buffer);
			write (stream, current.bytes);
			write (stream, frontier.bytes);
			debug_assert (!current.is_zero ());
			debug_assert (!frontier.is_zero ());
		}
		auto this_l (shared_from_this ());
		if (connection->node->config.logging.bulk_pull_logging ())
		{
			connection->node->logger.try_log (boost::str (boost::format ("Sending frontier for %1% %2%") % current.to_account () % frontier.to_string ()));
		}
		next ();
		connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l] (boost::system::error_code const & ec, size_t size_a) {
			this_l->sent_action (ec, size_a);
		});
	}
	else
	{
		send_finished ();
	}
}

void nano::frontier_req_server::send_finished ()
{
	std::vector<uint8_t> send_buffer;
	{
		nano::vectorstream stream (send_buffer);
		nano::uint256_union zero (0);
		write (stream, zero.bytes);
		write (stream, zero.bytes);
	}
	auto this_l (shared_from_this ());
	if (connection->node->config.logging.network_logging ())
	{
		connection->node->logger.try_log ("Frontier sending finished");
	}
	connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l] (boost::system::error_code const & ec, size_t size_a) {
		this_l->no_block_sent (ec, size_a);
	});
}

void nano::frontier_req_server::no_block_sent (boost::system::error_code const & ec, size_t size_a)
{
	if (!ec)
	{
		connection->finish_request ();
	}
	else
	{
		if (connection->node->config.logging.network_logging ())
		{
			connection->node->logger.try_log (boost::str (boost::format ("Error sending frontier finish: %1%") % ec.message ()));
		}
	}
}

void nano::frontier_req_server::sent_action (boost::system::error_code const & ec, size_t size_a)
{
	if (!ec)
	{
		count++;
		send_next ();
	}
	else
	{
		if (connection->node->config.logging.network_logging ())
		{
			connection->node->logger.try_log (boost::str (boost::format ("Error sending frontier pair: %1%") % ec.message ()));
		}
	}
}

void nano::frontier_req_server::next ()
{
	// Filling accounts deque to prevent often read transactions
	if (accounts.empty ())
	{
		auto now (nano::seconds_since_epoch ());
		bool disable_age_filter (request->age == std::numeric_limits<decltype (request->age)>::max ());
		size_t max_size (128);
		auto transaction (connection->node->store.tx_begin_read ());
		if (!send_confirmed ())
		{
			for (auto i (connection->node->store.account.begin (transaction, current.number () + 1)), n (connection->node->store.account.end ()); i != n && accounts.size () != max_size; ++i)
			{
				nano::account_info const & info (i->second);
				if (disable_age_filter || (now - info.modified) <= request->age)
				{
					nano::account const & account (i->first);
					accounts.emplace_back (account, info.head);
				}
			}
		}
		else
		{
			for (auto i (connection->node->store.confirmation_height.begin (transaction, current.number () + 1)), n (connection->node->store.confirmation_height.end ()); i != n && accounts.size () != max_size; ++i)
			{
				nano::confirmation_height_info const & info (i->second);
				nano::block_hash const & confirmed_frontier (info.frontier);
				if (!confirmed_frontier.is_zero ())
				{
					nano::account const & account (i->first);
					accounts.emplace_back (account, confirmed_frontier);
				}
			}
		}
		/* If loop breaks before max_size, then accounts_end () is reached
		Add empty record to finish frontier_req_server */
		if (accounts.size () != max_size)
		{
			accounts.emplace_back (nano::account (0), nano::block_hash (0));
		}
	}
	// Retrieving accounts from deque
	auto const & account_pair (accounts.front ());
	current = account_pair.first;
	frontier = account_pair.second;
	accounts.pop_front ();
}

bool nano::frontier_req_server::send_confirmed ()
{
	return request->header.frontier_req_is_only_confirmed_present ();
}

max_stars_repo_name: starkmatt/nano-node

max_issues_repo_name: starkmatt/nano-node

max_forks_repo_name: starkmatt/nano-node


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "codecs/default/DefaultVectorsFormat.h"

#include <fcntl.h>
#include <unistd.h>

#include <boost/filesystem.hpp>

#include "utils/Exception.h"
#include "utils/Log.h"

namespace milvus {
namespace codec {

void
DefaultVectorsFormat::read(const store::DirectoryPtr& directory_ptr, segment::VectorsPtr& vectors_read) {
    const std::lock_guard<std::mutex> lock(mutex_);

    std::string dir_path = directory_ptr->GetDirPath();
    if (!boost::filesystem::is_directory(dir_path)) {
        std::string err_msg = "Directory: " + dir_path + "does not exist";
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_INVALID_ARGUMENT, err_msg);
    }

    boost::filesystem::path target_path(dir_path);
    typedef boost::filesystem::directory_iterator d_it;
    d_it it_end;
    d_it it(target_path);
    //    for (auto& it : boost::filesystem::directory_iterator(dir_path)) {
    for (; it != it_end; ++it) {
        const auto& path = it->path();
        if (path.extension().string() == raw_vector_extension_) {
            int rv_fd = open(path.c_str(), O_RDONLY, 00664);
            if (rv_fd == -1) {
                std::string err_msg = "Failed to open file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
            }
            size_t num_bytes = boost::filesystem::file_size(path);
            std::vector<uint8_t> vector_list;
            vector_list.resize(num_bytes);
            if (::read(rv_fd, vector_list.data(), num_bytes) == -1) {
                std::string err_msg = "Failed to read from file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }

            vectors_read->AddData(vector_list);
            vectors_read->SetName(path.stem().string());

            if (::close(rv_fd) == -1) {
                std::string err_msg = "Failed to close file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }
        }
        if (path.extension().string() == user_id_extension_) {
            int uid_fd = open(path.c_str(), O_RDONLY, 00664);
            if (uid_fd == -1) {
                std::string err_msg = "Failed to open file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
            }
            auto file_size = boost::filesystem::file_size(path);
            auto count = file_size / sizeof(segment::doc_id_t);
            std::vector<segment::doc_id_t> uids;
            uids.resize(count);
            if (::read(uid_fd, uids.data(), file_size) == -1) {
                std::string err_msg = "Failed to read from file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }

            vectors_read->AddUids(uids);

            if (::close(uid_fd) == -1) {
                std::string err_msg = "Failed to close file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }
        }
    }
}

void
DefaultVectorsFormat::write(const store::DirectoryPtr& directory_ptr, const segment::VectorsPtr& vectors) {
    const std::lock_guard<std::mutex> lock(mutex_);

    std::string dir_path = directory_ptr->GetDirPath();

    const std::string rv_file_path = dir_path + "/" + vectors->GetName() + raw_vector_extension_;
    const std::string uid_file_path = dir_path + "/" + vectors->GetName() + user_id_extension_;

    /*
    FILE* rv_file = fopen(rv_file_path.c_str(), "wb");
    if (rv_file == nullptr) {
        std::string err_msg = "Failed to open file: " + rv_file_path;
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
    }

    fwrite((void*)(it.second->GetData()), sizeof(char), it.second->GetNumBytes(), rv_file);
    fclose(rv_file);

    FILE* uid_file = fopen(uid_file_path.c_str(), "wb");
    if (uid_file == nullptr) {
        std::string err_msg = "Failed to open file: " + uid_file_path;
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
    }

    fwrite((void*)(it.second->GetUids()), sizeof it.second->GetUids()[0], it.second->GetCount(), uid_file);
    fclose(rv_file);
    */

    int rv_fd = open(rv_file_path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 00664);
    if (rv_fd == -1) {
        std::string err_msg = "Failed to open file: " + rv_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
    }
    int uid_fd = open(uid_file_path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 00664);
    if (uid_fd == -1) {
        std::string err_msg = "Failed to open file: " + uid_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
    }

    auto start = std::chrono::high_resolution_clock::now();

    if (::write(rv_fd, vectors->GetData().data(), vectors->GetData().size()) == -1) {
        std::string err_msg = "Failed to write to file" + rv_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_WRITE_ERROR, err_msg);
    }
    if (::close(rv_fd) == -1) {
        std::string err_msg = "Failed to close file: " + rv_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_WRITE_ERROR, err_msg);
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> diff = end - start;
    ENGINE_LOG_DEBUG << "Writing raw vectors took " << diff.count() << " s";

    start = std::chrono::high_resolution_clock::now();
    if (::write(uid_fd, vectors->GetUids().data(), sizeof(segment::doc_id_t) * vectors->GetCount()) == -1) {
        std::string err_msg = "Failed to write to file" + uid_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_WRITE_ERROR, err_msg);
    }
    if (::close(uid_fd) == -1) {
        std::string err_msg = "Failed to close file: " + uid_file_path + ", error: " + std::strerror(errno);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_WRITE_ERROR, err_msg);
    }
    end = std::chrono::high_resolution_clock::now();
    diff = end - start;
    ENGINE_LOG_DEBUG << "Writing uids took " << diff.count() << " s";
}

void
DefaultVectorsFormat::read_uids(const store::DirectoryPtr& directory_ptr, std::vector<segment::doc_id_t>& uids) {
    const std::lock_guard<std::mutex> lock(mutex_);

    std::string dir_path = directory_ptr->GetDirPath();
    if (!boost::filesystem::is_directory(dir_path)) {
        std::string err_msg = "Directory: " + dir_path + "does not exist";
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_INVALID_ARGUMENT, err_msg);
    }

    boost::filesystem::path target_path(dir_path);
    typedef boost::filesystem::directory_iterator d_it;
    d_it it_end;
    d_it it(target_path);
    //    for (auto& it : boost::filesystem::directory_iterator(dir_path)) {
    for (; it != it_end; ++it) {
        const auto& path = it->path();
        if (path.extension().string() == user_id_extension_) {
            int uid_fd = open(path.c_str(), O_RDONLY, 00664);
            if (uid_fd == -1) {
                std::string err_msg = "Failed to open file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
            }
            auto file_size = boost::filesystem::file_size(path);
            auto count = file_size / sizeof(segment::doc_id_t);
            uids.resize(count);
            if (::read(uid_fd, uids.data(), file_size) == -1) {
                std::string err_msg = "Failed to read from file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }
            if (::close(uid_fd) == -1) {
                std::string err_msg = "Failed to close file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }
        }
    }
}

void
DefaultVectorsFormat::read_vectors(const store::DirectoryPtr& directory_ptr, off_t offset, size_t num_bytes,
                                   std::vector<uint8_t>& raw_vectors) {
    const std::lock_guard<std::mutex> lock(mutex_);

    std::string dir_path = directory_ptr->GetDirPath();
    if (!boost::filesystem::is_directory(dir_path)) {
        std::string err_msg = "Directory: " + dir_path + "does not exist";
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(SERVER_INVALID_ARGUMENT, err_msg);
    }

    boost::filesystem::path target_path(dir_path);
    typedef boost::filesystem::directory_iterator d_it;
    d_it it_end;
    d_it it(target_path);
    //    for (auto& it : boost::filesystem::directory_iterator(dir_path)) {
    for (; it != it_end; ++it) {
        const auto& path = it->path();
        if (path.extension().string() == raw_vector_extension_) {
            int rv_fd = open(path.c_str(), O_RDONLY, 00664);
            if (rv_fd == -1) {
                std::string err_msg = "Failed to open file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_CANNOT_CREATE_FILE, err_msg);
            }
            int off = lseek(rv_fd, offset, SEEK_SET);
            if (off == -1) {
                std::string err_msg = "Failed to seek file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }

            raw_vectors.resize(num_bytes);

            if (::read(rv_fd, raw_vectors.data(), num_bytes) == -1) {
                std::string err_msg = "Failed to read from file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }

            if (::close(rv_fd) == -1) {
                std::string err_msg = "Failed to close file: " + path.string() + ", error: " + std::strerror(errno);
                ENGINE_LOG_ERROR << err_msg;
                throw Exception(SERVER_WRITE_ERROR, err_msg);
            }
        }
    }
}

}  // namespace codec
}  // namespace milvus


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.

// This file was modified by Oracle on 2014-2017.
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.

// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP

#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>

#include <boost/geometry/formulas/spherical.hpp>

#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>

#include <boost/geometry/strategies/side.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>

namespace boost { namespace geometry
{

namespace strategy { namespace side
{

/*!
\brief Check at which side of a Great Circle segment a point lies
         left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
\tparam CalculationType \tparam_calculation
 */
template <typename CalculationType = void>
class side_by_cross_track
{

public :
    template <typename P1, typename P2, typename P>
    static inline int apply(P1 const& p1, P2 const& p2, P const& p)
    {
        typedef typename promote_floating_point
            <
                typename select_calculation_type_alt
                    <
                        CalculationType,
                        P1, P2, P
                    >::type
            >::type calc_t;

        calc_t d1 = 0.001; // m_strategy.apply(sp1, p);

        calc_t lon1 = geometry::get_as_radian<0>(p1);
        calc_t lat1 = geometry::get_as_radian<1>(p1);
        calc_t lon2 = geometry::get_as_radian<0>(p2);
        calc_t lat2 = geometry::get_as_radian<1>(p2);
        calc_t lon = geometry::get_as_radian<0>(p);
        calc_t lat = geometry::get_as_radian<1>(p);

        calc_t crs_AD = geometry::formula::spherical_azimuth<calc_t, false>
                             (lon1, lat1, lon, lat).azimuth;

        calc_t crs_AB = geometry::formula::spherical_azimuth<calc_t, false>
                             (lon1, lat1, lon2, lat2).azimuth;

        calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB));

        return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;
    }
};

}} // namespace strategy::side

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
#ifndef JHMI_LIVER_LOAD_VESSEL_PROTOBUF_NRC_2016_02_10
#define JHMI_LIVER_LOAD_VESSEL_PROTOBUF_NRC_2016_02_10

#include "messages/vessel_tree.pb.h"
#include "utility/load_protobuf.hpp"
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <boost/filesystem.hpp>

namespace jhmi {
  auto load_vessel_protobuf(jhmi_message::VesselTree const& vt) {
    vidx_to<jhmi_detail::flat_vessel> vns;
    RANGES_FOR(auto&& vtv, vt.vessels()) {

      physical_vessel v{dbl3{vtv.sx(), vtv.sy(), vtv.sz()}*meters,
                             dbl3{vtv.ex(), vtv.ey(), vtv.ez()}*meters,
                             vtv.radius()*meters,
                             cell_id{vtv.cell()},
                             vtv.flow() * boost::units::pow<3>(meters) / seconds,
                             vtv.exit_pressure() * pascals,
                             vessel_id{vtv.id()}, vtv.is_const()};
      vessel_id parent{vtv.parent()};
      vessel_id left{vtv.left()};
      vessel_id right{vtv.right()};
      vns.insert(std::make_pair(v.id(), jhmi_detail::flat_vessel{v, parent, left, right}));
    }
    return vns;
  }
}//jhmi

#endif


text:
#ifdef COMPILATION// -*-indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4;-*-
$CXX $0 -o $0x -lcudart -lcufft `pkg-config --libs fftw3` -lboost_unit_test_framework&&$0x&&rm $0x;exit
#endif
// © Alfredo A. Correa 2020

#ifndef MULTI_ADAPTORS_CUFFTW_HPP
#define MULTI_ADAPTORS_CUFFTW_HPP

#include "../adaptors/../utility.hpp"
#include "../adaptors/../array.hpp"
#include "../adaptors/../config/NODISCARD.hpp"

#include "../adaptors/cuda.hpp"

#include<numeric>

#include<experimental/tuple>
#include<experimental/array>

#include<vector>

#include "../complex.hpp"

//#include<execution>
#include<future>
#include<cufft.h>

namespace boost{
namespace multi{
namespace memory{
namespace cuda{

#if 0
template<class T1, class T1const, class T2, class T2const>
auto copy(
	array_iterator<T1, 1, managed::ptr<T1const>> first,
	array_iterator<T1, 1, managed::ptr<T1const>> last,
	array_iterator<T2, 1, managed::ptr<T2const>> d_first
){
	assert(first.stride() == last.stride());
	auto s = cudaMemcpy2D(raw_pointer_cast(d_first.data()), d_first.stride()*sizeof(T2), raw_pointer_cast(first.data()), first.stride()*sizeof(T2), sizeof(T2), last - first, cudaMemcpyDefault);
	switch(s){
		case cudaSuccess: break;
		case cudaErrorInvalidValue: assert(0);
		case cudaErrorInvalidPitchValue: assert(0);
		case cudaErrorInvalidDevicePointer: assert(0);
		case cudaErrorInvalidMemcpyDirection: assert(0);
		default: assert(0); // unknown error
	}
	return d_first + (last - first);
}
#endif

}}}}

namespace boost{
namespace multi{
namespace cufft{

class sign{
	int impl_;
public:
	sign() = default;
	constexpr sign(int i) : impl_{i}{}
	constexpr operator int() const{return impl_;}
};

constexpr sign forward{CUFFT_FORWARD};
constexpr sign none{0};
constexpr sign backward{CUFFT_INVERSE};

static_assert(forward != none and none != backward and backward != forward, "!");

class plan{
	using complex_type = cufftDoubleComplex;
	complex_type const* idata_     = nullptr;
	complex_type*       odata_     = nullptr;
	int                 direction_ = 0;
	cufftHandle h_;
	plan() = default;
	plan(plan const&) = delete;
	plan(plan&& other) :
		idata_{std::exchange(other.idata_, nullptr)},
		odata_{std::exchange(other.odata_, nullptr)},
		direction_{std::exchange(other.direction_, 0)},
		h_{std::exchange(other.h_, {})}
	{} // needed in <=C++14 for return
	void ExecZ2Z(complex_type const* idata, complex_type* odata, int direction) const{
		++tl_execute_count;
	//	assert(idata_ and odata_);
	//	assert(direction_!=0);
		cufftResult r = ::cufftExecZ2Z(h_, const_cast<complex_type*>(idata), odata, direction);
		switch(r){
			case CUFFT_SUCCESS        : break;// "cuFFT successfully executed the FFT plan."
			case CUFFT_INVALID_PLAN   : throw std::runtime_error{"The plan parameter is not a valid handle."};
		//	case CUFFT_ALLOC_FAILED   : throw std::runtime_error{"CUFFT failed to allocate GPU memory."};
		//	case CUFFT_INVALID_TYPE   : throw std::runtime_error{"The user requests an unsupported type."};
			case CUFFT_INVALID_VALUE  : throw std::runtime_error{"At least one of the parameters idata, odata, and direction is not valid."};
			case CUFFT_INTERNAL_ERROR : throw std::runtime_error{"Used for all internal driver errors."};
			case CUFFT_EXEC_FAILED    : throw std::runtime_error{"CUFFT failed to execute an FFT on the GPU."};
			case CUFFT_SETUP_FAILED   : throw std::runtime_error{"The cuFFT library failed to initialize."};
		//	case CUFFT_INVALID_SIZE   : throw std::runtime_error{"The user specifies an unsupported FFT size."};
		//	case CUFFT_UNALIGNED_DATA : throw std::runtime_error{"Unaligned data."};
		//	case CUFFT_INCOMPLETE_PARAMETER_LIST: throw std::runtime_error{"Incomplete parameter list."};
		//	case CUFFT_INVALID_DEVICE : throw std::runtime_error{"Invalid device."};
		//	case CUFFT_PARSE_ERROR    : throw std::runtime_error{"Parse error."};
		//	case CUFFT_NO_WORKSPACE   : throw std::runtime_error{"No workspace."};
		//	case CUFFT_NOT_IMPLEMENTED: throw std::runtime_error{"Not implemented."};
		//	case CUFFT_LICENSE_ERROR  : throw std::runtime_error{"License error."};
		//	case CUFFT_NOT_SUPPORTED  : throw std::runtime_error{"CUFFT_NOT_SUPPORTED"};
			default                   : throw std::runtime_error{"cufftExecZ2Z unknown error"};
		}
	//	if(cudaDeviceSynchronize() != cudaSuccess) throw std::runtime_error{"Cuda error: Failed to synchronize"};
	}
	void swap(plan& other){
		using std::swap;
		swap(idata_, other.idata_);
		swap(odata_, other.odata_);
		swap(direction_, other.direction_);
		swap(h_, other.h_);
	}
public:
	thread_local static int tl_execute_count;
	plan& operator=(plan other){swap(other); return *this;}
	void operator()() const{ExecZ2Z(idata_, odata_, direction_);}
	template<class I, class O>
	O&& execute_dft(I&& i, O&& o, int direction) const{
		ExecZ2Z(
			const_cast<complex_type*>(reinterpret_cast<complex_type const*>(base(i))),
			const_cast<complex_type*>(reinterpret_cast<complex_type const*>(base(o))),
			direction
		);
		return std::forward<O>(o);
	}
	template<class I, class O>
	void execute_dft(I&& i, O&& o) const{execute_dft(std::forward<I>(i), std::forward<O>(o), direction_);}
	~plan(){if(h_) cufftDestroy(h_);}
	using size_type = int;
	using ssize_type = int;

	template<class I, class O, //std::enable_if_t<(I::dimensionality < 4), int> =0,
		dimensionality_type D = I::dimensionality,
		typename = decltype(raw_pointer_cast(base(std::declval<I const&>())), reinterpret_cast<complex_type*      >(raw_pointer_cast(base(std::declval<O&>()))))
	>
	plan(I const& i, O&& o, sign s) :
		idata_{                          reinterpret_cast<complex_type const*>(raw_pointer_cast(base(i))) },
		odata_{const_cast<complex_type*>(reinterpret_cast<complex_type*      >(raw_pointer_cast(base(o))))},
		direction_{s}
	{
		assert( I::dimensionality < 4 );
		assert( CUFFT_FORWARD == s or CUFFT_INVERSE == s or s == 0 );
		assert( sizes(i) == sizes(o) );

		using std::experimental::apply;// using std::experimental::make_array;
		auto ion      = apply([](auto... t){return std::array< size_type, D>{static_cast< size_type>(t)...};}, sizes  (i));
		auto istrides = apply([](auto... t){return std::array<ssize_type, D>{static_cast<ssize_type>(t)...};}, strides(i));
		auto ostrides = apply([](auto... t){return std::array<ssize_type, D>{static_cast<ssize_type>(t)...};}, strides(o));

		std::array<std::tuple<int, int, int>, I::dimensionality> ssn;
		for(std::size_t i = 0; i != ssn.size(); ++i) ssn[i] = std::make_tuple(istrides[i], ostrides[i], ion[i]);
		std::sort(ssn.begin(), ssn.end(), std::greater<>{});

		for(std::size_t i = 0; i != ssn.size(); ++i){
			istrides[i] = std::get<0>(ssn[i]);
			ostrides[i] = std::get<1>(ssn[i]);
			ion[i]      = std::get<2>(ssn[i]);
		}// = std::tuple<int, int, int>(istrides[i], ostrides[i], ion[i]);

		int istride = istrides.back();
		auto inembed = istrides; inembed.fill(0);
		int ostride = ostrides.back();
		auto onembed = ostrides; onembed.fill(0);
		for(std::size_t i = 1; i != onembed.size(); ++i){
			assert(ostrides[i-1] >= ostrides[i]); // otherwise ordering is incompatible
			assert(ostrides[i-1]%ostrides[i]==0);
			onembed[i]=ostrides[i-1]/ostrides[i]; //	assert( onembed[i] <= ion[i] );
			assert(istrides[i-1]%istrides[i]==0);
			inembed[i]=istrides[i-1]/istrides[i]; //	assert( inembed[i] <= ion[i] );
		}

		direction_ = s;
		idata_ =                           reinterpret_cast<complex_type const*>(raw_pointer_cast(base(i))) ;
		odata_ = const_cast<complex_type*>(reinterpret_cast<complex_type*      >(raw_pointer_cast(base(o))));

		switch(::cufftPlanMany(
			/*cufftHandle *plan*/ &h_,
			/*int rank*/          ion.size(),
			/*int *n*/            ion.data(), //	/*NX*/      last - first,
			/*int *inembed*/      inembed.data(),
			/*int istride*/       istride,
			/*int idist*/         1, //stride(first),
			/*int *onembed*/      onembed.data(),
			/*int ostride*/       ostride,
			/*int odist*/         1, //stride(d_first),
			/*cufftType type*/    CUFFT_Z2Z,
			/*int batch*/         1 //BATCH
		)){
			case CUFFT_SUCCESS        : break;// "cuFFT successfully executed the FFT plan."
			case CUFFT_ALLOC_FAILED   : throw std::runtime_error{"CUFFT failed to allocate GPU memory."};
			case CUFFT_INVALID_VALUE  : throw std::runtime_error{"At least one of the parameters idata, odata, and direction is not valid."};
			case CUFFT_INTERNAL_ERROR : throw std::runtime_error{"Used for all internal driver errors."};
			case CUFFT_SETUP_FAILED   : throw std::runtime_error{"The cuFFT library failed to initialize."};
			case CUFFT_INVALID_SIZE   : throw std::runtime_error{"The user specifies an unsupported FFT size."};
			default                   : throw std::runtime_error{"cufftPlanMany unknown error"};
		}
	}
#ifndef __INTEL_COMPILER
	template<class It1, class It2, dimensionality_type D = decltype(*It1{})::dimensionality>
	static auto many(It1 first, It1 last, It2 d_first, int sign = 0, unsigned = 0)
	->std::decay_t<decltype(const_cast<complex_type*>(reinterpret_cast<complex_type*>(raw_pointer_cast(base(d_first)))), std::declval<plan>())>
#else
	template<class It1, class It2,
		dimensionality_type D = decltype(*It1{})::dimensionality,
		typename TT = decltype(const_cast<complex_type*>(reinterpret_cast<complex_type*>(It2{}.base().raw_pointer_cast())))
	>
	static auto many(It1 first, It1 last, It2 d_first, int sign = 0, unsigned = 0)
#endif
	{
		assert( CUFFT_FORWARD == sign or CUFFT_INVERSE == sign or sign == 0 );
		using namespace std::experimental; //using std::apply;
		assert(sizes(*first)==sizes(*d_first));
		auto ion      = apply([](auto... t){return std::array< size_type, D>{static_cast< size_type>(t)...};}, sizes  (*  first));

		assert(strides(*first) == strides(*last));
		auto istrides = apply([](auto... t){return std::array<ssize_type, D>{static_cast<ssize_type>(t)...};}, strides(*  first));
		auto ostrides = apply([](auto... t){return std::array<ssize_type, D>{static_cast<ssize_type>(t)...};}, strides(*d_first));

		std::array<std::tuple<int, int, int>, std::decay_t<decltype(*It1{})>::dimensionality> ssn;
		for(std::size_t i = 0; i != ssn.size(); ++i) ssn[i] = std::make_tuple(istrides[i], ostrides[i], ion[i]);
		std::sort(ssn.begin(), ssn.end(), std::greater<>{});

		for(std::size_t i = 0; i != ssn.size(); ++i){
			istrides[i] = std::get<0>(ssn[i]);
			ostrides[i] = std::get<1>(ssn[i]);
			ion[i]      = std::get<2>(ssn[i]);
		}

		int istride = istrides.back();
		auto inembed = istrides; inembed.fill(0);
		int ostride = ostrides.back();
		auto onembed = ostrides; onembed.fill(0);
		for(std::size_t i = 1; i != onembed.size(); ++i){
			assert(ostrides[i-1] >= ostrides[i]); // otherwise ordering is incompatible
			assert(ostrides[i-1]%ostrides[i]==0);
			onembed[i]=ostrides[i-1]/ostrides[i]; //	assert( onembed[i] <= ion[i] );
			assert(istrides[i-1]%istrides[i]==0);
			inembed[i]=istrides[i-1]/istrides[i]; //	assert( inembed[i] <= ion[i] );
		}

		plan ret;
		ret.direction_ = sign;
		ret.idata_ =                           reinterpret_cast<complex_type const*>(  first.base().raw_pointer_cast()) ;
		ret.odata_ = const_cast<complex_type*>(reinterpret_cast<complex_type*      >(d_first.base().raw_pointer_cast()));

		switch(::cufftPlanMany(
			/*cufftHandle *plan*/ &ret.h_,
			/*int rank*/          ion.size(),
			/*int *n*/            ion.data(), //	/*NX*/      last - first,
			/*int *inembed*/      inembed.data(),
			/*int istride*/       istride,
			/*int idist*/         stride(first),
			/*int *onembed*/      onembed.data(),
			/*int ostride*/       ostride,
			/*int odist*/         stride(d_first),
			/*cufftType type*/    CUFFT_Z2Z,
			/*int batch*/         last - first //BATCH
		)){
			case CUFFT_SUCCESS        : break;// "cuFFT successfully executed the FFT plan."
		//	case CUFFT_INVALID_PLAN   : throw std::runtime_error{"The plan parameter is not a valid handle."};
			case CUFFT_ALLOC_FAILED   : throw std::runtime_error{"CUFFT failed to allocate GPU memory."};
		//	case CUFFT_INVALID_TYPE   : throw std::runtime_error{"The user requests an unsupported type."};
			case CUFFT_INVALID_VALUE  : throw std::runtime_error{"At least one of the parameters idata, odata, and direction is not valid."};
			case CUFFT_INTERNAL_ERROR : throw std::runtime_error{"Used for all internal driver errors."};
		//	case CUFFT_EXEC_FAILED    : throw std::runtime_error{"CUFFT failed to execute an FFT on the GPU."};
			case CUFFT_SETUP_FAILED   : throw std::runtime_error{"The cuFFT library failed to initialize."};
			case CUFFT_INVALID_SIZE   : throw std::runtime_error{"The user specifies an unsupported FFT size."};
		//	case CUFFT_UNALIGNED_DATA : throw std::runtime_error{"Unaligned data."};
		//	case CUFFT_INCOMPLETE_PARAMETER_LIST: throw std::runtime_error{"Incomplete parameter list."};
		//	case CUFFT_INVALID_DEVICE : throw std::runtime_error{"Invalid device."};
		//	case CUFFT_PARSE_ERROR    : throw std::runtime_error{"Parse error."};
		//	case CUFFT_NO_WORKSPACE   : throw std::runtime_error{"No workspace."};
		//	case CUFFT_NOT_IMPLEMENTED: throw std::runtime_error{"Not implemented."};
		//	case CUFFT_LICENSE_ERROR  : throw std::runtime_error{"License error."};
		//	case CUFFT_NOT_SUPPORTED  : throw std::runtime_error{"CUFFT_NOT_SUPPORTED"};
			default                   : throw std::runtime_error{"cufftPlanMany unknown error"};
		}
		return ret;
	}
};

thread_local int plan::tl_execute_count = 0;

template<typename In, class Out>
auto dft(In const& i, Out&& o, int s)
->decltype(cufft::plan{i, o, s}(), std::forward<Out>(o)){
	return cufft::plan{i, o, s}(), std::forward<Out>(o);}

template<typename In, typename R = multi::array<typename In::element_type, In::dimensionality, decltype(get_allocator(std::declval<In>()))>>
NODISCARD("when first argument is const")
R dft(In const& i, int s){
	static_assert(std::is_trivially_default_constructible<typename In::element_type>{}, "!");
	R ret(extensions(i), get_allocator(i));
	cufft::dft(i, ret, s);
	return ret;
}

#ifndef __INTEL_COMPILER
template<typename It1, typename It2>
auto many_dft(It1 first, It1 last, It2 d_first, sign s)
->decltype(plan::many(first, last, d_first, s)(), d_first + (last - first)){
	return plan::many(first, last, d_first, s)(), d_first + (last - first);}
#else
template<typename It1, typename It2>
auto many_dft(It1 first, It1 last, It2 d_first, sign s)
->decltype(plan::many(first, last, d_first, s)(), d_first + (last - first)){
	return plan::many(first, last, d_first, s)(), d_first + (last - first);}
#endif

template<typename In, class Out,  std::size_t D = In::dimensionality, std::enable_if_t<(D==1), int> = 0>
Out&& dft(std::array<bool, D> which, In const& i, Out&& o, int s){
	if(which[0]) return cufft::dft(i, std::forward<Out>(o), s);
	else return std::forward<Out>(std::forward<Out>(o) = i);
}

template<typename In, class Out, std::size_t D = In::dimensionality, std::enable_if_t<(D>1), int> = 0>
auto dft(std::array<bool, D> which, In const& i, Out&& o, int s)
->decltype(many_dft(i.begin(), i.end(), o.begin(), s),std::forward<Out>(o))
{
	assert(extension(i) == extension(o));
	std::array<bool, D-1> tail = reinterpret_cast<std::array<bool, D-1> const&>(which[1]);
	auto ff = std::find(begin(which)+1, end(which), false);
	if(which[0] == true){
		if(ff==end(which)) cufft::dft(i, std::forward<Out>(o), s);
		else{
			auto n = ff - which.begin();
			std::rotate(begin(which), ff, end(which));
			dft(which, (i<<n), (o<<n), s);
		}
	}else if(which[0]==false){
		if(D==1 or std::none_of(begin(which)+1, end(which), [](auto e){return e;})){
			if(base(o) != base(i)) std::forward<Out>(o) = i;
			else if(o.layout() != i.layout()) std::forward<Out>(o) = +i;
		}
//		if(D==1 or std::all_of(begin(which)+1, end(which), [](auto e){return e==false;})){
//			if(base(o) != base(i)) std::forward<Out>(o) = i;//.assign(i);//std::forward<Out>(o) = i;
//			else if(o.layout() != i.layout()) std::forward<Out>(o) = +i;
//		}
		else if(ff==end(which)) many_dft(i.begin(), i.end(), o.begin(), s);
		else{
			if(which.size() > 1 and which[1] == false and i.is_flattable() and o.is_flattable()) cufft::dft(tail, i.flatted(), o.flatted(), s);
			else{
				auto d_min = 0; auto n_min = size(i);
				for(auto d = 0; d != D; ++d){if((size(i<<d) < n_min) and (tail[d]==false)){n_min = size(i<<d); d_min = d;}}
				if(d_min!=0){
					std::rotate(which.begin(), which.begin()+d_min, which.end());
					dft(which, i<<d_min, o<<d_min, s);
				}else{
					if(base(i) == base(o) and i.layout() != o.layout()){
						auto tmp = +i;
						for(auto idx : extension(i)) cufft::dft(tail, tmp[idx], o[idx], s);
					}else for(auto idx : extension(i)) cufft::dft(tail, i[idx], o[idx], s);
				}
			}
		}
	}
	return std::forward<Out>(o);
}

template<typename In,  std::size_t D = In::dimensionality>
NODISCARD("when passing a const argument")
auto dft(std::array<bool, D> which, In const& i, int sign)->std::decay_t<decltype(
dft(which, i, typename In::decay_type(extensions(i), get_allocator(i)), sign))>{return
dft(which, i, typename In::decay_type(extensions(i), get_allocator(i)), sign);}

template<typename In,  std::size_t D = In::dimensionality>
auto dft(std::array<bool, D> which, In&& i, int sign)
->decltype(dft(which, i, i, sign), std::forward<In>(i)){
	return dft(which, i, i, sign), std::forward<In>(i);}

//template<typename... A> auto            dft_forward(A&&... a)
//->decltype(cufft::dft(std::forward<A>(a)..., cufft::forward)){
//	return cufft::dft(std::forward<A>(a)..., cufft::forward);}

template<typename Array, typename A> NODISCARD("when passing a const argument")
auto dft_forward(Array arr, A const& a)
->decltype(cufft::dft(arr, a, cufft::forward)){
	return cufft::dft(arr, a, cufft::forward);}

template<typename Array, dimensionality_type D> NODISCARD("when passing a const argument")
auto dft_forward(Array arr, multi::cuda::array<std::complex<double>, D>&& a)
->decltype(cufft::dft(arr, a, cufft::forward), multi::cuda::array<std::complex<double>, D>{}){//assert(0);
	return cufft::dft(arr, a, cufft::forward), std::move(a);}

template<typename A> NODISCARD("when passing a const argument")
auto dft_forward(A const& a)
->decltype(cufft::dft(a, cufft::forward)){
	return cufft::dft(a, cufft::forward);}

template<typename... A> auto            dft_backward(A&&... a)
->decltype(cufft::dft(std::forward<A>(a)..., cufft::backward)){
	return cufft::dft(std::forward<A>(a)..., cufft::backward);}

template<typename Array, typename A> NODISCARD("when passing a const argument")
auto dft_backward(Array arr, A const& a)
->decltype(cufft::dft(arr, a, cufft::backward)){
	return cufft::dft(arr, a, cufft::backward);}

template<typename A> NODISCARD("when passing a const argument")
auto dft_backward(A const& a)
->decltype(cufft::dft(a, cufft::backward)){
	return cufft::dft(a, cufft::backward);}

}

}}

#if not __INCLUDE_LEVEL__ // TEST BELOW

#define BOOST_TEST_MODULE "C++ Unit Tests for Multi cuFFT adaptor"
#define BOOST_TEST_DYN_LINK
#include<boost/test/unit_test.hpp>

#include <boost/timer/timer.hpp>

#include "../adaptors/cuda.hpp"
#include "../adaptors/fftw.hpp"
#include "../adaptors/cufft.hpp"

//#include "../adaptors/fft.hpp"

#include<complex>
#include<thrust/complex.h>
#include "../complex.hpp"

#include<cuda_runtime.h> // cudaDeviceSynchronize

#include<iostream>

namespace multi = boost::multi;
using complex = std::complex<double>;
namespace utf = boost::unit_test;

template <class T>
__attribute__((always_inline)) inline void DoNotOptimize(const T &value) {
	asm volatile("" : "+m"(const_cast<T &>(value)));
}

struct watch : private std::chrono::high_resolution_clock{
	std::string label_; time_point  start_;
	watch(std::string label ="") : label_{label}, start_{}{
		cudaDeviceSynchronize();
		start_ = now();
	}
	~watch(){
		cudaDeviceSynchronize();
		auto const count = std::chrono::duration<double>(now() - start_).count();
		std::cerr<< label_<<": "<< count <<" sec"<<std::endl;
	}
};

constexpr complex I{0, 1};

#if 1

BOOST_AUTO_TEST_CASE(cufft_2D, *boost::unit_test::tolerance(0.0001)){

	multi::array<complex, 2> const in_cpu = {
		{ 1. + 2.*I, 9. - 1.*I, 2. + 4.*I},
		{ 3. + 3.*I, 7. - 4.*I, 1. + 9.*I},
		{ 4. + 1.*I, 5. + 3.*I, 2. + 4.*I},
		{ 3. - 1.*I, 8. + 7.*I, 2. + 1.*I},
		{ 31. - 1.*I, 18. + 7.*I, 2. + 10.*I}
	};
	multi::array<complex, 2> fw_cpu(extensions(in_cpu));
	multi::fftw::dft(in_cpu, fw_cpu, multi::fftw::forward);

	multi::cuda::array<complex, 2> const in_gpu = in_cpu;
	multi::cuda::array<complex, 2> fw_gpu(extensions(in_gpu));
	multi::cufft::dft(in_gpu, fw_gpu, multi::cufft::forward);

	BOOST_TEST( imag(static_cast<complex>(fw_gpu[3][2]) - fw_cpu[3][2]) == 0. );

	auto fw2_gpu = multi::cufft::dft(in_gpu, multi::cufft::forward);
	BOOST_TEST( imag(static_cast<complex>(fw2_gpu[3][1]) - fw_cpu[3][1]) == 0. );

	multi::cuda::managed::array<complex, 2> const in_mng = in_cpu;
	multi::cuda::managed::array<complex, 2> fw_mng(extensions(in_gpu));
	multi::cufft::dft(in_mng, fw_mng, multi::cufft::forward);

	BOOST_TEST( imag(fw_mng[3][2] - fw_cpu[3][2]) == 0. );

	auto fw2_mng = multi::fftw::dft(in_mng, multi::fftw::forward);
	BOOST_TEST( imag(fw2_mng[3][1] - fw_cpu[3][1]) == 0. );

}

BOOST_AUTO_TEST_CASE(cufft_3D_timing, *boost::unit_test::tolerance(0.0001)){

	auto x = std::make_tuple(300, 300, 300);
	{
		multi::array<complex, 3> const in_cpu(x, 10.);
		BOOST_ASSERT( in_cpu.num_elements()*sizeof(complex) < 2e9 );
		multi::array<complex, 3> fw_cpu(extensions(in_cpu), 99.);
		{
		//	boost::timer::auto_cpu_timer t;  // 1.041691s wall, 1.030000s user + 0.000000s system = 1.030000s CPU (98.9%)
			multi::fftw::dft(in_cpu, fw_cpu, multi::fftw::forward);
			BOOST_TEST( fw_cpu[8][9][10] != 99. );
		}
	}
	{
		multi::cuda::array<complex, 3> const in_gpu(x, 10.);
		multi::cuda::array<complex, 3> fw_gpu(extensions(in_gpu), 99.);
		{
		//	boost::timer::auto_cpu_timer t; //  0.208237s wall, 0.200000s user + 0.010000s system = 0.210000s CPU (100.8%)
			multi::cufft::dft(in_gpu, fw_gpu, multi::fftw::forward);

			BOOST_TEST( static_cast<complex>(fw_gpu[8][9][10]) != 99. );
		}
	}
	{
		multi::cuda::managed::array<complex, 3> const in_gpu(x, 10.);
		multi::cuda::managed::array<complex, 3> fw_gpu(extensions(in_gpu), 99.);
		{
		//	boost::timer::auto_cpu_timer t; //  0.208237s wall, 0.200000s user + 0.010000s system = 0.210000s CPU (100.8%)
			multi::cufft::dft(in_gpu, fw_gpu, multi::cufft::forward);
		//	BOOST_TEST( fw_gpu[8][9][10].operator complex() != 99. );
		}
		{
		//	boost::timer::auto_cpu_timer t; //  0.208237s wall, 0.200000s user + 0.010000s system = 0.210000s CPU (100.8%)
			multi::cufft::dft(in_gpu, fw_gpu, multi::cufft::forward);
		//	BOOST_TEST( fw_gpu[8][9][10].operator complex() != 99. );
		}
	}
}

BOOST_AUTO_TEST_CASE(cufft_combinations, *utf::tolerance(0.00001)){

	auto const in = []{
		multi::array<complex, 4> ret({32, 90, 98, 96});
		std::generate(ret.data_elements(), ret.data_elements() + ret.num_elements(),
			[](){return complex{std::rand()*1./RAND_MAX, std::rand()*1./RAND_MAX};}
		);
		return ret;
	}();
	std::clog<<"memory size "<< in.num_elements()*sizeof(complex)/1e6 <<" MB\n";

	multi::cuda::array<complex, 4> const in_gpu = in;
	multi::cuda::managed::array<complex, 4> const in_mng = in;

	using std::clog;
	for(auto c : std::vector<std::array<bool, 4>>{
		{false, true , true , true },
		{false, true , true , false},
		{true , false, false, false},
		{true , true , false, false},
		{false, false, true , false},
		{false, false, false, false},
	}){
		std::clog<<"case "; copy(begin(c), end(c), std::ostream_iterator<bool>{std::clog,", "}); std::clog<<std::endl;
		multi::array<complex, 4> out = in;
		multi::array<complex, 4> in_rw = in;
		[&, _ = watch{"cpu_opl "}]{
			multi::fftw::dft_forward(c, in, out);
		}();
		[&, _ = watch{"cpu_ipl "}]{
			multi::fftw::dft(c, in_rw, multi::fftw::forward);
			BOOST_TEST( abs( static_cast<multi::complex<double>>(in_rw[5][4][3][1]) - multi::complex<double>(out[5][4][3][1]) ) == 0. );
		}();
		{
			multi::array<complex, 4> in_rw2 = in;
			[&, _ = watch{"cpu_mov "}]{
				multi::array<complex, 4> const out_mov = multi::fftw::dft_forward(c, std::move(in_rw2));
			//	what(out_mov);
				BOOST_TEST( abs( static_cast<multi::complex<double>>(out_mov[5][4][3][1]) - multi::complex<double>(out[5][4][3][1]) ) == 0. );
				BOOST_REQUIRE( is_empty(in_rw2) );
				BOOST_REQUIRE( extensions(out_mov) == extensions(in) );
			}();
		}

		[&, _ = watch{"cpu_new "}]{
			auto const out_cpy = multi::fftw::dft_forward(c, in);
			BOOST_TEST( abs( static_cast<multi::complex<double>>(out_cpy[5][4][3][1]) - multi::complex<double>(out[5][4][3][1]) ) == 0. );
		}();
		multi::cuda::array<complex, 4> out_gpu(extensions(in_gpu));
		[&, _ = watch{"gpu_opl "}]{
			multi::cufft::dft(c, in_gpu   , out_gpu, multi::cufft::forward);
			BOOST_TEST( abs( static_cast<complex>(out_gpu[5][4][3][1]) - out[5][4][3][1] ) == 0. );
		}();
		{
			multi::cuda::array<complex, 4> in_rw_gpu = in_gpu;
			[&, _ = watch{"gpu_ipl "}]{
				multi::cufft::dft(c, in_rw_gpu, multi::cufft::forward);
				BOOST_TEST( abs( static_cast<complex>(in_rw_gpu[5][4][3][1]) - out[5][4][3][1] ) == 0. );
			}();
		}
		{
			multi::cuda::array<complex, 4> in_rw_gpu = in_gpu;
			[&, _ = watch{"gpu_mov "}]{
				multi::cuda::array<complex, 4> const out_mov = multi::cufft::dft_forward(c, std::move(in_rw_gpu));
			//	BOOST_REQUIRE( in_rw_gpu.empty() );
			//	BOOST_TEST( abs( static_cast<complex>(out_mov[5][4][3][1]) - out[5][4][3][1] ) == 0. );
			}();
		}
		{
			multi::cuda::array<complex, 4> in_rw_gpu = in_gpu;
			[&, _ = watch{"gpu_mov "}]{
				multi::cuda::array<complex, 4> out_mov = std::move(in_rw_gpu);
				multi::cufft::dft(c, out_mov, multi::cufft::forward);
			//	BOOST_REQUIRE( in_rw_gpu.empty() );
			//	BOOST_TEST( abs( static_cast<complex>(out_mov[5][4][3][1]) - out[5][4][3][1] ) == 0. );
			}();
		}
		cudaDeviceSynchronize();
		[&, _ = watch{"gpu_new "}]{
			multi::cuda::array<complex, 4> const out_cpy = multi::cufft::dft(c, in_gpu, multi::cufft::forward);
		}();
		multi::cuda::managed::array<complex, 4> out_mng(extensions(in_mng));
		[&, _ = watch{"mng_cld "}]{
			multi::cufft::dft(c, in_mng, out_mng, multi::cufft::forward);
			BOOST_TEST( abs( out_mng[5][4][3][1] - out[5][4][3][1] ) == 0. );
		}();
		[&, _ = watch{"mng_hot "}]{
			multi::cufft::dft(c, in_mng   , out_mng, multi::cufft::forward);
			BOOST_TEST( abs( out_mng[5][4][3][1] - out[5][4][3][1] ) == 0. );
		}();
		[&, _ = watch{"mng_new "}]{
			auto const out_mng = multi::cufft::dft(c, in_mng, multi::cufft::forward);
			BOOST_TEST( abs( out_mng[5][4][3][1] - out[5][4][3][1] ) == 0. );
		}();
	}
	std::clog<<std::endl;

}

BOOST_AUTO_TEST_CASE(cufft_many_3D, *utf::tolerance(0.00001) ){

	auto const in_cpu = []{
		multi::array<complex, 4> ret({45, 18, 32, 16});
		std::generate(
			ret.data_elements(), ret.data_elements() + ret.num_elements(),
			[](){return complex{std::rand()*1./RAND_MAX, std::rand()*1./RAND_MAX};}
		);
		return ret;
	}();

	multi::cuda::array<complex, 4> const in = in_cpu;
	multi::cuda::array<complex, 4>       out(extensions(in));

#if 0
	multi::cufft::many_dft(begin(unrotated(in)), end(unrotated(in)), begin(unrotated(out)), +1);

	multi::array<complex, 4> out_cpu(extensions(in));
	multi::fft::many_dft(begin(unrotated(in_cpu)), end(unrotated(in_cpu)), begin(unrotated(out_cpu)), +1);

	BOOST_TEST( imag( static_cast<complex>(out[5][4][3][2]) - out_cpu[5][4][3][2]) == 0. );
#endif
}

#if 0

BOOST_AUTO_TEST_CASE(cufft_4D, *utf::tolerance(0.00001)){
	auto const in = []{
		multi::array<complex, 3> ret({10, 10, 10});
		std::generate(ret.data_elements(), ret.data_elements() + ret.num_elements(),
			[](){return complex{std::rand()*1./RAND_MAX, std::rand()*1./RAND_MAX};}
		);
		return ret;
	}();

	multi::array<complex, 3> out(extensions(in));
//	multi::fftw::dft({true, false, true}, in, out, multi::fftw::forward);
	multi::fft::many_dft(begin(in<<1), end(in<<1), begin(out<<1), multi::fftw::forward);

	multi::cuda::array<complex, 3> in_gpu = in;
	multi::cuda::array<complex, 3> out_gpu(extensions(in));

//	multi::cufft::dft({true, false, true}, in_gpu, out_gpu, multi::fft::forward);//multi::cufft::forward);
	multi::cufft::many_dft(begin(in_gpu<<1), end(in_gpu<<1), begin(out_gpu<<1), multi::fftw::forward);
	BOOST_TEST( imag( static_cast<complex>(out_gpu[5][4][3]) - out[5][4][3]) == 0. );
}

//BOOST_AUTO_TEST_CASE(cu

#if 0
BOOST_AUTO_TEST_CASE(cufft_4D){
	auto const in = []{
		multi::array<complex, 3> ret({10, 10, 10});
		ret[2][3][4] = 99.;
		return ret;
	}();
	multi::array<complex, 3> out(extensions(in));

	multi::fftw::dft({true, true, false}, in, out, multi::fftw::forward);

//	auto fwd = multi::fftw::dft({true, true, true, true}, in, out, multi::fftw::forward);
//	BOOST_REQUIRE(in[2][3][4][5] == 99.);
	std::cout << out[9][1][2] << std::endl;
	for(auto i = 0; i != out.num_elements(); ++i) std:cout << (out.data_elements()[i]) <<' ';

#if 0
	multi::cuda::array<complex, 3> in_gpu = in;//[]{
//		multi::cuda::array<complex, 4> ret({10, 10, 10, 10});
//		ret[2][3][4][5] = 99.;
//		return ret;
//	}();
	multi::cuda::array<complex, 3> out_gpu(extensions(in));
	multi::cufft::dft({true, true, false}, in_gpu, out_gpu, multi::cufft::forward);

	std::cout << out_gpu[5][4][3].operator complex() << std::endl;

//	multi::cufft::dft({true, true, true, true}, in_gpu, out_gpu, multi::cufft::forward);
//	multi::cufft::dft({true, true, true, true}, in_gpu, out_gpu, multi::cufft::forward);
#endif

}
#endif
#endif
#endif

#endif
#endif

max_stars_repo_name: kryczko/qmcpack

max_issues_repo_name: kryczko/qmcpack

max_forks_repo_name: kryczko/qmcpack


text:
#define BOOST_TEST_MODULE hffix Unit Tests
#include <boost/test/included/unit_test.hpp>

#include <hffix.hpp>
#include <hffix_fields.hpp>

#if __cplusplus >= 201703L
using namespace std::literals::string_view_literals;
#endif
using namespace hffix;

#if __cplusplus >= 201103L
#include <chrono>
#include <iomanip>
#endif
#include <iterator>

BOOST_AUTO_TEST_CASE(basic)
{
    // Print the BOOST version, mostly so we can see it in Travis.
    std::cout << "BOOST version " << BOOST_LIB_VERSION << std::endl;

    char b[1024];
    message_writer w(b);
    w.push_back_header("FIX.4.2");
    w.push_back_string(tag::MsgType, "A");
    w.push_back_trailer();
    message_reader r(b);

    // A reader constructed from a writer should have the same size.
    BOOST_CHECK(w.message_size() == r.message_size());

    // Construct an invalid iterator.
    message_reader::const_iterator j;

    // Field value comparisons.
    message_reader::const_iterator i = r.begin();
    BOOST_CHECK(r.find_with_hint(tag::MsgType, i));
    BOOST_CHECK(i->value() == "A");
    BOOST_CHECK(i->value() == (const char*)"A");
    BOOST_CHECK(i->value() != "B");
    BOOST_CHECK(i->value() == std::string("A"));
    BOOST_CHECK(i->value() != std::string("B"));
#if __cplusplus >= 201703L
    BOOST_CHECK(i->value() == "A"sv); // string_view_literals
    BOOST_CHECK(i->value() != "B"sv); // string_view_literals
#endif

    // message_writer preconditions
    {
        message_writer w(b);
        BOOST_CHECK_THROW(w.push_back_trailer(false), std::logic_error);
    }
    {
        message_writer w(b);
        w.push_back_header("FIX.4.2");
        BOOST_CHECK_THROW(w.push_back_header("FIX.4.2"), std::logic_error);
    }
}

#if __cplusplus >= 201103L // message_writer_bounds test requires C++11

// find the minimum size buffer the message printed by f() will fit
// call the function with a buffer ranging from 100 bytes to 0 bytes
// record the smallest size where it does not throw an exception, make
// sure there's a single point where it starts throwing and that it keeps
// throwing for smaller buffer sizes
template <typename F>
int test_bound_checking(F f)
{
    char buffer[101];
    int minimum_size = 101;
    for (int i = 100; i >= 0; --i) {
        message_writer writer(buffer, buffer + i);
        try {
            buffer[i] = '\x55';
            f(writer);
            BOOST_CHECK(minimum_size == i + 1);
            minimum_size = i;
        }
        catch (std::out_of_range const& e) {}
        // make sure the next byte was not clobbered
        BOOST_CHECK(buffer[i] == '\x55');
    }
    return minimum_size;
}

BOOST_AUTO_TEST_CASE(message_writer_bounds)
{
    using W = message_writer;
    BOOST_CHECK(test_bound_checking([](W& w) { w.push_back_header("FIX.4.2"); } ) == 19);
    BOOST_CHECK(test_bound_checking([](W& w) {
                w.push_back_header("FIX.4.2");
                w.push_back_trailer(false);
            } ) == 26);
    BOOST_CHECK(test_bound_checking([](W& w) {
                w.push_back_header("FIX.4.2");
                w.push_back_trailer(true);
            } ) == 26);

    // 14 characters
    auto const test_string = "string literal";
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_string(58, test_string, test_string + 14); } ) == 4 + 14);
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_string(58, test_string); } ) == 4 + 14);
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_string(58, std::string(test_string)); } ) == 4 + 14);
#if HFFIX_HAS_STRING_VIEW
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_string(58, std::string_view(test_string)); } ) == 4 + 14);
#endif
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_char(58, 'a'); } ) == 5);
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_int(58, 55); } ) == 6);

    // 58=123.456|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_decimal(58, 123456, -3); } ) == 11);

    // 58=123456|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_decimal(58, 123456, 0); } ) == 10);

    // 58=19700101|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_date(58, 1970, 1, 1); } ) == 12);

    // 58=197001|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_monthyear(58, 1970, 1); } ) == 10);

    // 58=HH:MM:SS|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_timeonly(58, 23, 59, 59, 999); } ) == 16);

    // 58=YYYYMMDD-HH:MM:SS|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_timestamp(58, 1970, 1, 1, 23, 59, 59); } ) == 21);

    // 58=YYYYMMDD-HH:MM:SS.sss|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_timestamp(58, 1970, 1, 1, 23, 59, 59, 999); } ) == 25);

    // 58=14|59=..............|
    BOOST_CHECK(test_bound_checking([&](W& w) { w.push_back_data(58, 59, test_string, test_string + 14); } ) == 24);
}
#endif // message_writer_bounds test requires C++11

void test_checksum(message_writer& mw, char const (&expected)[4])
{
    mw.push_back_trailer();
    char const* end = mw.message_end();

    BOOST_CHECK(end[-4] == expected[0]);
    BOOST_CHECK(end[-3] == expected[1]);
    BOOST_CHECK(end[-2] == expected[2]);
}

BOOST_AUTO_TEST_CASE(checksum_empty)
{
    char buffer[50] = {};
    message_writer writer(buffer);

    // 8=FIX.4.2\x01 = (56+61+70+73+88+46+52+46+50+1) % 256 = 31
    // 9=000000\x01 = (57+61+48+48+48+48+48+48+1) % 256 = 151
    // (31 + 151) % 256 = 182
    writer.push_back_header("FIX.4.2");
    test_checksum(writer, "182");
}

BOOST_AUTO_TEST_CASE(checksum)
{
    char buffer[50] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_decimal(58, 123, 0);

    // 8=FIX.4.2\x01 = (56+61+70+73+88+46+52+46+50+1) % 256 = 31
    // 9=000007\x01 = (57+61+48+48+48+48+48+48+1) % 256 = 158
    // 58=123\x01 = (53+56+61+49+50+51+1) % 256 = 65
    // (31 + 158 + 65) % 256 = 254
    test_checksum(writer, "254");
}

BOOST_AUTO_TEST_CASE(checksum_negative)
{
    char buffer[50] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_char(58, '\x80');

    // 8=FIX.4.2\x01 = (56+61+70+73+88+46+52+46+50+1) % 256 = 31
    // 9=000005\x01 = (57+61+48+48+48+48+48+48+1) % 256 = 156
    // 58=\x80\x01 = (53+56+61+128+1) % 256 = 43
    // (31 + 156 + 43) % 256 = 230
    test_checksum(writer, "230");
}

BOOST_AUTO_TEST_CASE(checksum_calc)
{
    char buffer[50] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_string(tag::MsgType, "A");
    writer.push_back_trailer();

    message_reader mr(writer);
    BOOST_CHECK_EQUAL(mr.calculate_check_sum(), mr.check_sum()->value().as_int<unsigned char>());
}

// test that null fields can be iterated properly by message_reader
BOOST_AUTO_TEST_CASE(null_field_value)
{
    char buffer[50] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_string(hffix::tag::MsgType, "A");
    writer.push_back_string(37, "");
    writer.push_back_string(38, "whatever");
    writer.push_back_trailer();

    message_reader reader(writer);
    message_reader::const_iterator i = reader.begin();
    BOOST_CHECK(reader.find_with_hint(38, i));
}

BOOST_AUTO_TEST_CASE(data_length)
{
    char buffer[100] = {};
    message_writer writer(buffer);
    std::string datum("datum");
    writer.push_back_header("FIX.4.2");
    writer.push_back_string(tag::MsgType, "A");
    writer.push_back_data(
        tag::RawDataLength,
        tag::RawData,
        &*datum.begin(),
        &*datum.end()
        );
    writer.push_back_data(
        tag::EncodedUnderlyingProvisionTextLen,
        tag::EncodedUnderlyingProvisionText,
        &*datum.begin(),
        &*datum.end()
        );
    writer.push_back_trailer();

    message_reader reader(writer);
    message_reader::const_iterator i;

    bool found;

    i = reader.begin();
    found = reader.find_with_hint(tag::RawDataLength, i);
    BOOST_REQUIRE(!found);

    i = reader.begin();
    found = reader.find_with_hint(tag::EncodedUnderlyingProvisionTextLen, i);
    BOOST_REQUIRE(!found);

    i = reader.begin();
    found = reader.find_with_hint(tag::RawData, i);
    BOOST_REQUIRE(found);
    BOOST_REQUIRE(i != reader.end());
    BOOST_CHECK_EQUAL(i->value().as_string(), datum);

    found = reader.find_with_hint(tag::EncodedUnderlyingProvisionText, i);
    BOOST_REQUIRE(found);
    BOOST_REQUIRE(i != reader.end());
    BOOST_CHECK_EQUAL(i->value().as_string(), datum);
}

BOOST_AUTO_TEST_CASE(iterating)
{
    char b[1024];
    char* ptr = b;
    unsigned num = 0;
    for(size_t i = 0; i < 10; i++ ) {
      message_writer w(ptr, 1024 - (ptr - b));
      w.push_back_header("FIX.4.2");
      w.push_back_string(tag::MsgType, "A");
      w.push_back_trailer();
      ptr += w.message_size();
    }

    for (message_reader reader(b);
        reader.is_complete();
        reader = reader.next_message_reader()) {
        if(reader.is_complete() && reader.is_valid()) {
          BOOST_CHECK_EQUAL(std::distance(reader.begin(), reader.end()), 1);
          num++;
        }
    }
    BOOST_CHECK_EQUAL(num, 10u);
}

#if __cplusplus >= 201103L
// test that std::chrono values can be written and read correctly
BOOST_AUTO_TEST_CASE(chrono)
{
    using namespace std::chrono;
    using TimePoint = time_point<system_clock, milliseconds>;

    TimePoint tsend(milliseconds(1502282096123ULL)); // 2017-08-09 12:34:56.123

    milliseconds timeofday =
            hours(12) + minutes(34) + seconds(0) + milliseconds(789);

    char buffer[100] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_string(hffix::tag::MsgType, "A");
    writer.push_back_timestamp(hffix::tag::SendingTime, tsend);
    writer.push_back_timeonly(hffix::tag::MDEntryTime, timeofday);
    writer.push_back_trailer();

    message_reader reader(writer);
    message_reader::const_iterator i = reader.begin();
    reader.find_with_hint(hffix::tag::SendingTime, i);
    BOOST_CHECK_EQUAL(i->value().as_string(), std::string("20170809-12:34:56.123"));

    TimePoint trecv;
    bool tparsed = i->value().as_timestamp(trecv);

    BOOST_CHECK(tparsed);
    BOOST_CHECK(tsend == trecv);

    message_reader::const_iterator j = reader.begin();
    reader.find_with_hint(hffix::tag::MDEntryTime, j);
    BOOST_CHECK_EQUAL(j->value().as_string(), std::string("12:34:00.789"));

    milliseconds todrecv;
    bool dparsed = j->value().as_timeonly(todrecv);
    BOOST_CHECK(dparsed);
    BOOST_CHECK(timeofday == todrecv);

    // TODO check this when we have a way to parse milliseconds with put_time.
    // std::time_t trecv_t = std::chrono::system_clock::to_time_t(trecv);
    // std::ostringstream oss;
    // oss << std::put_time(std::localtime(&trecv_t), "%Y%m%d-%T");
    // std::string tstr = oss.str();
    // BOOST_CHECK_EQUAL(tstr, i->value().as_string());
}

// test that std::chrono values can be written and read correctly
BOOST_AUTO_TEST_CASE(chrono_nano)
{
    using namespace std::chrono;
    using TimePoint = time_point<system_clock, nanoseconds>;

    TimePoint tsend(nanoseconds(1502282096123456789ULL)); // 2017-08-09 12:34:56.123456789

    nanoseconds timeofday =
            hours(12) + minutes(34) + seconds(0) + nanoseconds(789456123);

    char buffer[100] = {};
    message_writer writer(buffer);
    writer.push_back_header("FIX.4.2");
    writer.push_back_string(hffix::tag::MsgType, "A");
    writer.push_back_timestamp_nano(hffix::tag::SendingTime, tsend);
    writer.push_back_timeonly_nano(hffix::tag::MDEntryTime, timeofday);
    writer.push_back_trailer();

    message_reader reader(writer);
    message_reader::const_iterator i = reader.begin();
    reader.find_with_hint(hffix::tag::SendingTime, i);
    BOOST_CHECK_EQUAL(i->value().as_string(), std::string("20170809-12:34:56.123456789"));

    TimePoint trecv;
    bool tparsed = i->value().as_timestamp_nano(trecv);

    BOOST_CHECK(tparsed);
    BOOST_CHECK(tsend == trecv);

    message_reader::const_iterator j = reader.begin();
    reader.find_with_hint(hffix::tag::MDEntryTime, j);
    BOOST_CHECK_EQUAL(j->value().as_string(), std::string("12:34:00.789456123"));

    nanoseconds todrecv;
    bool dparsed = j->value().as_timeonly_nano(todrecv);
    BOOST_CHECK(dparsed);
    BOOST_CHECK(timeofday == todrecv);

    // TODO check this when we have a way to parse nanoseconds with put_time.
    // std::time_t trecv_t = std::chrono::system_clock::to_time_t(trecv);
    // std::ostringstream oss;
    // oss << std::put_time(std::localtime(&trecv_t), "%Y%m%d-%T");
    // std::string tstr = oss.str();
    // BOOST_CHECK_EQUAL(tstr, i->value().as_string());
}
#endif

max_stars_repo_name: jamesdbrock/hffix

max_issues_repo_name: jamesdbrock/hffix

max_forks_repo_name: jamesdbrock/hffix