<commit_before>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2013-2014, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the Daemon developers nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "Common.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <signal.h>
#ifdef __native_client__
#include <nacl/nacl_exception.h>
#else
#include <dlfcn.h>
#endif
#endif

namespace Sys {

#ifdef _WIN32
SteadyClock::time_point SteadyClock::now() NOEXCEPT
{
	// Determine performance counter frequency
	static double nanosec_per_tic = 0.0;
	if (nanosec_per_tic == 0.0) {
		LARGE_INTEGER freq;
		QueryPerformanceFrequency(&freq);
		nanosec_per_tic = 1000000000.0 / freq.QuadPart;
	}

	LARGE_INTEGER time;
	QueryPerformanceCounter(&time);
	return time_point(duration(rep(nanosec_per_tic * time.QuadPart)));
}
#endif

void SleepFor(SteadyClock::duration time)
{
#ifdef _WIN32
	static ULONG maxRes = 0;
	static NTSTATUS(WINAPI *pNtSetTimerResolution) (ULONG resolution, BOOLEAN set_resolution, ULONG* current_resolution);
	static NTSTATUS(WINAPI *pNtDelayExecution) (BOOLEAN alertable, const LARGE_INTEGER* timeout);
	if (maxRes == 0) {
		// Load ntdll.dll functions
		std::string errorString;
		DynamicLib ntdll = DynamicLib::Open("ntdll.dll", errorString);
		if (!ntdll)
			Sys::Error("Failed to load ntdll.dll: %s", errorString);
		auto pNtQueryTimerResolution = ntdll.LoadSym<NTSTATUS WINAPI(ULONG*, ULONG*, ULONG*)>("NtQueryTimerResolution", errorString);
		if (!pNtQueryTimerResolution)
			Sys::Error("Failed to load NtQueryTimerResolution from ntdll.dll: %s", errorString);
		pNtSetTimerResolution = ntdll.LoadSym<NTSTATUS WINAPI(ULONG, BOOLEAN, ULONG*)>("NtSetTimerResolution", errorString);
		if (!pNtSetTimerResolution)
			Sys::Error("Failed to load NtSetTimerResolution from ntdll.dll: %s", errorString);
		pNtDelayExecution = ntdll.LoadSym<NTSTATUS WINAPI(BOOLEAN, const LARGE_INTEGER*)>("NtDelayExecution", errorString);
		if (!pNtDelayExecution)
			Sys::Error("Failed to load NtDelayExecution from ntdll.dll: %s", errorString);

		// Determine the maximum available timer resolution
		ULONG minRes, curRes;
		if (pNtQueryTimerResolution(&minRes, &maxRes, &curRes) != 0)
			maxRes = 10000; // Default to 1ms
	}

	// Increase the system timer resolution for the duration of the sleep
	ULONG curRes;
	pNtSetTimerResolution(maxRes, TRUE, &curRes);

	// Convert to NT units of 100ns
	typedef std::chrono::duration<int64_t, std::ratio<1, 10000000>> NTDuration;
	auto ntTime = std::chrono::duration_cast<NTDuration>(time);

	// Store the delay as a negative number to indicate a relative sleep
	LARGE_INTEGER duration;
	duration.QuadPart = -ntTime.count();
	pNtDelayExecution(FALSE, &duration);

	// Restore timer resolution after sleeping
	pNtSetTimerResolution(maxRes, FALSE, &curRes);
#else
	std::this_thread::sleep_for(time);
#endif
}

SteadyClock::time_point SleepUntil(SteadyClock::time_point time)
{
	// Early exit if we are already past the deadline
	auto now = SteadyClock::now();
	if (now >= time) {
		// We were already past our deadline, which means that the previous frame
		// ran for too long. Use the current time as the base for the next frame.
		return now;
	}

	// Perform the actual sleep
	SleepFor(time - now);

	// We may have overslept, so use the target time rather than the
	// current time as the base for the next frame. That way we ensure
	// that the frame rate remains consistent.
	return time;
}

void Drop(Str::StringRef message)
{
	// Transform into a fatal error if too many errors are generated in quick
	// succession.
	static Sys::SteadyClock::time_point lastError;
	Sys::SteadyClock::time_point now = Sys::SteadyClock::now();
	static int errorCount = 0;
	if (now - lastError < std::chrono::milliseconds(100)) {
		if (++errorCount > 3)
			Sys::Error(message);
	} else
		errorCount = 0;
	lastError = now;

	throw DropErr(message.c_str());
}

#ifdef _WIN32
std::string Win32StrError(uint32_t error)
{
	std::string out;
	char* message;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), reinterpret_cast<char *>(&message), 0, nullptr)) {
		out = message;

		// FormatMessage adds ".\r\n" to messages, but we don't want those
		if (out.back() == '\n')
			out.pop_back();
		if (out.back() == '\r')
			out.pop_back();
		if (out.back() == '.')
			out.pop_back();
		LocalFree(message);
	} else
		out = Str::Format("Unknown error 0x%08lx", error);
	return out;
}
#endif

// Setup crash handling
#ifdef _WIN32
static const char *WindowsExceptionString(DWORD code)
{
	switch (code) {
	case EXCEPTION_ACCESS_VIOLATION:
		return "Access violation";
	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
		return "Array bounds exceeded";
	case EXCEPTION_BREAKPOINT:
		return "Breakpoint was encountered";
	case EXCEPTION_DATATYPE_MISALIGNMENT:
		return "Datatype misalignment";
	case EXCEPTION_FLT_DENORMAL_OPERAND:
		return "Float: Denormal operand";
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
		return "Float: Divide by zero";
	case EXCEPTION_FLT_INEXACT_RESULT:
		return "Float: Inexact result";
	case EXCEPTION_FLT_INVALID_OPERATION:
		return "Float: Invalid operation";
	case EXCEPTION_FLT_OVERFLOW:
		return "Float: Overflow";
	case EXCEPTION_FLT_STACK_CHECK:
		return "Float: Stack check";
	case EXCEPTION_FLT_UNDERFLOW:
		return "Float: Underflow";
	case EXCEPTION_ILLEGAL_INSTRUCTION:
		return "Illegal instruction";
	case EXCEPTION_IN_PAGE_ERROR:
		return "Page error";
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
		return "Integer: Divide by zero";
	case EXCEPTION_INT_OVERFLOW:
		return "Integer: Overflow";
	case EXCEPTION_INVALID_DISPOSITION:
		return "Invalid disposition";
	case EXCEPTION_NONCONTINUABLE_EXCEPTION:
		return "Noncontinuable exception";
	case EXCEPTION_PRIV_INSTRUCTION:
		return "Privileged instruction";
	case EXCEPTION_SINGLE_STEP:
		return "Single step";
	case EXCEPTION_STACK_OVERFLOW:
		return "Stack overflow";
	default:
		return "Unknown exception";
	}
}
static LONG WINAPI CrashHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
	// Reset handler so that any future errors cause a crash
	SetUnhandledExceptionFilter(nullptr);

	// TODO: backtrace

	Sys::Error("Crashed with exception 0x%lx: %s", ExceptionInfo->ExceptionRecord->ExceptionCode, WindowsExceptionString(ExceptionInfo->ExceptionRecord->ExceptionCode));

	return EXCEPTION_CONTINUE_EXECUTION;
}
void SetupCrashHandler()
{
	SetUnhandledExceptionFilter(CrashHandler);
}
#elif defined(__native_client__)
static void CrashHandler(struct NaClExceptionContext *)
{
	// TODO: backtrace

	Sys::Error("Crashed with NaCl exception");
}
void SetupCrashHandler()
{
	nacl_exception_set_handler(CrashHandler);
}
#else
static void CrashHandler(int sig)
{
	// TODO: backtrace

	Sys::Error("Crashed with signal %d: %s", sig, strsignal(sig));
}
void SetupCrashHandler()
{
	struct sigaction sa;
	sa.sa_flags = SA_RESETHAND | SA_NODEFER;
	sa.sa_handler = CrashHandler;
	sigemptyset(&sa.sa_mask);
	for (int sig: {SIGILL, SIGFPE, SIGSEGV, SIGABRT, SIGBUS, SIGTRAP})
		sigaction(sig, &sa, nullptr);
}
#endif

#ifndef __native_client__
void DynamicLib::Close()
{
	if (!handle)
		return;

#ifdef _WIN32
	FreeLibrary(static_cast<HMODULE>(handle));
#else
	dlclose(handle);
#endif
	handle = nullptr;
}

DynamicLib DynamicLib::Open(Str::StringRef filename, std::string& errorString)
{
#ifdef _WIN32
	void* handle = LoadLibraryW(Str::UTF8To16(filename).c_str());
	if (!handle)
		errorString = Win32StrError(GetLastError());
#else
	// Handle relative paths correctly
	const char* dlopenFilename = filename.c_str();
	std::string relativePath;
	if (filename.find('/') == std::string::npos) {
		relativePath = "./" + filename;
		dlopenFilename = relativePath.c_str();
	}

	void* handle = dlopen(dlopenFilename, RTLD_NOW);
	if (!handle)
		errorString = dlerror();
#endif

	DynamicLib out;
	out.handle = handle;
	return out;
}

intptr_t DynamicLib::InternalLoadSym(Str::StringRef sym, std::string& errorString)
{
#ifdef _WIN32
	intptr_t p = reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), sym.c_str()));
	if (!p)
		errorString = Win32StrError(GetLastError());
	return p;
#else
	intptr_t p = reinterpret_cast<intptr_t>(dlsym(handle, sym.c_str()));
	if (!p)
		errorString = dlerror();
	return p;
#endif
}
#endif // __native_client__

bool processTerminating = false;

void OSExit(int exitCode) {
    processTerminating = true;
    exit(exitCode);
}

bool IsProcessTerminating() {
	return processTerminating;
}

void GenRandomBytes(void* dest, size_t size)
{
#ifdef _WIN32
	HCRYPTPROV prov;
	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
		Sys::Error("CryptAcquireContext failed: %s", Win32StrError(GetLastError()));

	if (!CryptGenRandom(prov, size, (BYTE*)dest))
		Sys::Error("CryptGenRandom failed: %s", Win32StrError(GetLastError()));

	CryptReleaseContext(prov, 0);
#else
	try {
		FS::RawPath::OpenRead("/dev/urandom").Read(dest, size);
	} catch (std::system_error& err) {
		Sys::Error("Failed to generate random bytes: %s", err.what());
	}
#endif
}

} // namespace Sys

// Global operator new/delete override to not throw an exception when out of
// memory. Instead, it is preferable to simply crash with an error.
void* operator new(size_t n)
{
	void* p = malloc(n);
	if (!p)
		Sys::Error("Out of memory");
	return p;
}
void operator delete(void* p) NOEXCEPT
{
	if (!Sys::processTerminating) {
		free(p);
	}
}
<commit_msg>Implement Sys::GenRandomBytes for NaCl<commit_after>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2013-2014, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the Daemon developers nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "Common.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <signal.h>
#ifdef __native_client__
#include <nacl/nacl_exception.h>
#include <nacl/nacl_random.h>
#else
#include <dlfcn.h>
#endif
#endif

namespace Sys {

#ifdef _WIN32
SteadyClock::time_point SteadyClock::now() NOEXCEPT
{
	// Determine performance counter frequency
	static double nanosec_per_tic = 0.0;
	if (nanosec_per_tic == 0.0) {
		LARGE_INTEGER freq;
		QueryPerformanceFrequency(&freq);
		nanosec_per_tic = 1000000000.0 / freq.QuadPart;
	}

	LARGE_INTEGER time;
	QueryPerformanceCounter(&time);
	return time_point(duration(rep(nanosec_per_tic * time.QuadPart)));
}
#endif

void SleepFor(SteadyClock::duration time)
{
#ifdef _WIN32
	static ULONG maxRes = 0;
	static NTSTATUS(WINAPI *pNtSetTimerResolution) (ULONG resolution, BOOLEAN set_resolution, ULONG* current_resolution);
	static NTSTATUS(WINAPI *pNtDelayExecution) (BOOLEAN alertable, const LARGE_INTEGER* timeout);
	if (maxRes == 0) {
		// Load ntdll.dll functions
		std::string errorString;
		DynamicLib ntdll = DynamicLib::Open("ntdll.dll", errorString);
		if (!ntdll)
			Sys::Error("Failed to load ntdll.dll: %s", errorString);
		auto pNtQueryTimerResolution = ntdll.LoadSym<NTSTATUS WINAPI(ULONG*, ULONG*, ULONG*)>("NtQueryTimerResolution", errorString);
		if (!pNtQueryTimerResolution)
			Sys::Error("Failed to load NtQueryTimerResolution from ntdll.dll: %s", errorString);
		pNtSetTimerResolution = ntdll.LoadSym<NTSTATUS WINAPI(ULONG, BOOLEAN, ULONG*)>("NtSetTimerResolution", errorString);
		if (!pNtSetTimerResolution)
			Sys::Error("Failed to load NtSetTimerResolution from ntdll.dll: %s", errorString);
		pNtDelayExecution = ntdll.LoadSym<NTSTATUS WINAPI(BOOLEAN, const LARGE_INTEGER*)>("NtDelayExecution", errorString);
		if (!pNtDelayExecution)
			Sys::Error("Failed to load NtDelayExecution from ntdll.dll: %s", errorString);

		// Determine the maximum available timer resolution
		ULONG minRes, curRes;
		if (pNtQueryTimerResolution(&minRes, &maxRes, &curRes) != 0)
			maxRes = 10000; // Default to 1ms
	}

	// Increase the system timer resolution for the duration of the sleep
	ULONG curRes;
	pNtSetTimerResolution(maxRes, TRUE, &curRes);

	// Convert to NT units of 100ns
	typedef std::chrono::duration<int64_t, std::ratio<1, 10000000>> NTDuration;
	auto ntTime = std::chrono::duration_cast<NTDuration>(time);

	// Store the delay as a negative number to indicate a relative sleep
	LARGE_INTEGER duration;
	duration.QuadPart = -ntTime.count();
	pNtDelayExecution(FALSE, &duration);

	// Restore timer resolution after sleeping
	pNtSetTimerResolution(maxRes, FALSE, &curRes);
#else
	std::this_thread::sleep_for(time);
#endif
}

SteadyClock::time_point SleepUntil(SteadyClock::time_point time)
{
	// Early exit if we are already past the deadline
	auto now = SteadyClock::now();
	if (now >= time) {
		// We were already past our deadline, which means that the previous frame
		// ran for too long. Use the current time as the base for the next frame.
		return now;
	}

	// Perform the actual sleep
	SleepFor(time - now);

	// We may have overslept, so use the target time rather than the
	// current time as the base for the next frame. That way we ensure
	// that the frame rate remains consistent.
	return time;
}

void Drop(Str::StringRef message)
{
	// Transform into a fatal error if too many errors are generated in quick
	// succession.
	static Sys::SteadyClock::time_point lastError;
	Sys::SteadyClock::time_point now = Sys::SteadyClock::now();
	static int errorCount = 0;
	if (now - lastError < std::chrono::milliseconds(100)) {
		if (++errorCount > 3)
			Sys::Error(message);
	} else
		errorCount = 0;
	lastError = now;

	throw DropErr(message.c_str());
}

#ifdef _WIN32
std::string Win32StrError(uint32_t error)
{
	std::string out;
	char* message;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), reinterpret_cast<char *>(&message), 0, nullptr)) {
		out = message;

		// FormatMessage adds ".\r\n" to messages, but we don't want those
		if (out.back() == '\n')
			out.pop_back();
		if (out.back() == '\r')
			out.pop_back();
		if (out.back() == '.')
			out.pop_back();
		LocalFree(message);
	} else
		out = Str::Format("Unknown error 0x%08lx", error);
	return out;
}
#endif

// Setup crash handling
#ifdef _WIN32
static const char *WindowsExceptionString(DWORD code)
{
	switch (code) {
	case EXCEPTION_ACCESS_VIOLATION:
		return "Access violation";
	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
		return "Array bounds exceeded";
	case EXCEPTION_BREAKPOINT:
		return "Breakpoint was encountered";
	case EXCEPTION_DATATYPE_MISALIGNMENT:
		return "Datatype misalignment";
	case EXCEPTION_FLT_DENORMAL_OPERAND:
		return "Float: Denormal operand";
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
		return "Float: Divide by zero";
	case EXCEPTION_FLT_INEXACT_RESULT:
		return "Float: Inexact result";
	case EXCEPTION_FLT_INVALID_OPERATION:
		return "Float: Invalid operation";
	case EXCEPTION_FLT_OVERFLOW:
		return "Float: Overflow";
	case EXCEPTION_FLT_STACK_CHECK:
		return "Float: Stack check";
	case EXCEPTION_FLT_UNDERFLOW:
		return "Float: Underflow";
	case EXCEPTION_ILLEGAL_INSTRUCTION:
		return "Illegal instruction";
	case EXCEPTION_IN_PAGE_ERROR:
		return "Page error";
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
		return "Integer: Divide by zero";
	case EXCEPTION_INT_OVERFLOW:
		return "Integer: Overflow";
	case EXCEPTION_INVALID_DISPOSITION:
		return "Invalid disposition";
	case EXCEPTION_NONCONTINUABLE_EXCEPTION:
		return "Noncontinuable exception";
	case EXCEPTION_PRIV_INSTRUCTION:
		return "Privileged instruction";
	case EXCEPTION_SINGLE_STEP:
		return "Single step";
	case EXCEPTION_STACK_OVERFLOW:
		return "Stack overflow";
	default:
		return "Unknown exception";
	}
}
static LONG WINAPI CrashHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
	// Reset handler so that any future errors cause a crash
	SetUnhandledExceptionFilter(nullptr);

	// TODO: backtrace

	Sys::Error("Crashed with exception 0x%lx: %s", ExceptionInfo->ExceptionRecord->ExceptionCode, WindowsExceptionString(ExceptionInfo->ExceptionRecord->ExceptionCode));

	return EXCEPTION_CONTINUE_EXECUTION;
}
void SetupCrashHandler()
{
	SetUnhandledExceptionFilter(CrashHandler);
}
#elif defined(__native_client__)
static void CrashHandler(struct NaClExceptionContext *)
{
	// TODO: backtrace

	Sys::Error("Crashed with NaCl exception");
}
void SetupCrashHandler()
{
	nacl_exception_set_handler(CrashHandler);
}
#else
static void CrashHandler(int sig)
{
	// TODO: backtrace

	Sys::Error("Crashed with signal %d: %s", sig, strsignal(sig));
}
void SetupCrashHandler()
{
	struct sigaction sa;
	sa.sa_flags = SA_RESETHAND | SA_NODEFER;
	sa.sa_handler = CrashHandler;
	sigemptyset(&sa.sa_mask);
	for (int sig: {SIGILL, SIGFPE, SIGSEGV, SIGABRT, SIGBUS, SIGTRAP})
		sigaction(sig, &sa, nullptr);
}
#endif

#ifndef __native_client__
void DynamicLib::Close()
{
	if (!handle)
		return;

#ifdef _WIN32
	FreeLibrary(static_cast<HMODULE>(handle));
#else
	dlclose(handle);
#endif
	handle = nullptr;
}

DynamicLib DynamicLib::Open(Str::StringRef filename, std::string& errorString)
{
#ifdef _WIN32
	void* handle = LoadLibraryW(Str::UTF8To16(filename).c_str());
	if (!handle)
		errorString = Win32StrError(GetLastError());
#else
	// Handle relative paths correctly
	const char* dlopenFilename = filename.c_str();
	std::string relativePath;
	if (filename.find('/') == std::string::npos) {
		relativePath = "./" + filename;
		dlopenFilename = relativePath.c_str();
	}

	void* handle = dlopen(dlopenFilename, RTLD_NOW);
	if (!handle)
		errorString = dlerror();
#endif

	DynamicLib out;
	out.handle = handle;
	return out;
}

intptr_t DynamicLib::InternalLoadSym(Str::StringRef sym, std::string& errorString)
{
#ifdef _WIN32
	intptr_t p = reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), sym.c_str()));
	if (!p)
		errorString = Win32StrError(GetLastError());
	return p;
#else
	intptr_t p = reinterpret_cast<intptr_t>(dlsym(handle, sym.c_str()));
	if (!p)
		errorString = dlerror();
	return p;
#endif
}
#endif // __native_client__

bool processTerminating = false;

void OSExit(int exitCode) {
    processTerminating = true;
    exit(exitCode);
}

bool IsProcessTerminating() {
	return processTerminating;
}

void GenRandomBytes(void* dest, size_t size)
{
#ifdef _WIN32
	HCRYPTPROV prov;
	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
		Sys::Error("CryptAcquireContext failed: %s", Win32StrError(GetLastError()));

	if (!CryptGenRandom(prov, size, (BYTE*)dest))
		Sys::Error("CryptGenRandom failed: %s", Win32StrError(GetLastError()));

	CryptReleaseContext(prov, 0);
#elif defined(__native_client__)
	size_t bytes_written;
	if (nacl_secure_random(dest, size, &bytes_written) != 0 || bytes_written != size)
		Sys::Error("nacl_secure_random failed");
#else
	try {
		FS::RawPath::OpenRead("/dev/urandom").Read(dest, size);
	} catch (std::system_error& err) {
		Sys::Error("Failed to generate random bytes: %s", err.what());
	}
#endif
}

} // namespace Sys

// Global operator new/delete override to not throw an exception when out of
// memory. Instead, it is preferable to simply crash with an error.
void* operator new(size_t n)
{
	void* p = malloc(n);
	if (!p)
		Sys::Error("Out of memory");
	return p;
}
void operator delete(void* p) NOEXCEPT
{
	if (!Sys::processTerminating) {
		free(p);
	}
}
<|endoftext|>


<commit_before>#include <mill/math/Vector.hpp>
#include <mill/util/logger.hpp>
#include "mode_calc_help.hpp"
#include "mode_calc_rmsd.hpp"
#include "mode_calc_wham.hpp"
#include "mode_calc_dist.hpp"
#include "mode_calc_angle.hpp"
#include "mode_calc_aabb.hpp"
#include "mode_calc_obb.hpp"
#include "mode_calc_center.hpp"

namespace mill
{

const char* mode_calc_help_usage() noexcept
{
    return "usage: mill calc [command] [parameters...]\n\n"
           "    avaiable commands\n"
           "    - rmsd\n"
           "      : calculate RMSD between a reference and frames in trajectory\n"
           "    - wham\n"
           "      : reconstruct free energy surface by WHAM\n"
           "    - dist\n"
           "      : calculate distance from traj file\n"
           "    - angle\n"
           "      : calculate angle from traj file\n"
           "    - aabb\n"
           "      : construct AABB\n"
           "    - obb\n"
           "      : construct OBB using covariances\n"
           "    - center\n"
           "      : calculate geometric center\n"
           "    - help\n"
           "      : print detailed explanation of each command\n";
}

//! this function forwards the arguments to different modes.
int mode_calc_help(std::deque<std::string_view> args)
{
    using namespace std::literals::string_view_literals;
    if(args.empty())
    {
        log::info(mode_calc_help_usage());
        return 0;
    }

    const auto command = args.front();

    if(command == "rmsd")
    {
        return mode_calc_rmsd({"help"sv});
    }
    else if(command == "dist")
    {
        return mode_calc_dist({"help"sv});
    }
    else if(command == "angle")
    {
        return mode_calc_angle({"help"sv});
    }
    else if(command == "wham")
    {
        return mode_calc_wham({"help"sv});
    }
    else if(command == "obb")
    {
        return mode_calc_obb({"help"sv});
    }
    else if(command == "aabb")
    {
        return mode_calc_aabb({"help"sv});
    }
    else if(command == "center")
    {
        return mode_calc_center({"help"sv});
    }
    else if(command == "help")
    {
        log::info(mode_calc_help_usage());
        return 0;
    }
    else
    {
        log::error("mill calc help: unknown command : ", command);
        log::error(mode_calc_help_usage());
        return 1;
    }
}

} // mill
<commit_msg>:children_crossing: add autocorrelation to calc help<commit_after>#include <mill/math/Vector.hpp>
#include <mill/util/logger.hpp>
#include "mode_calc_help.hpp"
#include "mode_calc_rmsd.hpp"
#include "mode_calc_wham.hpp"
#include "mode_calc_dist.hpp"
#include "mode_calc_angle.hpp"
#include "mode_calc_aabb.hpp"
#include "mode_calc_obb.hpp"
#include "mode_calc_center.hpp"
#include "mode_calc_autocorrelation.hpp"

namespace mill
{

const char* mode_calc_help_usage() noexcept
{
    return "usage: mill calc [command] [parameters...]\n\n"
           "    avaiable commands\n"
           "    - rmsd\n"
           "      : calculate RMSD between a reference and frames in trajectory\n"
           "    - wham\n"
           "      : reconstruct free energy surface by WHAM\n"
           "    - dist\n"
           "      : calculate distance from traj file\n"
           "    - angle\n"
           "      : calculate angle from traj file\n"
           "    - aabb\n"
           "      : construct AABB\n"
           "    - obb\n"
           "      : construct OBB using covariances\n"
           "    - center\n"
           "      : calculate geometric center\n"
           "    - autocorrelation\n"
           "      : calculate autocorrelation of data\n"
           "    - help\n"
           "      : print detailed explanation of each command\n";
}

//! this function forwards the arguments to different modes.
int mode_calc_help(std::deque<std::string_view> args)
{
    using namespace std::literals::string_view_literals;
    if(args.empty())
    {
        log::info(mode_calc_help_usage());
        return 0;
    }

    const auto command = args.front();

    if(command == "rmsd")
    {
        return mode_calc_rmsd({"help"sv});
    }
    else if(command == "dist")
    {
        return mode_calc_dist({"help"sv});
    }
    else if(command == "angle")
    {
        return mode_calc_angle({"help"sv});
    }
    else if(command == "wham")
    {
        return mode_calc_wham({"help"sv});
    }
    else if(command == "obb")
    {
        return mode_calc_obb({"help"sv});
    }
    else if(command == "aabb")
    {
        return mode_calc_aabb({"help"sv});
    }
    else if(command == "center")
    {
        return mode_calc_center({"help"sv});
    }
    else if(command == "autocorrelation")
    {
        return mode_calc_autocorrelation({"help"sv});
    }
    else if(command == "help")
    {
        log::info(mode_calc_help_usage());
        return 0;
    }
    else
    {
        log::error("mill calc help: unknown command : ", command);
        log::error(mode_calc_help_usage());
        return 1;
    }
}

} // mill
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: core_resource.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: fs $ $Date: 2001-04-26 11:18:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBA_CORE_RESOURCE_HXX_
#define _DBA_CORE_RESOURCE_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

class SimpleResMgr;
//.........................................................................
namespace dbaccess
{

#define DBACORE_RESSTRING(id) ResourceManager::loadString(id)

    //==================================================================
    //= ResourceManager
    //= handling ressources within the DBA-Core library
    //==================================================================
    class ResourceManager
    {
        static SimpleResMgr*    m_pImpl;

    private:
        // no instantiation allowed
        ResourceManager() { }
        ~ResourceManager() { }

        // we'll instantiate one static member of the following class, which, in it's dtor,
        // ensures that m_pImpl will be deleted
        class EnsureDelete
        {
        public:
            EnsureDelete() { }
            ~EnsureDelete();
        };
        friend class EnsureDelete;

    protected:
        static void ensureImplExists();

    public:
        /** loads the string with the specified resource id from the FormLayer resource file
        */
        static ::rtl::OUString loadString(sal_uInt16 _nResId);
    };

//.........................................................................
}
//.........................................................................

#endif // _DBA_CORE_RESOURCE_HXX_

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.504); FILE MERGED 2005/09/05 17:32:29 rt 1.2.504.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: core_resource.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 13:36:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DBA_CORE_RESOURCE_HXX_
#define _DBA_CORE_RESOURCE_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

class SimpleResMgr;
//.........................................................................
namespace dbaccess
{

#define DBACORE_RESSTRING(id) ResourceManager::loadString(id)

    //==================================================================
    //= ResourceManager
    //= handling ressources within the DBA-Core library
    //==================================================================
    class ResourceManager
    {
        static SimpleResMgr*    m_pImpl;

    private:
        // no instantiation allowed
        ResourceManager() { }
        ~ResourceManager() { }

        // we'll instantiate one static member of the following class, which, in it's dtor,
        // ensures that m_pImpl will be deleted
        class EnsureDelete
        {
        public:
            EnsureDelete() { }
            ~EnsureDelete();
        };
        friend class EnsureDelete;

    protected:
        static void ensureImplExists();

    public:
        /** loads the string with the specified resource id from the FormLayer resource file
        */
        static ::rtl::OUString loadString(sal_uInt16 _nResId);
    };

//.........................................................................
}
//.........................................................................

#endif // _DBA_CORE_RESOURCE_HXX_

<|endoftext|>


<commit_before>#include <chrono>
#include <derecho/sst/multicast_sst.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>

#include "aggregate_bandwidth.hpp"
#include "initialize.h"
#include "log_results.hpp"

using namespace std;
using namespace sst;

volatile bool done = false;

struct exp_results {
    uint32_t num_nodes;
    int num_senders_selector;
    uint max_msg_size;
    double sum_message_rate;
    void print(std::ofstream& fout) {
        fout << num_nodes << " " << num_senders_selector << " "
             << max_msg_size << " " << sum_message_rate << endl;
    }
};

#ifndef NDEBUG
#define DEBUG_MSG(str)                 \
    do {                               \
        std::cout << str << std::endl; \
    } while(false)
#else
#define DEBUG_MSG(str) \
    do {               \
    } while(false)
#endif

int main(int argc, char* argv[]) {
    constexpr uint max_msg_size = 1;
    const unsigned int num_messages = 1000000;
    if(argc < 4) {
        cout << "Insufficient number of command line arguments" << endl;
        cout << "Usage: " << argv[0] << " <num_nodes> <window_size><num_senders_selector (0 - all senders, 1 - half senders, 2 - one sender)>" << endl;
        cout << "Thank you" << endl;
        exit(1);
    }
    uint32_t num_nodes = atoi(argv[1]);
    uint32_t window_size = atoi(argv[2]);
    int num_senders_selector = atoi(argv[3]);
    const uint32_t node_id = derecho::getConfUInt32(CONF_DERECHO_LOCAL_ID);
    const std::map<uint32_t, std::pair<ip_addr_t, uint16_t>> ip_addrs_and_ports = initialize(num_nodes);

    // initialize the rdma resources
#ifdef USE_VERBS_API
    verbs_initialize(ip_addrs_and_ports, ip_addrs_and_ports, node_id);
#else
    lf_initialize(ip_addrs_and_ports, node_id);
#endif

    std::vector<uint32_t> members;
    for(const auto& p : ip_addrs_and_ports) {
        members.push_back(p.first);
    }

    uint32_t num_senders = num_nodes, row_offset = 0;
    if(num_senders_selector == 0) {
    } else if(num_senders_selector == 1) {
        num_senders = num_nodes / 2;
        row_offset = (num_nodes + 1) / 2;
    } else {
        num_senders = 1;
        row_offset = num_nodes - 1;
    }

    std::shared_ptr<multicast_sst> sst = make_shared<multicast_sst>(
            sst::SSTParams(members, node_id),
            window_size,
            num_senders, max_msg_size);

    uint32_t node_rank = sst->get_local_index();

    auto check_failures_loop = [&sst]() {
        pthread_setname_np(pthread_self(), "check_failures");
        while(true) {
            std::this_thread::sleep_for(chrono::microseconds(1000));
            if(sst) {
                sst->put_with_completion((char*)std::addressof(sst->heartbeat[0]) - sst->getBaseAddress(), sizeof(bool));
            }
        }
    };

    thread failures_thread = std::thread(check_failures_loop);

    vector<bool> completed(num_senders, false);
    uint num_finished = 0;
    auto sst_receive_handler = [&num_finished, num_senders_selector, &num_nodes, &num_messages, &completed](
                                       uint32_t sender_rank, uint64_t index,
                                       volatile char* msg, uint32_t size) {
        if(index == num_messages - 1) {
            completed[sender_rank] = true;
            num_finished++;
        }
        if(num_finished == num_nodes || (num_senders_selector == 1 && num_finished == num_nodes / 2) || (num_senders_selector == 2 && num_finished == 1)) {
            done = true;
        }
    };
    auto receiver_pred = [&](const multicast_sst& sst) {
        return true;
    };
    vector<int64_t> last_max_num_received(num_senders, -1);
    auto receiver_trig = [&completed, last_max_num_received, window_size, num_nodes, node_rank, sst_receive_handler,
                          row_offset, num_senders](multicast_sst& sst) mutable {
        while(true) {
            for(uint j = 0; j < num_senders; ++j) {
                auto num_received = sst.num_received_sst[node_rank][j] + 1;
                uint32_t slot = num_received % window_size;
                if((int64_t&)sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * (slot + 1) - sizeof(uint64_t)] == (num_received / window_size + 1)) {
                    sst_receive_handler(j, num_received,
                                        &sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * slot],
                                        sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * (slot + 1) - 2 * sizeof(uint64_t)]);
                    sst.num_received_sst[node_rank][j]++;
                }
            }
            bool time_to_push = true;
            for(uint j = 0; j < num_senders; ++j) {
                if(completed[j]) {
                    continue;
                }
                if(sst.num_received_sst[node_rank][j] - last_max_num_received[j] <= window_size / 2) {
                    time_to_push = false;
                }
            }
            if(time_to_push) {
                break;
            }
        }
        sst.put(sst.num_received_sst.get_base() - sst.getBaseAddress(),
                sizeof(sst.num_received_sst[0][0]) * num_senders);
        for(uint j = 0; j < num_senders; ++j) {
            last_max_num_received[j] = sst.num_received_sst[node_rank][j];
        }
    };
    // inserting later

    vector<uint32_t> indices(num_nodes);
    iota(indices.begin(), indices.end(), 0);
    std::vector<int> is_sender(num_nodes, 1);
    if(num_senders_selector == 0) {
    } else if(num_senders_selector == 1) {
        for(uint i = 0; i <= (num_nodes - 1) / 2; ++i) {
            is_sender[i] = 0;
        }
    } else {
        for(uint i = 0; i < num_nodes - 1; ++i) {
            is_sender[i] = 0;
        }
    }
    sst::multicast_group<multicast_sst> g(sst, indices, window_size, max_msg_size, is_sender);

    DEBUG_MSG("Group created");

    // now
    sst->predicates.insert(receiver_pred, receiver_trig,
                           sst::PredicateType::RECURRENT);
    // uint count = 0;
    struct timespec start_time, end_time;
    // start timer
    clock_gettime(CLOCK_REALTIME, &start_time);
    if(node_rank == num_nodes - 1 || num_senders_selector == 0 || (node_rank > (num_nodes - 1) / 2 && num_senders_selector == 1)) {
        for(uint i = 0; i < num_messages; ++i) {
            volatile char* buf;
            while((buf = g.get_buffer(max_msg_size)) == NULL) {
                // ++count;
            }
            // for(uint i = 0; i < size; ++i) {
            //     buf[i] = 'a' + rand() % 26;
            // }
            g.send();
        }
    }
    // cout << "Done sending" << endl;
    while(!done) {
    }
    // end timer
    clock_gettime(CLOCK_REALTIME, &end_time);
    double my_time = ((end_time.tv_sec * 1e9 + end_time.tv_nsec) - (start_time.tv_sec * 1e9 + start_time.tv_nsec));
    double message_rate = (num_messages * 1e9) / my_time;
    ;
    if(num_senders_selector == 0) {
        message_rate *= num_nodes;
    } else if(num_senders_selector == 1) {
        message_rate *= num_nodes / 2;
    }

    double sum_message_rate = aggregate_bandwidth(members, node_rank, message_rate);
    log_results(exp_results{num_nodes, num_senders_selector, max_msg_size, sum_message_rate},
                "data_multicast");
    sst->sync_with_members();
}
<commit_msg>adapt multicast_throughput for libfabric too.<commit_after>#include <chrono>
#include <derecho/sst/multicast_sst.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>

#include "aggregate_bandwidth.hpp"
#include "initialize.h"
#include "log_results.hpp"

using namespace std;
using namespace sst;

volatile bool done = false;

struct exp_results {
    uint32_t num_nodes;
    int num_senders_selector;
    uint max_msg_size;
    double sum_message_rate;
    void print(std::ofstream& fout) {
        fout << num_nodes << " " << num_senders_selector << " "
             << max_msg_size << " " << sum_message_rate << endl;
    }
};

#ifndef NDEBUG
#define DEBUG_MSG(str)                 \
    do {                               \
        std::cout << str << std::endl; \
    } while(false)
#else
#define DEBUG_MSG(str) \
    do {               \
    } while(false)
#endif

int main(int argc, char* argv[]) {
    constexpr uint max_msg_size = 1;
    const unsigned int num_messages = 1000000;
    if(argc < 4) {
        cout << "Insufficient number of command line arguments" << endl;
        cout << "Usage: " << argv[0] << " <num_nodes> <window_size><num_senders_selector (0 - all senders, 1 - half senders, 2 - one sender)>" << endl;
        cout << "Thank you" << endl;
        exit(1);
    }
    uint32_t num_nodes = atoi(argv[1]);
    uint32_t window_size = atoi(argv[2]);
    int num_senders_selector = atoi(argv[3]);
    const uint32_t node_id = derecho::getConfUInt32(CONF_DERECHO_LOCAL_ID);
    const std::map<uint32_t, std::pair<ip_addr_t, uint16_t>> ip_addrs_and_ports = initialize(num_nodes);

    // initialize the rdma resources
#ifdef USE_VERBS_API
    verbs_initialize(ip_addrs_and_ports, ip_addrs_and_ports, node_id);
#else
    lf_initialize(ip_addrs_and_ports, ip_addrs_and_ports, node_id);
#endif

    std::vector<uint32_t> members;
    for(const auto& p : ip_addrs_and_ports) {
        members.push_back(p.first);
    }

    uint32_t num_senders = num_nodes, row_offset = 0;
    if(num_senders_selector == 0) {
    } else if(num_senders_selector == 1) {
        num_senders = num_nodes / 2;
        row_offset = (num_nodes + 1) / 2;
    } else {
        num_senders = 1;
        row_offset = num_nodes - 1;
    }

    std::shared_ptr<multicast_sst> sst = make_shared<multicast_sst>(
            sst::SSTParams(members, node_id),
            window_size,
            num_senders, max_msg_size);

    uint32_t node_rank = sst->get_local_index();

    auto check_failures_loop = [&sst]() {
        pthread_setname_np(pthread_self(), "check_failures");
        while(true) {
            std::this_thread::sleep_for(chrono::microseconds(1000));
            if(sst) {
                sst->put_with_completion((char*)std::addressof(sst->heartbeat[0]) - sst->getBaseAddress(), sizeof(bool));
            }
        }
    };

    thread failures_thread = std::thread(check_failures_loop);

    vector<bool> completed(num_senders, false);
    uint num_finished = 0;
    auto sst_receive_handler = [&num_finished, num_senders_selector, &num_nodes, &num_messages, &completed](
                                       uint32_t sender_rank, uint64_t index,
                                       volatile char* msg, uint32_t size) {
        if(index == num_messages - 1) {
            completed[sender_rank] = true;
            num_finished++;
        }
        if(num_finished == num_nodes || (num_senders_selector == 1 && num_finished == num_nodes / 2) || (num_senders_selector == 2 && num_finished == 1)) {
            done = true;
        }
    };
    auto receiver_pred = [&](const multicast_sst& sst) {
        return true;
    };
    vector<int64_t> last_max_num_received(num_senders, -1);
    auto receiver_trig = [&completed, last_max_num_received, window_size, num_nodes, node_rank, sst_receive_handler,
                          row_offset, num_senders](multicast_sst& sst) mutable {
        while(true) {
            for(uint j = 0; j < num_senders; ++j) {
                auto num_received = sst.num_received_sst[node_rank][j] + 1;
                uint32_t slot = num_received % window_size;
                if((int64_t&)sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * (slot + 1) - sizeof(uint64_t)] == (num_received / window_size + 1)) {
                    sst_receive_handler(j, num_received,
                                        &sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * slot],
                                        sst.slots[row_offset + j][(max_msg_size + 2 * sizeof(uint64_t)) * (slot + 1) - 2 * sizeof(uint64_t)]);
                    sst.num_received_sst[node_rank][j]++;
                }
            }
            bool time_to_push = true;
            for(uint j = 0; j < num_senders; ++j) {
                if(completed[j]) {
                    continue;
                }
                if(sst.num_received_sst[node_rank][j] - last_max_num_received[j] <= window_size / 2) {
                    time_to_push = false;
                }
            }
            if(time_to_push) {
                break;
            }
        }
        sst.put(sst.num_received_sst.get_base() - sst.getBaseAddress(),
                sizeof(sst.num_received_sst[0][0]) * num_senders);
        for(uint j = 0; j < num_senders; ++j) {
            last_max_num_received[j] = sst.num_received_sst[node_rank][j];
        }
    };
    // inserting later

    vector<uint32_t> indices(num_nodes);
    iota(indices.begin(), indices.end(), 0);
    std::vector<int> is_sender(num_nodes, 1);
    if(num_senders_selector == 0) {
    } else if(num_senders_selector == 1) {
        for(uint i = 0; i <= (num_nodes - 1) / 2; ++i) {
            is_sender[i] = 0;
        }
    } else {
        for(uint i = 0; i < num_nodes - 1; ++i) {
            is_sender[i] = 0;
        }
    }
    sst::multicast_group<multicast_sst> g(sst, indices, window_size, max_msg_size, is_sender);

    DEBUG_MSG("Group created");

    // now
    sst->predicates.insert(receiver_pred, receiver_trig,
                           sst::PredicateType::RECURRENT);
    // uint count = 0;
    struct timespec start_time, end_time;
    // start timer
    clock_gettime(CLOCK_REALTIME, &start_time);
    if(node_rank == num_nodes - 1 || num_senders_selector == 0 || (node_rank > (num_nodes - 1) / 2 && num_senders_selector == 1)) {
        for(uint i = 0; i < num_messages; ++i) {
            volatile char* buf;
            while((buf = g.get_buffer(max_msg_size)) == NULL) {
                // ++count;
            }
            // for(uint i = 0; i < size; ++i) {
            //     buf[i] = 'a' + rand() % 26;
            // }
            g.send();
        }
    }
    // cout << "Done sending" << endl;
    while(!done) {
    }
    // end timer
    clock_gettime(CLOCK_REALTIME, &end_time);
    double my_time = ((end_time.tv_sec * 1e9 + end_time.tv_nsec) - (start_time.tv_sec * 1e9 + start_time.tv_nsec));
    double message_rate = (num_messages * 1e9) / my_time;
    ;
    if(num_senders_selector == 0) {
        message_rate *= num_nodes;
    } else if(num_senders_selector == 1) {
        message_rate *= num_nodes / 2;
    }

    double sum_message_rate = aggregate_bandwidth(members, node_rank, message_rate);
    log_results(exp_results{num_nodes, num_senders_selector, max_msg_size, sum_message_rate},
                "data_multicast");
    sst->sync_with_members();
}
<|endoftext|>


<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Repository handling.
  */

#include "thcrap.h"
#include "thcrap_update_wrapper.h"
#include <algorithm>

TH_CALLER_FREE char *RepoGetLocalFN(const char *id)
{
	return strdup_cat("repos/", id, "/repo.js");
}

repo_t *RepoLoadJson(json_t *repo_js)
{
	if (!json_is_object(repo_js)) {
		return nullptr;
	}
	repo_t *repo = (repo_t*)malloc(sizeof(repo_t));

	repo->id = json_object_get_string_copy(repo_js, "id");
	repo->title = json_object_get_string_copy(repo_js, "title");
	repo->contact = json_object_get_string_copy(repo_js, "contact");
	repo->servers = json_object_get_string_array_copy(repo_js, "servers");
	repo->neighbors = json_object_get_string_array_copy(repo_js, "neighbors");

	json_t *patches = json_object_get(repo_js, "patches");
	if (json_is_object(patches)) {
		if (size_t patch_count = json_object_size(patches)) {
			repo->patches = new repo_patch_t[patch_count + 1];
			repo->patches[patch_count].patch_id = NULL;

			const char* patch_id;
			json_t* patch_title;
			repo_patch_t* patch = repo->patches;
			json_object_foreach(patches, patch_id, patch_title) {
				patch->patch_id = strdup(patch_id);
				patch->title = json_string_copy(patch_title);
				++patch;
			}
		}
	}
	else {
		repo->patches = NULL;
	}

	return repo;
}

bool RepoWrite(const repo_t *repo)
{
	if (!repo || !repo->id) {
		return false;
	}

	json_t* repo_js = json_object();

	// Prepare json file
	json_object_set_new(repo_js, "id", json_string(repo->id));
	if (repo->title) {
		json_object_set_new(repo_js, "title", json_string(repo->title));
	}
	if (repo->contact) {
		json_object_set_new(repo_js, "contact", json_string(repo->contact));
	}
	if (repo->servers) {
		json_t *servers = json_array();
		for (size_t i = 0; repo->servers[i]; i++) {
			json_array_append_new(servers, json_string(repo->servers[i]));
		}
		json_object_set_new(repo_js, "servers", servers);
	}
	if (repo->neighbors) {
		json_t *neighbors = json_array();
		for (size_t i = 0; repo->neighbors[i]; i++) {
			json_array_append_new(neighbors, json_string(repo->neighbors[i]));
		}
		json_object_set_new(repo_js, "neighbors", neighbors);
	}
	if (repo->patches) {
		json_t *patches = json_object();
		for (size_t i = 0; repo->patches[i].patch_id; i++) {
			json_object_set_new(patches, repo->patches[i].patch_id, json_string(repo->patches[i].title));
		}
		json_object_set_new(repo_js, "patches", patches);
	}

	// Write json file
	char *repo_fn_local = RepoGetLocalFN(repo->id);
	auto repo_path = std::filesystem::u8path(repo_fn_local);
	auto repo_dir = repo_path;
	repo_dir.remove_filename();
	free(repo_fn_local);

	std::filesystem::create_directories(repo_dir);
	int ret = json_dump_file(repo_js, repo_path.u8string().c_str(), JSON_INDENT(4)) == 0;
	json_decref(repo_js);
	return ret;
}

void RepoFree(repo_t *repo)
{
	if (repo) {
		free(repo->id);
		free(repo->title);
		free(repo->contact);

		if (repo->servers) {
			for (size_t i = 0; repo->servers[i]; i++) {
				free(repo->servers[i]);
			}
			free(repo->servers);
		}

		if (repo->neighbors) {
			for (size_t i = 0; repo->neighbors[i]; i++) {
				free(repo->neighbors[i]);
			}
			free(repo->neighbors);
		}

		if (repo->patches) {
			for (size_t i = 0; repo->patches[i].patch_id; i++) {
				free(repo->patches[i].patch_id);
				free(repo->patches[i].title);
			}
			delete[] repo->patches;
		}

		free(repo);
	}
}

repo_t *RepoLocalNext(HANDLE *hFind)
{
	json_t *repo_js = NULL;
	WIN32_FIND_DATAA w32fd;
	BOOL find_ret = 0;
	if(*hFind == NULL) {
		// Too bad we can't do "*/repo.js" or something similar.
		*hFind = FindFirstFile("repos/*", &w32fd);
		if(*hFind == INVALID_HANDLE_VALUE) {
			return NULL;
		}
	} else {
		find_ret = W32_ERR_WRAP(FindNextFile(*hFind, &w32fd));
	}
	while(!find_ret) {
		if(
			(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			&& strcmp(w32fd.cFileName, ".")
			&& strcmp(w32fd.cFileName, "..")
		) {
			char *repo_local_fn = RepoGetLocalFN(w32fd.cFileName);
			repo_js = json_load_file_report(repo_local_fn);
			free(repo_local_fn);
			if(repo_js) {
				repo_t *repo = RepoLoadJson(repo_js);
				json_decref(repo_js);
				return repo;
			}
		}
		find_ret = W32_ERR_WRAP(FindNextFile(*hFind, &w32fd));
	};
	FindClose(*hFind);
	return NULL;
}

repo_t **RepoLoad(void)
{
	HANDLE hFind = nullptr;
	std::vector<repo_t*> repo_vector;

	while (repo_t* repo = RepoLocalNext(&hFind)) {
		repo_vector.push_back(repo);
	}
	if (repo_vector.empty()) {
		return nullptr;
	}
	std::sort(repo_vector.begin(), repo_vector.end(), [](repo_t *a, repo_t *b) {
		return strcmp(a->id, b->id) < 0;
	});

	size_t repo_count = repo_vector.size();
	repo_t **repo_array = (repo_t**)malloc(sizeof(repo_t*) * (repo_count + 1));
	repo_array[repo_count] = nullptr;
	memcpy(repo_array, repo_vector.data(), sizeof(repo_t*) * repo_count);

	return repo_array;
}
<commit_msg>thcrap: handle exception in RepoWrire<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Repository handling.
  */

#include "thcrap.h"
#include "thcrap_update_wrapper.h"
#include <algorithm>

TH_CALLER_FREE char *RepoGetLocalFN(const char *id)
{
	return strdup_cat("repos/", id, "/repo.js");
}

repo_t *RepoLoadJson(json_t *repo_js)
{
	if (!json_is_object(repo_js)) {
		return nullptr;
	}
	repo_t *repo = (repo_t*)malloc(sizeof(repo_t));

	repo->id = json_object_get_string_copy(repo_js, "id");
	repo->title = json_object_get_string_copy(repo_js, "title");
	repo->contact = json_object_get_string_copy(repo_js, "contact");
	repo->servers = json_object_get_string_array_copy(repo_js, "servers");
	repo->neighbors = json_object_get_string_array_copy(repo_js, "neighbors");

	json_t *patches = json_object_get(repo_js, "patches");
	if (json_is_object(patches)) {
		if (size_t patch_count = json_object_size(patches)) {
			repo->patches = new repo_patch_t[patch_count + 1];
			repo->patches[patch_count].patch_id = NULL;

			const char* patch_id;
			json_t* patch_title;
			repo_patch_t* patch = repo->patches;
			json_object_foreach(patches, patch_id, patch_title) {
				patch->patch_id = strdup(patch_id);
				patch->title = json_string_copy(patch_title);
				++patch;
			}
		}
	}
	else {
		repo->patches = NULL;
	}

	return repo;
}

bool RepoWrite(const repo_t *repo)
{
	if (!repo || !repo->id) {
		return false;
	}

	json_t* repo_js = json_object();

	// Prepare json file
	json_object_set_new(repo_js, "id", json_string(repo->id));
	if (repo->title) {
		json_object_set_new(repo_js, "title", json_string(repo->title));
	}
	if (repo->contact) {
		json_object_set_new(repo_js, "contact", json_string(repo->contact));
	}
	if (repo->servers) {
		json_t *servers = json_array();
		for (size_t i = 0; repo->servers[i]; i++) {
			json_array_append_new(servers, json_string(repo->servers[i]));
		}
		json_object_set_new(repo_js, "servers", servers);
	}
	if (repo->neighbors) {
		json_t *neighbors = json_array();
		for (size_t i = 0; repo->neighbors[i]; i++) {
			json_array_append_new(neighbors, json_string(repo->neighbors[i]));
		}
		json_object_set_new(repo_js, "neighbors", neighbors);
	}
	if (repo->patches) {
		json_t *patches = json_object();
		for (size_t i = 0; repo->patches[i].patch_id; i++) {
			json_object_set_new(patches, repo->patches[i].patch_id, json_string(repo->patches[i].title));
		}
		json_object_set_new(repo_js, "patches", patches);
	}

	// Write json file
	char *repo_fn_local = RepoGetLocalFN(repo->id);
	auto repo_path = std::filesystem::u8path(repo_fn_local);
	auto repo_dir = repo_path;
	repo_dir.remove_filename();
	free(repo_fn_local);

	try {
		std::filesystem::create_directories(repo_dir);
	}
	catch (std::filesystem::filesystem_error e) {
		log_printf("Failed to create repo folder %s.\nError %d: %s\n", repo_dir.u8string(), e.code().value(), e.what());
		return false;
	}
	int ret = json_dump_file(repo_js, repo_path.u8string().c_str(), JSON_INDENT(4)) == 0;
	json_decref(repo_js);
	return ret;
}

void RepoFree(repo_t *repo)
{
	if (repo) {
		free(repo->id);
		free(repo->title);
		free(repo->contact);

		if (repo->servers) {
			for (size_t i = 0; repo->servers[i]; i++) {
				free(repo->servers[i]);
			}
			free(repo->servers);
		}

		if (repo->neighbors) {
			for (size_t i = 0; repo->neighbors[i]; i++) {
				free(repo->neighbors[i]);
			}
			free(repo->neighbors);
		}

		if (repo->patches) {
			for (size_t i = 0; repo->patches[i].patch_id; i++) {
				free(repo->patches[i].patch_id);
				free(repo->patches[i].title);
			}
			delete[] repo->patches;
		}

		free(repo);
	}
}

repo_t *RepoLocalNext(HANDLE *hFind)
{
	json_t *repo_js = NULL;
	WIN32_FIND_DATAA w32fd;
	BOOL find_ret = 0;
	if(*hFind == NULL) {
		// Too bad we can't do "*/repo.js" or something similar.
		*hFind = FindFirstFile("repos/*", &w32fd);
		if(*hFind == INVALID_HANDLE_VALUE) {
			return NULL;
		}
	} else {
		find_ret = W32_ERR_WRAP(FindNextFile(*hFind, &w32fd));
	}
	while(!find_ret) {
		if(
			(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			&& strcmp(w32fd.cFileName, ".")
			&& strcmp(w32fd.cFileName, "..")
		) {
			char *repo_local_fn = RepoGetLocalFN(w32fd.cFileName);
			repo_js = json_load_file_report(repo_local_fn);
			free(repo_local_fn);
			if(repo_js) {
				repo_t *repo = RepoLoadJson(repo_js);
				json_decref(repo_js);
				return repo;
			}
		}
		find_ret = W32_ERR_WRAP(FindNextFile(*hFind, &w32fd));
	};
	FindClose(*hFind);
	return NULL;
}

repo_t **RepoLoad(void)
{
	HANDLE hFind = nullptr;
	std::vector<repo_t*> repo_vector;

	while (repo_t* repo = RepoLocalNext(&hFind)) {
		repo_vector.push_back(repo);
	}
	if (repo_vector.empty()) {
		return nullptr;
	}
	std::sort(repo_vector.begin(), repo_vector.end(), [](repo_t *a, repo_t *b) {
		return strcmp(a->id, b->id) < 0;
	});

	size_t repo_count = repo_vector.size();
	repo_t **repo_array = (repo_t**)malloc(sizeof(repo_t*) * (repo_count + 1));
	repo_array[repo_count] = nullptr;
	memcpy(repo_array, repo_vector.data(), sizeof(repo_t*) * repo_count);

	return repo_array;
}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2006 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/exceptions.h>
#include <base/memory_consumption.h>
#include <dofs/dof_objects.h>
#include <dofs/dof_handler.h>
#include <fe/fe.h>

namespace internal
{
  namespace DoFHandler
  {
    template<int dim>
    unsigned int
    DoFObjects<dim>::memory_consumption () const
    {
      return (MemoryConsumption::memory_consumption (dofs));
    }

    template <int dim>
    template <int spacedim>
    inline
    unsigned int
    DoFObjects<dim>::n_active_fe_indices (const ::DoFHandler<spacedim> &,
						    const unsigned) const
    {
      return 1;
    }

    template <int dim>
    template <int spacedim>
    inline
    bool
    DoFObjects<dim>::fe_index_is_active (const ::DoFHandler<spacedim> &,
						   const unsigned int,
						   const unsigned int fe_index) const
    {
      Assert (fe_index == 0,
              ExcMessage ("Only zero fe_index values are allowed for "
                          "non-hp DoFHandlers."));
      return true;
    }

    template <int dim>
    template <int spacedim>
    unsigned int
    DoFObjects<dim>::
    get_dof_index (const ::DoFHandler<spacedim> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const
    {
      unsigned int dofs_per_obj;
      switch (dim)
	{
	  case 1 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_line;
		break;
	  case 2 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_quad;
		break;
	  case 3 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_hex;
	}

      Assert (fe_index == ::DoFHandler<spacedim>::default_fe_index,
	      ExcMessage ("Only the default FE index is allowed for non-hp DoFHandler objects"));
      Assert (local_index<dofs_per_obj,
	      ExcIndexRange (local_index, 0, dofs_per_obj));
      Assert (obj_index * dofs_per_obj+local_index
	      <
	      dofs.size(),
	      ExcInternalError());

      return dofs[obj_index * dofs_per_obj + local_index];
    }

    template <int dim>
    template <int spacedim>
    void
    DoFObjects<dim>::
    set_dof_index (const ::DoFHandler<spacedim> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index)
    {
      unsigned int dofs_per_obj;
      switch (dim)
	{
	  case 1 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_line;
		break;
	  case 2 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_quad;
		break;
	  case 3 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_hex;
	}

      Assert (fe_index == ::DoFHandler<spacedim>::default_fe_index,
	      ExcMessage ("Only the default FE index is allowed for non-hp DoFHandler objects"));
      Assert (local_index<dofs_per_obj,
	      ExcIndexRange (local_index, 0, dof_handler.get_fe().dofs_per_line));
      Assert (obj_index * dofs_per_obj+local_index
	      <
	      dofs.size(),
	      ExcInternalError());

      dofs[obj_index * dofs_per_obj + local_index] = global_index;
    }

// explicit instantiations
    template
    unsigned int
    DoFObjects<1>::
    memory_consumption () const;

    template
    unsigned int
    DoFObjects<1>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<1>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<1>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<1>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#if deal_II_dimension >= 2

    template
    unsigned int
    DoFObjects<2>::
    memory_consumption () const;

    template
    unsigned int
    DoFObjects<2>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<2>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<2>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<2>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#endif

#if deal_II_dimension >= 3

    template
    unsigned int
    DoFObjects<3>::
    memory_consumption () const;

    template
    unsigned int
    DoFObjects<3>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<3>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<3>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<3>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#endif

  }
}
<commit_msg>Remove inlines to avoid icc8's undefined reference to DoFObjects::n_active_fe_indices. Clean up.<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2006 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/exceptions.h>
#include <base/memory_consumption.h>
#include <dofs/dof_objects.h>
#include <dofs/dof_handler.h>
#include <fe/fe.h>

namespace internal
{
  namespace DoFHandler
  {
    template<int dim>
    unsigned int
    DoFObjects<dim>::memory_consumption () const
    {
      return (MemoryConsumption::memory_consumption (dofs));
    }

    template <int dim>
    template <int spacedim>
    unsigned int
    DoFObjects<dim>::n_active_fe_indices (const ::DoFHandler<spacedim> &,
					  const unsigned) const
    {
      return 1;
    }

    template <int dim>
    template <int spacedim>
    bool
    DoFObjects<dim>::fe_index_is_active (const ::DoFHandler<spacedim> &,
					 const unsigned int,
					 const unsigned int fe_index) const
    {
      Assert (fe_index == 0,
              ExcMessage ("Only zero fe_index values are allowed for "
                          "non-hp DoFHandlers."));
      return true;
    }

    template <int dim>
    template <int spacedim>
    unsigned int
    DoFObjects<dim>::
    get_dof_index (const ::DoFHandler<spacedim> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const
    {
      unsigned int dofs_per_obj;
      switch (dim)
	{
	  case 1 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_line;
		break;
	  case 2 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_quad;
		break;
	  case 3 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_hex;
	}

      Assert (fe_index == ::DoFHandler<spacedim>::default_fe_index,
	      ExcMessage ("Only the default FE index is allowed for non-hp DoFHandler objects"));
      Assert (local_index<dofs_per_obj,
	      ExcIndexRange (local_index, 0, dofs_per_obj));
      Assert (obj_index * dofs_per_obj+local_index
	      <
	      dofs.size(),
	      ExcInternalError());

      return dofs[obj_index * dofs_per_obj + local_index];
    }

    template <int dim>
    template <int spacedim>
    void
    DoFObjects<dim>::
    set_dof_index (const ::DoFHandler<spacedim> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index)
    {
      unsigned int dofs_per_obj;
      switch (dim)
	{
	  case 1 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_line;
		break;
	  case 2 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_quad;
		break;
	  case 3 :
		dofs_per_obj = dof_handler.get_fe().dofs_per_hex;
	}

      Assert (fe_index == ::DoFHandler<spacedim>::default_fe_index,
	      ExcMessage ("Only the default FE index is allowed for non-hp DoFHandler objects"));
      Assert (local_index<dofs_per_obj,
	      ExcIndexRange (local_index, 0, dof_handler.get_fe().dofs_per_line));
      Assert (obj_index * dofs_per_obj+local_index
	      <
	      dofs.size(),
	      ExcInternalError());

      dofs[obj_index * dofs_per_obj + local_index] = global_index;
    }

// explicit instantiations

    template class DoFObjects<1>;

    template
    unsigned int
    DoFObjects<1>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<1>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<1>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<1>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#if deal_II_dimension >= 2

    template class DoFObjects<2>;

    template
    unsigned int
    DoFObjects<2>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<2>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<2>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<2>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#endif

#if deal_II_dimension >= 3

    template class DoFObjects<3>;

    template
    unsigned int
    DoFObjects<3>::
    get_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index) const;

    template
    void
    DoFObjects<3>::
    set_dof_index (const ::DoFHandler<deal_II_dimension> &dof_handler,
		   const unsigned int       obj_index,
		   const unsigned int       fe_index,
		   const unsigned int       local_index,
		   const unsigned int       global_index);

    template
    unsigned int
    DoFObjects<3>::
    n_active_fe_indices (const ::DoFHandler<deal_II_dimension> &,
			 const unsigned) const;

    template
    bool
    DoFObjects<3>::
    fe_index_is_active (const ::DoFHandler<deal_II_dimension> &,
			const unsigned int,
			const unsigned int fe_index) const;

#endif

  }
}
<|endoftext|>


<commit_before><include stdio.h>

project element static[object(slider) {
	slider.static.Movable.object(for {user::prefs} meta::element)
} if [[element.slider: IOerror(pre: set, re-set: center)].post:'./makefile'];
<commit_msg>Update file property.cpp<commit_after><include stdio.h>

project element static[object(slider) {
	slider.static.Movable.object(for {user::prefs} meta::element)
} if [[element.slider: IOerror(pre: set, re-set: center)].post:'./makefile'];
else [[ property.element(construct::meta, _init_, propert: null, event: (ev:EventArgs()))
		]]
<|endoftext|>


<commit_before>#pragma once
#ifndef SOLVER_LBFGS_ATLAS_HPP
#define SOLVER_LBFGS_ATLAS_HPP

#include <utility/Constants.hpp>
// #include <utility/Exception.hpp>
#include <engine/Backend_par.hpp>
#include <algorithm>

using namespace Utility;

template <> inline
void Method_Solver<Solver::LBFGS_Atlas>::Initialize ()
{
    this->n_lbfgs_memory = 3; // how many updates the solver tracks to estimate the hessian
    this->atlas_updates      = std::vector<field<vector2field>>( this->noi, field<vector2field>( this->n_lbfgs_memory, vector2field(this->nos, { 0,0 } ) ));
    this->grad_atlas_updates = std::vector<field<vector2field>>( this->noi, field<vector2field>( this->n_lbfgs_memory, vector2field(this->nos, { 0,0 } ) ));
    this->rho                  = scalarfield( this->n_lbfgs_memory, 0 );
    this->alpha                = scalarfield( this->n_lbfgs_memory, 0 );
    this->forces               = std::vector<vectorfield>( this->noi, vectorfield( this->nos, { 0,0,0 } ) );
    this->forces_virtual       = std::vector<vectorfield>( this->noi, vectorfield( this->nos, { 0,0,0 } ) );
    this->atlas_coords3        = std::vector<scalarfield>( this->noi, scalarfield(this->nos, 1) );
    this->atlas_directions     = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_residuals      = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_residuals_last = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_q_vec          = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->maxmove = 0.05;
    this->local_iter = 0;

    for (int img=0; img<this->noi; img++)
    {
        // Choose atlas3 coordinates
        for(int i=0; i<this->nos; i++)
        {
            this->atlas_coords3[img][i] = (*this->configurations[img])[i][2] > 0 ? 1.0 : -1.0;
            // Solver_Kernels::ncg_spins_to_atlas( *this->configurations[i], this->atlas_coords[i], this->atlas_coords3[i] );
        }
    }
}

/*
    Stereographic coordinate system implemented according to an idea of F. Rybakov
    TODO: reference painless conjugate gradients
    See also Jorge Nocedal and Stephen J. Wright 'Numerical Optimization' Second Edition, 2006 (p. 121)
*/
template <> inline
void Method_Solver<Solver::LBFGS_Atlas>::Iteration()
{
    int noi = configurations.size();
    int nos = (*configurations[0]).size();

    // Current force
    this->Calculate_Force( this->configurations, this->forces );

    for( int img=0; img<this->noi; img++ )
    {
        auto& image = *this->configurations[img];
        auto& grad_ref = this->atlas_residuals[img];

        auto fv = this->forces_virtual[img].data();
        auto f = this->forces[img].data();
        auto s = image.data();

        Backend::par::apply( this->nos, [f,fv,s] SPIRIT_LAMBDA (int idx) {
            fv[idx] = s[idx].cross(f[idx]);
        } );

        Solver_Kernels::atlas_calc_gradients(grad_ref, image, this->forces[img], this->atlas_coords3[img]);
    }

    // Calculate search direction
    Solver_Kernels::lbfgs_get_searchdir(this->local_iter,
            this->rho, this->alpha, this->atlas_q_vec,
            this->atlas_directions, this->atlas_updates,
            this->grad_atlas_updates, this->atlas_residuals, this->atlas_residuals_last,
            this->n_lbfgs_memory, maxmove);

    scalar a_norm_rms = 0;
    // Scale by averaging
    for(int img=0; img<noi; img++)
    {
        a_norm_rms = std::max(a_norm_rms, sqrt( Backend::par::reduce(this->atlas_directions[img], [] SPIRIT_LAMBDA (const Vector2 & v){ return v.squaredNorm(); }) / nos ));
    }
    scalar scaling = (a_norm_rms > maxmove) ? maxmove/a_norm_rms : 1.0;

    for(int img=0; img<noi; img++)
    {
        auto d = atlas_directions[img].data();
        Backend::par::apply(nos, [scaling, d] SPIRIT_LAMBDA (int idx){
            d[idx] *= scaling;
        });
    }

    // Rotate spins
    Solver_Kernels::atlas_rotate( this->configurations, this->atlas_coords3, this->atlas_directions );

    if(Solver_Kernels::ncg_atlas_check_coordinates(this->configurations, this->atlas_coords3, -0.6))
    {
        Solver_Kernels::lbfgs_atlas_transform_direction(this->configurations, this->atlas_coords3, this->atlas_updates, this->grad_atlas_updates, this->atlas_directions, this->atlas_residuals_last, this->rho);
    }
}

template <> inline
std::string Method_Solver<Solver::LBFGS_Atlas>::SolverName()
{
    return "LBFGS_Atlas";
}

template <> inline
std::string Method_Solver<Solver::LBFGS_Atlas>::SolverFullName()
{
    return "Limited memory Broyden-Fletcher-Goldfarb-Shanno using stereographic atlas";
}

#endif<commit_msg>Core: Fixed compilation error when using float + CPU<commit_after>#pragma once
#ifndef SOLVER_LBFGS_ATLAS_HPP
#define SOLVER_LBFGS_ATLAS_HPP

#include <utility/Constants.hpp>
// #include <utility/Exception.hpp>
#include <engine/Backend_par.hpp>
#include <algorithm>

using namespace Utility;

template <> inline
void Method_Solver<Solver::LBFGS_Atlas>::Initialize ()
{
    this->n_lbfgs_memory = 3; // how many updates the solver tracks to estimate the hessian
    this->atlas_updates      = std::vector<field<vector2field>>( this->noi, field<vector2field>( this->n_lbfgs_memory, vector2field(this->nos, { 0,0 } ) ));
    this->grad_atlas_updates = std::vector<field<vector2field>>( this->noi, field<vector2field>( this->n_lbfgs_memory, vector2field(this->nos, { 0,0 } ) ));
    this->rho                  = scalarfield( this->n_lbfgs_memory, 0 );
    this->alpha                = scalarfield( this->n_lbfgs_memory, 0 );
    this->forces               = std::vector<vectorfield>( this->noi, vectorfield( this->nos, { 0,0,0 } ) );
    this->forces_virtual       = std::vector<vectorfield>( this->noi, vectorfield( this->nos, { 0,0,0 } ) );
    this->atlas_coords3        = std::vector<scalarfield>( this->noi, scalarfield(this->nos, 1) );
    this->atlas_directions     = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_residuals      = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_residuals_last = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->atlas_q_vec          = std::vector<vector2field>( this->noi, vector2field( this->nos, { 0,0 } ) );
    this->maxmove = 0.05;
    this->local_iter = 0;

    for (int img=0; img<this->noi; img++)
    {
        // Choose atlas3 coordinates
        for(int i=0; i<this->nos; i++)
        {
            this->atlas_coords3[img][i] = (*this->configurations[img])[i][2] > 0 ? 1.0 : -1.0;
            // Solver_Kernels::ncg_spins_to_atlas( *this->configurations[i], this->atlas_coords[i], this->atlas_coords3[i] );
        }
    }
}

/*
    Stereographic coordinate system implemented according to an idea of F. Rybakov
    TODO: reference painless conjugate gradients
    See also Jorge Nocedal and Stephen J. Wright 'Numerical Optimization' Second Edition, 2006 (p. 121)
*/
template <> inline
void Method_Solver<Solver::LBFGS_Atlas>::Iteration()
{
    int noi = configurations.size();
    int nos = (*configurations[0]).size();

    // Current force
    this->Calculate_Force( this->configurations, this->forces );

    for( int img=0; img<this->noi; img++ )
    {
        auto& image = *this->configurations[img];
        auto& grad_ref = this->atlas_residuals[img];

        auto fv = this->forces_virtual[img].data();
        auto f = this->forces[img].data();
        auto s = image.data();

        Backend::par::apply( this->nos, [f,fv,s] SPIRIT_LAMBDA (int idx) {
            fv[idx] = s[idx].cross(f[idx]);
        } );

        Solver_Kernels::atlas_calc_gradients(grad_ref, image, this->forces[img], this->atlas_coords3[img]);
    }

    // Calculate search direction
    Solver_Kernels::lbfgs_get_searchdir(this->local_iter,
            this->rho, this->alpha, this->atlas_q_vec,
            this->atlas_directions, this->atlas_updates,
            this->grad_atlas_updates, this->atlas_residuals, this->atlas_residuals_last,
            this->n_lbfgs_memory, maxmove);

    scalar a_norm_rms = 0;
    // Scale by averaging
    for(int img=0; img<noi; img++)
    {
        a_norm_rms = std::max(a_norm_rms, scalar( sqrt( Backend::par::reduce(this->atlas_directions[img], [] SPIRIT_LAMBDA (const Vector2 & v){ return v.squaredNorm(); }) / nos )));
    }
    scalar scaling = (a_norm_rms > maxmove) ? maxmove/a_norm_rms : 1.0;

    for(int img=0; img<noi; img++)
    {
        auto d = atlas_directions[img].data();
        Backend::par::apply(nos, [scaling, d] SPIRIT_LAMBDA (int idx){
            d[idx] *= scaling;
        });
    }

    // Rotate spins
    Solver_Kernels::atlas_rotate( this->configurations, this->atlas_coords3, this->atlas_directions );

    if(Solver_Kernels::ncg_atlas_check_coordinates(this->configurations, this->atlas_coords3, -0.6))
    {
        Solver_Kernels::lbfgs_atlas_transform_direction(this->configurations, this->atlas_coords3, this->atlas_updates, this->grad_atlas_updates, this->atlas_directions, this->atlas_residuals_last, this->rho);
    }
}

template <> inline
std::string Method_Solver<Solver::LBFGS_Atlas>::SolverName()
{
    return "LBFGS_Atlas";
}

template <> inline
std::string Method_Solver<Solver::LBFGS_Atlas>::SolverFullName()
{
    return "Limited memory Broyden-Fletcher-Goldfarb-Shanno using stereographic atlas";
}

#endif<|endoftext|>