<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "winrtpackagedeploymentstep.h"
#include "winrtdevice.h"
#include "winrtconstants.h"

#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/kitinformation.h>
#include <coreplugin/idocument.h>
#include <utils/fileutils.h>
#include <qtsupport/profilereader.h>
#include <proparser/qmakevfs.h>
#include <utils/hostosinfo.h>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QRegularExpression>
#include <QRegularExpressionMatchIterator>

using namespace ProjectExplorer;

namespace WinRt {
namespace Internal {

WinRtPackageDeploymentStep::WinRtPackageDeploymentStep(BuildStepList *bsl)
    : AbstractProcessStep(bsl, Constants::WINRT_BUILD_STEP_DEPLOY)
{
    setDisplayName(tr("Deploy Qt binaries and application files to output directory"));
}

bool WinRtPackageDeploymentStep::init()
{
    Utils::FileName proFile = Utils::FileName::fromString(project()->document()->filePath());
    const QString targetPath
            = target()->applicationTargets().targetForProject(proFile).toString()
                + QLatin1String(".exe");
    // ### Actually, targetForProject is supposed to return the file path including the file
    // extension. Whenever this will eventually work, we have to remove the .exe suffix here.

    ProcessParameters *params = processParameters();
    params->setCommand(QLatin1String("windeployqt.exe"));
    params->setArguments(QDir::toNativeSeparators(targetPath));
    params->setEnvironment(target()->activeBuildConfiguration()->environment());

    return AbstractProcessStep::init();
}

BuildStepConfigWidget *WinRtPackageDeploymentStep::createConfigWidget()
{
    return new SimpleBuildStepConfigWidget(this);
}

} // namespace Internal
} // namespace WinRt
<commit_msg>WinRt: simplify project file path retrieval<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "winrtpackagedeploymentstep.h"
#include "winrtdevice.h"
#include "winrtconstants.h"

#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/kitinformation.h>
#include <utils/fileutils.h>
#include <qtsupport/profilereader.h>
#include <proparser/qmakevfs.h>
#include <utils/hostosinfo.h>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QRegularExpression>
#include <QRegularExpressionMatchIterator>

using namespace ProjectExplorer;

namespace WinRt {
namespace Internal {

WinRtPackageDeploymentStep::WinRtPackageDeploymentStep(BuildStepList *bsl)
    : AbstractProcessStep(bsl, Constants::WINRT_BUILD_STEP_DEPLOY)
{
    setDisplayName(tr("Deploy Qt binaries and application files to output directory"));
}

bool WinRtPackageDeploymentStep::init()
{
    Utils::FileName proFile = Utils::FileName::fromString(project()->projectFilePath());
    const QString targetPath
            = target()->applicationTargets().targetForProject(proFile).toString()
                + QLatin1String(".exe");
    // ### Actually, targetForProject is supposed to return the file path including the file
    // extension. Whenever this will eventually work, we have to remove the .exe suffix here.

    ProcessParameters *params = processParameters();
    params->setCommand(QLatin1String("windeployqt.exe"));
    params->setArguments(QDir::toNativeSeparators(targetPath));
    params->setEnvironment(target()->activeBuildConfiguration()->environment());

    return AbstractProcessStep::init();
}

BuildStepConfigWidget *WinRtPackageDeploymentStep::createConfigWidget()
{
    return new SimpleBuildStepConfigWidget(this);
}

} // namespace Internal
} // namespace WinRt
<|endoftext|>


<commit_before>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#ifdef _DIRECTX9
#include <d3d9.h>

#include <hltypes/hlog.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Color.h"
#include "DirectX9_RenderSystem.h"
#include "DirectX9_Texture.h"
#include "Image.h"

#define APRIL_D3D_DEVICE (((DirectX9_RenderSystem*)april::rendersys)->d3dDevice)

namespace april
{
	DirectX9_Texture::DirectX9_Texture(bool fromResource) : DirectX_Texture(fromResource), d3dTexture(NULL), d3dSurface(NULL), d3dFormat(D3DFMT_UNKNOWN), renderTarget(false)
	{
	}

	DirectX9_Texture::~DirectX9_Texture()
	{
		this->unload();
		this->waitForAsyncLoad();
	}

	bool DirectX9_Texture::_createInternalTexture(unsigned char* data, int size, Type type)
	{
		this->d3dPool = D3DPOOL_DEFAULT;
		this->d3dUsage = 0;
		// some GPUs seem to have problems creating off-screen A8 surfaces when D3DPOOL_DEFAULT is used
		if (!((DirectX9_RenderSystem*)april::rendersys)->_supportsA8Surface && this->d3dFormat == D3DFMT_A8)
		{
			this->d3dPool = D3DPOOL_MANAGED;
		}
		else if (this->type != TYPE_IMMUTABLE)
		{
			this->d3dUsage = D3DUSAGE_DYNAMIC;
		}
		// TODOaa - change pool to save memory
		if (type == TYPE_RENDER_TARGET)
		{
			this->d3dUsage = D3DUSAGE_RENDERTARGET;
			this->renderTarget = true;
		}
		HRESULT hr = APRIL_D3D_DEVICE->CreateTexture(this->width, this->height, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
		if (hr == D3DERR_OUTOFVIDEOMEMORY)
		{
			static bool _preventRecursion = false;
			if (!_preventRecursion)
			{
				_preventRecursion = true;
				april::window->handleLowMemoryWarning();
				_preventRecursion = false;
				hr = APRIL_D3D_DEVICE->CreateTexture(this->width, this->height, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
			}
		}
		if (FAILED(hr))
		{
			RenderSystem::Caps caps = april::rendersys->getCaps();
			// maybe it failed, because NPOT textures aren't supported
			if (!caps.npotTexturesLimited && !caps.npotTextures)
			{
				int w = this->width;
				int h = this->height;
				this->_setupPot(w, h);
				hr = APRIL_D3D_DEVICE->CreateTexture(w, h, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
				if (!FAILED(hr) && data != NULL)
				{
					unsigned char* newData = this->_createPotData(w, h, data);
					this->type = TYPE_VOLATILE; // so the write call right below goes through
					this->write(0, 0, w, h, 0, 0, newData, w, h, this->format);
					this->type = type;
					delete [] newData;
					this->firstUpload = false;
				}
			}
			if (FAILED(hr))
			{
				hlog::error(april::logTag, "Failed to create DX9 texture!");
				return false;
			}
		}
		return true;
	}

	void DirectX9_Texture::_assignFormat()
	{
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		switch (nativeFormat)
		{
		case Image::FORMAT_BGRA:
			this->d3dFormat = D3DFMT_A8R8G8B8;
			break;
		case Image::FORMAT_BGRX:
			this->d3dFormat = D3DFMT_X8R8G8B8;
			break;
		case Image::FORMAT_ALPHA:
			this->d3dFormat = D3DFMT_A8; // lots of GPUs don't support A8 (even modern ones) so we use L8
			break;
		case Image::FORMAT_GRAYSCALE:
			this->d3dFormat = D3DFMT_L8;
			break;
		case Image::FORMAT_PALETTE: // TODOaa - needs changing, ARGB shouldn't be here
			this->d3dFormat = D3DFMT_A8R8G8B8;
			break;
		}
	}

	void DirectX9_Texture::unload()
	{
		Texture::unload();
		if (this->d3dTexture != NULL)
		{
			hlog::write(april::logTag, "Unloading texture: " + this->_getInternalName());
			if (this->d3dSurface != NULL)
			{
				this->d3dSurface->Release();
				this->d3dSurface = NULL;
			}
			this->d3dTexture->Release();
			this->d3dTexture = NULL;
		}
	}

	bool DirectX9_Texture::isLoaded()
	{
		return (this->d3dTexture != NULL);
	}

	IDirect3DSurface9* DirectX9_Texture::_getSurface()
	{
		if (this->d3dSurface == NULL)
		{
			this->d3dTexture->GetSurfaceLevel(0, &this->d3dSurface);
		}
		return this->d3dSurface;
	}

	Texture::Lock DirectX9_Texture::_tryLockSystem(int x, int y, int w, int h)
	{
		Lock lock;
		D3DLOCKED_RECT lockRect;
		HRESULT hr;
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		int nativeBpp = Image::getFormatBpp(nativeFormat);
		if (this->d3dPool == D3DPOOL_MANAGED)
		{
			RECT rect;
			rect.left = x;
			rect.top = y;
			rect.right = x + w;
			rect.bottom = y + h;
			hr = this->d3dTexture->LockRect(0, &lockRect, &rect, D3DLOCK_DISCARD);
			if (!FAILED(hr))
			{
				lock.systemBuffer = this->d3dTexture;
				lock.activateLock(0, 0, w, h, x, y, (unsigned char*)lockRect.pBits, lockRect.Pitch / nativeBpp, h, nativeFormat);
			}
			return lock;
		}
		IDirect3DSurface9* surface = NULL;
		hr = APRIL_D3D_DEVICE->CreateOffscreenPlainSurface(w, h, this->d3dFormat, D3DPOOL_SYSTEMMEM, &surface, NULL);
		if (FAILED(hr))
		{
			return lock;
		}
		hr = surface->LockRect(&lockRect, NULL, D3DLOCK_DISCARD);
		if (FAILED(hr))
		{
			surface->Release();
			return lock;
		}
		lock.systemBuffer = surface;
		// a D3DLOCKED_RECT always has a "pitch" that is a multiple of 4
		lock.activateLock(0, 0, w, h, x, y, (unsigned char*)lockRect.pBits, lockRect.Pitch / nativeBpp, h, nativeFormat);
		return lock;
		// TODOaa - render target locking
		/*
		Lock lock;
		D3DLOCKED_RECT lockRect;
		HRESULT hr = this->d3dTexture->LockRect(0, &lockRect, NULL, D3DLOCK_DISCARD);
		if (!FAILED(hr))
		{
			lock.buffer = this->_getSurface();
			lock.activateLock((unsigned char*)lockRect.pBits);
			return lock;
		}
		// could be a render target
		hr = APRIL_D3D_DEVICE->CreateOffscreenPlainSurface(this->width, this->height, this->d3dFormat, D3DPOOL_SYSTEMMEM, &lock.buffer, NULL);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, CreateOffscreenPlainSurface() call failed!");
			return lock;
		}
		hr = APRIL_D3D_DEVICE->GetRenderTargetData(this->_getSurface(), lock.buffer);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, GetRenderTargetData() call failed!");
			return lock;
		}
		hr = lock.buffer->LockRect(&lockRect, NULL, D3DLOCK_DISCARD);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, surface lock failed!");
			return lock;
		}
		lock.activateRenderTarget((unsigned char*)lockRect.pBits);
		return lock;
		*/
	}

	bool DirectX9_Texture::_unlockSystem(Lock& lock, bool update)
	{
		if (lock.systemBuffer == NULL)
		{
			return false;
		}
		if (this->d3dPool == D3DPOOL_MANAGED)
		{
			IDirect3DTexture9* texture = (IDirect3DTexture9*)lock.systemBuffer;
			if (lock.locked)
			{
				texture->UnlockRect(0);
			}
		}
		else
		{
			IDirect3DSurface9* surface = (IDirect3DSurface9*)lock.systemBuffer;
			if (update)
			{
				if (lock.locked)
				{
					surface->UnlockRect();
					RECT rect;
					rect.left = lock.x;
					rect.top = lock.y;
					rect.right = lock.x + lock.w;
					rect.bottom = lock.y + lock.h;
					POINT dest;
					dest.x = lock.dx;
					dest.y = lock.dy;
					APRIL_D3D_DEVICE->UpdateSurface(surface, &rect, this->_getSurface(), &dest);
				}
				else if (lock.renderTarget)
				{
					// TODOaa - implement
					/*
					surface->UnlockRect();
					if (update)
					{
						APRIL_D3D_DEVICE->UpdateSurface(lock.buffer, NULL, this->_getSurface(), NULL);
					}
					*/
				}
			}
			surface->Release();
		}
		return true;
	}

}
#endif
<commit_msg>- added special fix for DX9 textures to call a low-memory warning if the device is out of VRAM<commit_after>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#ifdef _DIRECTX9
#include <d3d9.h>

#include <hltypes/hlog.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Color.h"
#include "DirectX9_RenderSystem.h"
#include "DirectX9_Texture.h"
#include "Image.h"

#define APRIL_D3D_DEVICE (((DirectX9_RenderSystem*)april::rendersys)->d3dDevice)

namespace april
{
	DirectX9_Texture::DirectX9_Texture(bool fromResource) : DirectX_Texture(fromResource), d3dTexture(NULL), d3dSurface(NULL), d3dFormat(D3DFMT_UNKNOWN), renderTarget(false)
	{
	}

	DirectX9_Texture::~DirectX9_Texture()
	{
		this->unload();
		this->waitForAsyncLoad();
	}

	bool DirectX9_Texture::_createInternalTexture(unsigned char* data, int size, Type type)
	{
		this->d3dPool = D3DPOOL_DEFAULT;
		this->d3dUsage = 0;
		// some GPUs seem to have problems creating off-screen A8 surfaces when D3DPOOL_DEFAULT is used
		if (!((DirectX9_RenderSystem*)april::rendersys)->_supportsA8Surface && this->d3dFormat == D3DFMT_A8)
		{
			this->d3dPool = D3DPOOL_MANAGED;
		}
		else if (this->type != TYPE_IMMUTABLE)
		{
			this->d3dUsage = D3DUSAGE_DYNAMIC;
		}
		// TODOaa - change pool to save memory
		if (type == TYPE_RENDER_TARGET)
		{
			this->d3dUsage = D3DUSAGE_RENDERTARGET;
			this->renderTarget = true;
		}
		HRESULT hr = APRIL_D3D_DEVICE->CreateTexture(this->width, this->height, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
		if (hr == D3DERR_OUTOFVIDEOMEMORY)
		{
			static bool _preventRecursion = false;
			if (!_preventRecursion)
			{
				_preventRecursion = true;
				april::window->handleLowMemoryWarning();
				_preventRecursion = false;
				hr = APRIL_D3D_DEVICE->CreateTexture(this->width, this->height, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
			}
			if (hr == D3DERR_OUTOFVIDEOMEMORY)
			{
				hlog::error(april::logTag, "Failed to create DX9 texture: Not enough VRAM!");
				return false;
			}
		}
		if (FAILED(hr))
		{
			RenderSystem::Caps caps = april::rendersys->getCaps();
			// maybe it failed, because NPOT textures aren't supported
			if (!caps.npotTexturesLimited && !caps.npotTextures)
			{
				int w = this->width;
				int h = this->height;
				this->_setupPot(w, h);
				hr = APRIL_D3D_DEVICE->CreateTexture(w, h, 1, this->d3dUsage, this->d3dFormat, this->d3dPool, &this->d3dTexture, NULL);
				if (!FAILED(hr) && data != NULL)
				{
					unsigned char* newData = this->_createPotData(w, h, data);
					this->type = TYPE_VOLATILE; // so the write call right below goes through
					this->write(0, 0, w, h, 0, 0, newData, w, h, this->format);
					this->type = type;
					delete [] newData;
					this->firstUpload = false;
				}
			}
			if (FAILED(hr))
			{
				hlog::error(april::logTag, "Failed to create DX9 texture!");
				return false;
			}
		}
		return true;
	}

	void DirectX9_Texture::_assignFormat()
	{
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		switch (nativeFormat)
		{
		case Image::FORMAT_BGRA:
			this->d3dFormat = D3DFMT_A8R8G8B8;
			break;
		case Image::FORMAT_BGRX:
			this->d3dFormat = D3DFMT_X8R8G8B8;
			break;
		case Image::FORMAT_ALPHA:
			this->d3dFormat = D3DFMT_A8; // lots of GPUs don't support A8 (even modern ones) so we use L8
			break;
		case Image::FORMAT_GRAYSCALE:
			this->d3dFormat = D3DFMT_L8;
			break;
		case Image::FORMAT_PALETTE: // TODOaa - needs changing, ARGB shouldn't be here
			this->d3dFormat = D3DFMT_A8R8G8B8;
			break;
		}
	}

	void DirectX9_Texture::unload()
	{
		Texture::unload();
		if (this->d3dTexture != NULL)
		{
			hlog::write(april::logTag, "Unloading texture: " + this->_getInternalName());
			if (this->d3dSurface != NULL)
			{
				this->d3dSurface->Release();
				this->d3dSurface = NULL;
			}
			this->d3dTexture->Release();
			this->d3dTexture = NULL;
		}
	}

	bool DirectX9_Texture::isLoaded()
	{
		return (this->d3dTexture != NULL);
	}

	IDirect3DSurface9* DirectX9_Texture::_getSurface()
	{
		if (this->d3dSurface == NULL)
		{
			this->d3dTexture->GetSurfaceLevel(0, &this->d3dSurface);
		}
		return this->d3dSurface;
	}

	Texture::Lock DirectX9_Texture::_tryLockSystem(int x, int y, int w, int h)
	{
		Lock lock;
		D3DLOCKED_RECT lockRect;
		HRESULT hr;
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		int nativeBpp = Image::getFormatBpp(nativeFormat);
		if (this->d3dPool == D3DPOOL_MANAGED)
		{
			RECT rect;
			rect.left = x;
			rect.top = y;
			rect.right = x + w;
			rect.bottom = y + h;
			hr = this->d3dTexture->LockRect(0, &lockRect, &rect, D3DLOCK_DISCARD);
			if (!FAILED(hr))
			{
				lock.systemBuffer = this->d3dTexture;
				lock.activateLock(0, 0, w, h, x, y, (unsigned char*)lockRect.pBits, lockRect.Pitch / nativeBpp, h, nativeFormat);
			}
			return lock;
		}
		IDirect3DSurface9* surface = NULL;
		hr = APRIL_D3D_DEVICE->CreateOffscreenPlainSurface(w, h, this->d3dFormat, D3DPOOL_SYSTEMMEM, &surface, NULL);
		if (FAILED(hr))
		{
			return lock;
		}
		hr = surface->LockRect(&lockRect, NULL, D3DLOCK_DISCARD);
		if (FAILED(hr))
		{
			surface->Release();
			return lock;
		}
		lock.systemBuffer = surface;
		// a D3DLOCKED_RECT always has a "pitch" that is a multiple of 4
		lock.activateLock(0, 0, w, h, x, y, (unsigned char*)lockRect.pBits, lockRect.Pitch / nativeBpp, h, nativeFormat);
		return lock;
		// TODOaa - render target locking
		/*
		Lock lock;
		D3DLOCKED_RECT lockRect;
		HRESULT hr = this->d3dTexture->LockRect(0, &lockRect, NULL, D3DLOCK_DISCARD);
		if (!FAILED(hr))
		{
			lock.buffer = this->_getSurface();
			lock.activateLock((unsigned char*)lockRect.pBits);
			return lock;
		}
		// could be a render target
		hr = APRIL_D3D_DEVICE->CreateOffscreenPlainSurface(this->width, this->height, this->d3dFormat, D3DPOOL_SYSTEMMEM, &lock.buffer, NULL);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, CreateOffscreenPlainSurface() call failed!");
			return lock;
		}
		hr = APRIL_D3D_DEVICE->GetRenderTargetData(this->_getSurface(), lock.buffer);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, GetRenderTargetData() call failed!");
			return lock;
		}
		hr = lock.buffer->LockRect(&lockRect, NULL, D3DLOCK_DISCARD);
		if (FAILED(hr))
		{
			hlog::error(april::logTag, "Failed to get pixel data, surface lock failed!");
			return lock;
		}
		lock.activateRenderTarget((unsigned char*)lockRect.pBits);
		return lock;
		*/
	}

	bool DirectX9_Texture::_unlockSystem(Lock& lock, bool update)
	{
		if (lock.systemBuffer == NULL)
		{
			return false;
		}
		if (this->d3dPool == D3DPOOL_MANAGED)
		{
			IDirect3DTexture9* texture = (IDirect3DTexture9*)lock.systemBuffer;
			if (lock.locked)
			{
				texture->UnlockRect(0);
			}
		}
		else
		{
			IDirect3DSurface9* surface = (IDirect3DSurface9*)lock.systemBuffer;
			if (update)
			{
				if (lock.locked)
				{
					surface->UnlockRect();
					RECT rect;
					rect.left = lock.x;
					rect.top = lock.y;
					rect.right = lock.x + lock.w;
					rect.bottom = lock.y + lock.h;
					POINT dest;
					dest.x = lock.dx;
					dest.y = lock.dy;
					APRIL_D3D_DEVICE->UpdateSurface(surface, &rect, this->_getSurface(), &dest);
				}
				else if (lock.renderTarget)
				{
					// TODOaa - implement
					/*
					surface->UnlockRect();
					if (update)
					{
						APRIL_D3D_DEVICE->UpdateSurface(lock.buffer, NULL, this->_getSurface(), NULL);
					}
					*/
				}
			}
			surface->Release();
		}
		return true;
	}

}
#endif
<|endoftext|>


<commit_before>// Test ../include/Spectra/LinAlg/UpperHessenbergQR.h and
//      ../include/Spectra/LinAlg/DoubleShiftQR.h
#include <Eigen/Core>
#include <Eigen/QR>
#include <Spectra/LinAlg/UpperHessenbergQR.h>
#include <Spectra/LinAlg/DoubleShiftQR.h>

using namespace Spectra;

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using Eigen::MatrixXd;
using Eigen::VectorXd;
typedef Eigen::Map<Eigen::MatrixXd> MapMat;

template <typename Solver, typename MatrixType>
void run_test(MatrixType &H)
{
    Solver decomp(H);
    int n = H.rows();

    // Obtain Q matrix
    MatrixXd I = MatrixXd::Identity(n, n);
    MatrixXd Q = I;
    decomp.apply_QY(Q);

    // Test orthogonality
    MatrixXd QtQ = Q.transpose() * Q;
    INFO( "||Q'Q - I||_inf = " << (QtQ - I).cwiseAbs().maxCoeff() );
    REQUIRE( (QtQ - I).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    MatrixXd QQt = Q * Q.transpose();
    INFO( "||QQ' - I||_inf = " << (QQt - I).cwiseAbs().maxCoeff() );
    REQUIRE( (QQt - I).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Calculate R = Q'H
    MatrixXd R = decomp.matrix_R();
    MatrixXd Rlower = R.triangularView<Eigen::Lower>();
    Rlower.diagonal().setZero();
    INFO( "Whether R is upper triangular, error = " << Rlower.cwiseAbs().maxCoeff() );
    REQUIRE( Rlower.cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Compare H and QR
    INFO( "||H - QR||_inf = " << (H - Q * R).cwiseAbs().maxCoeff() );
    REQUIRE( (H - Q * R).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Test RQ
    MatrixXd RQ_true = R;
    decomp.apply_YQ(RQ_true);
    MatrixXd RQ;
    decomp.matrix_QtHQ(RQ);
    INFO( "max error of RQ = " << (RQ - RQ_true).cwiseAbs().maxCoeff() );
    REQUIRE( (RQ - RQ_true).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Test "apply" functions
    MatrixXd Y = MatrixXd::Random(n, n);

    MatrixXd QY = Y;
    decomp.apply_QY(QY);
    INFO( "max error of QY = " << (QY - Q * Y).cwiseAbs().maxCoeff() );
    REQUIRE( (QY - Q * Y).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    MatrixXd YQ = Y;
    decomp.apply_YQ(YQ);
    INFO( "max error of YQ = " << (YQ - Y * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (YQ - Y * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    MatrixXd QtY = Y;
    decomp.apply_QtY(QtY);
    INFO( "max error of Q'Y = " << (QtY - Q.transpose() * Y).cwiseAbs().maxCoeff() );
    REQUIRE( (QtY - Q.transpose() * Y).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    MatrixXd YQt = Y;
    decomp.apply_YQt(YQt);
    INFO( "max error of YQ' = " << (YQt - Y * Q.transpose()).cwiseAbs().maxCoeff() );
    REQUIRE( (YQt - Y * Q.transpose()).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Test "apply" functions for vectors
    VectorXd y = VectorXd::Random(n);

    VectorXd Qy = y;
    decomp.apply_QY(Qy);
    INFO( "max error of Qy = " << (Qy - Q * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qy - Q * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    VectorXd Qty = y;
    decomp.apply_QtY(Qty);
    INFO( "max error of Q'y = " << (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );
}

TEST_CASE("QR of upper Hessenberg matrix", "[QR]")
{
    std::srand(123);
    int n = 100;
    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = m.triangularView<Eigen::Upper>();
    H.diagonal(-1) = m.diagonal(-1);

    run_test< UpperHessenbergQR<double> >(H);

    MapMat Hmap(H.data(), H.rows(), H.cols());
    run_test< UpperHessenbergQR<double> >(Hmap);
}

TEST_CASE("QR of Tridiagonal matrix", "[QR]")
{
    std::srand(123);
    int n = 100;
    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = MatrixXd::Zero(n, n);
    H.diagonal() = m.diagonal();
    H.diagonal(-1) = m.diagonal(-1);
    H.diagonal(1) = m.diagonal(-1);

    run_test< TridiagQR<double> >(H);

    MapMat Hmap(H.data(), H.rows(), H.cols());
    run_test< TridiagQR<double> >(Hmap);
}

TEST_CASE("QR decomposition with double shifts", "QR")
{
    std::srand(123);
    int n = 100;
    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = m.triangularView<Eigen::Upper>();
    H.diagonal(-1) = m.diagonal(-1);
    H(1, 0) = 0;  // Test for the case when sub-diagonal element is zero

    double s = 2, t = 3;

    MatrixXd M = H * H - s * H + t * MatrixXd::Identity(n, n);
    Eigen::HouseholderQR<MatrixXd> qr(M);
    MatrixXd Q0 = qr.householderQ();

    DoubleShiftQR<double> decomp(H, s, t);
    MatrixXd Q = MatrixXd::Identity(n, n);
    decomp.apply_YQ(Q);

    // Equal up to signs
    INFO( "max error of Q = " << (Q.cwiseAbs() - Q0.cwiseAbs()).cwiseAbs().maxCoeff() );
    REQUIRE( (Q.cwiseAbs() - Q0.cwiseAbs()).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Test Q'HQ
    MatrixXd QtHQ;
    decomp.matrix_QtHQ(QtHQ);
    INFO( "max error of Q'HQ = " << (QtHQ - Q.transpose() * H * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (QtHQ - Q.transpose() * H * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    // Test apply functions
    VectorXd y = VectorXd::Random(n);
    MatrixXd Y = MatrixXd::Random(n / 2, n);

    VectorXd Qty = y;
    decomp.apply_QtY(Qty);
    INFO( "max error of Q'y = " << (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );

    MatrixXd YQ = Y;
    decomp.apply_YQ(YQ);
    INFO( "max error of YQ = " << (YQ- Y * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (YQ- Y * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-12) );
}
<commit_msg>test for shifts<commit_after>// Test ../include/Spectra/LinAlg/UpperHessenbergQR.h and
//      ../include/Spectra/LinAlg/DoubleShiftQR.h
#include <Eigen/Core>
#include <Eigen/QR>
#include <Spectra/LinAlg/UpperHessenbergQR.h>
#include <Spectra/LinAlg/DoubleShiftQR.h>

using namespace Spectra;

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using Eigen::MatrixXd;
using Eigen::VectorXd;
typedef Eigen::Map<Eigen::MatrixXd> MapMat;

template <typename Solver, typename MatrixType>
void run_test(MatrixType &H, double shift)
{
    Solver decomp(H, shift);
    const int n = H.rows();
    const double tol = 1e-12;
    MatrixXd Hs = H - shift * MatrixXd::Identity(n, n);

    // Obtain Q matrix
    MatrixXd I = MatrixXd::Identity(n, n);
    MatrixXd Q = I;
    decomp.apply_QY(Q);

    // Test orthogonality
    MatrixXd QtQ = Q.transpose() * Q;
    INFO( "||Q'Q - I||_inf = " << (QtQ - I).cwiseAbs().maxCoeff() );
    REQUIRE( (QtQ - I).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    MatrixXd QQt = Q * Q.transpose();
    INFO( "||QQ' - I||_inf = " << (QQt - I).cwiseAbs().maxCoeff() );
    REQUIRE( (QQt - I).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Obtain R matrix and test whether it is upper triangular
    MatrixXd R = decomp.matrix_R();
    MatrixXd Rlower = R.triangularView<Eigen::StrictlyLower>();
    INFO( "Whether R is upper triangular, error = " << Rlower.cwiseAbs().maxCoeff() );
    REQUIRE( Rlower.cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Compare Hs = H - s * I and QR
    INFO( "||Hs - QR||_inf = " << (Hs - Q * R).cwiseAbs().maxCoeff() );
    REQUIRE( (Hs - Q * R).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Obtain Q'HQ
    MatrixXd QtHQ_true = Q.transpose() * H * Q;
    MatrixXd QtHQ;
    decomp.matrix_QtHQ(QtHQ);
    INFO( "max error of Q'HQ = " << (QtHQ - QtHQ_true).cwiseAbs().maxCoeff() );
    REQUIRE( (QtHQ - QtHQ_true).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Test "apply" functions
    MatrixXd Y = MatrixXd::Random(n, n);

    MatrixXd QY = Y;
    decomp.apply_QY(QY);
    INFO( "max error of QY = " << (QY - Q * Y).cwiseAbs().maxCoeff() );
    REQUIRE( (QY - Q * Y).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    MatrixXd YQ = Y;
    decomp.apply_YQ(YQ);
    INFO( "max error of YQ = " << (YQ - Y * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (YQ - Y * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    MatrixXd QtY = Y;
    decomp.apply_QtY(QtY);
    INFO( "max error of Q'Y = " << (QtY - Q.transpose() * Y).cwiseAbs().maxCoeff() );
    REQUIRE( (QtY - Q.transpose() * Y).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    MatrixXd YQt = Y;
    decomp.apply_YQt(YQt);
    INFO( "max error of YQ' = " << (YQt - Y * Q.transpose()).cwiseAbs().maxCoeff() );
    REQUIRE( (YQt - Y * Q.transpose()).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Test "apply" functions for vectors
    VectorXd y = VectorXd::Random(n);

    VectorXd Qy = y;
    decomp.apply_QY(Qy);
    INFO( "max error of Qy = " << (Qy - Q * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qy - Q * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    VectorXd Qty = y;
    decomp.apply_QtY(Qty);
    INFO( "max error of Q'y = " << (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );
}

TEST_CASE("QR of upper Hessenberg matrix", "[QR]")
{
    std::srand(123);
    int n = 100;
    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = m.triangularView<Eigen::Upper>();
    H.diagonal(-1) = m.diagonal(-1);

    run_test< UpperHessenbergQR<double> >(H, 1.2345);

    MapMat Hmap(H.data(), H.rows(), H.cols());
    run_test< UpperHessenbergQR<double> >(Hmap, 0.6789);
}

TEST_CASE("QR of Tridiagonal matrix", "[QR]")
{
    std::srand(123);
    int n = 100;
    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = MatrixXd::Zero(n, n);
    H.diagonal() = m.diagonal();
    H.diagonal(-1) = m.diagonal(-1);
    H.diagonal(1) = m.diagonal(-1);

    run_test< TridiagQR<double> >(H, 1.2345);

    MapMat Hmap(H.data(), H.rows(), H.cols());
    run_test< TridiagQR<double> >(Hmap, 0.6789);
}

TEST_CASE("QR decomposition with double shifts", "[QR]")
{
    std::srand(123);
    const int n = 100;
    const double tol = 1e-12;

    MatrixXd m = MatrixXd::Random(n, n);
    m.array() -= 0.5;
    MatrixXd H = m.triangularView<Eigen::Upper>();
    H.diagonal(-1) = m.diagonal(-1);
    H(1, 0) = 0;  // Test for the case when sub-diagonal element is zero

    const double s = 2, t = 3;

    MatrixXd M = H * H - s * H + t * MatrixXd::Identity(n, n);
    Eigen::HouseholderQR<MatrixXd> qr(M);
    MatrixXd Q0 = qr.householderQ();

    DoubleShiftQR<double> decomp(H, s, t);
    MatrixXd Q = MatrixXd::Identity(n, n);
    decomp.apply_YQ(Q);

    // Equal up to signs
    INFO( "max error of Q = " << (Q.cwiseAbs() - Q0.cwiseAbs()).cwiseAbs().maxCoeff() );
    REQUIRE( (Q.cwiseAbs() - Q0.cwiseAbs()).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Test Q'HQ
    MatrixXd QtHQ;
    decomp.matrix_QtHQ(QtHQ);
    INFO( "max error of Q'HQ = " << (QtHQ - Q.transpose() * H * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (QtHQ - Q.transpose() * H * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    // Test apply functions
    VectorXd y = VectorXd::Random(n);
    MatrixXd Y = MatrixXd::Random(n / 2, n);

    VectorXd Qty = y;
    decomp.apply_QtY(Qty);
    INFO( "max error of Q'y = " << (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() );
    REQUIRE( (Qty - Q.transpose() * y).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );

    MatrixXd YQ = Y;
    decomp.apply_YQ(YQ);
    INFO( "max error of YQ = " << (YQ- Y * Q).cwiseAbs().maxCoeff() );
    REQUIRE( (YQ- Y * Q).cwiseAbs().maxCoeff() == Approx(0.0).margin(tol) );
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <Eigen/QR>

template<typename MatrixType> void qr(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;

  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;

  MatrixType a = MatrixType::Random(rows,cols);
  HouseholderQR<MatrixType> qrOfA(a);

  MatrixQType q = qrOfA.householderQ();
  VERIFY_IS_UNITARY(q);

  MatrixType r = qrOfA.matrixQR().template triangularView<Upper>();
  VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
}

template<typename MatrixType, int Cols2> void qr_fixedsize()
{
  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
  typedef typename MatrixType::Scalar Scalar;
  Matrix<Scalar,Rows,Cols> m1 = Matrix<Scalar,Rows,Cols>::Random();
  HouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);

  Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
  // FIXME need better way to construct trapezoid
  for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);

  VERIFY_IS_APPROX(m1, qr.householderQ() * r);

  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);
}

template<typename MatrixType> void qr_invertible()
{
  using std::log;
  using std::abs;
  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
  typedef typename MatrixType::Scalar Scalar;

  int size = internal::random<int>(10,50);

  MatrixType m1(size, size), m2(size, size), m3(size, size);
  m1 = MatrixType::Random(size,size);

  if (internal::is_same<RealScalar,float>::value)
  {
    // let's build a matrix more stable to inverse
    MatrixType a = MatrixType::Random(size,size*2);
    m1 += a * a.adjoint();
  }

  HouseholderQR<MatrixType> qr(m1);
  m3 = MatrixType::Random(size,size);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);

  // now construct a matrix with prescribed determinant
  m1.setZero();
  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
  RealScalar absdet = abs(m1.diagonal().prod());
  m3 = qr.householderQ(); // get a unitary
  m1 = m3 * m1 * m3;
  qr.compute(m1);
  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
}

template<typename MatrixType> void qr_verify_assert()
{
  MatrixType tmp;

  HouseholderQR<MatrixType> qr;
  VERIFY_RAISES_ASSERT(qr.matrixQR())
  VERIFY_RAISES_ASSERT(qr.solve(tmp))
  VERIFY_RAISES_ASSERT(qr.householderQ())
  VERIFY_RAISES_ASSERT(qr.absDeterminant())
  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
}

void test_qr()
{
  for(int i = 0; i < g_repeat; i++) {
   CALL_SUBTEST_1( qr(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
   CALL_SUBTEST_2( qr(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
   CALL_SUBTEST_3(( qr_fixedsize<Matrix<float,3,4>, 2 >() ));
   CALL_SUBTEST_4(( qr_fixedsize<Matrix<double,6,2>, 4 >() ));
   CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,2,5>, 7 >() ));
   CALL_SUBTEST_11( qr(Matrix<float,1,1>()) );
  }

  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
    CALL_SUBTEST_6( qr_invertible<MatrixXd>() );
    CALL_SUBTEST_7( qr_invertible<MatrixXcf>() );
    CALL_SUBTEST_8( qr_invertible<MatrixXcd>() );
  }

  CALL_SUBTEST_9(qr_verify_assert<Matrix3f>());
  CALL_SUBTEST_10(qr_verify_assert<Matrix3d>());
  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
  CALL_SUBTEST_6(qr_verify_assert<MatrixXd>());
  CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>());
  CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>());

  // Test problem size constructors
  CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20));
}
<commit_msg>reduce false negative in the qr unit test<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <Eigen/QR>

template<typename MatrixType> void qr(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;

  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;

  MatrixType a = MatrixType::Random(rows,cols);
  HouseholderQR<MatrixType> qrOfA(a);

  MatrixQType q = qrOfA.householderQ();
  VERIFY_IS_UNITARY(q);

  MatrixType r = qrOfA.matrixQR().template triangularView<Upper>();
  VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
}

template<typename MatrixType, int Cols2> void qr_fixedsize()
{
  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
  typedef typename MatrixType::Scalar Scalar;
  Matrix<Scalar,Rows,Cols> m1 = Matrix<Scalar,Rows,Cols>::Random();
  HouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);

  Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
  // FIXME need better way to construct trapezoid
  for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);

  VERIFY_IS_APPROX(m1, qr.householderQ() * r);

  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);
}

template<typename MatrixType> void qr_invertible()
{
  using std::log;
  using std::abs;
  using std::pow;
  using std::max;
  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
  typedef typename MatrixType::Scalar Scalar;

  int size = internal::random<int>(10,50);

  MatrixType m1(size, size), m2(size, size), m3(size, size);
  m1 = MatrixType::Random(size,size);

  if (internal::is_same<RealScalar,float>::value)
  {
    // let's build a matrix more stable to inverse
    MatrixType a = MatrixType::Random(size,size*4);
    m1 += a * a.adjoint();
  }

  HouseholderQR<MatrixType> qr(m1);
  m3 = MatrixType::Random(size,size);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);

  // now construct a matrix with prescribed determinant
  m1.setZero();
  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
  RealScalar absdet = abs(m1.diagonal().prod());
  m3 = qr.householderQ(); // get a unitary
  m1 = m3 * m1 * m3;
  qr.compute(m1);
  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
  // This test is tricky if the determinant becomes too small.
  // Since we generate random numbers with magnitude rrange [0,1], the average determinant is 0.5^size
  VERIFY_IS_MUCH_SMALLER_THAN( abs(absdet-qr.absDeterminant()), (max)(RealScalar(pow(0.5,size)),(max)(abs(absdet),abs(qr.absDeterminant()))) );

}

template<typename MatrixType> void qr_verify_assert()
{
  MatrixType tmp;

  HouseholderQR<MatrixType> qr;
  VERIFY_RAISES_ASSERT(qr.matrixQR())
  VERIFY_RAISES_ASSERT(qr.solve(tmp))
  VERIFY_RAISES_ASSERT(qr.householderQ())
  VERIFY_RAISES_ASSERT(qr.absDeterminant())
  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
}

void test_qr()
{
  for(int i = 0; i < g_repeat; i++) {
   CALL_SUBTEST_1( qr(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
   CALL_SUBTEST_2( qr(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
   CALL_SUBTEST_3(( qr_fixedsize<Matrix<float,3,4>, 2 >() ));
   CALL_SUBTEST_4(( qr_fixedsize<Matrix<double,6,2>, 4 >() ));
   CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,2,5>, 7 >() ));
   CALL_SUBTEST_11( qr(Matrix<float,1,1>()) );
  }

  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
    CALL_SUBTEST_6( qr_invertible<MatrixXd>() );
    CALL_SUBTEST_7( qr_invertible<MatrixXcf>() );
    CALL_SUBTEST_8( qr_invertible<MatrixXcd>() );
  }

  CALL_SUBTEST_9(qr_verify_assert<Matrix3f>());
  CALL_SUBTEST_10(qr_verify_assert<Matrix3d>());
  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
  CALL_SUBTEST_6(qr_verify_assert<MatrixXd>());
  CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>());
  CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>());

  // Test problem size constructors
  CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20));
}
<|endoftext|>


<commit_before>#include "php_cld2.h"
#include "compact_lang_det_impl.h"

zend_class_entry *cld2_detector_ce;
zend_class_entry *cld2_language_ce;
zend_object_handlers cld2_object_handlers;

struct st_detected_language {
    CLD2::Language language;
    int probability;
    bool is_reliable;
    char* language_code;
    char* language_name;
};

st_detected_language detect_language(char *text, int text_len, bool is_plain_text, char *tld_hint)
{
    int flags = 0;
    bool is_reliable;

    // Detect language
    CLD2::Language language3[3];
    int percent3[3];
    double normalized_score3[3];
    int text_bytes;

    //CLD2::CLDHints cld_hints = {NULL, this->getTldHint(), this->getEncHint(), this->getLangHint()};

    CLD2::CLDHints cld_hints = {NULL, tld_hint, 0, CLD2::UNKNOWN_LANGUAGE};
    CLD2::Language lang = CLD2::ExtDetectLanguageSummary(
                text,
                text_len,
                is_plain_text,
                &cld_hints,
                flags,
                language3,
                percent3,
                normalized_score3,
                NULL,
                &text_bytes,
                &is_reliable);

    st_detected_language dl;
    dl.language = lang;
    dl.probability = percent3[0];
    dl.is_reliable = is_reliable;
    dl.language_code = strdup(CLD2::LanguageCode(lang));
    dl.language_name = strdup(CLD2::LanguageName(lang));

    return dl;
}

PHP_METHOD(cld2_detector, detect)
{
    zval *detector, *is_plain, *tld_hint;
    char *text;
    int text_len;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &detector, cld2_detector_ce, &text, &text_len) == FAILURE) {
        RETURN_NULL();
    }

    is_plain = zend_read_property(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, 1 TSRMLS_CC);
    tld_hint = zend_read_property(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") -1, 1 TSRMLS_CC);

    st_detected_language dl = detect_language(text, text_len, (bool) is_plain, (char *) tld_hint);

    // Prepare array
    array_init(return_value);
    add_assoc_string(return_value, "language_code", dl.language_code, 1);
    add_assoc_string(return_value, "language_name", dl.language_name, 1);
    add_assoc_long(return_value, "language_probability", dl.probability);
    add_assoc_bool(return_value, "is_reliable", dl.is_reliable);
}

PHP_METHOD(cld2_detector, isPlainText)
{
    zval *detector, *is_plain;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &detector, cld2_detector_ce) == FAILURE) {
        RETURN_NULL();
    }

    is_plain = zend_read_property(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, 1 TSRMLS_CC);

    RETVAL_ZVAL(is_plain, 1, 0);
}

PHP_METHOD(cld2_detector, setPlainText)
{
    zval *detector;
    zend_bool is_plain;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &detector, cld2_detector_ce, &is_plain) == FAILURE) {
        RETURN_NULL();
    }

    zend_update_property_bool(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, is_plain TSRMLS_CC);
}

PHP_METHOD(cld2_detector, getTldHint)
{
    zval *detector, *tld_hint;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &detector, cld2_detector_ce) == FAILURE) {
        RETURN_NULL();
    }

    tld_hint = zend_read_property(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") - 1, 1 TSRMLS_CC);

    RETVAL_ZVAL(tld_hint, 1, 0);
}

PHP_METHOD(cld2_detector, setTldHint)
{
    zval *detector;

    char *hint;
    int hint_len;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &detector, cld2_detector_ce, &hint, &hint_len) == FAILURE) {
        RETURN_NULL();
    }

    zend_update_property_string(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") - 1, hint TSRMLS_CC);
}

zend_function_entry cld2_methods[] = {
    PHP_ME(cld2_detector, detect, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, isPlainText, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, setPlainText, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, getTldHint, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, setTldHint, NULL, ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}
};

PHP_MINIT_FUNCTION(cld2)
{
    // Detector
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "CLD2Detector", cld2_methods);
    cld2_detector_ce = zend_register_internal_class(&ce TSRMLS_CC);
    zend_declare_property_bool(cld2_detector_ce, "isPlainText", sizeof("isPlainText") - 1 , 0, ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(cld2_detector_ce, "tldHint", sizeof("tldHint") - 1, "", ZEND_ACC_PUBLIC TSRMLS_CC);

    // Language
    zend_class_entry ce_Language;
    INIT_CLASS_ENTRY(ce_Language, "CLD2Language", NULL);
    cld2_language_ce = zend_register_internal_class(&ce_Language TSRMLS_CC);

    memcpy(&cld2_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    cld2_object_handlers.clone_obj = NULL;

    return SUCCESS;
}

zend_module_entry cld2_module_entry = {
    STANDARD_MODULE_HEADER,
    PHP_CLD2_EXTNAME,
    NULL,                  /* Functions */
    PHP_MINIT(cld2),
    NULL,                  /* MSHUTDOWN */
    NULL,                  /* RINIT */
    NULL,                  /* RSHUTDOWN */
    NULL,                  /* MINFO */
    PHP_CLD2_EXTVER,
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_CLD2
extern "C" {
ZEND_GET_MODULE(cld2)
}
#endif
<commit_msg>Initial CLD2Language languages constants<commit_after>#include "php_cld2.h"
#include "compact_lang_det_impl.h"

zend_class_entry *cld2_detector_ce;
zend_class_entry *cld2_language_ce;
zend_object_handlers cld2_object_handlers;

struct st_detected_language {
    CLD2::Language language;
    int probability;
    bool is_reliable;
    char* language_code;
    char* language_name;
};

st_detected_language detect_language(char *text, int text_len, bool is_plain_text, char *tld_hint)
{
    int flags = 0;
    bool is_reliable;

    // Detect language
    CLD2::Language language3[3];
    int percent3[3];
    double normalized_score3[3];
    int text_bytes;

    //CLD2::CLDHints cld_hints = {NULL, this->getTldHint(), this->getEncHint(), this->getLangHint()};

    CLD2::CLDHints cld_hints = {NULL, tld_hint, 0, CLD2::UNKNOWN_LANGUAGE};
    CLD2::Language lang = CLD2::ExtDetectLanguageSummary(
                text,
                text_len,
                is_plain_text,
                &cld_hints,
                flags,
                language3,
                percent3,
                normalized_score3,
                NULL,
                &text_bytes,
                &is_reliable);

    st_detected_language dl;
    dl.language = lang;
    dl.probability = percent3[0];
    dl.is_reliable = is_reliable;
    dl.language_code = strdup(CLD2::LanguageCode(lang));
    dl.language_name = strdup(CLD2::LanguageName(lang));

    return dl;
}

PHP_METHOD(cld2_detector, detect)
{
    zval *detector, *is_plain, *tld_hint;
    char *text;
    int text_len;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &detector, cld2_detector_ce, &text, &text_len) == FAILURE) {
        RETURN_NULL();
    }

    is_plain = zend_read_property(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, 1 TSRMLS_CC);
    tld_hint = zend_read_property(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") -1, 1 TSRMLS_CC);

    st_detected_language dl = detect_language(text, text_len, (bool) is_plain, (char *) tld_hint);

    // Prepare array
    array_init(return_value);
    add_assoc_string(return_value, "language_code", dl.language_code, 1);
    add_assoc_string(return_value, "language_name", dl.language_name, 1);
    add_assoc_long(return_value, "language_probability", dl.probability);
    add_assoc_bool(return_value, "is_reliable", dl.is_reliable);
}

PHP_METHOD(cld2_detector, isPlainText)
{
    zval *detector, *is_plain;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &detector, cld2_detector_ce) == FAILURE) {
        RETURN_NULL();
    }

    is_plain = zend_read_property(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, 1 TSRMLS_CC);

    RETVAL_ZVAL(is_plain, 1, 0);
}

PHP_METHOD(cld2_detector, setPlainText)
{
    zval *detector;
    zend_bool is_plain;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &detector, cld2_detector_ce, &is_plain) == FAILURE) {
        RETURN_NULL();
    }

    zend_update_property_bool(cld2_detector_ce, detector, "isPlainText", sizeof("isPlainText") -1, is_plain TSRMLS_CC);
}

PHP_METHOD(cld2_detector, getTldHint)
{
    zval *detector, *tld_hint;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &detector, cld2_detector_ce) == FAILURE) {
        RETURN_NULL();
    }

    tld_hint = zend_read_property(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") - 1, 1 TSRMLS_CC);

    RETVAL_ZVAL(tld_hint, 1, 0);
}

PHP_METHOD(cld2_detector, setTldHint)
{
    zval *detector;

    char *hint;
    int hint_len;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &detector, cld2_detector_ce, &hint, &hint_len) == FAILURE) {
        RETURN_NULL();
    }

    zend_update_property_string(cld2_detector_ce, detector, "tldHint", sizeof("tldHint") - 1, hint TSRMLS_CC);
}

zend_function_entry cld2_methods[] = {
    PHP_ME(cld2_detector, detect, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, isPlainText, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, setPlainText, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, getTldHint, NULL, ZEND_ACC_PUBLIC)
    PHP_ME(cld2_detector, setTldHint, NULL, ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}
};

PHP_MINIT_FUNCTION(cld2)
{
    // Detector
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "CLD2Detector", cld2_methods);
    cld2_detector_ce = zend_register_internal_class(&ce TSRMLS_CC);
    zend_declare_property_bool(cld2_detector_ce, "isPlainText", sizeof("isPlainText") - 1 , 0, ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(cld2_detector_ce, "tldHint", sizeof("tldHint") - 1, "", ZEND_ACC_PUBLIC TSRMLS_CC);

    // Language
    zend_class_entry ce_Language;
    INIT_CLASS_ENTRY(ce_Language, "CLD2Language", NULL);
    cld2_language_ce = zend_register_internal_class(&ce_Language TSRMLS_CC);

    for (int i = 0; i < CLD2::NUM_LANGUAGES; i++) {
        CLD2::Language lan = (CLD2::Language)(i);
        zend_declare_class_constant_long(cld2_language_ce, CLD2::LanguageName(lan),  strlen(CLD2::LanguageName(lan)), i);
    }

    memcpy(&cld2_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    cld2_object_handlers.clone_obj = NULL;

    return SUCCESS;
}

zend_module_entry cld2_module_entry = {
    STANDARD_MODULE_HEADER,
    PHP_CLD2_EXTNAME,
    NULL,                  /* Functions */
    PHP_MINIT(cld2),
    NULL,                  /* MSHUTDOWN */
    NULL,                  /* RINIT */
    NULL,                  /* RSHUTDOWN */
    NULL,                  /* MINFO */
    PHP_CLD2_EXTVER,
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_CLD2
extern "C" {
ZEND_GET_MODULE(cld2)
}
#endif
<|endoftext|>


<commit_before>// tmpstream.C -- Temporary stream object for extracting strings.
//
// Copyright 1996-2001 Per Abrahamsen and Sren Hansen
// Copyright 2000-2001 KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy 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 Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

//
// I'd use "ostringstream", but it isn't in GCC 2.95.2.

#include "tmpstream.h"
#include "assertion.h"

#if defined (__BORLANDC__)
// Borland C++ 5.01 doesn't spell stream with an m.
#include <strstrea.h>
#else
#include <strstream>
#endif

using namespace std;

struct TmpStream::Implementation
{
  ostrstream out;
  bool done;
  char* str;

  Implementation ()
    : done (false),
      str (NULL)
  { }
  ~Implementation ()
  {
    if (str)
      delete [] str;
  }
};

ostream&
TmpStream::operator () ()
{
  daisy_assert (!impl.done);
  return impl.out;
}

const char*
TmpStream::str ()
{
  if (!impl.done)
    {
      impl.done = true;
      impl.out << '\0';
      impl.str = impl.out.str ();
    }
  daisy_assert (impl.str);
  return impl.str;
}

TmpStream::TmpStream ()
  : impl (*new Implementation)
{ }

TmpStream::~TmpStream ()
{ delete &impl; }
<commit_msg>More BCC hacking<commit_after>// tmpstream.C -- Temporary stream object for extracting strings.
//
// Copyright 1996-2001 Per Abrahamsen and Sren Hansen
// Copyright 2000-2001 KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy 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 Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

//
// I'd use "ostringstream", but it isn't in GCC 2.95.2.

#include "tmpstream.h"
#include "assertion.h"

#if defined (__BORLANDC__)
// Borland C++ 5.01 doesn't spell stream with an m.
#include <strstrea.h>
#else
#include <strstream>
#endif

using namespace std;

struct TmpStream::Implementation
{
  ostrstream out;
  bool done;
  char* str;

  Implementation ()
    : done (false),
      str (NULL)
  { }
  ~Implementation ()
  {
    if (str)
      delete [] str;
  }
};

std::ostream&
TmpStream::operator () ()
{
  daisy_assert (!impl.done);
  return impl.out;
}

const char*
TmpStream::str ()
{
  if (!impl.done)
    {
      impl.done = true;
      impl.out << '\0';
      impl.str = impl.out.str ();
    }
  daisy_assert (impl.str);
  return impl.str;
}

TmpStream::TmpStream ()
  : impl (*new Implementation)
{ }

TmpStream::~TmpStream ()
{ delete &impl; }
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS ooo19126 (1.8.12); FILE MERGED 2005/09/05 17:27:59 rt 1.8.12.1: #i54170# Change license header: remove SISSL<commit_after><|endoftext|>


<commit_before>#include <zorba/item_sequence.h>
#include <zorba/stateless_function.h>

#include "errors/error_factory.h"
#include "runtime/core/var_iterators.h"
#include "runtime/core/fncall_iterator.h"
#include "functions/function.h"
#include "runtime/base/plan_iterator_wrapper.h"

namespace xqp {

UDFunctionCallIteratorState::UDFunctionCallIteratorState()
  : theFnBodyStateBlock(NULL),
    thePlan(NULL),
    thePlanStateSize(0),
    thePlanOpen(false) { }

UDFunctionCallIteratorState::~UDFunctionCallIteratorState()
{
}

void UDFunctionCallIteratorState::openPlan()
{
  uint32_t planOffset = 0;
  thePlan->open(*theFnBodyStateBlock, planOffset);
  thePlanOpen = true;
}

void UDFunctionCallIteratorState::closePlan()
{
  if (thePlanOpen) {
    thePlan->close(*theFnBodyStateBlock);
  }
  thePlanOpen = false;
}

void UDFunctionCallIteratorState::resetPlan()
{
  if (thePlanOpen) {
    thePlan->reset(*theFnBodyStateBlock);
  }
}

void UDFunctionCallIteratorState::resetChildIters()
{
  std::vector<Iterator_t>::const_iterator lIter = theChildIterators.begin();
  std::vector<Iterator_t>::const_iterator lEnd = theChildIterators.end();
  for ( ; lIter != lEnd; ++lIter)
    (*lIter)->close();

  theChildIterators.clear();
}

void UDFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::openImpl(planState, offset);
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->thePlan = theUDF->get_plan().getp();
  state->thePlanStateSize = state->thePlan->getStateSizeOfSubtree();
  state->theFnBodyStateBlock = new PlanState(state->thePlanStateSize);

}

void UDFunctionCallIterator::closeImpl(PlanState& planState)
{
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->closePlan();
  delete state->theFnBodyStateBlock;
  state->resetChildIters();

  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::closeImpl(planState);
}

void UDFunctionCallIterator::resetImpl(PlanState& planState) const
{
  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::resetImpl(planState);
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->resetPlan();
  state->resetChildIters();
}

Item_t UDFunctionCallIterator::nextImpl(PlanState& planState) const
{
  Item_t lSequenceItem;
  UDFunctionCallIteratorState *state;

  DEFAULT_STACK_INIT(UDFunctionCallIteratorState, state, planState);

  {
    // Bind the args.
    state->openPlan();
    std::vector<ref_iter_t>& iters = theUDF->get_param_iters();
    for (uint32_t i = 0; i < iters.size (); ++i) {
      ref_iter_t& ref = iters[i];
      if ( ref != NULL) {
        state->theChildIterators.push_back(new PlanIteratorWrapper(theChildren[i], planState));
        state->theChildIterators.back()->open();
        ref->bind(state->theChildIterators.back(), *state->theFnBodyStateBlock);
      }
    }
  }

  while ((lSequenceItem = consumeNext(state->thePlan, *state->theFnBodyStateBlock)) != NULL) {
    STACK_PUSH(lSequenceItem, state);
  }

  STACK_END();
}

// external functions
class ExtFuncArgItemSequence : public ItemSequence {
  public:
    ExtFuncArgItemSequence(PlanIter_t child, PlanState& stateBlock)
      : m_child(child),
      m_stateBlock(stateBlock) { }

    Item_t next() { return m_child->consumeNext(m_child.getp(), m_stateBlock); }

  private:
    PlanIter_t m_child;
    PlanState& m_stateBlock;
};

StatelessExtFunctionCallIteratorState::StatelessExtFunctionCallIteratorState() { }

StatelessExtFunctionCallIteratorState::~StatelessExtFunctionCallIteratorState() { }

void StatelessExtFunctionCallIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  m_result = NULL;
}

StatelessExtFunctionCallIterator::StatelessExtFunctionCallIterator(const QueryLoc& loc,
    std::vector<PlanIter_t>& args,
    const StatelessExternalFunction *function)
  : NaryBaseIterator<StatelessExtFunctionCallIterator, StatelessExtFunctionCallIteratorState>(loc, args),
    m_function(function) { }

void StatelessExtFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
  NaryBaseIterator<StatelessExtFunctionCallIterator, StatelessExtFunctionCallIteratorState>::openImpl(planState, offset);
  StatelessExtFunctionCallIteratorState *state = StateTraitsImpl<StatelessExtFunctionCallIteratorState>::getState(planState, this->stateOffset);
  int n = theChildren.size();
  state->m_extArgs.resize(n);
  for(int i = 0; i < n; ++i) {
    state->m_extArgs[i] = new ExtFuncArgItemSequence(theChildren[i], planState);
  }
}

Item_t StatelessExtFunctionCallIterator::nextImpl(PlanState& planState) const
{
  StatelessExtFunctionCallIteratorState *state;
  Item_t lSequenceItem;
  DEFAULT_STACK_INIT(StatelessExtFunctionCallIteratorState, state, planState);

  state->m_result = m_function->evaluate(state->m_extArgs);
  while((lSequenceItem = state->m_result->next()) != NULL) {
    STACK_PUSH(lSequenceItem, state);
  }

  STACK_END();
}

}

/* vim:set ts=2 sw=2: */
<commit_msg>Fixed leak in UDF<commit_after>#include <zorba/item_sequence.h>
#include <zorba/stateless_function.h>

#include "errors/error_factory.h"
#include "runtime/core/var_iterators.h"
#include "runtime/core/fncall_iterator.h"
#include "functions/function.h"
#include "runtime/base/plan_iterator_wrapper.h"

namespace xqp {

UDFunctionCallIteratorState::UDFunctionCallIteratorState()
  : theFnBodyStateBlock(NULL),
    thePlan(NULL),
    thePlanStateSize(0),
    thePlanOpen(false) { }

UDFunctionCallIteratorState::~UDFunctionCallIteratorState()
{
}

void UDFunctionCallIteratorState::openPlan()
{
  uint32_t planOffset = 0;
  if (!thePlanOpen) {
    thePlan->open(*theFnBodyStateBlock, planOffset);
  }
  thePlanOpen = true;
}

void UDFunctionCallIteratorState::closePlan()
{
  if (thePlanOpen) {
    thePlan->close(*theFnBodyStateBlock);
  }
  thePlanOpen = false;
}

void UDFunctionCallIteratorState::resetPlan()
{
  if (thePlanOpen) {
    thePlan->reset(*theFnBodyStateBlock);
  }
}

void UDFunctionCallIteratorState::resetChildIters()
{
  std::vector<Iterator_t>::const_iterator lIter = theChildIterators.begin();
  std::vector<Iterator_t>::const_iterator lEnd = theChildIterators.end();
  for ( ; lIter != lEnd; ++lIter)
    (*lIter)->close();

  theChildIterators.clear();
}

void UDFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::openImpl(planState, offset);
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->thePlan = theUDF->get_plan().getp();
  state->thePlanStateSize = state->thePlan->getStateSizeOfSubtree();
  state->theFnBodyStateBlock = new PlanState(state->thePlanStateSize);

}

void UDFunctionCallIterator::closeImpl(PlanState& planState)
{
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->closePlan();
  delete state->theFnBodyStateBlock;
  state->resetChildIters();

  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::closeImpl(planState);
}

void UDFunctionCallIterator::resetImpl(PlanState& planState) const
{
  NaryBaseIterator<UDFunctionCallIterator, UDFunctionCallIteratorState>::resetImpl(planState);
  UDFunctionCallIteratorState *state = StateTraitsImpl<UDFunctionCallIteratorState>::getState(planState, this->stateOffset);

  state->resetPlan();
  state->resetChildIters();
}

Item_t UDFunctionCallIterator::nextImpl(PlanState& planState) const
{
  Item_t lSequenceItem;
  UDFunctionCallIteratorState *state;

  DEFAULT_STACK_INIT(UDFunctionCallIteratorState, state, planState);

  {
    // Bind the args.
    state->openPlan();
    std::vector<ref_iter_t>& iters = theUDF->get_param_iters();
    for (uint32_t i = 0; i < iters.size (); ++i) {
      ref_iter_t& ref = iters[i];
      if ( ref != NULL) {
        state->theChildIterators.push_back(new PlanIteratorWrapper(theChildren[i], planState));
        state->theChildIterators.back()->open();
        ref->bind(state->theChildIterators.back(), *state->theFnBodyStateBlock);
      }
    }
  }

  while ((lSequenceItem = consumeNext(state->thePlan, *state->theFnBodyStateBlock)) != NULL) {
    STACK_PUSH(lSequenceItem, state);
  }

  STACK_END();
}

// external functions
class ExtFuncArgItemSequence : public ItemSequence {
  public:
    ExtFuncArgItemSequence(PlanIter_t child, PlanState& stateBlock)
      : m_child(child),
      m_stateBlock(stateBlock) { }

    Item_t next() { return m_child->consumeNext(m_child.getp(), m_stateBlock); }

  private:
    PlanIter_t m_child;
    PlanState& m_stateBlock;
};

StatelessExtFunctionCallIteratorState::StatelessExtFunctionCallIteratorState() { }

StatelessExtFunctionCallIteratorState::~StatelessExtFunctionCallIteratorState() { }

void StatelessExtFunctionCallIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
  m_result = NULL;
}

StatelessExtFunctionCallIterator::StatelessExtFunctionCallIterator(const QueryLoc& loc,
    std::vector<PlanIter_t>& args,
    const StatelessExternalFunction *function)
  : NaryBaseIterator<StatelessExtFunctionCallIterator, StatelessExtFunctionCallIteratorState>(loc, args),
    m_function(function) { }

void StatelessExtFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
  NaryBaseIterator<StatelessExtFunctionCallIterator, StatelessExtFunctionCallIteratorState>::openImpl(planState, offset);
  StatelessExtFunctionCallIteratorState *state = StateTraitsImpl<StatelessExtFunctionCallIteratorState>::getState(planState, this->stateOffset);
  int n = theChildren.size();
  state->m_extArgs.resize(n);
  for(int i = 0; i < n; ++i) {
    state->m_extArgs[i] = new ExtFuncArgItemSequence(theChildren[i], planState);
  }
}

Item_t StatelessExtFunctionCallIterator::nextImpl(PlanState& planState) const
{
  StatelessExtFunctionCallIteratorState *state;
  Item_t lSequenceItem;
  DEFAULT_STACK_INIT(StatelessExtFunctionCallIteratorState, state, planState);

  state->m_result = m_function->evaluate(state->m_extArgs);
  while((lSequenceItem = state->m_result->next()) != NULL) {
    STACK_PUSH(lSequenceItem, state);
  }

  STACK_END();
}

}

/* vim:set ts=2 sw=2: */
<|endoftext|>


<commit_before>//
//  PushPillar.cpp
//  Created by Matt Kaufmann on 03/31/14.
//

#include "ExampleGame/Components/GameScripts/Units/Assassin.h"
#include "ExampleGame/Components/GameScripts/Units/Obstacles/PushPillar.h"
#include "ExampleGame/Components/Grid/GridManager.h"
#include "ExampleGame/Components/Grid/GridNavigator.h"
#include "ExampleGame/GameSingletons/GameSingletons.h"
#include "ExampleGame/Messages/Declarations.h"
#include "Vajra/Engine/Components/DerivedComponents/Transform/Transform.h"
#include "Vajra/Engine/Core/Engine.h"
#include "Vajra/Engine/SceneGraph/SceneGraph3D.h"
#include "Vajra/Utilities/MathUtilities.h"

PushPillar::PushPillar() : BaseUnit() {
	this->init();
}

PushPillar::PushPillar(Object* object_) : BaseUnit(object_) {
	this->init();
}

PushPillar::~PushPillar() {
	this->destroy();
}

void PushPillar::init() {
	this->unitType = UNIT_TYPE_OBSTACLE;
	this->gridNavRef->SetMaxNavigableUnitType(UNIT_TYPE_NONE);
	this->gridNavRef->SetMovementSpeed(2.0f);

	this->isSliding = false;
	this->slideX = 0;
	this->slideZ = 0;
	this->riderId = OBJECT_ID_INVALID;

	this->addSubscriptionToMessageType(MESSAGE_TYPE_NAVIGATION_REACHED_DESTINATION, this->GetTypeId(), false);
	this->addSubscriptionToMessageType(MESSAGE_TYPE_GRID_ZONE_ENTERED_CELL        , this->GetTypeId(), false);
	this->addSubscriptionToMessageType(MESSAGE_TYPE_GRID_ZONE_EXITED_CELL         , this->GetTypeId(), false);
}

void PushPillar::destroy() {

}

void PushPillar::HandleMessage(MessageChunk messageChunk) {
	BaseUnit::HandleMessage(messageChunk);

	switch (messageChunk->GetMessageType()) {
		case MESSAGE_TYPE_NAVIGATION_REACHED_DESTINATION:
			if (this->isSliding) {
				this->slide();
			}
			break;

		case MESSAGE_TYPE_GRID_ZONE_ENTERED_CELL:
			if (messageChunk->GetSenderId() == this->GetObject()->GetId()) {
				this->onZoneEnteredCell(messageChunk->messageData.iv1.x, messageChunk->messageData.iv1.z);
			}
			break;

		case MESSAGE_TYPE_GRID_ZONE_EXITED_CELL:
			if (messageChunk->GetSenderId() == this->GetObject()->GetId()) {
				this->onZoneExitedCell(messageChunk->messageData.iv1.x, messageChunk->messageData.iv1.z);
			}
			break;
	}
}

bool PushPillar::CanBeKilledBy(ObjectIdType id, glm::vec3 /*source*/) {
	GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(id);
	ASSERT(gObj != nullptr, "GameObject exists with id %d", id);
	if (gObj != nullptr) {
		BaseUnit* unit = gObj->GetComponent<BaseUnit>();
		if (unit != nullptr) {
			// Pillars can only be pushed by the assassin.
			if (unit->GetUnitType() == UNIT_TYPE_ASSASSIN) {
				return true;
			}
		}
	}
	return false;
}

void PushPillar::start() {
	this->gridNavRef->SetTurnSpeedRadians(0.0f);
}

void PushPillar::end() {

}

void PushPillar::update() {

}

void PushPillar::onUnitSpecialHit(ObjectIdType id, int gridX, int gridZ, glm::vec3 source) {
	// First check if the attack hit my cell
	GridCell* cell = this->gridNavRef->GetCurrentCell();
	if (cell != nullptr) {
		if ((cell->x == gridX) && (cell->z == gridZ)) {
			// Check if the attacker can kill me
			if (this->CanBeKilledBy(id, source)) {
				// Move it!
				this->startSliding(this->gameObjectRef->GetTransform()->GetPositionWorld() - source);
			}
		}
	}
}

void PushPillar::Kill() {

}

void PushPillar::startSliding(glm::vec3 direction) {
	// Convert the direction vector to one of the cardinal directions (N/S/E/W)
	if      (direction.x >  ROUNDING_ERROR) { this->slideX =  1; }
	else if (direction.x < -ROUNDING_ERROR) { this->slideX = -1; }
	else                                    { this->slideX =  0; }
	if      (direction.z >  ROUNDING_ERROR) { this->slideZ =  1; }
	else if (direction.z < -ROUNDING_ERROR) { this->slideZ = -1; }
	else                                    { this->slideZ =  0; }

	if ((this->slideX != 0) && (this->slideZ != 0)) {
		// Pillars can't slide diagonally. If either X or Z greatly outweighs the other, clamp to that direction. Otherwise, don't move.
		float ratio = direction.x * this->slideX * this->slideZ / direction.z;
		if (ratio < 2.0f) { this->slideX = 0; }
		if (ratio > 0.5f) { this->slideZ = 0; }
	}

	if ((this->slideX != 0) || (this->slideZ != 0)) {
		this->isSliding = true;
		this->childUnitOnTop();
		this->slide();
	}
}

void PushPillar::slide() {
	GridCell* myCell = this->gridNavRef->GetCurrentCell();
	if (myCell != nullptr) {
		GridCell* targetCell = SINGLETONS->GetGridManager()->GetGrid()->GetCell(myCell->x + this->slideX, myCell->z - this->slideZ);
		if (!this->gridNavRef->SetDestination(targetCell)) {
			this->stopSliding();
		}
	}
	else {
		this->stopSliding();
	}
}

void PushPillar::stopSliding() {
	this->isSliding = false;
	this->unchildUnitOnTop();
}

void PushPillar::childUnitOnTop() {
	GridCell* cell = this->gridNavRef->GetCurrentCell();
	if (cell != nullptr) {
		int elevation = this->gridNavRef->GetElevation() + 1;
		this->riderId = cell->GetOccupantIdAtElevation(elevation);
		if (this->riderId != OBJECT_ID_INVALID) {
			GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(riderId);
			if (gObj != nullptr) {
				this->gameObjectRef->AddChild_maintainTransform(this->riderId);

				// If it's a unit that's moving, stop it:
				GridNavigator* gNav = gObj->GetComponent<GridNavigator>();
				if (gNav != nullptr) {
					if(gObj->GetComponent<BaseUnit>()) {
						if(gObj->GetComponent<BaseUnit>()->GetUnitType() == UnitType::UNIT_TYPE_ASSASSIN) {
							gObj->GetComponent<Assassin>()->cancelSpecial();
						}
					}

					gNav->HaltMovement();
					gNav->DisableNavigation();
				}
			}
		}
	}
}

void PushPillar::unchildUnitOnTop() {
	if (this->riderId != OBJECT_ID_INVALID) {
		GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(this->riderId);
		ASSERT(gObj != nullptr, "Object exists with id %d", this->riderId);
		if (gObj != nullptr) {
			gObj->GetParentSceneGraph()->GetRootGameObject()->AddChild_maintainTransform(this->riderId);

			// Re-enable the navigator.
			GridNavigator* gNav = gObj->GetComponent<GridNavigator>();
			if (gNav != nullptr) {
				GridCell* cell = this->gridNavRef->GetCurrentCell();
				if (cell != nullptr) {
					int elevation = this->gridNavRef->GetElevation() + 1;
					gNav->SetGridPosition(cell, elevation);
				}

				gNav->EnableNavigation();
			}
		}
		this->riderId = OBJECT_ID_INVALID;
	}
}

void PushPillar::onZoneEnteredCell(int gridX, int gridZ) {
	// When the pillar enters a cell, that cell becomes passable above the pillar
	int elevation = this->gridNavRef->GetElevation();
	if (elevation < (NUM_ELEVATIONS - 1)) {
		SINGLETONS->GetGridManager()->GetGrid()->SetCellPassableAtElevation(gridX, gridZ, elevation + 1, true);
	}
}

void PushPillar::onZoneExitedCell(int gridX, int gridZ) {
	// When the pillar exits a cell, that cell becomes impassable at the higher elevation
	int elevation = this->gridNavRef->GetElevation();
	if (elevation < (NUM_ELEVATIONS - 1)) {
		SINGLETONS->GetGridManager()->GetGrid()->SetCellPassableAtElevation(gridX, gridZ, elevation + 1, false);
	}
}
<commit_msg>Units that manage to move onto a pillar in motion will "stick" to it and keep moving with it.<commit_after>//
//  PushPillar.cpp
//  Created by Matt Kaufmann on 03/31/14.
//

#include "ExampleGame/Components/GameScripts/Units/Assassin.h"
#include "ExampleGame/Components/GameScripts/Units/Obstacles/PushPillar.h"
#include "ExampleGame/Components/Grid/GridManager.h"
#include "ExampleGame/Components/Grid/GridNavigator.h"
#include "ExampleGame/GameSingletons/GameSingletons.h"
#include "ExampleGame/Messages/Declarations.h"
#include "Vajra/Engine/Components/DerivedComponents/Transform/Transform.h"
#include "Vajra/Engine/Core/Engine.h"
#include "Vajra/Engine/SceneGraph/SceneGraph3D.h"
#include "Vajra/Utilities/MathUtilities.h"

PushPillar::PushPillar() : BaseUnit() {
	this->init();
}

PushPillar::PushPillar(Object* object_) : BaseUnit(object_) {
	this->init();
}

PushPillar::~PushPillar() {
	this->destroy();
}

void PushPillar::init() {
	this->unitType = UNIT_TYPE_OBSTACLE;
	this->gridNavRef->SetMaxNavigableUnitType(UNIT_TYPE_NONE);
	this->gridNavRef->SetMovementSpeed(2.0f);

	this->isSliding = false;
	this->slideX = 0;
	this->slideZ = 0;
	this->riderId = OBJECT_ID_INVALID;

	this->addSubscriptionToMessageType(MESSAGE_TYPE_NAVIGATION_REACHED_DESTINATION, this->GetTypeId(), false);
	this->addSubscriptionToMessageType(MESSAGE_TYPE_GRID_ZONE_ENTERED             , this->GetTypeId(), false);
	this->addSubscriptionToMessageType(MESSAGE_TYPE_GRID_ZONE_ENTERED_CELL        , this->GetTypeId(), false);
	this->addSubscriptionToMessageType(MESSAGE_TYPE_GRID_ZONE_EXITED_CELL         , this->GetTypeId(), false);
}

void PushPillar::destroy() {

}

void PushPillar::HandleMessage(MessageChunk messageChunk) {
	BaseUnit::HandleMessage(messageChunk);

	switch (messageChunk->GetMessageType()) {
		case MESSAGE_TYPE_NAVIGATION_REACHED_DESTINATION:
			if (this->isSliding) {
				this->slide();
			}
			break;

		case MESSAGE_TYPE_GRID_ZONE_ENTERED:
			if (this->isSliding && (messageChunk->GetSenderId() != this->gameObjectRef->GetId())) {
				this->childUnitOnTop();
			}
			break;

		case MESSAGE_TYPE_GRID_ZONE_ENTERED_CELL:
			if (messageChunk->GetSenderId() == this->GetObject()->GetId()) {
				this->onZoneEnteredCell(messageChunk->messageData.iv1.x, messageChunk->messageData.iv1.z);
			}
			break;

		case MESSAGE_TYPE_GRID_ZONE_EXITED_CELL:
			if (messageChunk->GetSenderId() == this->GetObject()->GetId()) {
				this->onZoneExitedCell(messageChunk->messageData.iv1.x, messageChunk->messageData.iv1.z);
			}
			break;
	}
}

bool PushPillar::CanBeKilledBy(ObjectIdType id, glm::vec3 /*source*/) {
	GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(id);
	ASSERT(gObj != nullptr, "GameObject exists with id %d", id);
	if (gObj != nullptr) {
		BaseUnit* unit = gObj->GetComponent<BaseUnit>();
		if (unit != nullptr) {
			// Pillars can only be pushed by the assassin.
			if (unit->GetUnitType() == UNIT_TYPE_ASSASSIN) {
				return true;
			}
		}
	}
	return false;
}

void PushPillar::start() {
	this->gridNavRef->SetTurnSpeedRadians(0.0f);
}

void PushPillar::end() {

}

void PushPillar::update() {

}

void PushPillar::onUnitSpecialHit(ObjectIdType id, int gridX, int gridZ, glm::vec3 source) {
	// First check if the attack hit my cell
	GridCell* cell = this->gridNavRef->GetCurrentCell();
	if (cell != nullptr) {
		if ((cell->x == gridX) && (cell->z == gridZ)) {
			// Check if the attacker can kill me
			if (this->CanBeKilledBy(id, source)) {
				// Move it!
				this->startSliding(this->gameObjectRef->GetTransform()->GetPositionWorld() - source);
			}
		}
	}
}

void PushPillar::Kill() {

}

void PushPillar::startSliding(glm::vec3 direction) {
	// Convert the direction vector to one of the cardinal directions (N/S/E/W)
	if      (direction.x >  ROUNDING_ERROR) { this->slideX =  1; }
	else if (direction.x < -ROUNDING_ERROR) { this->slideX = -1; }
	else                                    { this->slideX =  0; }
	if      (direction.z >  ROUNDING_ERROR) { this->slideZ =  1; }
	else if (direction.z < -ROUNDING_ERROR) { this->slideZ = -1; }
	else                                    { this->slideZ =  0; }

	if ((this->slideX != 0) && (this->slideZ != 0)) {
		// Pillars can't slide diagonally. If either X or Z greatly outweighs the other, clamp to that direction. Otherwise, don't move.
		float ratio = direction.x * this->slideX * this->slideZ / direction.z;
		if (ratio < 2.0f) { this->slideX = 0; }
		if (ratio > 0.5f) { this->slideZ = 0; }
	}

	if ((this->slideX != 0) || (this->slideZ != 0)) {
		this->isSliding = true;
		this->childUnitOnTop();
		this->slide();
	}
}

void PushPillar::slide() {
	GridCell* myCell = this->gridNavRef->GetCurrentCell();
	if (myCell != nullptr) {
		GridCell* targetCell = SINGLETONS->GetGridManager()->GetGrid()->GetCell(myCell->x + this->slideX, myCell->z - this->slideZ);
		if (!this->gridNavRef->SetDestination(targetCell)) {
			this->stopSliding();
		}
	}
	else {
		this->stopSliding();
	}
}

void PushPillar::stopSliding() {
	this->isSliding = false;
	this->unchildUnitOnTop();
}

void PushPillar::childUnitOnTop() {
	GridCell* cell = this->gridNavRef->GetCurrentCell();
	if (cell != nullptr) {
		int elevation = this->gridNavRef->GetElevation() + 1;
		this->riderId = cell->GetOccupantIdAtElevation(elevation);
		if (this->riderId != OBJECT_ID_INVALID) {
			GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(riderId);
			if (gObj != nullptr) {
				this->gameObjectRef->AddChild_maintainTransform(this->riderId);

				// If it's a unit that's moving, stop it:
				GridNavigator* gNav = gObj->GetComponent<GridNavigator>();
				if (gNav != nullptr) {
					if(gObj->GetComponent<BaseUnit>()) {
						if(gObj->GetComponent<BaseUnit>()->GetUnitType() == UnitType::UNIT_TYPE_ASSASSIN) {
							gObj->GetComponent<Assassin>()->cancelSpecial();
						}
					}

					gNav->HaltMovement();
					gNav->DisableNavigation();
				}
			}
		}
	}
}

void PushPillar::unchildUnitOnTop() {
	if (this->riderId != OBJECT_ID_INVALID) {
		GameObject* gObj = ENGINE->GetSceneGraph3D()->GetGameObjectById(this->riderId);
		ASSERT(gObj != nullptr, "Object exists with id %d", this->riderId);
		if (gObj != nullptr) {
			gObj->GetParentSceneGraph()->GetRootGameObject()->AddChild_maintainTransform(this->riderId);

			// Re-enable the navigator.
			GridNavigator* gNav = gObj->GetComponent<GridNavigator>();
			if (gNav != nullptr) {
				GridCell* cell = this->gridNavRef->GetCurrentCell();
				if (cell != nullptr) {
					int elevation = this->gridNavRef->GetElevation() + 1;
					gNav->SetGridPosition(cell, elevation);
				}

				gNav->EnableNavigation();
			}
		}
		this->riderId = OBJECT_ID_INVALID;
	}
}

void PushPillar::onZoneEnteredCell(int gridX, int gridZ) {
	// When the pillar enters a cell, that cell becomes passable above the pillar
	int elevation = this->gridNavRef->GetElevation();
	if (elevation < (NUM_ELEVATIONS - 1)) {
		SINGLETONS->GetGridManager()->GetGrid()->SetCellPassableAtElevation(gridX, gridZ, elevation + 1, true);
	}
}

void PushPillar::onZoneExitedCell(int gridX, int gridZ) {
	// When the pillar exits a cell, that cell becomes impassable at the higher elevation
	int elevation = this->gridNavRef->GetElevation();
	if (elevation < (NUM_ELEVATIONS - 1)) {
		SINGLETONS->GetGridManager()->GetGrid()->SetCellPassableAtElevation(gridX, gridZ, elevation + 1, false);
	}
}
<|endoftext|>