<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 */

#include "PivotLayoutTreeListData.hxx"
#include "PivotLayoutDialog.hxx"

#include <svtools/treelistentry.hxx>
#include "pivot.hxx"
#include "scabstdlg.hxx"

using namespace std;

extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeScPivotLayoutTreeListData(vcl::Window *pParent, VclBuilder::stringmap& )
{
    return new ScPivotLayoutTreeListData(pParent, WB_BORDER | WB_TABSTOP | WB_CLIPCHILDREN | WB_FORCE_MAKEVISIBLE);
}

namespace
{

OUString lclGetFunctionMaskName(const sal_uInt16 nFunctionMask)
{
    switch (nFunctionMask)
    {
        case PIVOT_FUNC_SUM:       return OUString("Sum");
        case PIVOT_FUNC_COUNT:     return OUString("Count");
        case PIVOT_FUNC_AVERAGE:   return OUString("Mean");
        case PIVOT_FUNC_MAX:       return OUString("Max");
        case PIVOT_FUNC_MIN:       return OUString("Min");
        case PIVOT_FUNC_PRODUCT:   return OUString("Product");
        case PIVOT_FUNC_COUNT_NUM: return OUString("Count");
        case PIVOT_FUNC_STD_DEV:   return OUString("StDev");
        case PIVOT_FUNC_STD_DEVP:  return OUString("StDevP");
        case PIVOT_FUNC_STD_VAR:   return OUString("Var");
        case PIVOT_FUNC_STD_VARP:  return OUString("VarP");
        default:
            break;
    }
    return OUString();
}

OUString lclCreateDataItemName(const sal_uInt16 nFunctionMask, const OUString& rName, const sal_uInt8 nDuplicationCount)
{
    OUStringBuffer aBuffer;
    aBuffer.append(lclGetFunctionMaskName(nFunctionMask));
    aBuffer.append(" - ");
    aBuffer.append(rName);
    if(nDuplicationCount > 0)
    {
        aBuffer.append(" ");
        aBuffer.append(OUString::number(nDuplicationCount));
    }

    return aBuffer.makeStringAndClear();
}

} // anonymous namespace

ScPivotLayoutTreeListData::ScPivotLayoutTreeListData(vcl::Window* pParent, WinBits nBits) :
    ScPivotLayoutTreeListBase(pParent, nBits, DATA_LIST)
{}

ScPivotLayoutTreeListData::~ScPivotLayoutTreeListData()
{}

bool ScPivotLayoutTreeListData::DoubleClickHdl()
{
    ScItemValue* pCurrentItemValue = (ScItemValue*) GetCurEntry()->GetUserData();
    ScPivotFuncData& rCurrentFunctionData = pCurrentItemValue->maFunctionData;

    SCCOL nCurrentColumn = rCurrentFunctionData.mnCol;
    ScDPLabelData* pCurrentLabelData = mpParent->GetLabelData(nCurrentColumn);
    if (!pCurrentLabelData)
        return false;

    ScAbstractDialogFactory* pFactory = ScAbstractDialogFactory::Create();

    boost::scoped_ptr<AbstractScDPFunctionDlg> pDialog(
        pFactory->CreateScDPFunctionDlg(this, mpParent->GetLabelDataVector(), *pCurrentLabelData, rCurrentFunctionData));

    if (pDialog->Execute() == RET_OK)
    {
        rCurrentFunctionData.mnFuncMask = pDialog->GetFuncMask();
        pCurrentLabelData->mnFuncMask = pDialog->GetFuncMask();

        rCurrentFunctionData.maFieldRef = pDialog->GetFieldRef();

        ScDPLabelData* pDFData = mpParent->GetLabelData(rCurrentFunctionData.mnCol);

        AdjustDuplicateCount(pCurrentItemValue);

        OUString sDataItemName = lclCreateDataItemName(
                                    rCurrentFunctionData.mnFuncMask,
                                    pDFData->maName,
                                    rCurrentFunctionData.mnDupCount);

        SetEntryText(GetCurEntry(), sDataItemName);
    }

    return true;
}

void ScPivotLayoutTreeListData::FillDataField(ScPivotFieldVector& rDataFields)
{
    Clear();
    maDataItemValues.clear();

    ScPivotFieldVector::iterator it;
    for (it = rDataFields.begin(); it != rDataFields.end(); ++it)
    {
        ScPivotField& rField = *it;

        if (rField.nCol == PIVOT_DATA_FIELD)
            continue;

        SCCOL nColumn;
        if (rField.mnOriginalDim >= 0)
            nColumn = rField.mnOriginalDim;
        else
            nColumn = rField.nCol;

        ScItemValue* pOriginalItemValue = mpParent->GetItem(nColumn);
        ScItemValue* pItemValue = new ScItemValue(pOriginalItemValue->maName, nColumn, rField.nFuncMask);

        pItemValue->mpOriginalItemValue = pOriginalItemValue;
        pItemValue->maFunctionData.mnOriginalDim = rField.mnOriginalDim;
        pItemValue->maFunctionData.maFieldRef = rField.maFieldRef;

        AdjustDuplicateCount(pItemValue);
        OUString sDataItemName = lclCreateDataItemName(pItemValue->maFunctionData.mnFuncMask,
                                                       pItemValue->maName,
                                                       pItemValue->maFunctionData.mnDupCount);

        maDataItemValues.push_back(pItemValue);
        InsertEntry(sDataItemName, NULL, false, TREELIST_APPEND, pItemValue);
    }
}

void ScPivotLayoutTreeListData::PushDataFieldNames(vector<ScDPName>& rDataFieldNames)
{
    SvTreeListEntry* pLoopEntry;
    for (pLoopEntry = First(); pLoopEntry != NULL; pLoopEntry = Next(pLoopEntry))
    {
        ScItemValue* pEachItemValue = (ScItemValue*) pLoopEntry->GetUserData();
        SCCOL nColumn = pEachItemValue->maFunctionData.mnCol;

        ScDPLabelData* pLabelData = mpParent->GetLabelData(nColumn);

        if (pLabelData == NULL && pLabelData->maName.isEmpty())
            continue;

        OUString sLayoutName = pLabelData->maLayoutName;
        if (sLayoutName.isEmpty())
        {
            sLayoutName = lclCreateDataItemName(
                            pEachItemValue->maFunctionData.mnFuncMask,
                            pEachItemValue->maName,
                            pEachItemValue->maFunctionData.mnDupCount);
        }

        rDataFieldNames.push_back(ScDPName(pLabelData->maName, sLayoutName, pLabelData->mnDupCount));
    }
}

void ScPivotLayoutTreeListData::InsertEntryForSourceTarget(SvTreeListEntry* pSource, SvTreeListEntry* pTarget)
{
    ScItemValue* pItemValue = (ScItemValue*) pSource->GetUserData();

    if(mpParent->IsDataElement(pItemValue->maFunctionData.mnCol))
        return;

    if (HasEntry(pSource))
    {
        OUString rText = GetEntryText(pSource);
        GetModel()->Remove(pSource);
        sal_uLong nPosition = (pTarget == NULL) ? TREELIST_APPEND : GetModel()->GetAbsPos(pTarget) + 1;
        InsertEntry(rText, NULL, false, nPosition, pItemValue);
    }
    else
    {
        sal_uLong nPosition = (pTarget == NULL) ? TREELIST_APPEND : GetModel()->GetAbsPos(pTarget) + 1;
        InsertEntryForItem(pItemValue->mpOriginalItemValue, nPosition);
    }
}

void ScPivotLayoutTreeListData::InsertEntryForItem(ScItemValue* pItemValue, sal_uLong nPosition)
{
    ScItemValue* pDataItemValue = new ScItemValue(pItemValue);
    pDataItemValue->mpOriginalItemValue = pItemValue;
    maDataItemValues.push_back(pDataItemValue);

    ScPivotFuncData& rFunctionData = pDataItemValue->maFunctionData;

    if (rFunctionData.mnFuncMask == PIVOT_FUNC_NONE ||
        rFunctionData.mnFuncMask == PIVOT_FUNC_AUTO)
    {
        rFunctionData.mnFuncMask = PIVOT_FUNC_SUM;
    }

    AdjustDuplicateCount(pDataItemValue);

    OUString sDataName = lclCreateDataItemName(
                            rFunctionData.mnFuncMask,
                            pDataItemValue->maName,
                            rFunctionData.mnDupCount);

    InsertEntry(sDataName, NULL, false, nPosition, pDataItemValue);
}

void ScPivotLayoutTreeListData::AdjustDuplicateCount(ScItemValue* pInputItemValue)
{
    ScPivotFuncData& rInputFunctionData = pInputItemValue->maFunctionData;

    bool bFoundDuplicate = false;

    rInputFunctionData.mnDupCount = 0;
    sal_uInt8 nMaxDuplicateCount = 0;

    SvTreeListEntry* pEachEntry;
    for (pEachEntry = First(); pEachEntry != NULL; pEachEntry = Next(pEachEntry))
    {
        ScItemValue* pItemValue = (ScItemValue*) pEachEntry->GetUserData();
        if (pItemValue == pInputItemValue)
            continue;

        ScPivotFuncData& rFunctionData = pItemValue->maFunctionData;

        if (rFunctionData.mnCol      == rInputFunctionData.mnCol &&
            rFunctionData.mnFuncMask == rInputFunctionData.mnFuncMask)
        {
            bFoundDuplicate = true;
            if(rFunctionData.mnDupCount > nMaxDuplicateCount)
                nMaxDuplicateCount = rFunctionData.mnDupCount;
        }
    }

    if(bFoundDuplicate)
    {
        rInputFunctionData.mnDupCount = nMaxDuplicateCount + 1;
    }
}

void ScPivotLayoutTreeListData::KeyInput(const KeyEvent& rKeyEvent)
{
    vcl::KeyCode aCode = rKeyEvent.GetKeyCode();
    sal_uInt16 nCode = aCode.GetCode();

    if (nCode == KEY_DELETE)
    {
        const SvTreeListEntry* pEntry = GetCurEntry();
        if (pEntry)
            GetModel()->Remove(pEntry);
        return;
    }

    SvTreeListBox::KeyInput(rKeyEvent);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>avoid NULL ptr deref.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 */

#include "PivotLayoutTreeListData.hxx"
#include "PivotLayoutDialog.hxx"

#include <svtools/treelistentry.hxx>
#include "pivot.hxx"
#include "scabstdlg.hxx"

using namespace std;

extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeScPivotLayoutTreeListData(vcl::Window *pParent, VclBuilder::stringmap& )
{
    return new ScPivotLayoutTreeListData(pParent, WB_BORDER | WB_TABSTOP | WB_CLIPCHILDREN | WB_FORCE_MAKEVISIBLE);
}

namespace
{

OUString lclGetFunctionMaskName(const sal_uInt16 nFunctionMask)
{
    switch (nFunctionMask)
    {
        case PIVOT_FUNC_SUM:       return OUString("Sum");
        case PIVOT_FUNC_COUNT:     return OUString("Count");
        case PIVOT_FUNC_AVERAGE:   return OUString("Mean");
        case PIVOT_FUNC_MAX:       return OUString("Max");
        case PIVOT_FUNC_MIN:       return OUString("Min");
        case PIVOT_FUNC_PRODUCT:   return OUString("Product");
        case PIVOT_FUNC_COUNT_NUM: return OUString("Count");
        case PIVOT_FUNC_STD_DEV:   return OUString("StDev");
        case PIVOT_FUNC_STD_DEVP:  return OUString("StDevP");
        case PIVOT_FUNC_STD_VAR:   return OUString("Var");
        case PIVOT_FUNC_STD_VARP:  return OUString("VarP");
        default:
            break;
    }
    return OUString();
}

OUString lclCreateDataItemName(const sal_uInt16 nFunctionMask, const OUString& rName, const sal_uInt8 nDuplicationCount)
{
    OUStringBuffer aBuffer;
    aBuffer.append(lclGetFunctionMaskName(nFunctionMask));
    aBuffer.append(" - ");
    aBuffer.append(rName);
    if(nDuplicationCount > 0)
    {
        aBuffer.append(" ");
        aBuffer.append(OUString::number(nDuplicationCount));
    }

    return aBuffer.makeStringAndClear();
}

} // anonymous namespace

ScPivotLayoutTreeListData::ScPivotLayoutTreeListData(vcl::Window* pParent, WinBits nBits) :
    ScPivotLayoutTreeListBase(pParent, nBits, DATA_LIST)
{}

ScPivotLayoutTreeListData::~ScPivotLayoutTreeListData()
{}

bool ScPivotLayoutTreeListData::DoubleClickHdl()
{
    ScItemValue* pCurrentItemValue = (ScItemValue*) GetCurEntry()->GetUserData();
    ScPivotFuncData& rCurrentFunctionData = pCurrentItemValue->maFunctionData;

    SCCOL nCurrentColumn = rCurrentFunctionData.mnCol;
    ScDPLabelData* pCurrentLabelData = mpParent->GetLabelData(nCurrentColumn);
    if (!pCurrentLabelData)
        return false;

    ScAbstractDialogFactory* pFactory = ScAbstractDialogFactory::Create();

    boost::scoped_ptr<AbstractScDPFunctionDlg> pDialog(
        pFactory->CreateScDPFunctionDlg(this, mpParent->GetLabelDataVector(), *pCurrentLabelData, rCurrentFunctionData));

    if (pDialog->Execute() == RET_OK)
    {
        rCurrentFunctionData.mnFuncMask = pDialog->GetFuncMask();
        pCurrentLabelData->mnFuncMask = pDialog->GetFuncMask();

        rCurrentFunctionData.maFieldRef = pDialog->GetFieldRef();

        ScDPLabelData* pDFData = mpParent->GetLabelData(rCurrentFunctionData.mnCol);

        AdjustDuplicateCount(pCurrentItemValue);

        OUString sDataItemName = lclCreateDataItemName(
                                    rCurrentFunctionData.mnFuncMask,
                                    pDFData->maName,
                                    rCurrentFunctionData.mnDupCount);

        SetEntryText(GetCurEntry(), sDataItemName);
    }

    return true;
}

void ScPivotLayoutTreeListData::FillDataField(ScPivotFieldVector& rDataFields)
{
    Clear();
    maDataItemValues.clear();

    ScPivotFieldVector::iterator it;
    for (it = rDataFields.begin(); it != rDataFields.end(); ++it)
    {
        ScPivotField& rField = *it;

        if (rField.nCol == PIVOT_DATA_FIELD)
            continue;

        SCCOL nColumn;
        if (rField.mnOriginalDim >= 0)
            nColumn = rField.mnOriginalDim;
        else
            nColumn = rField.nCol;

        ScItemValue* pOriginalItemValue = mpParent->GetItem(nColumn);
        ScItemValue* pItemValue = new ScItemValue(pOriginalItemValue->maName, nColumn, rField.nFuncMask);

        pItemValue->mpOriginalItemValue = pOriginalItemValue;
        pItemValue->maFunctionData.mnOriginalDim = rField.mnOriginalDim;
        pItemValue->maFunctionData.maFieldRef = rField.maFieldRef;

        AdjustDuplicateCount(pItemValue);
        OUString sDataItemName = lclCreateDataItemName(pItemValue->maFunctionData.mnFuncMask,
                                                       pItemValue->maName,
                                                       pItemValue->maFunctionData.mnDupCount);

        maDataItemValues.push_back(pItemValue);
        InsertEntry(sDataItemName, NULL, false, TREELIST_APPEND, pItemValue);
    }
}

void ScPivotLayoutTreeListData::PushDataFieldNames(vector<ScDPName>& rDataFieldNames)
{
    SvTreeListEntry* pLoopEntry;
    for (pLoopEntry = First(); pLoopEntry != NULL; pLoopEntry = Next(pLoopEntry))
    {
        ScItemValue* pEachItemValue = (ScItemValue*) pLoopEntry->GetUserData();
        SCCOL nColumn = pEachItemValue->maFunctionData.mnCol;

        ScDPLabelData* pLabelData = mpParent->GetLabelData(nColumn);

        if (pLabelData == NULL || pLabelData->maName.isEmpty())
            continue;

        OUString sLayoutName = pLabelData->maLayoutName;
        if (sLayoutName.isEmpty())
        {
            sLayoutName = lclCreateDataItemName(
                            pEachItemValue->maFunctionData.mnFuncMask,
                            pEachItemValue->maName,
                            pEachItemValue->maFunctionData.mnDupCount);
        }

        rDataFieldNames.push_back(ScDPName(pLabelData->maName, sLayoutName, pLabelData->mnDupCount));
    }
}

void ScPivotLayoutTreeListData::InsertEntryForSourceTarget(SvTreeListEntry* pSource, SvTreeListEntry* pTarget)
{
    ScItemValue* pItemValue = (ScItemValue*) pSource->GetUserData();

    if(mpParent->IsDataElement(pItemValue->maFunctionData.mnCol))
        return;

    if (HasEntry(pSource))
    {
        OUString rText = GetEntryText(pSource);
        GetModel()->Remove(pSource);
        sal_uLong nPosition = (pTarget == NULL) ? TREELIST_APPEND : GetModel()->GetAbsPos(pTarget) + 1;
        InsertEntry(rText, NULL, false, nPosition, pItemValue);
    }
    else
    {
        sal_uLong nPosition = (pTarget == NULL) ? TREELIST_APPEND : GetModel()->GetAbsPos(pTarget) + 1;
        InsertEntryForItem(pItemValue->mpOriginalItemValue, nPosition);
    }
}

void ScPivotLayoutTreeListData::InsertEntryForItem(ScItemValue* pItemValue, sal_uLong nPosition)
{
    ScItemValue* pDataItemValue = new ScItemValue(pItemValue);
    pDataItemValue->mpOriginalItemValue = pItemValue;
    maDataItemValues.push_back(pDataItemValue);

    ScPivotFuncData& rFunctionData = pDataItemValue->maFunctionData;

    if (rFunctionData.mnFuncMask == PIVOT_FUNC_NONE ||
        rFunctionData.mnFuncMask == PIVOT_FUNC_AUTO)
    {
        rFunctionData.mnFuncMask = PIVOT_FUNC_SUM;
    }

    AdjustDuplicateCount(pDataItemValue);

    OUString sDataName = lclCreateDataItemName(
                            rFunctionData.mnFuncMask,
                            pDataItemValue->maName,
                            rFunctionData.mnDupCount);

    InsertEntry(sDataName, NULL, false, nPosition, pDataItemValue);
}

void ScPivotLayoutTreeListData::AdjustDuplicateCount(ScItemValue* pInputItemValue)
{
    ScPivotFuncData& rInputFunctionData = pInputItemValue->maFunctionData;

    bool bFoundDuplicate = false;

    rInputFunctionData.mnDupCount = 0;
    sal_uInt8 nMaxDuplicateCount = 0;

    SvTreeListEntry* pEachEntry;
    for (pEachEntry = First(); pEachEntry != NULL; pEachEntry = Next(pEachEntry))
    {
        ScItemValue* pItemValue = (ScItemValue*) pEachEntry->GetUserData();
        if (pItemValue == pInputItemValue)
            continue;

        ScPivotFuncData& rFunctionData = pItemValue->maFunctionData;

        if (rFunctionData.mnCol      == rInputFunctionData.mnCol &&
            rFunctionData.mnFuncMask == rInputFunctionData.mnFuncMask)
        {
            bFoundDuplicate = true;
            if(rFunctionData.mnDupCount > nMaxDuplicateCount)
                nMaxDuplicateCount = rFunctionData.mnDupCount;
        }
    }

    if(bFoundDuplicate)
    {
        rInputFunctionData.mnDupCount = nMaxDuplicateCount + 1;
    }
}

void ScPivotLayoutTreeListData::KeyInput(const KeyEvent& rKeyEvent)
{
    vcl::KeyCode aCode = rKeyEvent.GetKeyCode();
    sal_uInt16 nCode = aCode.GetCode();

    if (nCode == KEY_DELETE)
    {
        const SvTreeListEntry* pEntry = GetCurEntry();
        if (pEntry)
            GetModel()->Remove(pEntry);
        return;
    }

    SvTreeListBox::KeyInput(rKeyEvent);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "Matrix.h"

namespace Aggplus
{
	CMatrix::CMatrix(double m11, double m12, double m21, double m22, double dx, double dy) : m_agg_mtx(m11, m12, m21, m22, dx, dy)
	{
	}

	CMatrix::CMatrix() : m_agg_mtx()
	{
	}

	CMatrix::~CMatrix()
	{
	}

	void CMatrix::Translate(double offsetX, double offsetY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_translation(offsetX, offsetY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_translation(offsetX, offsetY));
		}
	}

	void CMatrix::Scale(double scaleX, double scaleY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_scaling(scaleX, scaleY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_scaling(scaleX, scaleY));
		}
	}

	void CMatrix::Shear(double shearX, double shearY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_skewing(shearX, shearY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_skewing(shearX, shearY));
		}
	}

	void CMatrix::TransformVectors(PointF* pts, int count)
	{
		// Store matrix to an array [6] of double
		double M[6]; m_agg_mtx.store_to(M);

		for(int i = 0; i < count; ++i)
		{
			double x =pts[i].X;
			double y =pts[i].Y;
			m_agg_mtx.transform(&x, &y);
			pts[i].X =(float)(x-M[4]);
			pts[i].Y =(float)(y-M[5]);
		}
	}

	void CMatrix::TransformPoints(PointF* pts, int count)
	{
		for(int i = 0; i < count; ++i)
		{
			double x = pts[i].X;
			double y = pts[i].Y;
			m_agg_mtx.transform(&x, &y);
			pts[i].X = (float)x;
			pts[i].Y = (float)y;
		}
	}

	void CMatrix::TransformPoint(double& x, double& y)
	{
		m_agg_mtx.transform(&x, &y);
	}

	void CMatrix::Rotate(double angle, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
	}

	void CMatrix::RotateAt(double angle, const PointF &center, MatrixOrder order)
	{
		Translate(-center.X, -center.Y, order);
		if(order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		Translate(center.X, center.Y, order);
		return;
	}

	void CMatrix::RotateAt(double angle, double x, double y, MatrixOrder order)
	{
		Translate(-x, -y, order);
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		Translate(x, y, order);
	}

	void CMatrix::Multiply(const CMatrix* matrix, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(matrix->m_agg_mtx);
		}
		else
		{
			m_agg_mtx.multiply(matrix->m_agg_mtx);
		}
	}

	double CMatrix::OffsetX() const
	{
		double M[6]; m_agg_mtx.store_to(M);
		return (M[4]);
	}
	double CMatrix::OffsetY() const
	{
		double M[6]; m_agg_mtx.store_to(M);
		return (M[5]);
	}

	Status CMatrix::GetElements(REAL* m) const
	{
		double M[6]; m_agg_mtx.store_to(M);
		m[0]=(REAL)M[0];
		m[1]=(REAL)M[1];
		m[2]=(REAL)M[2];
		m[3]=(REAL)M[3];
		m[4]=(REAL)M[4];
		m[5]=(REAL)M[5];
		return Ok;
	}

	Status CMatrix::GetElements(double* m) const
	{
		m_agg_mtx.store_to(m);
		return Ok;
	}

	void CMatrix::Reset()
	{
		m_agg_mtx.reset();
	}

	const CMatrix& CMatrix::operator=(const CMatrix& Src)
	{
		m_agg_mtx	= Src.m_agg_mtx;
		return		*this;
	}

	Status CMatrix::Invert()
	{
		double d = m_agg_mtx.determinant();
		if (0.0001 >= abs(d))
			return InvalidParameter;

		m_agg_mtx.invert();
		return Ok;
	}

	//Temp
	//Used in X_BrushLinearGradient constructor
	double CMatrix::z_Rotation() const
	{
		return agg::rad2deg(m_agg_mtx.rotation());
	}

	void CMatrix::TransformPoints( PointF* dst, const PointF* src, int count ) const
	{
		for(int i = 0; i < count; ++i)
		{
			double x = src[i].X * m_agg_mtx.sx + src[i].Y * m_agg_mtx.shx + m_agg_mtx.tx;
			double y = src[i].Y * m_agg_mtx.sy + src[i].X * m_agg_mtx.shy + m_agg_mtx.ty;

			dst[i].X = (float)x;
			dst[i].Y = (float)y;
		}
	}

	bool CMatrix::IsIdentity() const
	{
		return m_agg_mtx.is_identity();
	}
	bool CMatrix::IsIdentity2() const
	{
		return agg::is_equal_eps(m_agg_mtx.sx,  1.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.shy, 0.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.shx, 0.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.sy,  1.0, agg::affine_epsilon);
	}
}<commit_msg>git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@55219 954022d7-b5bf-4e40-9824-e11837661b57<commit_after>#include "Matrix.h"

namespace Aggplus
{
	CMatrix::CMatrix(double m11, double m12, double m21, double m22, double dx, double dy) : m_agg_mtx(m11, m12, m21, m22, dx, dy)
	{
	}

	CMatrix::CMatrix() : m_agg_mtx()
	{
	}

	CMatrix::~CMatrix()
	{
	}

	void CMatrix::Translate(double offsetX, double offsetY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_translation(offsetX, offsetY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_translation(offsetX, offsetY));
		}
	}

	void CMatrix::Scale(double scaleX, double scaleY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_scaling(scaleX, scaleY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_scaling(scaleX, scaleY));
		}
	}

	void CMatrix::Shear(double shearX, double shearY, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_skewing(shearX, shearY));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_skewing(shearX, shearY));
		}
	}

	void CMatrix::TransformVectors(PointF* pts, int count)
	{
		// Store matrix to an array [6] of double
		double M[6]; m_agg_mtx.store_to(M);

		for(int i = 0; i < count; ++i)
		{
			double x =pts[i].X;
			double y =pts[i].Y;
			m_agg_mtx.transform(&x, &y);
			pts[i].X =(float)(x-M[4]);
			pts[i].Y =(float)(y-M[5]);
		}
	}

	void CMatrix::TransformPoints(PointF* pts, int count)
	{
		for(int i = 0; i < count; ++i)
		{
			double x = pts[i].X;
			double y = pts[i].Y;
			m_agg_mtx.transform(&x, &y);
			pts[i].X = (float)x;
			pts[i].Y = (float)y;
		}
	}

	void CMatrix::TransformPoint(double& x, double& y)
	{
		m_agg_mtx.transform(&x, &y);
	}

	void CMatrix::Rotate(double angle, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
	}

	void CMatrix::RotateAt(double angle, const PointF &center, MatrixOrder order)
	{
		Translate(-center.X, -center.Y, order);
		if(order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		Translate(center.X, center.Y, order);
		return;
	}

	void CMatrix::RotateAt(double angle, double x, double y, MatrixOrder order)
	{
		Translate(-x, -y, order);
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		else
		{
			m_agg_mtx.multiply(agg::trans_affine_rotation(agg::deg2rad(angle)));
		}
		Translate(x, y, order);
	}

	void CMatrix::Multiply(const CMatrix* matrix, MatrixOrder order)
	{
		if (order == MatrixOrderPrepend)
		{
			m_agg_mtx.premultiply(matrix->m_agg_mtx);
		}
		else
		{
			m_agg_mtx.multiply(matrix->m_agg_mtx);
		}
	}

	double CMatrix::OffsetX() const
	{
		double M[6]; m_agg_mtx.store_to(M);
		return (M[4]);
	}
	double CMatrix::OffsetY() const
	{
		double M[6]; m_agg_mtx.store_to(M);
		return (M[5]);
	}

	Status CMatrix::GetElements(REAL* m) const
	{
		double M[6]; m_agg_mtx.store_to(M);
		m[0]=(REAL)M[0];
		m[1]=(REAL)M[1];
		m[2]=(REAL)M[2];
		m[3]=(REAL)M[3];
		m[4]=(REAL)M[4];
		m[5]=(REAL)M[5];
		return Ok;
	}

	Status CMatrix::GetElements(double* m) const
	{
		m_agg_mtx.store_to(m);
		return Ok;
	}

	void CMatrix::Reset()
	{
		m_agg_mtx.reset();
	}

	const CMatrix& CMatrix::operator=(const CMatrix& Src)
	{
		m_agg_mtx	= Src.m_agg_mtx;
		return		*this;
	}

	Status CMatrix::Invert()
	{
		double d = m_agg_mtx.determinant();
        if (0.0001 >= fabs(d))
			return InvalidParameter;

		m_agg_mtx.invert();
		return Ok;
	}

	//Temp
	//Used in X_BrushLinearGradient constructor
	double CMatrix::z_Rotation() const
	{
		return agg::rad2deg(m_agg_mtx.rotation());
	}

	void CMatrix::TransformPoints( PointF* dst, const PointF* src, int count ) const
	{
		for(int i = 0; i < count; ++i)
		{
			double x = src[i].X * m_agg_mtx.sx + src[i].Y * m_agg_mtx.shx + m_agg_mtx.tx;
			double y = src[i].Y * m_agg_mtx.sy + src[i].X * m_agg_mtx.shy + m_agg_mtx.ty;

			dst[i].X = (float)x;
			dst[i].Y = (float)y;
		}
	}

	bool CMatrix::IsIdentity() const
	{
		return m_agg_mtx.is_identity();
	}
	bool CMatrix::IsIdentity2() const
	{
		return agg::is_equal_eps(m_agg_mtx.sx,  1.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.shy, 0.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.shx, 0.0, agg::affine_epsilon) &&
               agg::is_equal_eps(m_agg_mtx.sy,  1.0, agg::affine_epsilon);
	}
}<|endoftext|>


<commit_before>//! Copyright (c) 2013 ASMlover. All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//!  * Redistributions of source code must retain the above copyright
//!    notice, this list ofconditions and the following disclaimer.
//!
//!  * Redistributions in binary form must reproduce the above copyright
//!    notice, this list of conditions and the following disclaimer in
//!    the documentation and/or other materialsprovided with the
//!    distribution.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//! COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//! POSSIBILITY OF SUCH DAMAGE.
#include <sys/timeb.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "os_tool.h"
#include "message.h"
#include "net.h"

class ConnectorHandler : public EventHandler {
public:
  virtual bool AcceptEvent(Socket* s, Address* addr)
  {
    fprintf(stdout, "accept connector [%d] from <%s, %d>\n",
        s->fd(), addr->ip(), addr->port());
    return true;
  }

  virtual void CloseEvent(Socket* s)
  {
    fprintf(stdout, "connector [%d] closed\n", s->fd());
  }

  virtual bool ReadEvent(Socket* s)
  {
    MessageHeader header;
    char buf[128] = {0};

    if (s->Read(sizeof(header), (char*)&header) > 0) {
      if (s->Read(header.size, buf) > 0) {
        fprintf(stdout, "recv from connector [%d] : %s\n",
            s->fd(), buf);

        s->Write((const char*)&header, sizeof(header));
        s->Write(buf, strlen(buf));
      }
    }

    return true;
  }
};

static void
ServerMain(const char* ip = "127.0.0.1", unsigned short port = 5555)
{
  ConnectorHandler ch;
  SelectNetwork network;

  network.Attach(&ch);
  network.Init();
  if (network.Listen(ip, port)) {
    fprintf(stdout, "server starting <%s, %d> ...\n", ip, port);
  }
  else {
    fprintf(stderr, "server starting failed ...\n");
    return;
  }

  while (true)
    Tools::Sleep(100);

  network.Destroy();
}

static void
ClientMain(const char* ip = "127.0.0.1", unsigned short port = 5555)
{
  Socket s;
  s.Open();

  if (s.Connect(ip, port)) {
    fprintf(stdout, "connect to server <%s, %d> success ...\n", ip, port);
  }
  else {
    fprintf(stderr, "connect to server failed ...\n");
    return;
  }

  char buf[128];
  struct timeb tb;
  struct tm* now;
  MessageHeader header;
  while (true) {
    ftime(&tb);
    now = localtime(&tb.time);
    sprintf(buf, "[%04d-%02d-%02d %02d:%02d:%02d:%03d]",
        now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,
        now->tm_hour, now->tm_min, now->tm_sec, tb.millitm);
    header.size = strlen(buf);
    s.WriteBlock((const char*)&header, sizeof(header));
    s.WriteBlock(buf, header.size);

    memset(&header, 0, sizeof(header));
    memset(buf, 0, sizeof(buf));
    if (kNetTypeError == s.ReadBlock(sizeof(header), (char*)&header))
      break;
    if (kNetTypeError == s.ReadBlock(header.size, buf))
      break;
    fprintf(stdout, "recv from server : %s\n", buf);

    Tools::Sleep(0);
  }

  s.Close();
}

int
main(int argc, char* argv[])
{
  if (argc < 2)  {
    fprintf(stderr, "usage : test [option ...]\n");
    return 0;
  }

  NetLibrary::Singleton().Init();

  if (0 == strcmp(argv[1], "srv"))
    ServerMain();
  else if (0 == strcmp(argv[1], "clt"))
    ClientMain();

  NetLibrary::Singleton().Destroy();
  return 0;
}
<commit_msg>add async client demo<commit_after>//! Copyright (c) 2013 ASMlover. All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//!  * Redistributions of source code must retain the above copyright
//!    notice, this list ofconditions and the following disclaimer.
//!
//!  * Redistributions in binary form must reproduce the above copyright
//!    notice, this list of conditions and the following disclaimer in
//!    the documentation and/or other materialsprovided with the
//!    distribution.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//! COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//! POSSIBILITY OF SUCH DAMAGE.
#include <sys/timeb.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "os_tool.h"
#include "message.h"
#include "net.h"

class ConnectorHandler : public EventHandler {
public:
  virtual bool AcceptEvent(Socket* s, Address* addr)
  {
    fprintf(stdout, "accept connector [%d] from <%s, %d>\n",
        s->fd(), addr->ip(), addr->port());
    return true;
  }

  virtual void CloseEvent(Socket* s)
  {
    fprintf(stdout, "connector [%d] closed\n", s->fd());
  }

  virtual bool ReadEvent(Socket* s)
  {
    MessageHeader header;
    char buf[128] = {0};

    if (s->Read(sizeof(header), (char*)&header) > 0) {
      if (s->Read(header.size, buf) > 0) {
        fprintf(stdout, "recv from connector [%d] : %s\n",
            s->fd(), buf);

        s->Write((const char*)&header, sizeof(header));
        s->Write(buf, strlen(buf));
      }
    }

    return true;
  }
};

static void
ServerMain(const char* ip = "127.0.0.1", unsigned short port = 5555)
{
  ConnectorHandler ch;
  SelectNetwork network;

  network.Attach(&ch);
  network.Init();
  if (network.Listen(ip, port)) {
    fprintf(stdout, "server starting <%s, %d> ...\n", ip, port);
  }
  else {
    fprintf(stderr, "server starting failed ...\n");
    return;
  }

  while (true)
    Tools::Sleep(100);

  network.Destroy();
}

static void
ClientMain(const char* ip = "127.0.0.1", unsigned short port = 5555)
{
  Socket s;
  s.Open();

  if (s.Connect(ip, port)) {
    fprintf(stdout, "connect to server <%s, %d> success ...\n", ip, port);
  }
  else {
    fprintf(stderr, "connect to server failed ...\n");
    return;
  }

  char buf[128];
  struct timeb tb;
  struct tm* now;
  MessageHeader header;
  while (true) {
    ftime(&tb);
    now = localtime(&tb.time);
    sprintf(buf, "[%04d-%02d-%02d %02d:%02d:%02d:%03d]",
        now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,
        now->tm_hour, now->tm_min, now->tm_sec, tb.millitm);
    header.size = strlen(buf);
    s.WriteBlock((const char*)&header, sizeof(header));
    s.WriteBlock(buf, header.size);

    memset(&header, 0, sizeof(header));
    memset(buf, 0, sizeof(buf));
    if (kNetTypeError == s.ReadBlock(sizeof(header), (char*)&header))
      break;
    if (kNetTypeError == s.ReadBlock(header.size, buf))
      break;
    fprintf(stdout, "recv from server : %s\n", buf);

    Tools::Sleep(0);
  }

  s.Close();
}

static bool _s_connected = false;
class ClientHandler : public EventHandler {
public:
  virtual void CloseEvent(Socket* s)
  {
    fprintf(stdout, "client [%d] closed\n", s->fd());
    _s_connected = false;
  }

  virtual bool ReadEvent(Socket* s)
  {
    MessageHeader header;
    char buf[128] = {0};

    if (s->Read(sizeof(header), (char*)&header) > 0) {
      if (s->Read(header.size, buf) > 0) {
        fprintf(stdout, "recv from server [%d] : %s\n",
            s->fd(), buf);
      }
    }

    return true;
  }
};

static void
AsyncClientMain(const char* ip = "127.0.0.1", unsigned short port = 5555)
{
  ClientHandler ch;
  SelectNetwork network;

  network.Attach(&ch);
  network.Init();

  Socket* s = network.Connect(ip, port);
  if (NULL == s) {
    fprintf(stderr, "connect to server failed ...\n");
    return;
  }
  else {
    fprintf(stdout, "connect to server<%s, %d> success ...\n", ip, port);
  }
  _s_connected = true;

  char buf[128];
  struct timeb tb;
  struct tm* now;
  MessageHeader header;
  while (_s_connected) {
    ftime(&tb);
    now = localtime(&tb.time);
    sprintf(buf, "[%04d-%02d-%02d %02d:%02d:%02d:%03d]",
        now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,
        now->tm_hour, now->tm_min, now->tm_sec, tb.millitm);
    header.size = strlen(buf);
    s->Write((const char*)&header, sizeof(header));
    s->Write(buf, header.size);

    Tools::Sleep(0);
  }
}

int
main(int argc, char* argv[])
{
  if (argc < 2)  {
    fprintf(stderr, "usage : test [option ...]\n");
    return 0;
  }

  NetLibrary::Singleton().Init();

  if (0 == strcmp(argv[1], "srv"))
    ServerMain();
  else if (0 == strcmp(argv[1], "clt"))
    ClientMain();
  else if (0 == strcmp(argv[1], "async-clt"))
    AsyncClientMain();

  NetLibrary::Singleton().Destroy();
  return 0;
}
<|endoftext|>


<commit_before>// MIT License
//
// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <iostream>
#include <vector>
#include <algorithm>

// Google Test
#include <gtest/gtest.h>
// HIP API
#include <hip/hip_runtime.h>
// rocPRIM API
#include <rocprim/rocprim.hpp>

#include "test_utils.hpp"

#define HIP_CHECK(error)         \
    ASSERT_EQ(static_cast<hipError_t>(error),hipSuccess)

namespace rp = rocprim;

// Params for tests
template<
    class InputType,
    class OutputType = InputType
>
struct DeviceTransformParams
{
    using input_type = InputType;
    using output_type = OutputType;
};

// ---------------------------------------------------------
// Test for reduce ops taking single input value
// ---------------------------------------------------------

template<class Params>
class RocprimDeviceTransformTests : public ::testing::Test
{
public:
    using input_type = typename Params::input_type;
    using output_type = typename Params::output_type;
    const bool debug_synchronous = false;
};

typedef ::testing::Types<
    DeviceTransformParams<int>,
    DeviceTransformParams<unsigned long>,
    DeviceTransformParams<short, int>,
    DeviceTransformParams<int, float>
> RocprimDeviceTransformTestsParams;

std::vector<size_t> get_sizes()
{
    std::vector<size_t> sizes = {
        1, 10, 53, 211,
        1024, 2048, 5096,
        34567, (1 << 17) - 1220
    };
    const std::vector<size_t> random_sizes = test_utils::get_random_data<size_t>(2, 1, 16384);
    sizes.insert(sizes.end(), random_sizes.begin(), random_sizes.end());
    std::sort(sizes.begin(), sizes.end());
    return sizes;
}

TYPED_TEST_CASE(RocprimDeviceTransformTests, RocprimDeviceTransformTestsParams);

template<class T>
struct transform
{
    __device__ __host__ inline
    constexpr T operator()(const T& a) const
    {
        return a + 5;
    }
};

TYPED_TEST(RocprimDeviceTransformTests, Transform)
{
    using T = typename TestFixture::input_type;
    using U = typename TestFixture::output_type;
    const bool debug_synchronous = TestFixture::debug_synchronous;

    const std::vector<size_t> sizes = get_sizes();
    for(auto size : sizes)
    {
        hipStream_t stream = 0; // default

        SCOPED_TRACE(testing::Message() << "with size = " << size);

        // Generate data
        std::vector<T> input = test_utils::get_random_data<T>(size, 1, 100);
        std::vector<U> output(input.size(), 0);

        T * d_input;
        U * d_output;
        HIP_CHECK(hipMalloc(&d_input, input.size() * sizeof(T)));
        HIP_CHECK(hipMalloc(&d_output, output.size() * sizeof(U)));
        HIP_CHECK(
            hipMemcpy(
                d_input, input.data(),
                input.size() * sizeof(T),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Calculate expected results on host
        std::vector<U> expected(input.size());
        std::transform(input.begin(), input.end(), expected.begin(), transform<U>());

        // Run
        HIP_CHECK(
            rocprim::transform(
                d_input, d_output, input.size(),
                transform<U>(), stream, debug_synchronous
            )
        );
        HIP_CHECK(hipPeekAtLastError());
        HIP_CHECK(hipDeviceSynchronize());

        // Copy output to host
        HIP_CHECK(
            hipMemcpy(
                output.data(), d_output,
                output.size() * sizeof(U),
                hipMemcpyDeviceToHost
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Check if output values are as expected
        for(size_t i = 0; i < output.size(); i++)
        {
            SCOPED_TRACE(testing::Message() << "where index = " << i);
            auto diff = std::max<U>(std::abs(0.01f * expected[i]), U(0.01f));
            if(std::is_integral<U>::value) diff = 0;
            ASSERT_NEAR(output[i], expected[i], diff);
        }

        hipFree(d_input);
        hipFree(d_output);
    }
}

template<class T1, class T2, class U>
struct binary_transform
{
    __device__ __host__ inline
    constexpr U operator()(const T1& a, const T2& b) const
    {
        return a + b;
    }
};

TYPED_TEST(RocprimDeviceTransformTests, BinaryTransform)
{
    using T1 = typename TestFixture::input_type;
    using T2 = typename TestFixture::input_type;
    using U = typename TestFixture::output_type;
    const bool debug_synchronous = TestFixture::debug_synchronous;

    const std::vector<size_t> sizes = get_sizes();
    for(auto size : sizes)
    {
        hipStream_t stream = 0; // default

        SCOPED_TRACE(testing::Message() << "with size = " << size);

        // Generate data
        std::vector<T1> input1 = test_utils::get_random_data<T1>(size, 1, 100);
        std::vector<T2> input2 = test_utils::get_random_data<T2>(size, 1, 100);
        std::vector<U> output(input1.size(), 0);

        T1 * d_input1;
        T2 * d_input2;
        U * d_output;
        HIP_CHECK(hipMalloc(&d_input1, input1.size() * sizeof(T1)));
        HIP_CHECK(hipMalloc(&d_input2, input2.size() * sizeof(T2)));
        HIP_CHECK(hipMalloc(&d_output, output.size() * sizeof(U)));
        HIP_CHECK(
            hipMemcpy(
                d_input1, input1.data(),
                input1.size() * sizeof(T1),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(
            hipMemcpy(
                d_input2, input2.data(),
                input2.size() * sizeof(T2),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Calculate expected results on host
        std::vector<U> expected(input1.size());
        std::transform(
            input1.begin(), input1.end(), input2.begin(),
            expected.begin(), binary_transform<T1, T2, U>()
        );

        // Run
        HIP_CHECK(
            rocprim::transform(
                d_input1, d_input2, d_output, input1.size(),
                binary_transform<T1, T2, U>(), stream, debug_synchronous
            )
        );
        HIP_CHECK(hipPeekAtLastError());
        HIP_CHECK(hipDeviceSynchronize());

        // Copy output to host
        HIP_CHECK(
            hipMemcpy(
                output.data(), d_output,
                output.size() * sizeof(U),
                hipMemcpyDeviceToHost
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Check if output values are as expected
        for(size_t i = 0; i < output.size(); i++)
        {
            SCOPED_TRACE(testing::Message() << "where index = " << i);
            auto diff = std::max<U>(std::abs(0.01f * expected[i]), U(0.01f));
            if(std::is_integral<U>::value) diff = 0;
            ASSERT_NEAR(output[i], expected[i], diff);
        }

        hipFree(d_input1);
        hipFree(d_input2);
        hipFree(d_output);
    }
}
<commit_msg>Use identity_iterator in transform test (HIP)<commit_after>// MIT License
//
// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <iostream>
#include <vector>
#include <algorithm>

// Google Test
#include <gtest/gtest.h>
// HIP API
#include <hip/hip_runtime.h>
// rocPRIM API
#include <rocprim/rocprim.hpp>

#include "test_utils.hpp"

#define HIP_CHECK(error)         \
    ASSERT_EQ(static_cast<hipError_t>(error),hipSuccess)

namespace rp = rocprim;

// Params for tests
template<
    class InputType,
    class OutputType = InputType,
    bool UseIdentityIterator = false
>
struct DeviceTransformParams
{
    using input_type = InputType;
    using output_type = OutputType;
    static constexpr bool use_identity_iterator = UseIdentityIterator;
};

// ---------------------------------------------------------
// Test for reduce ops taking single input value
// ---------------------------------------------------------

template<class Params>
class RocprimDeviceTransformTests : public ::testing::Test
{
public:
    using input_type = typename Params::input_type;
    using output_type = typename Params::output_type;
    static constexpr bool use_identity_iterator = Params::use_identity_iterator;
    static constexpr bool debug_synchronous = false;
};

typedef ::testing::Types<
    DeviceTransformParams<int, int, true>,
    DeviceTransformParams<unsigned long>,
    DeviceTransformParams<short, int, true>,
    DeviceTransformParams<int, float>
> RocprimDeviceTransformTestsParams;

std::vector<size_t> get_sizes()
{
    std::vector<size_t> sizes = {
        1, 10, 53, 211,
        1024, 2048, 5096,
        34567, (1 << 17) - 1220
    };
    const std::vector<size_t> random_sizes = test_utils::get_random_data<size_t>(2, 1, 16384);
    sizes.insert(sizes.end(), random_sizes.begin(), random_sizes.end());
    std::sort(sizes.begin(), sizes.end());
    return sizes;
}

TYPED_TEST_CASE(RocprimDeviceTransformTests, RocprimDeviceTransformTestsParams);

template<class T>
struct transform
{
    __device__ __host__ inline
    constexpr T operator()(const T& a) const
    {
        return a + 5;
    }
};

TYPED_TEST(RocprimDeviceTransformTests, Transform)
{
    using T = typename TestFixture::input_type;
    using U = typename TestFixture::output_type;
    static constexpr bool use_identity_iterator = TestFixture::use_identity_iterator;
    const bool debug_synchronous = TestFixture::debug_synchronous;

    const std::vector<size_t> sizes = get_sizes();
    for(auto size : sizes)
    {
        hipStream_t stream = 0; // default

        SCOPED_TRACE(testing::Message() << "with size = " << size);

        // Generate data
        std::vector<T> input = test_utils::get_random_data<T>(size, 1, 100);
        std::vector<U> output(input.size(), 0);

        T * d_input;
        U * d_output;
        HIP_CHECK(hipMalloc(&d_input, input.size() * sizeof(T)));
        HIP_CHECK(hipMalloc(&d_output, output.size() * sizeof(U)));
        HIP_CHECK(
            hipMemcpy(
                d_input, input.data(),
                input.size() * sizeof(T),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Calculate expected results on host
        std::vector<U> expected(input.size());
        std::transform(input.begin(), input.end(), expected.begin(), transform<U>());

        // Run
        HIP_CHECK(
            rocprim::transform(
                d_input,
                test_utils::wrap_in_identity_iterator<use_identity_iterator>(d_output),
                input.size(), transform<U>(), stream, debug_synchronous
            )
        );
        HIP_CHECK(hipPeekAtLastError());
        HIP_CHECK(hipDeviceSynchronize());

        // Copy output to host
        HIP_CHECK(
            hipMemcpy(
                output.data(), d_output,
                output.size() * sizeof(U),
                hipMemcpyDeviceToHost
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Check if output values are as expected
        for(size_t i = 0; i < output.size(); i++)
        {
            SCOPED_TRACE(testing::Message() << "where index = " << i);
            auto diff = std::max<U>(std::abs(0.01f * expected[i]), U(0.01f));
            if(std::is_integral<U>::value) diff = 0;
            ASSERT_NEAR(output[i], expected[i], diff);
        }

        hipFree(d_input);
        hipFree(d_output);
    }
}

template<class T1, class T2, class U>
struct binary_transform
{
    __device__ __host__ inline
    constexpr U operator()(const T1& a, const T2& b) const
    {
        return a + b;
    }
};

TYPED_TEST(RocprimDeviceTransformTests, BinaryTransform)
{
    using T1 = typename TestFixture::input_type;
    using T2 = typename TestFixture::input_type;
    using U = typename TestFixture::output_type;
    static constexpr bool use_identity_iterator = TestFixture::use_identity_iterator;
    const bool debug_synchronous = TestFixture::debug_synchronous;

    const std::vector<size_t> sizes = get_sizes();
    for(auto size : sizes)
    {
        hipStream_t stream = 0; // default

        SCOPED_TRACE(testing::Message() << "with size = " << size);

        // Generate data
        std::vector<T1> input1 = test_utils::get_random_data<T1>(size, 1, 100);
        std::vector<T2> input2 = test_utils::get_random_data<T2>(size, 1, 100);
        std::vector<U> output(input1.size(), 0);

        T1 * d_input1;
        T2 * d_input2;
        U * d_output;
        HIP_CHECK(hipMalloc(&d_input1, input1.size() * sizeof(T1)));
        HIP_CHECK(hipMalloc(&d_input2, input2.size() * sizeof(T2)));
        HIP_CHECK(hipMalloc(&d_output, output.size() * sizeof(U)));
        HIP_CHECK(
            hipMemcpy(
                d_input1, input1.data(),
                input1.size() * sizeof(T1),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(
            hipMemcpy(
                d_input2, input2.data(),
                input2.size() * sizeof(T2),
                hipMemcpyHostToDevice
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Calculate expected results on host
        std::vector<U> expected(input1.size());
        std::transform(
            input1.begin(), input1.end(), input2.begin(),
            expected.begin(), binary_transform<T1, T2, U>()
        );

        // Run
        HIP_CHECK(
            rocprim::transform(
                d_input1, d_input2,
                test_utils::wrap_in_identity_iterator<use_identity_iterator>(d_output),
                input1.size(), binary_transform<T1, T2, U>(), stream, debug_synchronous
            )
        );
        HIP_CHECK(hipPeekAtLastError());
        HIP_CHECK(hipDeviceSynchronize());

        // Copy output to host
        HIP_CHECK(
            hipMemcpy(
                output.data(), d_output,
                output.size() * sizeof(U),
                hipMemcpyDeviceToHost
            )
        );
        HIP_CHECK(hipDeviceSynchronize());

        // Check if output values are as expected
        for(size_t i = 0; i < output.size(); i++)
        {
            SCOPED_TRACE(testing::Message() << "where index = " << i);
            auto diff = std::max<U>(std::abs(0.01f * expected[i]), U(0.01f));
            if(std::is_integral<U>::value) diff = 0;
            ASSERT_NEAR(output[i], expected[i], diff);
        }

        hipFree(d_input1);
        hipFree(d_input2);
        hipFree(d_output);
    }
}
<|endoftext|>


<commit_before>#include "labelContainer.h"
#include "tile/mapTile.h"

LabelContainer::LabelContainer() {}

LabelContainer::~LabelContainer() {
    m_labels.clear();
    m_pendingLabels.clear();
}

bool LabelContainer::addLabel(const TileID& _tileID, const std::string& _styleName, LabelTransform _transform, std::string _text, Label::Type _type, const glm::mat4& _model) {
    auto currentBuffer = m_ftContext->getCurrentBuffer();

    if (currentBuffer) {
        auto& container = m_pendingLabels[_styleName][_tileID];

        // lock concurrent collection
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            container.emplace_back(_transform, _text, currentBuffer, _type);

            container.back().rasterize();

            // ensure label is updated once
            container.back().update(m_viewProjection * _model, m_screenSize, 0);
        }

        return true;
    }

    return false;
}

void LabelContainer::removeLabels(const TileID& _tileID) {
    if (m_labels.size() > 0) {
        for (auto& styleTilepair : m_labels) {
            std::string styleName = styleTilepair.first;

            for (auto& tileLabelsPair : m_labels[styleName]) {
                const TileID& tileID = tileLabelsPair.first;
                if (tileID == _tileID) {
                    m_labels[styleName][tileID].clear();
                    {
                        std::lock_guard<std::mutex> lock(m_mutex);
                        m_pendingLabels[styleName][tileID].clear();
                    }
                }
            }
        }
    }
}

const std::vector<std::shared_ptr<Label>>& LabelContainer::getLabels(const std::string& _styleName, const TileID& _tileID) {
    return m_labels[_styleName][_tileID];
}

void LabelContainer::updateOcclusions() {
    // merge pending labels from threads
    for (auto& styleTilepair : m_pendingLabels) {
        std::string styleName = styleTilepair.first;

        for (auto& tileLabelsPair : m_pendingLabels[styleName]) {
            const TileID& tileID = tileLabelsPair.first;
            auto& pendingLabels = m_pendingLabels[styleName][tileID];
            auto& labels = m_labels[styleName][tileID];

            for (auto& label : pendingLabels) {
                // create a shared pointer as a copy of the label created in the thread
                labels.emplace_back(new Label(label));
            }

            {
                std::lock_guard<std::mutex> lock(m_mutex);
                pendingLabels.clear();
            }
        }
    }

    std::set<std::pair<std::shared_ptr<Label>, std::shared_ptr<Label>>> occlusions;
    std::vector<isect2d::AABB> aabbs;

    for (auto& styleTilepair : m_labels) {
        std::string styleName = styleTilepair.first;
        for (auto& tileLabelsPair : m_labels[styleName]) {
            auto& labels = tileLabelsPair.second;
            for(auto& label : labels) {
                if (!label->isVisible() || label->isOutOfScreen() || label->getType() == Label::Type::DEBUG) {
                    continue;
                }

                isect2d::AABB aabb = label->getAABB();
                aabb.m_userData = (void*) &label;
                aabbs.push_back(aabb);
            }
        }
    }

    // broad phase
    auto pairs = intersect(aabbs);

    for (auto pair : pairs) {
        const auto& aabb1 = aabbs[pair.first];
        const auto& aabb2 = aabbs[pair.second];

        auto l1 = *(std::shared_ptr<Label>*) aabb1.m_userData;
        auto l2 = *(std::shared_ptr<Label>*) aabb2.m_userData;

        // narrow phase
        if (intersect(l1->getOBB(), l2->getOBB())) {
            occlusions.insert({ l1, l2 });
        }
    }

    // no priorities, only occlude one of the two occluded label
    for (auto& pair : occlusions) {
        if(pair.second->isVisible()) {
            pair.first->setVisible(false);
        }
    }
}
<commit_msg>reduce time of locked thread state - Labels were before used as a shared_ptr, now that the thread is working on a Label object that is copied later on main thread we can rasterize and update on un-locked context<commit_after>#include "labelContainer.h"
#include "tile/mapTile.h"

LabelContainer::LabelContainer() {}

LabelContainer::~LabelContainer() {
    m_labels.clear();
    m_pendingLabels.clear();
}

bool LabelContainer::addLabel(const TileID& _tileID, const std::string& _styleName, LabelTransform _transform, std::string _text, Label::Type _type, const glm::mat4& _model) {
    auto currentBuffer = m_ftContext->getCurrentBuffer();

    if (currentBuffer) {
        auto& container = m_pendingLabels[_styleName][_tileID];
        Label l(_transform, _text, currentBuffer, _type);

        l.rasterize();
        l.update(m_viewProjection * _model, m_screenSize, 0);

        // lock concurrent collection
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            container.push_back(l);
        }

        return true;
    }

    return false;
}

void LabelContainer::removeLabels(const TileID& _tileID) {
    if (m_labels.size() > 0) {
        for (auto& styleTilepair : m_labels) {
            std::string styleName = styleTilepair.first;

            for (auto& tileLabelsPair : m_labels[styleName]) {
                const TileID& tileID = tileLabelsPair.first;
                if (tileID == _tileID) {
                    m_labels[styleName][tileID].clear();
                    {
                        std::lock_guard<std::mutex> lock(m_mutex);
                        m_pendingLabels[styleName][tileID].clear();
                    }
                }
            }
        }
    }
}

const std::vector<std::shared_ptr<Label>>& LabelContainer::getLabels(const std::string& _styleName, const TileID& _tileID) {
    return m_labels[_styleName][_tileID];
}

void LabelContainer::updateOcclusions() {
    // merge pending labels from threads
    for (auto& styleTilepair : m_pendingLabels) {
        std::string styleName = styleTilepair.first;

        for (auto& tileLabelsPair : m_pendingLabels[styleName]) {
            const TileID& tileID = tileLabelsPair.first;
            auto& pendingLabels = m_pendingLabels[styleName][tileID];
            auto& labels = m_labels[styleName][tileID];

            for (auto& label : pendingLabels) {
                // create a shared pointer as a copy of the label created in the thread
                labels.emplace_back(new Label(label));
            }

            {
                std::lock_guard<std::mutex> lock(m_mutex);
                pendingLabels.clear();
            }
        }
    }

    std::set<std::pair<std::shared_ptr<Label>, std::shared_ptr<Label>>> occlusions;
    std::vector<isect2d::AABB> aabbs;

    for (auto& styleTilepair : m_labels) {
        std::string styleName = styleTilepair.first;
        for (auto& tileLabelsPair : m_labels[styleName]) {
            auto& labels = tileLabelsPair.second;
            for(auto& label : labels) {
                if (!label->isVisible() || label->isOutOfScreen() || label->getType() == Label::Type::DEBUG) {
                    continue;
                }

                isect2d::AABB aabb = label->getAABB();
                aabb.m_userData = (void*) &label;
                aabbs.push_back(aabb);
            }
        }
    }

    // broad phase
    auto pairs = intersect(aabbs);

    for (auto pair : pairs) {
        const auto& aabb1 = aabbs[pair.first];
        const auto& aabb2 = aabbs[pair.second];

        auto l1 = *(std::shared_ptr<Label>*) aabb1.m_userData;
        auto l2 = *(std::shared_ptr<Label>*) aabb2.m_userData;

        // narrow phase
        if (intersect(l1->getOBB(), l2->getOBB())) {
            occlusions.insert({ l1, l2 });
        }
    }

    // no priorities, only occlude one of the two occluded label
    for (auto& pair : occlusions) {
        if(pair.second->isVisible()) {
            pair.first->setVisible(false);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "libmv/multiview/reconstruction_image_order_selection.h"
#include "libmv/multiview/robust_homography.h"

namespace libmv {

void SelectEfficientImageOrder(
    const Matches &matches,
    std::list<vector<Matches::ImageID> >*connected_graph_list) {
  typedef std::pair<Matches::ImageID, Matches::ImageID> ImagesTypePairs;
  typedef vector<ImagesTypePairs > ImagesPairs;
  double h, score, max_error_h = 1;
  Mat3 H;

  // TODO(julien) Find connected graph and do the rest of every graph
  {
    // Selects the two views that are not too closed but share common tracks
    size_t i = 0;
    double score_max_1 = 0;
    ImagesTypePairs image_pair_max_1;
    vector<Mat2X> xs(matches.NumImages());
    std::set<Matches::ImageID>::const_iterator image_iter1 =
      matches.get_images().begin();
    std::set<Matches::ImageID>::const_iterator image_iter2;
    image_pair_max_1 = ImagesTypePairs(*matches.get_images().begin(),
                                       *(++matches.get_images().begin()));
    vector<Mat> xs2;
    // HACK(julien) we force to keep the first image
    // TODO(julien) implements a better selection
    //for (;image_iter1 != matches.get_images().end(); ++image_iter1) {
    {
      image_iter2 = image_iter1;
      image_iter2++;
      for (;image_iter2 != matches.get_images().end(); ++image_iter2) {
        TwoViewPointMatchMatrices(matches, *image_iter1, *image_iter2, &xs2);
        if (xs2[0].cols() >= 4) {
          h = HomographyFromCorrespondences4PointRobust(xs2[0], xs2[1],
                                                        max_error_h,
                                                        &H, NULL, 1e-2);
          // the score is homography x number of matches
          //TODO(julien) Actually it should be the median of the homography...
          score = h * xs2[0].cols();
          i++;
          VLOG(1)   << "Score["<<i<<"] = " << score <<"\n";
          if (score > score_max_1) {
            score_max_1 = score;
            image_pair_max_1 = ImagesTypePairs(*image_iter1, *image_iter2);
            VLOG(1)   << " max score found !\n";
          }
        }
      }
    }
    vector<Matches::ImageID> v(matches.NumImages());
    if (score_max_1 != 0) {
      v[0] = image_pair_max_1.first;
      v[1] = image_pair_max_1.second;
      i = 2;
    } else {
      i = 0;
    }
    // Fill the rest of images (not ordered)
    // TODO(julien) maybe we can do better than a non ordered list here?
    image_iter1 = matches.get_images().begin();
    for (;image_iter1 != matches.get_images().end(); ++image_iter1) {
      if (score_max_1 == 0 || (*image_iter1 != v[0] && *image_iter1 != v[1])) {
        v[i] = *image_iter1;
        ++i;
      }
    }
    connected_graph_list->push_back(v);
  }
}
} // namespace libmv
<commit_msg>Add a image order selection method based on a max score selection.<commit_after>// Copyright (c) 2010 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <map>

#include "libmv/multiview/reconstruction_image_order_selection.h"
#include "libmv/multiview/robust_homography.h"

namespace libmv {

void FillPairwiseMatchesMatrix(const Matches &matches,
                               Mat *m) {
  m->resize(matches.NumImages(),
            matches.NumImages());
  m->setZero();
  std::set<Matches::ImageID>::const_iterator image_iter1 =
    matches.get_images().begin();
  std::set<Matches::ImageID>::const_iterator image_iter2;
  vector<Mat> xs2;
  for (;image_iter1 != matches.get_images().end(); ++image_iter1) {
    image_iter2 = image_iter1;
    image_iter2++;
    for (;image_iter2 != matches.get_images().end(); ++image_iter2) {
      TwoViewPointMatchMatrices(matches, *image_iter1, *image_iter2, &xs2);
      (*m)(*image_iter1, *image_iter2) = xs2[0].cols();
    }
  }
}

void FillPairwiseMatchesHomographyMatrix(const Matches &matches,
                                         Mat *m) {
  m->resize(matches.NumImages(),
            matches.NumImages());
  m->setZero();
  double h, max_error_h = 1;
  Mat3 H;
  std::set<Matches::ImageID>::const_iterator image_iter1 =
    matches.get_images().begin();
  std::set<Matches::ImageID>::const_iterator image_iter2;
  vector<Mat> xs2;
  for (;image_iter1 != matches.get_images().end(); ++image_iter1) {
    image_iter2 = image_iter1;
    image_iter2++;
    for (;image_iter2 != matches.get_images().end(); ++image_iter2) {
      TwoViewPointMatchMatrices(matches, *image_iter1, *image_iter2, &xs2);
      (*m)(*image_iter1, *image_iter2) = xs2[0].cols();
      if (xs2[0].cols() >= 4) {
        h = HomographyFromCorrespondences4PointRobust(xs2[0], xs2[1],
                                                      max_error_h,
                                                      &H, NULL, 1e-2);
        (*m)(*image_iter1, *image_iter2) *= h;
      }
    }
  }
}

bool AddIndex(int id, vector<uint> *id_ordered) {
  for (uint i = 0; i < id_ordered->size() ;++i) {
    if ((*id_ordered)[i] == id) {
      return false;
    }
  }
  id_ordered->push_back(id);
  return true;
}

void RecursivePairwiseHighScoresSearch(Mat &m,
                                       const Vec2i seed,
                                       vector<uint> *id_ordered) {
  double val_c, val_r;
  Vec2i max_c, max_r;
  int nothing;
  // Set to zero (to avoid to get the same couple)
  m(seed[0], seed[1]) = 0;

  // Find the best score for the col
  val_c = m.col(seed[1]).maxCoeff(&max_c[0], &nothing);
  max_c[1] = seed[1];
  // Find the best score for the row
  val_r = m.row(seed[0]).maxCoeff(&nothing, &max_r[1]);
  max_r[0] = seed[0];

  if (val_c > 0)
    m(max_c[0], max_c[1]) = 0;
  if (val_r > 0)
    m(max_r[0], max_r[1]) = 0;

  if (val_c < val_r) {
    if (val_r > 0) {
      AddIndex(max_r[1], id_ordered);
      RecursivePairwiseHighScoresSearch(m, max_r, id_ordered);
    }
    if (val_c > 0) {
      AddIndex(max_c[0], id_ordered);
      RecursivePairwiseHighScoresSearch(m, max_c, id_ordered);
    }
  } else {
    if (val_c > 0) {
      AddIndex(max_c[0], id_ordered);
      RecursivePairwiseHighScoresSearch(m, max_c, id_ordered);
    }
    if (val_r > 0){
      AddIndex(max_r[1], id_ordered);
      RecursivePairwiseHighScoresSearch(m, max_r, id_ordered);
    }
  }
}

void RecoverOrderFromPairwiseHighScores(
   const Matches &matches,
   Mat &m,
   std::list<vector<Matches::ImageID> > *connected_graph_list) {
  //connected_graph_list->clear();
  std::map<uint, Matches::ImageID> map_img_ids;
  std::set<Matches::ImageID>::const_iterator image_iter1 =
    matches.get_images().begin();
  uint i_img = 0;
  for (;image_iter1 != matches.get_images().end(); ++image_iter1, ++i_img) {
    map_img_ids[i_img] = *image_iter1;
  }

  Vec2i max;
  double val = 1;
  while (val > 0) {
    // Find the global best score
    val = m.maxCoeff(&max[0], &max[1]);
    //From this seed, find the second best score in the same col/row
    if (val > 0) {
      vector<uint> id_ordered;
      id_ordered.push_back(max[0]);
      id_ordered.push_back(max[1]);
      RecursivePairwiseHighScoresSearch(m, max, &id_ordered);
      vector<Matches::ImageID> v_ids(id_ordered.size());
      for (i_img = 0; i_img < id_ordered.size(); ++i_img) {
        v_ids[i_img] = (map_img_ids[id_ordered[i_img]]);
      }
      connected_graph_list->push_back(v_ids);
    }
  }
}

void SelectEfficientImageOrder(
    const Matches &matches,
    std::list<vector<Matches::ImageID> >*connected_graph_list) {
  Mat m;
  FillPairwiseMatchesHomographyMatrix(matches, &m);
  std::cout << " M = " << m <<"\n";
  RecoverOrderFromPairwiseHighScores(matches, m, connected_graph_list);
}

} // namespace libmv<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/portability/GTest.h>

#include <thrift/test/gen-cpp2/fatal_optionals_fatal.h>
#include <thrift/test/gen-cpp2/fatal_optionals_types.h>

class FatalOptionalsTest : public testing::Test {};

TEST_F(FatalOptionalsTest, isset) {
  using type = apache::thrift::test::has_fields;
  using meta = apache::thrift::reflect_struct<type>;

  {
    using member = meta::member::reqd;

    type obj;
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_TRUE(member::is_set(obj));
    static_assert(
        std::is_same<decltype(member::getter::ref(obj)), int32_t&>::value, "");
  }

  {
    using member = meta::member::norm;

    type obj;
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_TRUE(member::is_set(obj));
    static_assert(
        std::is_same<decltype(member::getter::ref(obj)), int32_t&>::value, "");
  }

  {
    using member = meta::member::optl;

    type obj;
    EXPECT_FALSE(meta::member::optl::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_FALSE(member::is_set(obj));
  }

  {
    using member = meta::member::optl;

    type obj;
    obj.optl = 3;
    EXPECT_TRUE(meta::member::optl::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_FALSE(member::is_set(obj));

    static_assert(
        std::is_same<
            decltype(member::getter::ref(obj)),
            apache::thrift::DeprecatedOptionalField<int32_t>&>::value,
        "");
  }
}
<commit_msg>Migrate to field_ref Thrift API<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/portability/GTest.h>

#include <thrift/test/gen-cpp2/fatal_optionals_fatal.h>
#include <thrift/test/gen-cpp2/fatal_optionals_types.h>

class FatalOptionalsTest : public testing::Test {};

TEST_F(FatalOptionalsTest, isset) {
  using type = apache::thrift::test::has_fields;
  using meta = apache::thrift::reflect_struct<type>;

  {
    using member = meta::member::reqd;

    type obj;
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_TRUE(member::is_set(obj));
    static_assert(
        std::is_same<decltype(member::getter::ref(obj)), int32_t&>::value, "");
  }

  {
    using member = meta::member::norm;

    type obj;
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_TRUE(member::is_set(obj));
    static_assert(
        std::is_same<decltype(member::getter::ref(obj)), int32_t&>::value, "");
  }

  {
    using member = meta::member::optl;

    type obj;
    EXPECT_FALSE(meta::member::optl::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_FALSE(member::is_set(obj));
  }

  {
    using member = meta::member::optl;

    type obj;
    obj.optl_ref() = 3;
    EXPECT_TRUE(meta::member::optl::is_set(obj));

    EXPECT_TRUE(member::mark_set(obj, true));
    EXPECT_TRUE(member::is_set(obj));

    EXPECT_FALSE(member::mark_set(obj, false));
    EXPECT_FALSE(member::is_set(obj));

    static_assert(
        std::is_same<
            decltype(member::getter::ref(obj)),
            apache::thrift::DeprecatedOptionalField<int32_t>&>::value,
        "");
  }
}
<|endoftext|>


<commit_before>// Arda Mavi - ardamavi.com

#include <iostream>
#include "Tas.h"
#include "Piyon.h"
#include "Tahta.h"

using namespace std;

Piyon::Piyon(takim renk, int x, int y) : Tas(renk, "Piyon", x, y){}

bool Piyon::vezirOlsunMu(takim renk,pair <int, int> gidilecekYer){

    if(renk == beyaz){
        // Tasin rengi beyaz ise:
        if(gidilecekYer.first == 7){
            return true;
        } else{
            return false;
        }
    }else{
        // Tasin rengi siyah ise:
        if(gidilecekYer.first == 0){
            return true;
        } else{
            return false;
        }
    }

}

bool Piyon::yolKntrl(vector<Tas*> taslar, pair<int, int> gidilecekYer, Tahta tahta){
    // benim konumum this->konum
    //taslar[i].konum

    if(this->getKonum() == gidilecekYer){
        return false;
    }

    int yon;
    int baslamaYeri;

    if (this->getTakim() == beyaz)
    {
        yon = 1;
        baslamaYeri = 1;
    }
    else{
        yon = -1;
        baslamaYeri = 6;
    }

    // Geri gidemez :
    if(yon == 1 && this->getKonum().first > gidilecekYer.first){
        return false;
    } else if(yon == -1 && this->getKonum().first < gidilecekYer.first){
        return false;
    }

    if(( gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second))
       && !((gidilecekYer == make_pair(this->getKonum().first+ (2 * yon), this->getKonum().second)) && this->getKonum().first == baslamaYeri)
       && (gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon)))
       && (gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon)))){
        return false;
    }

    int ileriLimiti = 1;
    // Piyon başlama yerindeyse
    if(this->getKonum().first == baslamaYeri){
        ileriLimiti = 2;
    }
    int mesafe = (gidilecekYer.first - this->getKonum().first) * yon;

    if (ileriLimiti < mesafe)
    {
        return false;
    }

    // İleri gidiliyorsa :
    if(gidilecekYer.second == this->getKonum().second) {

        for (int i = 0; i < taslar.size(); i++) {
            if (taslar[i]->getKonum() == this->getKonum()) {
                continue;
            }
            if (taslar[i]->getKonum() ==
                              make_pair(this->getKonum().first + (1 * yon), this->getKonum().second)) {
                return false;
            }
            if (mesafe > 1 && taslar[i]->getKonum() ==
                              make_pair(this->getKonum().first + (2 * yon), this->getKonum().second)) {
                return false;
            }
        }
    }

    // Capraz gidiyorsa
    if(gidilecekYer == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon))){

        // Eger caprazi doluysa:
        for (int i = 0; i < taslar.size(); i++) {
            if(taslar[i]->getKonum() == this->getKonum()){
                continue;
            }
            if(taslar[i]->getKonum() == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon))){
                if (taslar[i]->getTakim() == this->getTakim()) {
                    return false;
                }
                else {
                    return true;
                }
            }
        }
        if(tahta.getGecerkenAlma().second == yok){
          return false;
        }
        else if (tahta.getGecerkenAlma().second == this->getTakim())
        {
          return false;
        }

    } else if(gidilecekYer == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon))){
        // Eger çaprazi doluysa:
        for (int i = 0; i < taslar.size(); i++) {
            if(taslar[i]->getKonum() == this->getKonum()){
                continue;
            }
            if(taslar[i]->getKonum() == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon))){
                if (taslar[i]->getTakim() == this->getTakim()) {
                    return false;
                }
                else{
                    return true;
                }
            }
        }
        if(tahta.getGecerkenAlma().second == yok){
          return false;
        }
        else if (tahta.getGecerkenAlma().second == this->getTakim())
        {
          return false;
        }

    }

    // Piyon belirtilen konuma gidebilir mi?
    // 1. Piyon baslangic satirindaysa ve onu bos ise 1 veya 2 adim onune gidebilir.
    // 2. Piyon baslangic satirinda degilse ve onu bos ise 1 adim onune gidebilir.
    // 3. Piyon caprazinda rakip tas var ise, capraz onune gidebilir.

    return true;
}
<commit_msg>Piyon Geçerken Alma Kuralı Düzeltildi<commit_after>// Arda Mavi - ardamavi.com

#include <iostream>
#include "Tas.h"
#include "Piyon.h"
#include "Tahta.h"

using namespace std;

Piyon::Piyon(takim renk, int x, int y) : Tas(renk, "Piyon", x, y){}

bool Piyon::vezirOlsunMu(takim renk,pair <int, int> gidilecekYer){

    if(renk == beyaz){
        // Tasin rengi beyaz ise:
        if(gidilecekYer.first == 7){
            return true;
        } else{
            return false;
        }
    }else{
        // Tasin rengi siyah ise:
        if(gidilecekYer.first == 0){
            return true;
        } else{
            return false;
        }
    }

}

bool Piyon::yolKntrl(vector<Tas*> taslar, pair<int, int> gidilecekYer, Tahta tahta){
    // benim konumum this->konum
    //taslar[i].konum

    if(this->getKonum() == gidilecekYer){
        return false;
    }

    int yon;
    int baslamaYeri;

    if (this->getTakim() == beyaz)
    {
        yon = 1;
        baslamaYeri = 1;
    }
    else{
        yon = -1;
        baslamaYeri = 6;
    }

    // Geri gidemez :
    if(yon == 1 && this->getKonum().first > gidilecekYer.first){
        return false;
    } else if(yon == -1 && this->getKonum().first < gidilecekYer.first){
        return false;
    }

    if(( gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second))
       && !((gidilecekYer == make_pair(this->getKonum().first+ (2 * yon), this->getKonum().second)) && this->getKonum().first == baslamaYeri)
       && (gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon)))
       && (gidilecekYer != make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon)))){
        return false;
    }

    int ileriLimiti = 1;
    // Piyon başlama yerindeyse
    if(this->getKonum().first == baslamaYeri){
        ileriLimiti = 2;
    }
    int mesafe = (gidilecekYer.first - this->getKonum().first) * yon;

    if (ileriLimiti < mesafe)
    {
        return false;
    }

    // İleri gidiliyorsa :
    if(gidilecekYer.second == this->getKonum().second) {

        for (int i = 0; i < taslar.size(); i++) {
            if (taslar[i]->getKonum() == this->getKonum()) {
                continue;
            }
            if (taslar[i]->getKonum() ==
                              make_pair(this->getKonum().first + (1 * yon), this->getKonum().second)) {
                return false;
            }
            if (mesafe > 1 && taslar[i]->getKonum() ==
                              make_pair(this->getKonum().first + (2 * yon), this->getKonum().second)) {
                return false;
            }
        }
    }

    // Capraz gidiyorsa
    if(gidilecekYer == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon))){

        // Eger caprazi doluysa:
        for (int i = 0; i < taslar.size(); i++) {
            if(taslar[i]->getKonum() == this->getKonum()){
                continue;
            }
            if(taslar[i]->getKonum() == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second- (1 * yon))){
                if (taslar[i]->getTakim() == this->getTakim()) {
                    return false;
                }
                else {
                    return true;
                }
            }
        }
        if(tahta.getGecerkenAlma().second == yok){
          return false;
        }
        else if (tahta.getGecerkenAlma().second == this->getTakim())
        {
          return false;
        }else if(tahta.getGecerkenAlma().first != gidilecekYer){
          return false;
        }

    } else if(gidilecekYer == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon))){
        // Eger çaprazi doluysa:
        for (int i = 0; i < taslar.size(); i++) {
            if(taslar[i]->getKonum() == this->getKonum()){
                continue;
            }
            if(taslar[i]->getKonum() == make_pair(this->getKonum().first+ (1 * yon), this->getKonum().second+ (1 * yon))){
                if (taslar[i]->getTakim() == this->getTakim()) {
                    return false;
                }
                else{
                    return true;
                }
            }
        }
        if(tahta.getGecerkenAlma().second == yok){
          return false;
        }
        else if (tahta.getGecerkenAlma().second == this->getTakim())
        {
          return false;
        }else if(tahta.getGecerkenAlma().first != gidilecekYer){
          return false;
        }

    }

    // Piyon belirtilen konuma gidebilir mi?
    // 1. Piyon baslangic satirindaysa ve onu bos ise 1 veya 2 adim onune gidebilir.
    // 2. Piyon baslangic satirinda degilse ve onu bos ise 1 adim onune gidebilir.
    // 3. Piyon caprazinda rakip tas var ise, capraz onune gidebilir.

    return true;
}
<|endoftext|>


<commit_before><commit_msg>svx: this was supposed to be "image/x-eps"<commit_after><|endoftext|>


<commit_before>#include "Proxy.h"

namespace jni
{

jni::Class s_JNIBridgeClass("bitter/jnibridge/JNIBridge");
ExpandingArray<ProxyObject*> ProxyObject::g_AllProxies;

JNIEXPORT jobject JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke(JNIEnv* env, jobject thiz, jlong ptr, jclass clazz, jobject method, jobjectArray args)
{
	jmethodID methodID = env->FromReflectedMethod(method);
	ProxyInvoker* proxy = (ProxyInvoker*)ptr;
	return proxy->__Invoke(clazz, methodID, args);
}

JNIEXPORT void JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete(JNIEnv* env, jobject thiz, jlong ptr)
{
	delete (ProxyInvoker*)ptr;
}

bool ProxyInvoker::__Register()
{
	jni::LocalFrame frame;
	jni::Class nativeProxyClass("bitter/jnibridge/JNIBridge");
	char invokeMethodName[] = "invoke";
	char invokeMethodSignature[] = "(JLjava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
	char deleteMethodName[] = "delete";
	char deleteMethodSignature[] = "(J)V";

	JNINativeMethod nativeProxyFunction[] = {
		{invokeMethodName, invokeMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke},
		{deleteMethodName, deleteMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete}
	};

	if (nativeProxyClass) jni::GetEnv()->RegisterNatives(nativeProxyClass, nativeProxyFunction, 2); // <-- fix this
	return !jni::CheckError();
}

::jint ProxyObject::HashCode() const
{
	return java::lang::System::IdentityHashCode(java::lang::Object(__ProxyObject()));
}

::jboolean ProxyObject::Equals(const ::jobject arg0) const
{
	return jni::IsSameObject(__ProxyObject(), arg0);
}

java::lang::String ProxyObject::ToString() const
{
	return java::lang::String("<native proxy object>");
}

jobject ProxyObject::__Invoke(jclass clazz, jmethodID mid, jobjectArray args)
{
	jobject result;
	if (!__InvokeInternal(clazz, mid, args, &result))
	{
		java::lang::reflect::Method method(jni::ToReflectedMethod(clazz, mid, false));
		jni::ThrowNew<java::lang::NoSuchMethodError>(method.ToString().c_str());
	}

	return result;
}

void ProxyObject::DeleteAllProxies()
{
	while (g_AllProxies.GetCount() > 0)
	{
		delete g_AllProxies[0];
	}
	g_AllProxies.Clear();
}

bool ProxyObject::__TryInvoke(jclass clazz, jmethodID methodID, jobjectArray args, bool* success, jobject* result)
{
	if (*success)
		return false;

	// in case jmethodIDs are not unique across classes - couldn't find any spec regarding this
	if (!jni::IsSameObject(clazz, java::lang::Object::__CLASS))
		return false;

	static jmethodID methodIDs[] = {
		jni::GetMethodID(java::lang::Object::__CLASS, "hashCode", "()I"),
		jni::GetMethodID(java::lang::Object::__CLASS, "equals", "(Ljava/lang/Object;)Z"),
		jni::GetMethodID(java::lang::Object::__CLASS, "toString", "()Ljava/lang/String;")
	};
	if (methodIDs[0] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Integer>(HashCode())); *success = true; return true; }
	if (methodIDs[1] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Boolean>(Equals(::java::lang::Object(jni::GetObjectArrayElement(args, 0))))); *success = true; return true; }
	if (methodIDs[2] == methodID) {	*result = jni::NewLocalRef(static_cast<java::lang::String>(ToString())); *success = true;	return true; }

	return false;
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject* interfaces, size_t interfaces_len)
{
	Array<jobject> interfaceArray(java::lang::Class::__CLASS, interfaces_len, interfaces);

	static jmethodID newProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "newInterfaceProxy", "(J[Ljava/lang/Class;)Ljava/lang/Object;");
	return  jni::Op<jobject>::CallStaticMethod(s_JNIBridgeClass, newProxyMID, (jlong) nativePtr, static_cast<jobjectArray>(interfaceArray));
}

void ProxyObject::DisableInstance(jobject proxy)
{
	static jmethodID disableProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "disableInterfaceProxy", "(Ljava/lang/Object;)V");
	jni::Op<jvoid>::CallStaticMethod(s_JNIBridgeClass, disableProxyMID, proxy);
}

}<commit_msg>Change confusing while loop<commit_after>#include "Proxy.h"

namespace jni
{

jni::Class s_JNIBridgeClass("bitter/jnibridge/JNIBridge");
ExpandingArray<ProxyObject*> ProxyObject::g_AllProxies;

JNIEXPORT jobject JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke(JNIEnv* env, jobject thiz, jlong ptr, jclass clazz, jobject method, jobjectArray args)
{
	jmethodID methodID = env->FromReflectedMethod(method);
	ProxyInvoker* proxy = (ProxyInvoker*)ptr;
	return proxy->__Invoke(clazz, methodID, args);
}

JNIEXPORT void JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete(JNIEnv* env, jobject thiz, jlong ptr)
{
	delete (ProxyInvoker*)ptr;
}

bool ProxyInvoker::__Register()
{
	jni::LocalFrame frame;
	jni::Class nativeProxyClass("bitter/jnibridge/JNIBridge");
	char invokeMethodName[] = "invoke";
	char invokeMethodSignature[] = "(JLjava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
	char deleteMethodName[] = "delete";
	char deleteMethodSignature[] = "(J)V";

	JNINativeMethod nativeProxyFunction[] = {
		{invokeMethodName, invokeMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke},
		{deleteMethodName, deleteMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete}
	};

	if (nativeProxyClass) jni::GetEnv()->RegisterNatives(nativeProxyClass, nativeProxyFunction, 2); // <-- fix this
	return !jni::CheckError();
}

::jint ProxyObject::HashCode() const
{
	return java::lang::System::IdentityHashCode(java::lang::Object(__ProxyObject()));
}

::jboolean ProxyObject::Equals(const ::jobject arg0) const
{
	return jni::IsSameObject(__ProxyObject(), arg0);
}

java::lang::String ProxyObject::ToString() const
{
	return java::lang::String("<native proxy object>");
}

jobject ProxyObject::__Invoke(jclass clazz, jmethodID mid, jobjectArray args)
{
	jobject result;
	if (!__InvokeInternal(clazz, mid, args, &result))
	{
		java::lang::reflect::Method method(jni::ToReflectedMethod(clazz, mid, false));
		jni::ThrowNew<java::lang::NoSuchMethodError>(method.ToString().c_str());
	}

	return result;
}

void ProxyObject::DeleteAllProxies()
{
	for (int i = g_AllProxies.GetCount() - 1; i >= 0; i--)
	{
		delete g_AllProxies[i];
	}
	g_AllProxies.Clear();
}

bool ProxyObject::__TryInvoke(jclass clazz, jmethodID methodID, jobjectArray args, bool* success, jobject* result)
{
	if (*success)
		return false;

	// in case jmethodIDs are not unique across classes - couldn't find any spec regarding this
	if (!jni::IsSameObject(clazz, java::lang::Object::__CLASS))
		return false;

	static jmethodID methodIDs[] = {
		jni::GetMethodID(java::lang::Object::__CLASS, "hashCode", "()I"),
		jni::GetMethodID(java::lang::Object::__CLASS, "equals", "(Ljava/lang/Object;)Z"),
		jni::GetMethodID(java::lang::Object::__CLASS, "toString", "()Ljava/lang/String;")
	};
	if (methodIDs[0] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Integer>(HashCode())); *success = true; return true; }
	if (methodIDs[1] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Boolean>(Equals(::java::lang::Object(jni::GetObjectArrayElement(args, 0))))); *success = true; return true; }
	if (methodIDs[2] == methodID) {	*result = jni::NewLocalRef(static_cast<java::lang::String>(ToString())); *success = true;	return true; }

	return false;
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject* interfaces, size_t interfaces_len)
{
	Array<jobject> interfaceArray(java::lang::Class::__CLASS, interfaces_len, interfaces);

	static jmethodID newProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "newInterfaceProxy", "(J[Ljava/lang/Class;)Ljava/lang/Object;");
	return  jni::Op<jobject>::CallStaticMethod(s_JNIBridgeClass, newProxyMID, (jlong) nativePtr, static_cast<jobjectArray>(interfaceArray));
}

void ProxyObject::DisableInstance(jobject proxy)
{
	static jmethodID disableProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "disableInterfaceProxy", "(Ljava/lang/Object;)V");
	jni::Op<jvoid>::CallStaticMethod(s_JNIBridgeClass, disableProxyMID, proxy);
}

}<|endoftext|>