<commit_before>/*
 * Copyright 2013 Jeremie Roy. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/timer.h>
#include <bx/string.h>
#include <bx/math.h>

#include "font/font_manager.h"
#include "font/text_buffer_manager.h"
#include "entry/input.h"

#include <iconfontheaders/icons_font_awesome.h>
#include <iconfontheaders/icons_kenney.h>

#include <wchar.h>

#include "imgui/imgui.h"

namespace
{

TrueTypeHandle loadTtf(FontManager* _fm, const char* _filePath)
{
	uint32_t size;
	void* data = load(_filePath, &size);

	if (NULL != data)
	{
		TrueTypeHandle handle = _fm->createTtf( (uint8_t*)data, size);
		BX_FREE(entry::getAllocator(), data);
		return handle;
	}

	TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
	return invalid;
}

static const char* s_fontFilePath[] =
{
	"font/droidsans.ttf",
	"font/chp-fire.ttf",
	"font/bleeding_cowboys.ttf",
	"font/mias_scribblings.ttf",
	"font/ruritania.ttf",
	"font/signika-regular.ttf",
	"font/five_minutes.otf",
};

class ExampleFont : public entry::AppI
{
public:
	ExampleFont(const char* _name, const char* _description)
		: entry::AppI(_name, _description)
	{
	}

	void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
	{
		Args args(_argc, _argv);

		m_width  = _width;
		m_height = _height;
		m_debug  = BGFX_DEBUG_NONE;
		m_reset  = BGFX_RESET_VSYNC;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
						   , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
						   , 0x303030ff
						   , 1.0f
						   , 0
						   );

		// Init the text rendering system.
		m_fontManager = new FontManager(512);
		m_textBufferManager = new TextBufferManager(m_fontManager);

		// Load some TTF files.
		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			// Instantiate a usable font.
			m_fontFiles[ii] = loadTtf(m_fontManager, s_fontFilePath[ii]);
			m_fonts[ii] = m_fontManager->createFontByPixelSize(m_fontFiles[ii], 0, 32);

			// Preload glyphs and blit them to atlas.
			m_fontManager->preloadGlyph(m_fonts[ii], L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. \n");

			// You can unload the truetype files at this stage, but in that
			// case, the set of glyph's will be limited to the set of preloaded
			// glyph.
			m_fontManager->destroyTtf(m_fontFiles[ii]);
		}

		m_fontAwesomeTtf = loadTtf(m_fontManager, "font/fontawesome-webfont.ttf");
		m_fontKenneyTtf  = loadTtf(m_fontManager, "font/kenney-icon-font.ttf");

		// This font doesn't have any preloaded glyph's but the truetype file
		// is loaded so glyph will be generated as needed.
		m_fontAwesome72 = m_fontManager->createFontByPixelSize(m_fontAwesomeTtf, 0, 72);
		m_fontKenney64  = m_fontManager->createFontByPixelSize(m_fontKenneyTtf,  0, 64);

		m_visitorTtf = loadTtf(m_fontManager, "font/visitor1.ttf");

		// This font doesn't have any preloaded glyph's but the truetype file
		// is loaded so glyph will be generated as needed.
		m_visitor10 = m_fontManager->createFontByPixelSize(m_visitorTtf, 0, 10);

		//create a static text buffer compatible with alpha font
		//a static text buffer content cannot be modified after its first submit.
		m_staticText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Static);

		// The pen position represent the top left of the box of the first line
		// of text.
		m_textBufferManager->setPenPosition(m_staticText, 24.0f, 100.0f);

		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			// Add some text to the buffer.
			// The position of the pen is adjusted when there is an endline.
			m_textBufferManager->appendText(m_staticText, m_fonts[ii], L"The quick brown fox jumps over the lazy dog\n");
		}

		// Now write some styled text.

		// Setup style colors.
		m_textBufferManager->setBackgroundColor(m_staticText, 0x551111ff);
		m_textBufferManager->setUnderlineColor(m_staticText, 0xff2222ff);
		m_textBufferManager->setOverlineColor(m_staticText, 0x2222ffff);
		m_textBufferManager->setStrikeThroughColor(m_staticText, 0x22ff22ff);

		// Background.
		m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"The quick ");

		// Strike-through.
		m_textBufferManager->setStyle(m_staticText, STYLE_STRIKE_THROUGH);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"brown fox ");

		// Overline.
		m_textBufferManager->setStyle(m_staticText, STYLE_OVERLINE);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"jumps over ");

		// Underline.
		m_textBufferManager->setStyle(m_staticText, STYLE_UNDERLINE);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"the lazy ");

		// Background + strike-through.
		m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND | STYLE_STRIKE_THROUGH);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"dog\n");

		m_textBufferManager->setStyle(m_staticText, STYLE_NORMAL);
		m_textBufferManager->appendText(m_staticText, m_fontAwesome72,
			" " ICON_FA_POWER_OFF
			" " ICON_FA_TWITTER_SQUARE
			" " ICON_FA_CERTIFICATE
			" " ICON_FA_FLOPPY_O
			" " ICON_FA_GITHUB
			" " ICON_FA_GITHUB_ALT
			"\n"
			);
		m_textBufferManager->appendText(m_staticText, m_fontKenney64,
			" " ICON_KI_COMPUTER
			" " ICON_KI_JOYSTICK
			" " ICON_KI_EXLAMATION
			" " ICON_KI_STAR
			" " ICON_KI_BUTTON_START
			" " ICON_KI_DOWNLOAD
			"\n"
			);

		// Create a transient buffer for real-time data.
		m_transientText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Transient);

		imguiCreate();
	}

	virtual int shutdown() override
	{
		imguiDestroy();

		m_fontManager->destroyTtf(m_fontKenneyTtf);
		m_fontManager->destroyTtf(m_fontAwesomeTtf);
		m_fontManager->destroyTtf(m_visitorTtf);

		// Destroy the fonts.
		m_fontManager->destroyFont(m_fontKenney64);
		m_fontManager->destroyFont(m_fontAwesome72);
		m_fontManager->destroyFont(m_visitor10);
		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			m_fontManager->destroyFont(m_fonts[ii]);
		}

		m_textBufferManager->destroyTextBuffer(m_staticText);
		m_textBufferManager->destroyTextBuffer(m_transientText);

		delete m_textBufferManager;
		delete m_fontManager;

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() override
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);

			showExampleDialog(this);

			imguiEndFrame();

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(bx::getHPFrequency() );
			const double toMs = 1000.0 / freq;

			// Use transient text to display debug information.
			wchar_t fpsText[64];
			bx::swnprintf(fpsText, BX_COUNTOF(fpsText), L"Frame: % 7.3f[ms]", double(frameTime) * toMs);

			m_textBufferManager->clearTextBuffer(m_transientText);
			m_textBufferManager->setPenPosition(m_transientText, m_width - 150.0f, 10.0f);
			m_textBufferManager->appendText(m_transientText, m_visitor10, L"Transient\n");
			m_textBufferManager->appendText(m_transientText, m_visitor10, L"text buffer\n");
			m_textBufferManager->appendText(m_transientText, m_visitor10, fpsText);

			float at[3]  = { 0, 0,  0.0f };
			float eye[3] = { 0, 0, -1.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const float centering = 0.5f;

			// Setup a top-left ortho matrix for screen space drawing.
			const bgfx::HMD*  hmd  = bgfx::getHMD();
			const bgfx::Caps* caps = bgfx::getCaps();
			if (NULL != hmd
			&&  0 != (hmd->flags & BGFX_HMD_RENDERING) )
			{
				float proj[16];
				bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f, caps->homogeneousDepth);

				static float time = 0.0f;
				time += 0.05f;

				const float dist = 10.0f;
				const float offset0 = -proj[8] + (hmd->eye[0].viewOffset[0] / dist * proj[0]);
				const float offset1 = -proj[8] + (hmd->eye[1].viewOffset[0] / dist * proj[0]);

				float ortho[2][16];
				const float offsetx = m_width/2.0f;
				bx::mtxOrtho(
					  ortho[0]
					, centering
					, offsetx  + centering
					, m_height + centering
					, centering
					, -1.0f
					, 1.0f
					, offset0
					, caps->homogeneousDepth
					);
				bx::mtxOrtho(
					  ortho[1]
					, centering
					, offsetx  + centering
					, m_height + centering
					, centering
					, -1.0f
					, 1.0f
					, offset1
					, caps->homogeneousDepth
					);
				bgfx::setViewTransform(0, view, ortho[0], BGFX_VIEW_STEREO, ortho[1]);
				bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);
			}
			else
			{
				float ortho[16];
				bx::mtxOrtho(
					  ortho
					, centering
					, m_width  + centering
					, m_height + centering
					, centering
					, 0.0f
					, 100.0f
					, 0.0f
					, caps->homogeneousDepth
					);
				bgfx::setViewTransform(0, view, ortho);
				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
			}

			// Submit the debug text.
			m_textBufferManager->submitTextBuffer(m_transientText, 0);

			// Submit the static text.
			m_textBufferManager->submitTextBuffer(m_staticText, 0);

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	FontManager* m_fontManager;
	TextBufferManager* m_textBufferManager;

	FontHandle m_visitor10;
	TrueTypeHandle m_fontAwesomeTtf;
	TrueTypeHandle m_fontKenneyTtf;
	FontHandle m_fontAwesome72;
	FontHandle m_fontKenney64;
	TrueTypeHandle m_visitorTtf;

	TextBufferHandle m_transientText;
	TextBufferHandle m_staticText;

	static const uint32_t numFonts = BX_COUNTOF(s_fontFilePath);

	TrueTypeHandle m_fontFiles[numFonts];
	FontHandle m_fonts[numFonts];
};

} // namespace

ENTRY_IMPLEMENT_MAIN(ExampleFont, "10-font", "Use the font system to display text and styled text.");
<commit_msg>Removed use of wchar_t.<commit_after>/*
 * Copyright 2013 Jeremie Roy. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/timer.h>
#include <bx/string.h>
#include <bx/math.h>

#include "font/font_manager.h"
#include "font/text_buffer_manager.h"
#include "entry/input.h"

#include <iconfontheaders/icons_font_awesome.h>
#include <iconfontheaders/icons_kenney.h>

#include <wchar.h>

#include "imgui/imgui.h"

namespace
{

TrueTypeHandle loadTtf(FontManager* _fm, const char* _filePath)
{
	uint32_t size;
	void* data = load(_filePath, &size);

	if (NULL != data)
	{
		TrueTypeHandle handle = _fm->createTtf( (uint8_t*)data, size);
		BX_FREE(entry::getAllocator(), data);
		return handle;
	}

	TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
	return invalid;
}

static const char* s_fontFilePath[] =
{
	"font/droidsans.ttf",
	"font/chp-fire.ttf",
	"font/bleeding_cowboys.ttf",
	"font/mias_scribblings.ttf",
	"font/ruritania.ttf",
	"font/signika-regular.ttf",
	"font/five_minutes.otf",
};

class ExampleFont : public entry::AppI
{
public:
	ExampleFont(const char* _name, const char* _description)
		: entry::AppI(_name, _description)
	{
	}

	void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
	{
		Args args(_argc, _argv);

		m_width  = _width;
		m_height = _height;
		m_debug  = BGFX_DEBUG_NONE;
		m_reset  = BGFX_RESET_VSYNC;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
						   , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
						   , 0x303030ff
						   , 1.0f
						   , 0
						   );

		// Init the text rendering system.
		m_fontManager = new FontManager(512);
		m_textBufferManager = new TextBufferManager(m_fontManager);

		// Load some TTF files.
		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			// Instantiate a usable font.
			m_fontFiles[ii] = loadTtf(m_fontManager, s_fontFilePath[ii]);
			m_fonts[ii] = m_fontManager->createFontByPixelSize(m_fontFiles[ii], 0, 32);

			// Preload glyphs and blit them to atlas.
			m_fontManager->preloadGlyph(m_fonts[ii], L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. \n");

			// You can unload the truetype files at this stage, but in that
			// case, the set of glyph's will be limited to the set of preloaded
			// glyph.
			m_fontManager->destroyTtf(m_fontFiles[ii]);
		}

		m_fontAwesomeTtf = loadTtf(m_fontManager, "font/fontawesome-webfont.ttf");
		m_fontKenneyTtf  = loadTtf(m_fontManager, "font/kenney-icon-font.ttf");

		// This font doesn't have any preloaded glyph's but the truetype file
		// is loaded so glyph will be generated as needed.
		m_fontAwesome72 = m_fontManager->createFontByPixelSize(m_fontAwesomeTtf, 0, 72);
		m_fontKenney64  = m_fontManager->createFontByPixelSize(m_fontKenneyTtf,  0, 64);

		m_visitorTtf = loadTtf(m_fontManager, "font/visitor1.ttf");

		// This font doesn't have any preloaded glyph's but the truetype file
		// is loaded so glyph will be generated as needed.
		m_visitor10 = m_fontManager->createFontByPixelSize(m_visitorTtf, 0, 10);

		//create a static text buffer compatible with alpha font
		//a static text buffer content cannot be modified after its first submit.
		m_staticText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Static);

		// The pen position represent the top left of the box of the first line
		// of text.
		m_textBufferManager->setPenPosition(m_staticText, 24.0f, 100.0f);

		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			// Add some text to the buffer.
			// The position of the pen is adjusted when there is an endline.
			m_textBufferManager->appendText(m_staticText, m_fonts[ii], L"The quick brown fox jumps over the lazy dog\n");
		}

		// Now write some styled text.

		// Setup style colors.
		m_textBufferManager->setBackgroundColor(m_staticText, 0x551111ff);
		m_textBufferManager->setUnderlineColor(m_staticText, 0xff2222ff);
		m_textBufferManager->setOverlineColor(m_staticText, 0x2222ffff);
		m_textBufferManager->setStrikeThroughColor(m_staticText, 0x22ff22ff);

		// Background.
		m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"The quick ");

		// Strike-through.
		m_textBufferManager->setStyle(m_staticText, STYLE_STRIKE_THROUGH);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"brown fox ");

		// Overline.
		m_textBufferManager->setStyle(m_staticText, STYLE_OVERLINE);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"jumps over ");

		// Underline.
		m_textBufferManager->setStyle(m_staticText, STYLE_UNDERLINE);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"the lazy ");

		// Background + strike-through.
		m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND | STYLE_STRIKE_THROUGH);
		m_textBufferManager->appendText(m_staticText, m_fonts[0], L"dog\n");

		m_textBufferManager->setStyle(m_staticText, STYLE_NORMAL);
		m_textBufferManager->appendText(m_staticText, m_fontAwesome72,
			" " ICON_FA_POWER_OFF
			" " ICON_FA_TWITTER_SQUARE
			" " ICON_FA_CERTIFICATE
			" " ICON_FA_FLOPPY_O
			" " ICON_FA_GITHUB
			" " ICON_FA_GITHUB_ALT
			"\n"
			);
		m_textBufferManager->appendText(m_staticText, m_fontKenney64,
			" " ICON_KI_COMPUTER
			" " ICON_KI_JOYSTICK
			" " ICON_KI_EXLAMATION
			" " ICON_KI_STAR
			" " ICON_KI_BUTTON_START
			" " ICON_KI_DOWNLOAD
			"\n"
			);

		// Create a transient buffer for real-time data.
		m_transientText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Transient);

		imguiCreate();
	}

	virtual int shutdown() override
	{
		imguiDestroy();

		m_fontManager->destroyTtf(m_fontKenneyTtf);
		m_fontManager->destroyTtf(m_fontAwesomeTtf);
		m_fontManager->destroyTtf(m_visitorTtf);

		// Destroy the fonts.
		m_fontManager->destroyFont(m_fontKenney64);
		m_fontManager->destroyFont(m_fontAwesome72);
		m_fontManager->destroyFont(m_visitor10);
		for (uint32_t ii = 0; ii < numFonts; ++ii)
		{
			m_fontManager->destroyFont(m_fonts[ii]);
		}

		m_textBufferManager->destroyTextBuffer(m_staticText);
		m_textBufferManager->destroyTextBuffer(m_transientText);

		delete m_textBufferManager;
		delete m_fontManager;

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() override
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);

			showExampleDialog(this);

			imguiEndFrame();

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(bx::getHPFrequency() );
			const double toMs = 1000.0 / freq;

			// Use transient text to display debug information.
			char fpsText[64];
			bx::snprintf(fpsText, BX_COUNTOF(fpsText), "Frame: % 7.3f[ms]", double(frameTime) * toMs);

			m_textBufferManager->clearTextBuffer(m_transientText);
			m_textBufferManager->setPenPosition(m_transientText, m_width - 150.0f, 10.0f);
			m_textBufferManager->appendText(m_transientText, m_visitor10, "Transient\n");
			m_textBufferManager->appendText(m_transientText, m_visitor10, "text buffer\n");
			m_textBufferManager->appendText(m_transientText, m_visitor10, fpsText);

			float at[3]  = { 0, 0,  0.0f };
			float eye[3] = { 0, 0, -1.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const float centering = 0.5f;

			// Setup a top-left ortho matrix for screen space drawing.
			const bgfx::HMD*  hmd  = bgfx::getHMD();
			const bgfx::Caps* caps = bgfx::getCaps();
			if (NULL != hmd
			&&  0 != (hmd->flags & BGFX_HMD_RENDERING) )
			{
				float proj[16];
				bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f, caps->homogeneousDepth);

				static float time = 0.0f;
				time += 0.05f;

				const float dist = 10.0f;
				const float offset0 = -proj[8] + (hmd->eye[0].viewOffset[0] / dist * proj[0]);
				const float offset1 = -proj[8] + (hmd->eye[1].viewOffset[0] / dist * proj[0]);

				float ortho[2][16];
				const float offsetx = m_width/2.0f;
				bx::mtxOrtho(
					  ortho[0]
					, centering
					, offsetx  + centering
					, m_height + centering
					, centering
					, -1.0f
					, 1.0f
					, offset0
					, caps->homogeneousDepth
					);
				bx::mtxOrtho(
					  ortho[1]
					, centering
					, offsetx  + centering
					, m_height + centering
					, centering
					, -1.0f
					, 1.0f
					, offset1
					, caps->homogeneousDepth
					);
				bgfx::setViewTransform(0, view, ortho[0], BGFX_VIEW_STEREO, ortho[1]);
				bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);
			}
			else
			{
				float ortho[16];
				bx::mtxOrtho(
					  ortho
					, centering
					, m_width  + centering
					, m_height + centering
					, centering
					, 0.0f
					, 100.0f
					, 0.0f
					, caps->homogeneousDepth
					);
				bgfx::setViewTransform(0, view, ortho);
				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
			}

			// Submit the debug text.
			m_textBufferManager->submitTextBuffer(m_transientText, 0);

			// Submit the static text.
			m_textBufferManager->submitTextBuffer(m_staticText, 0);

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	FontManager* m_fontManager;
	TextBufferManager* m_textBufferManager;

	FontHandle m_visitor10;
	TrueTypeHandle m_fontAwesomeTtf;
	TrueTypeHandle m_fontKenneyTtf;
	FontHandle m_fontAwesome72;
	FontHandle m_fontKenney64;
	TrueTypeHandle m_visitorTtf;

	TextBufferHandle m_transientText;
	TextBufferHandle m_staticText;

	static const uint32_t numFonts = BX_COUNTOF(s_fontFilePath);

	TrueTypeHandle m_fontFiles[numFonts];
	FontHandle m_fonts[numFonts];
};

} // namespace

ENTRY_IMPLEMENT_MAIN(ExampleFont, "10-font", "Use the font system to display text and styled text.");
<|endoftext|>


<commit_before>#include <tiramisu/tiramisu.h>
#include "configure.h"

using namespace tiramisu;

expr mixf(expr x, expr y, expr a)
{
    return x * (1 - a) + y * a;
}

int main()
{
    init("resize_conv_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var o_x("o_x", 0, IMG_WIDTH), o_y("o_y", 0, IMG_HEIGHT), fin("fin", 0, FIn), n("n", 0, BATCH_SIZE);
    var x("x", 0, N), y("y", 0, N);

    var x_pad("x_pad", 0, N + 2), y_pad("y_pad", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y), fout("fout", 0, FOut);

    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, o_y, o_x, fin}, p_float32);
    input conv_filter("conv_filter", {fout_b, k_y, k_x, fin, ffout}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Resize computation
    computation init_resized_input("init_resized_input", {n, y_pad, x_pad, fin}, 0.f);

    expr o_r((cast(p_float32, y) + 0.5f) * (cast(p_float32, IMG_HEIGHT) / cast(p_float32, N)) - 0.5f);
    expr o_c((cast(p_float32, x) + 0.5f) * (cast(p_float32, IMG_WIDTH) / cast(p_float32, N)) - 0.5f);

    expr r_coeff(expr(o_r) - expr(o_floor, o_r));
    expr c_coeff(expr(o_c) - expr(o_floor, o_c));

    expr A00_r(cast(p_int32, expr(o_floor, o_r)));
    expr A00_c(cast(p_int32, expr(o_floor, o_c)));

    computation resize(
        "resize",
        {n, y, x, fin},
        mixf(
            mixf(
                c_input(n, A00_r, A00_c, fin),
                c_input(n, A00_r + 1, A00_c, fin),
                r_coeff
            ),

            mixf(
                c_input(n, A00_r, A00_c + 1, fin),
                c_input(n, A00_r + 1, A00_c + 1, fin),
                r_coeff
            ),

            c_coeff
        )
    );

    view input_resized("input_resized", {n, y_pad, x_pad, fin}, p_float32);

    // Convolution computation
    computation init_output("init_output", {n, fout_b, y, x, ffout}, conv_bias(fout_b, ffout));
    computation conv(
        "conv",
        {n, fout_b, y, x, k_y, k_x, fin, ffout},
        init_output(n, fout_b, y, x, ffout) + input_resized(n, y + k_y, x + k_x, fin)*conv_filter(fout_b, k_y, k_x, fin, ffout)
    );

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    init_resized_input.then(resize, n)
                      .then(init_output, n)
                      .then(conv, x);

    resize.tag_unroll_level(fin);
    resize.vectorize(x, 8);

    conv.tag_unroll_level(fin);
    conv.vectorize(ffout, FOUT_BLOCKING);

    conv.tag_parallel_level(n);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer input_resized_buf("input_resized_buf", {BATCH_SIZE, N + 2, N + 2, FIn}, p_float32, a_temporary);
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    init_resized_input.store_in(&input_resized_buf);
    resize.store_in(&input_resized_buf, {n, y + 1, x + 1, fin});
    input_resized.store_in(&input_resized_buf);

    init_output.store_in(&output_buf);
    conv.store_in(&output_buf, {n, fout_b, y, x, ffout});

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &output_buf
    }, "resize_conv_tiramisu.o");

    return 0;
}
<commit_msg>Resize-Conv : small edit to Tiramisu version<commit_after>#include <tiramisu/tiramisu.h>
#include "configure.h"

using namespace tiramisu;

expr mixf(expr x, expr y, expr a)
{
    return x + (y - x) * a;
}

int main()
{
    init("resize_conv_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var o_x("o_x", 0, IMG_WIDTH), o_y("o_y", 0, IMG_HEIGHT), fin("fin", 0, FIn), n("n", 0, BATCH_SIZE);
    var x("x", 0, N), y("y", 0, N);

    var x_pad("x_pad", 0, N + 2), y_pad("y_pad", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y), fout("fout", 0, FOut);

    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, o_y, o_x, fin}, p_float32);
    input conv_filter("conv_filter", {fout_b, k_y, k_x, fin, ffout}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Resize computation
    computation init_resized_input("init_resized_input", {n, y_pad, x_pad, fin}, 0.f);

    expr o_r((cast(p_float32, y) + 0.5f) * (cast(p_float32, IMG_HEIGHT) / cast(p_float32, N)) - 0.5f);
    expr o_c((cast(p_float32, x) + 0.5f) * (cast(p_float32, IMG_WIDTH) / cast(p_float32, N)) - 0.5f);

    expr r_coeff(expr(o_r) - expr(o_floor, o_r));
    expr c_coeff(expr(o_c) - expr(o_floor, o_c));

    expr A00_r(cast(p_int32, expr(o_floor, o_r)));
    expr A00_c(cast(p_int32, expr(o_floor, o_c)));

    computation resize(
        "resize",
        {n, y, x, fin},
        mixf(
            mixf(
                c_input(n, A00_r, A00_c, fin),
                c_input(n, A00_r + 1, A00_c, fin),
                r_coeff
            ),

            mixf(
                c_input(n, A00_r, A00_c + 1, fin),
                c_input(n, A00_r + 1, A00_c + 1, fin),
                r_coeff
            ),

            c_coeff
        )
    );

    view input_resized("input_resized", {n, y_pad, x_pad, fin}, p_float32);

    // Convolution computation
    computation init_output("init_output", {n, fout_b, y, x, ffout}, conv_bias(fout_b, ffout));
    computation conv(
        "conv",
        {n, fout_b, y, x, k_y, k_x, fin, ffout},
        init_output(n, fout_b, y, x, ffout) + input_resized(n, y + k_y, x + k_x, fin)*conv_filter(fout_b, k_y, k_x, fin, ffout)
    );

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    init_resized_input.then(resize, n)
                      .then(init_output, n)
                      .then(conv, x);

    resize.tag_unroll_level(fin);
    resize.vectorize(x, 8);

    conv.tag_unroll_level(fin);
    conv.vectorize(ffout, FOUT_BLOCKING);

    conv.tag_parallel_level(n);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer input_resized_buf("input_resized_buf", {BATCH_SIZE, N + 2, N + 2, FIn}, p_float32, a_temporary);
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    init_resized_input.store_in(&input_resized_buf);
    resize.store_in(&input_resized_buf, {n, y + 1, x + 1, fin});
    input_resized.store_in(&input_resized_buf);

    init_output.store_in(&output_buf);
    conv.store_in(&output_buf, {n, fout_b, y, x, ffout});

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &output_buf
    }, "resize_conv_tiramisu.o");

    return 0;
}
<|endoftext|>


<commit_before>///
/// @file  primecount.cpp
/// @brief Function definitions of primecount.hpp
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <calculator.hpp>
#include <int128_t.hpp>
#include <imath.hpp>

#include <algorithm>
#include <chrono>
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include <stdint.h>

#ifdef _OPENMP
  #include <omp.h>
#endif

#ifdef HAVE_MPI

#include <mpi.h>

namespace primecount {

int mpi_num_procs()
{
  int procs;
  MPI_Comm_size(MPI_COMM_WORLD, &procs);
  return procs;
}

int mpi_proc_id()
{
  int proc_id;
  MPI_Comm_rank(MPI_COMM_WORLD, &proc_id);
  return proc_id;
}

int mpi_master_proc_id()
{
  return 0;
}

bool is_mpi_master_proc()
{
  return mpi_proc_id() == mpi_master_proc_id();
}

} // namespace

#endif

using namespace std;

namespace {

#ifdef _OPENMP
  int threads_ = 0;
#endif

// Below 10^7 LMO is faster than Deleglise-Rivat
const int lmo_threshold_ = 10000000;

int status_precision_ = -1;

// Tuning factor used in the Lagarias-Miller-Odlyzko
// and Deleglise-Rivat algorithms.
double alpha_ = -1;

// Tuning factor used in Xavier Gourdon's algorithm
double alpha_y_ = -1;

// Tuning factor used in Xavier Gourdon's algorithm
double alpha_z_ = -1;

}

namespace primecount {

int64_t pi(int64_t x)
{
  return pi(x, get_num_threads());
}

int64_t pi(int64_t x, int threads)
{
  if (x <= lmo_threshold_)
    return pi_lmo5(x);
  else
    return pi_deleglise_rivat(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi(int128_t x)
{
  return pi(x, get_num_threads());
}

int128_t pi(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi((int64_t) x, threads);
  else
    return pi_deleglise_rivat(x, threads);
}

#endif

string pi(const string& x)
{
  return pi(x, get_num_threads());
}

string pi(const string& x, int threads)
{
  maxint_t pi_x = pi(to_maxint(x), threads);
  ostringstream oss;
  oss << pi_x;
  return oss.str();
}

int64_t pi_legendre(int64_t x)
{
  return pi_legendre(x, get_num_threads());
}

int64_t pi_lehmer(int64_t x)
{
  return pi_lehmer(x, get_num_threads());
}

int64_t pi_lmo(int64_t x)
{
  return pi_lmo(x, get_num_threads());
}

int64_t pi_lmo(int64_t x, int threads)
{
  return pi_lmo_parallel(x, threads);
}

int64_t pi_meissel(int64_t x)
{
  return pi_meissel(x, get_num_threads());
}

int64_t pi_deleglise_rivat(int64_t x)
{
  return pi_deleglise_rivat(x, get_num_threads());
}

int64_t pi_deleglise_rivat(int64_t x, int threads)
{
  return pi_deleglise_rivat_parallel1(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x)
{
  return pi_deleglise_rivat(x, get_num_threads());
}

int128_t pi_deleglise_rivat(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi_deleglise_rivat_parallel1((int64_t) x, threads);
  else
    return pi_deleglise_rivat_parallel2(x, threads);
}

#endif

int64_t nth_prime(int64_t n)
{
  return nth_prime(n, get_num_threads());
}

int64_t phi(int64_t x, int64_t a)
{
  return phi(x, a, get_num_threads());
}

/// Returns the largest integer supported by pi(x). The
/// return type is a string as get_max_x() can be a 128-bit
/// integer which is not supported by all compilers.
///
string get_max_x(double alpha)
{
  ostringstream oss;

#ifdef HAVE_INT128_T
  // primecount is limited by:
  // z <= 2^62, with z = x^(2/3) / alpha
  // x^(2/3) / alpha <= 2^62
  // x <= (2^62 * alpha)^(3/2)
  //
  double max_x = pow(pow(2.0, 62.0) * alpha, 3.0 / 2.0);
  oss << (int128_t) max_x;
#else
  unused_param(alpha);
  oss << numeric_limits<int64_t>::max();
#endif

  return oss.str();
}

/// Get the time in seconds
double get_time()
{
  auto now = chrono::steady_clock::now();
  auto time = now.time_since_epoch();
  auto micro = chrono::duration_cast<chrono::microseconds>(time);
  return (double) micro.count() / 1e6;
}

int ideal_num_threads(int threads, int64_t sieve_limit, int64_t thread_threshold)
{
  thread_threshold = max((int64_t) 1, thread_threshold);
  threads = (int) min((int64_t) threads, sieve_limit / thread_threshold);
  threads = max(1, threads);
  return threads;
}

void set_alpha(double alpha)
{
  alpha_ = alpha;
}

void set_alpha_y(double alpha_y)
{
  alpha_y_ = alpha_y;
}

void set_alpha_z(double alpha_z)
{
  alpha_z_ = alpha_z;
}

/// Tuning factor used in the Lagarias-Miller-Odlyzko
/// and Deleglise-Rivat algorithms.
///
double get_alpha(maxint_t x, int64_t y)
{
  // y = x13 * alpha, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Tuning factor used in Xavier Gourdon's algorithm.
double get_alpha_y(maxint_t x, int64_t y)
{
  // y = x13 * alpha_y, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Tuning factor used in Xavier Gourdon's algorithm.
double get_alpha_z(int64_t y, int64_t z)
{
  // z = y * alpha_z, thus alpha_z = z / y
  return (double) z / y;
}

/// Get the Lagarias-Miller-Odlyzko alpha tuning factor.
/// alpha = a log(x)^2 + b log(x) + c
/// a, b and c have been determined empirically.
/// @see doc/alpha-factor-tuning.pdf
///
double get_alpha_lmo(maxint_t x)
{
  double alpha = alpha_;

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    double a = 0.00156512;
    double b = -0.0261411;
    double c = 0.990948;
    double logx = log((double) x);

    alpha = a * pow(logx, 2) + b * logx + c;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// Get the Deleglise-Rivat alpha tuning factor.
/// alpha = a log(x)^3 + b log(x)^2 + c log(x) + d
/// a, b, c and d have been determined empirically.
/// @see doc/alpha-tuning-factor.pdf
///
double get_alpha_deleglise_rivat(maxint_t x)
{
  double alpha = alpha_;
  double x2 = (double) x;

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    double a = 0.00033826;
    double b = 0.0018113;
    double c = -0.110407;
    double d = 1.3724;
    double logx = log(x2);

    alpha = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// y = x^(1/3) * alpha_y, with alpha_y >= 1.
/// alpha_y is a tuning factor which should be determined
/// experimentally by running benchmarks.
///
/// Note that in Xavier Gourdon's paper alpha_y is named c
/// but we name it alpha_y since y = x^(1/3) * alpha_y
/// and the tuning factor in Tomás Oliveira e Silva's paper
/// is also named alpha.
///
double get_alpha_y_gourdon(maxint_t x)
{
  double alpha_y = alpha_y_;
  double x2 = (double) x;

  // use default alpha if no command-line alpha provided
  if (alpha_y < 1)
  {
    double a = 0.000451957;
    double b = -0.0128774;
    double c = 0.0999006;
    double d = 0.860792;
    double logx = log(x2);

    alpha_y = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
  }

  return in_between(1, alpha_y, iroot<6>(x));
}

/// z = y * alpha_z, with alpha_z >= 1.
/// In Xavier Gourdon's paper the alpha_z tuning factor
/// is named d. alpha_z should be determined experimentally
/// by running benchmarks.
///
double get_alpha_z_gourdon(maxint_t x)
{
  double alpha_y = get_alpha_y_gourdon(x);
  double alpha_z = alpha_z_;

  if (alpha_z < 1)
  {
    // Xavier Gourdon's fastpix11.exe binary uses d = 2.4 but
    // according to my benchmarks alpha_z should grow very slowly
    // and be much smaller than alpha_y.
    double log_alpha_y = log(max(1.0, alpha_y));
    double loglog_alpha_y = log(max(1.0, log_alpha_y));
    alpha_z = 1 + loglog_alpha_y;
  }

  double x16 = (double) iroot<6>(x);
  double max_alpha = min(alpha_y * alpha_z, x16);
  return in_between(1, alpha_z, max_alpha);
}

/// x_star = max(x^(1/4), x / y^2)
///
/// After my implementation of Xavier Gourdon's algorithm worked for
/// the first time there were still many miscalculations mainly for
/// small numbers < 10^6. By debugging I found that most errors were
/// related to the Sigma formulas (Σ0 - Σ6) and the x_star variable
/// was responsible for most errors. For some unknown reason the
/// bounds from Xavier's paper (max(x^(1/4), x / y^2)) don't seem to
/// be enough. By trial and error I figured out a few more bounds that
/// fix all miscalculations in my implementation.
///
int64_t get_x_star_gourdon(maxint_t x, int64_t y)
{
  // For some unknown reason it is necessary
  // to round up (x / y^2). Without rounding up
  // there are many miscalculations below 2000
  // in my implementation.
  y = max(y, (int64_t) 1);
  maxint_t yy = (maxint_t) y * y;
  maxint_t x_div_yy = ceil_div(x, yy);

  int64_t x_star = (int64_t) max(iroot<4>(x), x_div_yy);
  int64_t sqrt_xy = (int64_t) isqrt(x / y);

  // x_star <= y
  // x_star <= (x / y)^(1/2)
  // The bounds above are missing in Xavier Gourdon's
  // paper. Without these bounds many of the 7 Sigma
  // formulas (Σ0 - Σ6) return incorrect results for
  // numbers below 10^6.
  x_star = min(x_star, y);
  x_star = min(x_star, sqrt_xy);
  x_star = max(x_star, (int64_t) 1);

  return x_star;
}

void set_num_threads(int threads)
{
#ifdef _OPENMP
  threads_ = in_between(1, threads, omp_get_max_threads());
#endif
  primesieve::set_num_threads(threads);
}

int get_num_threads()
{
#ifdef _OPENMP
  if (threads_)
    return threads_;
  else
    return max(1, omp_get_max_threads());
#else
  return 1;
#endif
}

void set_status_precision(int precision)
{
  status_precision_ = in_between(0, precision, 5);
}

int get_status_precision(maxint_t x)
{
  // use default precision when no command-line precision provided
  if (status_precision_ < 0)
  {
    if ((double) x >= 1e23)
      return 2;
    if ((double) x >= 1e21)
      return 1;
  }

  return max(status_precision_, 0);
}

maxint_t to_maxint(const string& expr)
{
  maxint_t n = calculator::eval<maxint_t>(expr);
  return n;
}

string primecount_version()
{
  return PRIMECOUNT_VERSION;
}

} // namespace
<commit_msg>Tune alpha_y factor<commit_after>///
/// @file  primecount.cpp
/// @brief Function definitions of primecount.hpp
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <calculator.hpp>
#include <int128_t.hpp>
#include <imath.hpp>

#include <algorithm>
#include <chrono>
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include <stdint.h>

#ifdef _OPENMP
  #include <omp.h>
#endif

#ifdef HAVE_MPI

#include <mpi.h>

namespace primecount {

int mpi_num_procs()
{
  int procs;
  MPI_Comm_size(MPI_COMM_WORLD, &procs);
  return procs;
}

int mpi_proc_id()
{
  int proc_id;
  MPI_Comm_rank(MPI_COMM_WORLD, &proc_id);
  return proc_id;
}

int mpi_master_proc_id()
{
  return 0;
}

bool is_mpi_master_proc()
{
  return mpi_proc_id() == mpi_master_proc_id();
}

} // namespace

#endif

using namespace std;

namespace {

#ifdef _OPENMP
  int threads_ = 0;
#endif

// Below 10^7 LMO is faster than Deleglise-Rivat
const int lmo_threshold_ = 10000000;

int status_precision_ = -1;

// Tuning factor used in the Lagarias-Miller-Odlyzko
// and Deleglise-Rivat algorithms.
double alpha_ = -1;

// Tuning factor used in Xavier Gourdon's algorithm
double alpha_y_ = -1;

// Tuning factor used in Xavier Gourdon's algorithm
double alpha_z_ = -1;

}

namespace primecount {

int64_t pi(int64_t x)
{
  return pi(x, get_num_threads());
}

int64_t pi(int64_t x, int threads)
{
  if (x <= lmo_threshold_)
    return pi_lmo5(x);
  else
    return pi_deleglise_rivat(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi(int128_t x)
{
  return pi(x, get_num_threads());
}

int128_t pi(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi((int64_t) x, threads);
  else
    return pi_deleglise_rivat(x, threads);
}

#endif

string pi(const string& x)
{
  return pi(x, get_num_threads());
}

string pi(const string& x, int threads)
{
  maxint_t pi_x = pi(to_maxint(x), threads);
  ostringstream oss;
  oss << pi_x;
  return oss.str();
}

int64_t pi_legendre(int64_t x)
{
  return pi_legendre(x, get_num_threads());
}

int64_t pi_lehmer(int64_t x)
{
  return pi_lehmer(x, get_num_threads());
}

int64_t pi_lmo(int64_t x)
{
  return pi_lmo(x, get_num_threads());
}

int64_t pi_lmo(int64_t x, int threads)
{
  return pi_lmo_parallel(x, threads);
}

int64_t pi_meissel(int64_t x)
{
  return pi_meissel(x, get_num_threads());
}

int64_t pi_deleglise_rivat(int64_t x)
{
  return pi_deleglise_rivat(x, get_num_threads());
}

int64_t pi_deleglise_rivat(int64_t x, int threads)
{
  return pi_deleglise_rivat_parallel1(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x)
{
  return pi_deleglise_rivat(x, get_num_threads());
}

int128_t pi_deleglise_rivat(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi_deleglise_rivat_parallel1((int64_t) x, threads);
  else
    return pi_deleglise_rivat_parallel2(x, threads);
}

#endif

int64_t nth_prime(int64_t n)
{
  return nth_prime(n, get_num_threads());
}

int64_t phi(int64_t x, int64_t a)
{
  return phi(x, a, get_num_threads());
}

/// Returns the largest integer supported by pi(x). The
/// return type is a string as get_max_x() can be a 128-bit
/// integer which is not supported by all compilers.
///
string get_max_x(double alpha)
{
  ostringstream oss;

#ifdef HAVE_INT128_T
  // primecount is limited by:
  // z <= 2^62, with z = x^(2/3) / alpha
  // x^(2/3) / alpha <= 2^62
  // x <= (2^62 * alpha)^(3/2)
  //
  double max_x = pow(pow(2.0, 62.0) * alpha, 3.0 / 2.0);
  oss << (int128_t) max_x;
#else
  unused_param(alpha);
  oss << numeric_limits<int64_t>::max();
#endif

  return oss.str();
}

/// Get the time in seconds
double get_time()
{
  auto now = chrono::steady_clock::now();
  auto time = now.time_since_epoch();
  auto micro = chrono::duration_cast<chrono::microseconds>(time);
  return (double) micro.count() / 1e6;
}

int ideal_num_threads(int threads, int64_t sieve_limit, int64_t thread_threshold)
{
  thread_threshold = max((int64_t) 1, thread_threshold);
  threads = (int) min((int64_t) threads, sieve_limit / thread_threshold);
  threads = max(1, threads);
  return threads;
}

void set_alpha(double alpha)
{
  alpha_ = alpha;
}

void set_alpha_y(double alpha_y)
{
  alpha_y_ = alpha_y;
}

void set_alpha_z(double alpha_z)
{
  alpha_z_ = alpha_z;
}

/// Tuning factor used in the Lagarias-Miller-Odlyzko
/// and Deleglise-Rivat algorithms.
///
double get_alpha(maxint_t x, int64_t y)
{
  // y = x13 * alpha, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Tuning factor used in Xavier Gourdon's algorithm.
double get_alpha_y(maxint_t x, int64_t y)
{
  // y = x13 * alpha_y, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Tuning factor used in Xavier Gourdon's algorithm.
double get_alpha_z(int64_t y, int64_t z)
{
  // z = y * alpha_z, thus alpha_z = z / y
  return (double) z / y;
}

/// Get the Lagarias-Miller-Odlyzko alpha tuning factor.
/// alpha = a log(x)^2 + b log(x) + c
/// a, b and c have been determined empirically.
/// @see doc/alpha-factor-tuning.pdf
///
double get_alpha_lmo(maxint_t x)
{
  double alpha = alpha_;

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    double a = 0.00156512;
    double b = -0.0261411;
    double c = 0.990948;
    double logx = log((double) x);

    alpha = a * pow(logx, 2) + b * logx + c;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// Get the Deleglise-Rivat alpha tuning factor.
/// alpha = a log(x)^3 + b log(x)^2 + c log(x) + d
/// a, b, c and d have been determined empirically.
/// @see doc/alpha-tuning-factor.pdf
///
double get_alpha_deleglise_rivat(maxint_t x)
{
  double alpha = alpha_;
  double x2 = (double) x;

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    double a = 0.00033826;
    double b = 0.0018113;
    double c = -0.110407;
    double d = 1.3724;
    double logx = log(x2);

    alpha = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// y = x^(1/3) * alpha_y, with alpha_y >= 1.
/// alpha_y is a tuning factor which should be determined
/// experimentally by running benchmarks.
///
/// Note that in Xavier Gourdon's paper alpha_y is named c
/// but we name it alpha_y since y = x^(1/3) * alpha_y
/// and the tuning factor in Tomás Oliveira e Silva's paper
/// is also named alpha.
///
double get_alpha_y_gourdon(maxint_t x)
{
  double alpha_y = alpha_y_;
  double x2 = (double) x;

  // use default alpha if no command-line alpha provided
  if (alpha_y < 1)
  {
    double a = 0.000446563;
    double b = -0.0125132;
    double c = 0.094232;
    double d = 0.875222;
    double logx = log(x2);

    alpha_y = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
  }

  return in_between(1, alpha_y, iroot<6>(x));
}

/// z = y * alpha_z, with alpha_z >= 1.
/// In Xavier Gourdon's paper the alpha_z tuning factor
/// is named d. alpha_z should be determined experimentally
/// by running benchmarks.
///
double get_alpha_z_gourdon(maxint_t x)
{
  double alpha_y = get_alpha_y_gourdon(x);
  double alpha_z = alpha_z_;

  if (alpha_z < 1)
  {
    // Xavier Gourdon's fastpix11.exe binary uses d = 2.4 but
    // according to my benchmarks alpha_z should grow very slowly
    // and be much smaller than alpha_y.
    double log_alpha_y = log(max(1.0, alpha_y));
    double loglog_alpha_y = log(max(1.0, log_alpha_y));
    alpha_z = 1 + loglog_alpha_y;
  }

  double x16 = (double) iroot<6>(x);
  double max_alpha = min(alpha_y * alpha_z, x16);
  return in_between(1, alpha_z, max_alpha);
}

/// x_star = max(x^(1/4), x / y^2)
///
/// After my implementation of Xavier Gourdon's algorithm worked for
/// the first time there were still many miscalculations mainly for
/// small numbers < 10^6. By debugging I found that most errors were
/// related to the Sigma formulas (Σ0 - Σ6) and the x_star variable
/// was responsible for most errors. For some unknown reason the
/// bounds from Xavier's paper (max(x^(1/4), x / y^2)) don't seem to
/// be enough. By trial and error I figured out a few more bounds that
/// fix all miscalculations in my implementation.
///
int64_t get_x_star_gourdon(maxint_t x, int64_t y)
{
  // For some unknown reason it is necessary
  // to round up (x / y^2). Without rounding up
  // there are many miscalculations below 2000
  // in my implementation.
  y = max(y, (int64_t) 1);
  maxint_t yy = (maxint_t) y * y;
  maxint_t x_div_yy = ceil_div(x, yy);

  int64_t x_star = (int64_t) max(iroot<4>(x), x_div_yy);
  int64_t sqrt_xy = (int64_t) isqrt(x / y);

  // x_star <= y
  // x_star <= (x / y)^(1/2)
  // The bounds above are missing in Xavier Gourdon's
  // paper. Without these bounds many of the 7 Sigma
  // formulas (Σ0 - Σ6) return incorrect results for
  // numbers below 10^6.
  x_star = min(x_star, y);
  x_star = min(x_star, sqrt_xy);
  x_star = max(x_star, (int64_t) 1);

  return x_star;
}

void set_num_threads(int threads)
{
#ifdef _OPENMP
  threads_ = in_between(1, threads, omp_get_max_threads());
#endif
  primesieve::set_num_threads(threads);
}

int get_num_threads()
{
#ifdef _OPENMP
  if (threads_)
    return threads_;
  else
    return max(1, omp_get_max_threads());
#else
  return 1;
#endif
}

void set_status_precision(int precision)
{
  status_precision_ = in_between(0, precision, 5);
}

int get_status_precision(maxint_t x)
{
  // use default precision when no command-line precision provided
  if (status_precision_ < 0)
  {
    if ((double) x >= 1e23)
      return 2;
    if ((double) x >= 1e21)
      return 1;
  }

  return max(status_precision_, 0);
}

maxint_t to_maxint(const string& expr)
{
  maxint_t n = calculator::eval<maxint_t>(expr);
  return n;
}

string primecount_version()
{
  return PRIMECOUNT_VERSION;
}

} // namespace
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserview.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 11:56:48 $
 *
 *  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 _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif
#ifndef _TOOLS_RESID_HXX
#include <tools/resid.hxx>
#endif
// #95343# --------------------
#ifndef _COM_SUN_STAR_AWT_SIZE_HPP_
#include <com/sun/star/awt/Size.hpp>
#endif

//............................................................................
namespace pcr
{
//............................................................................

    class OPropertyEditor;

    //========================================================================
    //=
    //========================================================================
    class OPropertyBrowserView : public Window
    {
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >    m_xORB;

        OPropertyEditor*        m_pPropBox;
        sal_uInt16              m_nActivePage;
        Link                    m_aPageActivationHandler;

    protected:
        virtual void Resize();
        virtual void GetFocus();

    public:
        OPropertyBrowserView(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&    _xORB,
                        Window* pParent, WinBits nBits = 0);

        virtual ~OPropertyBrowserView();

        OPropertyEditor&    getPropertyBox() { return *m_pPropBox; }

        // page handling
        sal_uInt16  getActivaPage() const { return m_nActivePage; }
        void        activatePage(sal_uInt16 _nPage);

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }

        // #95343# ------------------
        ::com::sun::star::awt::Size getMinimumSize();

    protected:
        DECL_LINK(OnPageActivation, void*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_

<commit_msg>INTEGRATION: CWS dba22b (1.9.176); FILE MERGED 2006/12/18 11:07:27 fs 1.9.176.2: RESYNC: (1.9-1.10); FILE MERGED 2006/12/06 09:46:29 fs 1.9.176.1: #i63285# don't let DEL/BACKSPACE keys leave the property browser<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserview.hxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: vg $ $Date: 2007-01-15 14:40:35 $
 *
 *  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 _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif
#ifndef _TOOLS_RESID_HXX
#include <tools/resid.hxx>
#endif
// #95343# --------------------
#ifndef _COM_SUN_STAR_AWT_SIZE_HPP_
#include <com/sun/star/awt/Size.hpp>
#endif

//............................................................................
namespace pcr
{
//............................................................................

    class OPropertyEditor;

    //========================================================================
    //=
    //========================================================================
    class OPropertyBrowserView : public Window
    {
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >    m_xORB;

        OPropertyEditor*        m_pPropBox;
        sal_uInt16              m_nActivePage;
        Link                    m_aPageActivationHandler;

    protected:
        virtual void Resize();
        virtual void GetFocus();
        virtual long Notify( NotifyEvent& _rNEvt );

    public:
        OPropertyBrowserView(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&    _xORB,
                        Window* pParent, WinBits nBits = 0);

        virtual ~OPropertyBrowserView();

        OPropertyEditor&    getPropertyBox() { return *m_pPropBox; }

        // page handling
        sal_uInt16  getActivaPage() const { return m_nActivePage; }
        void        activatePage(sal_uInt16 _nPage);

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }

        // #95343# ------------------
        ::com::sun::star::awt::Size getMinimumSize();

    protected:
        DECL_LINK(OnPageActivation, void*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_

<|endoftext|>


<commit_before>//
// Created by haohanwang on 2/2/16.
//

#include <limits>
#include <stdexcept>

#ifdef BAZEL
#include "Models/MultiPopLasso.hpp"
#else
#include "MultiPopLasso.hpp"
#endif

using namespace std;
using namespace Eigen;

void MultiPopLasso::setXY(MatrixXd m, MatrixXd n) {
    X = m;
    y = n;
}

void MultiPopLasso::initBeta() {
    cout << "Multipop lasso does not suppor init beta explicitly here, beta will be initialized when formating data" << endl;
}

void MultiPopLasso::setLambda(double l) { lambda = l; }

void MultiPopLasso::setPopulation(VectorXd pop) {
    // population indicator must start from 0
    population = pop;
    popNum = (long)population.maxCoeff() + 1;
}

double MultiPopLasso::cost() {
    initTraining();
    return 0.5 * (y - X * beta).squaredNorm() + lambda * groupPenalization();
}

double MultiPopLasso::groupPenalization() {
    double r = 0;
    MatrixXd tmp = getBetaInside();
    for (long i = 0; i < tmp.rows(); i++) {
        r += tmp.row(i).squaredNorm();
    }
    return r;
}

void MultiPopLasso::assertReadyToRun() {
    // X and Y must be compatible
    if (!((X.rows() > 0) && (X.rows() == y.rows())
        && (X.cols() > 0) && (y.cols() > 0))) {
        throw runtime_error("X and Y matrices of size (" + to_string(X.rows()) + "," + to_string(X.cols()) + "), and (" +
            to_string(y.rows()) + "," + to_string(y.cols()) + ") are not compatible.");
    }
    // Population Labels must have n rows (one for each sample)
    if (population.rows() != X.rows()) {
        throw runtime_error("Population labels of length " + to_string(population.rows()) +
            " are the wrong size for X with " + to_string(X.rows()) + " samples.");
    }
    cerr << "assertReadyToRun passed" << endl;
}

void MultiPopLasso::setAttributeMatrix(const string& str, MatrixXd* Z) {
    if (str == "population") {
        cerr << "setting population" << endl;
        // todo: stop copying data
        setPopulation(VectorXd(Map<VectorXd>(Z->data(), Z->rows())));
    } else if (str == "X") {
        setX(*Z);
    } else if (str == "Y") {
        setY(*Z);
    } else {
        throw runtime_error("MultiPopLasso models have no attribute with name" + str);
    }
}

void MultiPopLasso::initTraining() {
    if (!initTrainingFlag){
        initTrainingFlag = true;
        reArrangeData();
        formatData();
        initC();
    }
}

void MultiPopLasso::reArrangeData() {
    // arrange data according to its population
    long r = X.rows();
    long c = X.cols();
    MatrixXd tmpX = MatrixXd::Zero(r, c);
    MatrixXd tmpY = MatrixXd::Zero(r, 1);
    VectorXd tmpPop = VectorXd::Zero(r);
    vector<long> idx;
    long count = 0;
    for (long i=0; i<popNum; i++){
        idx = getPopulationIndex(i);
        for (unsigned long j=0; j<idx.size(); j++){
            tmpX.row(count) = X.row(idx.at(j));
            tmpY.row(count) = y.row(idx.at(j));
            tmpPop(count++) = i;
        }
    }
    X = tmpX;
    y = tmpY;
    population = tmpPop;
}

void MultiPopLasso::removeColumns() {
    long c = X.cols();
    removeCols = VectorXi::Zero(c);
    for (long i = 0; i < c; i++) {
        double var = Math::getInstance().variance(X.col(i));
        if (var < 1e-3) {
            removeCols(i) = 1;
        }
    }
    long r = X.rows();
    long b = r / popNum;
    MatrixXd tmp;
    double cor;
    double std;
    for (long i = 0; i < r; i += b) {
        tmp = X.block(i, 0, b, c);
        for (long j = 0; j < c; j++) {
            if (removeCols(j) == 0) {
                for (long k = j + 1; k < c; k++) {
                    if (removeCols(k) == 0) {
                        cor = Math::getInstance().correlation(tmp.col(j), tmp.col(k));
                        if (cor > 0.98) {
                            removeCols(k) = 1;
                        }
                    }
                }
                std = Math::getInstance().std(tmp.col(j));
                if (std < 1e-9) {
                    removeCols(j) = 1;
                }
            }
        }
    }
}

MatrixXd MultiPopLasso::normalizeData_col(MatrixXd a) {
    long c = a.cols();
    VectorXd mean = a.colwise().mean();
    VectorXd std_inv = VectorXd::Zero(c);
    for (long i = 0; i < c; i++) {
        std_inv(i) = 1.0 / Math::getInstance().std(a.col(i));
    }
    return ((a.colwise() - mean).array().colwise() * std_inv.array()).matrix();
}

void MultiPopLasso::formatData() {
    // format data, put data into X matrix and init beta

    // todo: here we don't remove columns, may add it later
//    for (long i = removeCols.size() - 1; i >= 0; i--) {
//        if (removeCols(i) == 1) {
//            Math::getInstance().removeCol(&X, i);
//        }
//    }
    long c = X.cols();
    long r = X.rows();
    MatrixXd tmpX = MatrixXd::Zero(r, c * popNum);
    double pIdx = 0;
    for (long i=0;i<r;i++){
        pIdx = population(i);
        for (long j=0;j<c;j++){
            tmpX(i, j*popNum+pIdx) = X(i, j);
        }
    }
    X = tmpX;
    beta = MatrixXd::Random(c * popNum, 1);
    L = ((X.transpose()*X).eigenvalues()).real().maxCoeff();
}

void MultiPopLasso::initC() {
    long c = X.cols();
    C = MatrixXd::Zero(c * popNum, c);
    for (long i = 0; i < c; i++) {
        for (long j = 0; j < popNum; j++) {
            C(i*j+j, i) = gamma;
        }
    }
}

MatrixXd MultiPopLasso::proximal_derivative() {
    long r = beta.rows();
    long c = beta.cols();
    MatrixXd A = MatrixXd::Zero(r*popNum, c);
    MatrixXd tmp = C*beta;
    for (long i=0;i<r*popNum;i++){
        A.row(i) = Math::getInstance().L2Thresholding(tmp.row(i)/mu);
    }
    return X.transpose()*(X*beta-y) + C.transpose()*A;
}

MatrixXd MultiPopLasso::proximal_operator(MatrixXd in, float lr) {
    MatrixXd sign = ((in.array()>0).matrix()).cast<double>();
    sign += -1.0*((in.array()<0).matrix()).cast<double>();
    in = ((in.array().abs()-lr*lambda).max(0)).matrix();
    return (in.array()*sign.array()).matrix();
}

//MatrixXd MultiPopLasso::deriveMatrixA(double lr, long loops, double tol) {
//    long r = beta.rows();
//    long c = C.rows();
//    MatrixXd A = MatrixXd::Zero(r, c);
//    MatrixXd bct = beta*C.transpose();
//    double prev_residue = numeric_limits<double>::max();
//    double curr_residue;
//    for (long i=0;i<loops;i++){
//        A = A - lr*(bct - A);
//        A = project(A);
//        curr_residue = (bct*A).trace() - 0.5*A.norm();
//        if (prev_residue - curr_residue<= tol){
//            break;
//        }
//        else{
//            prev_residue = curr_residue;
//        }
//    }
//    return A;
//}
//
//MatrixXd MultiPopLasso::project(MatrixXd A) {
//    if (A.norm() <= 1){
//        return A;
//    }
//    else{
//        return A;
//    }
//}
//
double MultiPopLasso::getL(){
    double c = C.norm()/mu;
    return c + L;
}

vector<long> MultiPopLasso::getPopulationIndex(long pi) {
    vector<long> idx;
    for (long i=0;i<y.rows();i++){
        if (population(i) == pi){
            idx.push_back(i);
        }
    }
    return idx;
}

MatrixXd MultiPopLasso::getBetaInside() {
    long c = X.cols()/popNum;
    MatrixXd r = MatrixXd::Zero(popNum, c);
    for (long i=0;i<popNum;i++){
        for (long j=0;j<c;j++){
            r(i, j) = beta(j*popNum+i,i/popNum);
        }
    }
    return r;
}

MatrixXd MultiPopLasso::getBeta() {
    long c = X.cols()/popNum;
    MatrixXd r = MatrixXd::Zero(popNum*betaAll.cols(), c);
    for (long k=0;k<betaAll.cols();k++){
        for (long i=0;i<popNum;i++){
            for (long j=0;j<c;j++){
                r(i+k*popNum, j) = betaAll(j*popNum+i,k);
            }
        }
    }
    return r.transpose()*100;
}

void MultiPopLasso::setMu(double m) {
    mu = m;
}

void MultiPopLasso::setGamma(double g) {
    gamma = g;
}

MatrixXd MultiPopLasso::getFormattedBeta() {
    return beta;
}

MatrixXd MultiPopLasso::predict() {
    cout << "does not allow prediction with original X, please use predict(X, population) method instead"<<endl;
    return MatrixXd::Random(1,1);
}

MatrixXd MultiPopLasso::predict(MatrixXd x) {
    cout << "does not allow prediction without population information"<<endl;
    return MatrixXd::Random(1,1);
}

MatrixXd MultiPopLasso::predict(MatrixXd x, VectorXd pop){
    long r= x.rows();
    MatrixXd y(r, 1);
    MatrixXd b = getBeta();
    for (long i=0;i<r;i++){
        y.row(i) = x.row(i)*(b.row(long(pop(i))).transpose());
    }
    return y;
}

MultiPopLasso::MultiPopLasso() {
    initTrainingFlag = false;
    lambda = default_lambda;
    mu = default_mu;
    gamma = default_gamma;
    betaAll = MatrixXd::Ones(1,1);
}

MultiPopLasso::MultiPopLasso(const unordered_map<string, string> &options) {
    initTrainingFlag = false;
    try {
        lambda = stod(options.at("lambda"));
    } catch (std::out_of_range& oor) {
        lambda = default_lambda;
    }
    try {
        mu = stod(options.at("mu"));
    } catch (std::out_of_range& oor) {
        mu = default_mu;
    }
    try {
        gamma = stod(options.at("gamma"));
    } catch (std::out_of_range& oor) {
        gamma = default_gamma;
    }
    betaAll = MatrixXd::Ones(1,1);
}

void MultiPopLasso::updateBetaAll() {
    if (betaAll.rows() == 1){
        betaAll = beta;
    }
    else{
        betaAll.conservativeResize(betaAll.rows(),betaAll.cols()+1);
        betaAll.col(betaAll.cols()-1) = beta;
    }
}

MatrixXd MultiPopLasso::getBetaAll() {
    return betaAll;
}

void MultiPopLasso::reSetFlag() {
    initTrainingFlag = false;
}
<commit_msg>fix prediction for tests<commit_after>//
// Created by haohanwang on 2/2/16.
//

#include <limits>
#include <stdexcept>

#ifdef BAZEL
#include "Models/MultiPopLasso.hpp"
#else
#include "MultiPopLasso.hpp"
#endif

using namespace std;
using namespace Eigen;

void MultiPopLasso::setXY(MatrixXd m, MatrixXd n) {
    X = m;
    y = n;
}

void MultiPopLasso::initBeta() {
    cout << "Multipop lasso does not suppor init beta explicitly here, beta will be initialized when formating data" << endl;
}

void MultiPopLasso::setLambda(double l) { lambda = l; }

void MultiPopLasso::setPopulation(VectorXd pop) {
    // population indicator must start from 0
    population = pop;
    popNum = (long)population.maxCoeff() + 1;
}

double MultiPopLasso::cost() {
    initTraining();
    return 0.5 * (y - X * beta).squaredNorm() + lambda * groupPenalization();
}

double MultiPopLasso::groupPenalization() {
    double r = 0;
    MatrixXd tmp = getBetaInside();
    for (long i = 0; i < tmp.rows(); i++) {
        r += tmp.row(i).squaredNorm();
    }
    return r;
}

void MultiPopLasso::assertReadyToRun() {
    // X and Y must be compatible
    if (!((X.rows() > 0) && (X.rows() == y.rows())
        && (X.cols() > 0) && (y.cols() > 0))) {
        throw runtime_error("X and Y matrices of size (" + to_string(X.rows()) + "," + to_string(X.cols()) + "), and (" +
            to_string(y.rows()) + "," + to_string(y.cols()) + ") are not compatible.");
    }
    // Population Labels must have n rows (one for each sample)
    if (population.rows() != X.rows()) {
        throw runtime_error("Population labels of length " + to_string(population.rows()) +
            " are the wrong size for X with " + to_string(X.rows()) + " samples.");
    }
    cerr << "assertReadyToRun passed" << endl;
}

void MultiPopLasso::setAttributeMatrix(const string& str, MatrixXd* Z) {
    if (str == "population") {
        cerr << "setting population" << endl;
        // todo: stop copying data
        setPopulation(VectorXd(Map<VectorXd>(Z->data(), Z->rows())));
    } else if (str == "X") {
        setX(*Z);
    } else if (str == "Y") {
        setY(*Z);
    } else {
        throw runtime_error("MultiPopLasso models have no attribute with name" + str);
    }
}

void MultiPopLasso::initTraining() {
    if (!initTrainingFlag){
        initTrainingFlag = true;
        reArrangeData();
        formatData();
        initC();
    }
}

void MultiPopLasso::reArrangeData() {
    // arrange data according to its population
    long r = X.rows();
    long c = X.cols();
    MatrixXd tmpX = MatrixXd::Zero(r, c);
    MatrixXd tmpY = MatrixXd::Zero(r, 1);
    VectorXd tmpPop = VectorXd::Zero(r);
    vector<long> idx;
    long count = 0;
    for (long i=0; i<popNum; i++){
        idx = getPopulationIndex(i);
        for (unsigned long j=0; j<idx.size(); j++){
            tmpX.row(count) = X.row(idx.at(j));
            tmpY.row(count) = y.row(idx.at(j));
            tmpPop(count++) = i;
        }
    }
    X = tmpX;
    y = tmpY;
    population = tmpPop;
}

void MultiPopLasso::removeColumns() {
    long c = X.cols();
    removeCols = VectorXi::Zero(c);
    for (long i = 0; i < c; i++) {
        double var = Math::getInstance().variance(X.col(i));
        if (var < 1e-3) {
            removeCols(i) = 1;
        }
    }
    long r = X.rows();
    long b = r / popNum;
    MatrixXd tmp;
    double cor;
    double std;
    for (long i = 0; i < r; i += b) {
        tmp = X.block(i, 0, b, c);
        for (long j = 0; j < c; j++) {
            if (removeCols(j) == 0) {
                for (long k = j + 1; k < c; k++) {
                    if (removeCols(k) == 0) {
                        cor = Math::getInstance().correlation(tmp.col(j), tmp.col(k));
                        if (cor > 0.98) {
                            removeCols(k) = 1;
                        }
                    }
                }
                std = Math::getInstance().std(tmp.col(j));
                if (std < 1e-9) {
                    removeCols(j) = 1;
                }
            }
        }
    }
}

MatrixXd MultiPopLasso::normalizeData_col(MatrixXd a) {
    long c = a.cols();
    VectorXd mean = a.colwise().mean();
    VectorXd std_inv = VectorXd::Zero(c);
    for (long i = 0; i < c; i++) {
        std_inv(i) = 1.0 / Math::getInstance().std(a.col(i));
    }
    return ((a.colwise() - mean).array().colwise() * std_inv.array()).matrix();
}

void MultiPopLasso::formatData() {
    // format data, put data into X matrix and init beta

    // todo: here we don't remove columns, may add it later
//    for (long i = removeCols.size() - 1; i >= 0; i--) {
//        if (removeCols(i) == 1) {
//            Math::getInstance().removeCol(&X, i);
//        }
//    }
    long c = X.cols();
    long r = X.rows();
    MatrixXd tmpX = MatrixXd::Zero(r, c * popNum);
    double pIdx = 0;
    for (long i=0;i<r;i++){
        pIdx = population(i);
        for (long j=0;j<c;j++){
            tmpX(i, j*popNum+pIdx) = X(i, j);
        }
    }
    X = tmpX;
    beta = MatrixXd::Random(c * popNum, 1);
    L = ((X.transpose()*X).eigenvalues()).real().maxCoeff();
}

void MultiPopLasso::initC() {
    long c = X.cols();
    C = MatrixXd::Zero(c * popNum, c);
    for (long i = 0; i < c; i++) {
        for (long j = 0; j < popNum; j++) {
            C(i*j+j, i) = gamma;
        }
    }
}

MatrixXd MultiPopLasso::proximal_derivative() {
    long r = beta.rows();
    long c = beta.cols();
    MatrixXd A = MatrixXd::Zero(r*popNum, c);
    MatrixXd tmp = C*beta;
    for (long i=0;i<r*popNum;i++){
        A.row(i) = Math::getInstance().L2Thresholding(tmp.row(i)/mu);
    }
    return X.transpose()*(X*beta-y) + C.transpose()*A;
}

MatrixXd MultiPopLasso::proximal_operator(MatrixXd in, float lr) {
    MatrixXd sign = ((in.array()>0).matrix()).cast<double>();
    sign += -1.0*((in.array()<0).matrix()).cast<double>();
    in = ((in.array().abs()-lr*lambda).max(0)).matrix();
    return (in.array()*sign.array()).matrix();
}

//MatrixXd MultiPopLasso::deriveMatrixA(double lr, long loops, double tol) {
//    long r = beta.rows();
//    long c = C.rows();
//    MatrixXd A = MatrixXd::Zero(r, c);
//    MatrixXd bct = beta*C.transpose();
//    double prev_residue = numeric_limits<double>::max();
//    double curr_residue;
//    for (long i=0;i<loops;i++){
//        A = A - lr*(bct - A);
//        A = project(A);
//        curr_residue = (bct*A).trace() - 0.5*A.norm();
//        if (prev_residue - curr_residue<= tol){
//            break;
//        }
//        else{
//            prev_residue = curr_residue;
//        }
//    }
//    return A;
//}
//
//MatrixXd MultiPopLasso::project(MatrixXd A) {
//    if (A.norm() <= 1){
//        return A;
//    }
//    else{
//        return A;
//    }
//}
//
double MultiPopLasso::getL(){
    double c = C.norm()/mu;
    return c + L;
}

vector<long> MultiPopLasso::getPopulationIndex(long pi) {
    vector<long> idx;
    for (long i=0;i<y.rows();i++){
        if (population(i) == pi){
            idx.push_back(i);
        }
    }
    return idx;
}

MatrixXd MultiPopLasso::getBetaInside() {
    long c = X.cols()/popNum;
    MatrixXd r = MatrixXd::Zero(popNum, c);
    for (long i=0;i<popNum;i++){
        for (long j=0;j<c;j++){
            r(i, j) = beta(j*popNum+i,i/popNum);
        }
    }
    return r;
}

MatrixXd MultiPopLasso::getBeta() {
    long c = X.cols()/popNum;
    MatrixXd r = MatrixXd::Zero(popNum*betaAll.cols(), c);
    for (long k=0;k<betaAll.cols();k++){
        for (long i=0;i<popNum;i++){
            for (long j=0;j<c;j++){
                r(i+k*popNum, j) = betaAll(j*popNum+i,k);
            }
        }
    }
    return r.transpose()*100;
}

void MultiPopLasso::setMu(double m) {
    mu = m;
}

void MultiPopLasso::setGamma(double g) {
    gamma = g;
}

MatrixXd MultiPopLasso::getFormattedBeta() {
    return beta;
}

MatrixXd MultiPopLasso::predict() {
    cout << "does not allow prediction with original X, please use predict(X, population) method instead"<<endl;
    return MatrixXd::Random(1,1);
}

MatrixXd MultiPopLasso::predict(MatrixXd x) {
    cout << "does not allow prediction without population information"<<endl;
    return MatrixXd::Random(1,1);
}

MatrixXd MultiPopLasso::predict(MatrixXd x, VectorXd pop){
    long r= x.rows();
    MatrixXd y(r, 1);
    MatrixXd b = getBetaInside();
    for (long i=0;i<r;i++){
        y.row(i) = x.row(i)*(b.row(long(pop(i))).transpose());
    }
    return y;
}

MultiPopLasso::MultiPopLasso() {
    initTrainingFlag = false;
    lambda = default_lambda;
    mu = default_mu;
    gamma = default_gamma;
    betaAll = MatrixXd::Ones(1,1);
}

MultiPopLasso::MultiPopLasso(const unordered_map<string, string> &options) {
    initTrainingFlag = false;
    try {
        lambda = stod(options.at("lambda"));
    } catch (std::out_of_range& oor) {
        lambda = default_lambda;
    }
    try {
        mu = stod(options.at("mu"));
    } catch (std::out_of_range& oor) {
        mu = default_mu;
    }
    try {
        gamma = stod(options.at("gamma"));
    } catch (std::out_of_range& oor) {
        gamma = default_gamma;
    }
    betaAll = MatrixXd::Ones(1,1);
}

void MultiPopLasso::updateBetaAll() {
    if (betaAll.rows() == 1){
        betaAll = beta;
    }
    else{
        betaAll.conservativeResize(betaAll.rows(),betaAll.cols()+1);
        betaAll.col(betaAll.cols()-1) = beta;
    }
}

MatrixXd MultiPopLasso::getBetaAll() {
    return betaAll;
}

void MultiPopLasso::reSetFlag() {
    initTrainingFlag = false;
}
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/EngineLog.hpp>
# include <Siv3D/Keyboard.hpp>
# include <Siv3D/Window/IWindow.hpp>
# include <Siv3D/Common/Siv3DEngine.hpp>
# include "CTextInput.hpp"

extern "C"
{
	using namespace s3d;

	CTextInput* pTextInput = nullptr;

	XIMCallback preeditStart;
	XIMCallback preeditDraw;
	XIMCallback preeditDone;
	XIMCallback preeditCaret;

	void preeditStartCallback(XIC, XPointer, XPointer)
	{
		// do nothing
	}

	void preeditDoneCallback(XIC, XPointer, XPointer)
	{
		// do nothing
	}

	void preeditDrawCallback(XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *call_data)
	{
		pTextInput->preeditDrawCallback(ic, client_data, call_data);
	}

	void preeditCaretCallback(XIC, XPointer, XIMPreeditCaretCallbackStruct *)
	{
		// do nothing
	}

	XVaNestedList s3d_PreeditAttributes(XPointer client_data)
	{
		preeditStart.client_data = client_data;
		preeditStart.callback = (XIMProc)preeditStartCallback;
		preeditDone.client_data = client_data;
		preeditDone.callback = (XIMProc)preeditDoneCallback;
		preeditDraw.client_data = client_data;
		preeditDraw.callback = (XIMProc)preeditDrawCallback;
		preeditCaret.client_data = client_data;
		preeditCaret.callback = (XIMProc)preeditCaretCallback;

		return XVaCreateNestedList(0,
								   XNPreeditStartCallback, &preeditStart.client_data,
								   XNPreeditDoneCallback, &preeditDone.client_data,
								   XNPreeditDrawCallback, &preeditDraw.client_data,
								   XNPreeditCaretCallback, &preeditCaret.client_data,
								   NULL);
	}

	void s3d_InputText(char *text)
	{
		pTextInput->sendInputText(Unicode::FromUTF8(text));
	}

	void s3d_SetICFocus(XIC)
	{
		pTextInput->updateWindowFocus(true);
	}

	void s3d_UnsetICFocus(XIC)
	{
		pTextInput->updateWindowFocus(false);
	}

	XIC s3d_GetXICFromGLFWWindow(GLFWwindow *window);
}

namespace s3d
{
	CTextInput::CTextInput()
	{
		pTextInput = this;
	}

	CTextInput::~CTextInput()
	{
		LOG_SCOPED_TRACE(U"CTextInput::~CTextInput()");

		pTextInput = nullptr;
	}

	void CTextInput::init()
	{
		LOG_SCOPED_TRACE(U"CTextInput::init()");

		if (GLFWwindow* glfwWindow = static_cast<GLFWwindow*>(SIV3D_ENGINE(Window)->getHandle()))
		{
			::glfwSetCharCallback(glfwWindow, OnCharacterInput);
		}
	}

	void CTextInput::update()
	{
		{
			std::lock_guard lock{ m_mutex };

			m_chars = m_internalChars;

			m_internalChars.clear();
		}

		{
			std::lock_guard lock{ m_mutexPreeditStatus };

			m_preeditText = m_internalPreeditText;

			m_preeditTextStyle = m_internalPreeditTextStyle;

			m_preeditCaret = m_internalPreeditCaret;
		}
	}

	void CTextInput::pushChar(const uint32 ch)
	{
		std::lock_guard lock{ m_mutex };

		m_internalChars.push_back(static_cast<char32>(ch));
	}

	const String& CTextInput::getChars() const
	{
		return m_chars;
	}

	const String& CTextInput::getEditingText() const
	{
		return m_preeditText;
	}

	void CTextInput::enableIME(bool enabled)
	{
		m_imeEnabled = enabled;
		updateICFocus();
	}

	std::pair<int32, int32> CTextInput::getCursorIndex() const
	{
		return{ m_preeditCaret, 0};
	}

	const Array<String>& CTextInput::getCandidates() const
	{
		static const Array<String> dummy;
		return dummy;
	}

	const Array<EditingTextCharStyle>& CTextInput::getEditingTextStyle() const
	{
		return m_preeditTextStyle;
	}

	void CTextInput::preeditDrawCallback(XIC, XPointer, XIMPreeditDrawCallbackStruct* call_data)
	{
		std::lock_guard lock{ m_mutexPreeditStatus };

		m_internalPreeditCaret = call_data->caret;

		if (call_data->text)
		{
			String text;
			if (call_data->text->encoding_is_wchar)
			{
				text = Unicode::FromWstring(call_data->text->string.wide_char);
			}
			else
			{
				text = Unicode::FromUTF8(call_data->text->string.multi_byte);
			}

			m_internalPreeditText.erase(call_data->chg_first, call_data->chg_length);
			m_internalPreeditText.insert(call_data->chg_first, text);

			m_internalPreeditTextStyle.erase(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first + call_data->chg_length));
			m_internalPreeditTextStyle.insert(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), text.length(), EditingTextCharStyle::NoStyle);

			auto itr = std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first);
			EditingTextCharStyle style = EditingTextCharStyle::NoStyle;
			for(size_t idx = 0; idx < text.length(); idx++)
			{
				auto feedback = call_data->text->feedback[idx];
				if(feedback == 0)
				{
					*itr = style;
				}
				else
				{
					if (feedback & XIMReverse)
					{
						*itr |= EditingTextCharStyle::Highlight;
					}
					if (feedback & XIMHighlight)
					{
						*itr |= EditingTextCharStyle::DashedUnderline;
					}
					if (feedback & XIMUnderline)
					{
						*itr = (*itr & ~EditingTextCharStyle::UnderlineMask) | EditingTextCharStyle::Underline;
					}
				}
				itr++;
			}
		}
		else
		{
			m_internalPreeditTextStyle.erase(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first + call_data->chg_length));
			m_internalPreeditText.erase(call_data->chg_first, call_data->chg_length);
		}

	}

	void CTextInput::updateWindowFocus(bool focus)
	{
		m_windowHasFocus = focus;
		updateICFocus();
	}

	void CTextInput::sendInputText(const String& text)
	{
		std::lock_guard lock { m_mutexChars };

		m_internalChars.append(text);
	}

	void CTextInput::updateICFocus()
	{
		XIC ic = s3d_GetXICFromGLFWWindow(static_cast<GLFWwindow*>(SIV3D_ENGINE(Window)->getHandle()));
		if (ic)
		{
			if (m_imeEnabled && m_windowHasFocus)
			{
				XSetICFocus(ic);
			}
			else
			{
				XUnsetICFocus(ic);
			}
		}
	}

	void CTextInput::OnCharacterInput(GLFWwindow*, const uint32 codePoint)
	{
		SIV3D_ENGINE(TextInput)->pushChar(codePoint);
	}
}
<commit_msg>[Linux] 変数名の変更し忘れを修正<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/EngineLog.hpp>
# include <Siv3D/Keyboard.hpp>
# include <Siv3D/Window/IWindow.hpp>
# include <Siv3D/Common/Siv3DEngine.hpp>
# include "CTextInput.hpp"

extern "C"
{
	using namespace s3d;

	CTextInput* pTextInput = nullptr;

	XIMCallback preeditStart;
	XIMCallback preeditDraw;
	XIMCallback preeditDone;
	XIMCallback preeditCaret;

	void preeditStartCallback(XIC, XPointer, XPointer)
	{
		// do nothing
	}

	void preeditDoneCallback(XIC, XPointer, XPointer)
	{
		// do nothing
	}

	void preeditDrawCallback(XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *call_data)
	{
		pTextInput->preeditDrawCallback(ic, client_data, call_data);
	}

	void preeditCaretCallback(XIC, XPointer, XIMPreeditCaretCallbackStruct *)
	{
		// do nothing
	}

	XVaNestedList s3d_PreeditAttributes(XPointer client_data)
	{
		preeditStart.client_data = client_data;
		preeditStart.callback = (XIMProc)preeditStartCallback;
		preeditDone.client_data = client_data;
		preeditDone.callback = (XIMProc)preeditDoneCallback;
		preeditDraw.client_data = client_data;
		preeditDraw.callback = (XIMProc)preeditDrawCallback;
		preeditCaret.client_data = client_data;
		preeditCaret.callback = (XIMProc)preeditCaretCallback;

		return XVaCreateNestedList(0,
								   XNPreeditStartCallback, &preeditStart.client_data,
								   XNPreeditDoneCallback, &preeditDone.client_data,
								   XNPreeditDrawCallback, &preeditDraw.client_data,
								   XNPreeditCaretCallback, &preeditCaret.client_data,
								   NULL);
	}

	void s3d_InputText(char *text)
	{
		pTextInput->sendInputText(Unicode::FromUTF8(text));
	}

	void s3d_SetICFocus(XIC)
	{
		pTextInput->updateWindowFocus(true);
	}

	void s3d_UnsetICFocus(XIC)
	{
		pTextInput->updateWindowFocus(false);
	}

	XIC s3d_GetXICFromGLFWWindow(GLFWwindow *window);
}

namespace s3d
{
	CTextInput::CTextInput()
	{
		pTextInput = this;
	}

	CTextInput::~CTextInput()
	{
		LOG_SCOPED_TRACE(U"CTextInput::~CTextInput()");

		pTextInput = nullptr;
	}

	void CTextInput::init()
	{
		LOG_SCOPED_TRACE(U"CTextInput::init()");

		if (GLFWwindow* glfwWindow = static_cast<GLFWwindow*>(SIV3D_ENGINE(Window)->getHandle()))
		{
			::glfwSetCharCallback(glfwWindow, OnCharacterInput);
		}
	}

	void CTextInput::update()
	{
		{
			std::lock_guard lock{ m_mutexChars };

			m_chars = m_internalChars;

			m_internalChars.clear();
		}

		{
			std::lock_guard lock{ m_mutexPreeditStatus };

			m_preeditText = m_internalPreeditText;

			m_preeditTextStyle = m_internalPreeditTextStyle;

			m_preeditCaret = m_internalPreeditCaret;
		}
	}

	void CTextInput::pushChar(const uint32 ch)
	{
		std::lock_guard lock{ m_mutexChars };

		m_internalChars.push_back(static_cast<char32>(ch));
	}

	const String& CTextInput::getChars() const
	{
		return m_chars;
	}

	const String& CTextInput::getEditingText() const
	{
		return m_preeditText;
	}

	void CTextInput::enableIME(bool enabled)
	{
		m_imeEnabled = enabled;
		updateICFocus();
	}

	std::pair<int32, int32> CTextInput::getCursorIndex() const
	{
		return{ m_preeditCaret, 0};
	}

	const Array<String>& CTextInput::getCandidates() const
	{
		static const Array<String> dummy;
		return dummy;
	}

	const Array<EditingTextCharStyle>& CTextInput::getEditingTextStyle() const
	{
		return m_preeditTextStyle;
	}

	void CTextInput::preeditDrawCallback(XIC, XPointer, XIMPreeditDrawCallbackStruct* call_data)
	{
		std::lock_guard lock{ m_mutexPreeditStatus };

		m_internalPreeditCaret = call_data->caret;

		if (call_data->text)
		{
			String text;
			if (call_data->text->encoding_is_wchar)
			{
				text = Unicode::FromWstring(call_data->text->string.wide_char);
			}
			else
			{
				text = Unicode::FromUTF8(call_data->text->string.multi_byte);
			}

			m_internalPreeditText.erase(call_data->chg_first, call_data->chg_length);
			m_internalPreeditText.insert(call_data->chg_first, text);

			m_internalPreeditTextStyle.erase(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first + call_data->chg_length));
			m_internalPreeditTextStyle.insert(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), text.length(), EditingTextCharStyle::NoStyle);

			auto itr = std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first);
			EditingTextCharStyle style = EditingTextCharStyle::NoStyle;
			for(size_t idx = 0; idx < text.length(); idx++)
			{
				auto feedback = call_data->text->feedback[idx];
				if(feedback == 0)
				{
					*itr = style;
				}
				else
				{
					if (feedback & XIMReverse)
					{
						*itr |= EditingTextCharStyle::Highlight;
					}
					if (feedback & XIMHighlight)
					{
						*itr |= EditingTextCharStyle::DashedUnderline;
					}
					if (feedback & XIMUnderline)
					{
						*itr = (*itr & ~EditingTextCharStyle::UnderlineMask) | EditingTextCharStyle::Underline;
					}
				}
				itr++;
			}
		}
		else
		{
			m_internalPreeditTextStyle.erase(std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first), std::next(m_internalPreeditTextStyle.begin(), call_data->chg_first + call_data->chg_length));
			m_internalPreeditText.erase(call_data->chg_first, call_data->chg_length);
		}

	}

	void CTextInput::updateWindowFocus(bool focus)
	{
		m_windowHasFocus = focus;
		updateICFocus();
	}

	void CTextInput::sendInputText(const String& text)
	{
		std::lock_guard lock { m_mutexChars };

		m_internalChars.append(text);
	}

	void CTextInput::updateICFocus()
	{
		XIC ic = s3d_GetXICFromGLFWWindow(static_cast<GLFWwindow*>(SIV3D_ENGINE(Window)->getHandle()));
		if (ic)
		{
			if (m_imeEnabled && m_windowHasFocus)
			{
				XSetICFocus(ic);
			}
			else
			{
				XUnsetICFocus(ic);
			}
		}
	}

	void CTextInput::OnCharacterInput(GLFWwindow*, const uint32 codePoint)
	{
		SIV3D_ENGINE(TextInput)->pushChar(codePoint);
	}
}
<|endoftext|>