<commit_before>/*
	sample of somewhat homomorphic encryption(SHE)
*/
#define PUT(x) std::cout << #x << "=" << (x) << std::endl;
#include <cybozu/benchmark.hpp>
#include <mcl/she.hpp>

using namespace mcl::she;

void miniSample()
{
	// init library
	SHE::init();

	SecretKey sec;

	// init secret key by random_device
	sec.setByCSPRNG();

	// set range to decode GT DLP
	SHE::setRangeForDLP(1000);

	PublicKey pub;
	// get public key
	sec.getPublicKey(pub);

	const int N = 5;
	int a[] = { 1, 5, -3, 4, 6 };
	int b[] = { 4, 2, 1, 9, -2 };
	// compute correct value
	int sum = 0;
	for (size_t i = 0; i < N; i++) {
		sum += a[i] * b[i];
	}

	std::vector<CipherText> ca(N), cb(N);

	// encrypt each a[] and b[]
	for (size_t i = 0; i < N; i++) {
		pub.enc(ca[i], a[i]);
		pub.enc(cb[i], b[i]);
	}
	CipherText c;
	c.clearAsMultiplied(); // clear as multiplied before using c.add()
	// inner product of encrypted vector
	for (size_t i = 0; i < N; i++) {
		CipherText t;
		CipherText::mul(t, ca[i], cb[i]); // t = ca[i] * cb[i]
		c.add(t); // c += t
	}
	// decode it
	int m = sec.dec(c);
	// verify the value
	if (m == sum) {
		puts("ok");
	} else {
		printf("err correct %d err %d\n", sum, m);
	}
}

void usePrimitiveCipherText()
{
	// init library
	SHE::init();

	SecretKey sec;

	// init secret key by random_device
	sec.setByCSPRNG();

	// set range to decode GT DLP
	SHE::setRangeForGTDLP(100);

	PublicKey pub;
	// get public key
	sec.getPublicKey(pub);

	int a1 = 1, a2 = 2;
	int b1 = 5, b2 = -4;
	CipherTextG1 c1, c2; // size of CipherTextG1 = N * 2 ; N = 256-bit for CurveFp254BNb
	CipherTextG2 d1, d2; // size of CipherTextG2 = N * 4
	pub.enc(c1, a1);
	pub.enc(c2, a2);
	pub.enc(d1, b1);
	pub.enc(d2, b2);
	c1.add(c2); // CipherTextG1 is additive HE
	d1.add(d2); // CipherTextG2 is additive HE
	CipherTextGT cm; // size of CipherTextGT = N * 12 * 4
	CipherTextGT::mul(cm, c1, d1); // cm = c1 * d1
	cm.add(cm); // 2cm
	int m = sec.dec(cm);
	int ok = (a1 + a2) * (b1 + b2) * 2;
	if (m == ok) {
		puts("ok");
	} else {
		printf("err m=%d ok=%d\n", m, ok);
	}
	std::string s;
	s = c1.getStr(mcl::IoSerialize); // serialize
	printf("c1 data size %d byte\n", (int)s.size());

	c2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", c1 == c2 ? "ok" : "ng");

	s = d1.getStr(mcl::IoSerialize); // serialize
	printf("d1 data size %d byte\n", (int)s.size());
	d2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", d1 == d2 ? "ok" : "ng");

	s = cm.getStr(mcl::IoSerialize); // serialize
	printf("cm data size %d byte\n", (int)s.size());
	CipherTextGT cm2;
	cm2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", cm == cm2 ? "ok" : "ng");
}

int main()
	try
{
	miniSample();
	usePrimitiveCipherText();
} catch (std::exception& e) {
	printf("err %s\n", e.what());
	return 1;
}
<commit_msg>cast int64_t to int<commit_after>/*
	sample of somewhat homomorphic encryption(SHE)
*/
#define PUT(x) std::cout << #x << "=" << (x) << std::endl;
#include <cybozu/benchmark.hpp>
#include <mcl/she.hpp>

using namespace mcl::she;

void miniSample()
{
	// init library
	SHE::init();

	SecretKey sec;

	// init secret key by random_device
	sec.setByCSPRNG();

	// set range to decode GT DLP
	SHE::setRangeForDLP(1000);

	PublicKey pub;
	// get public key
	sec.getPublicKey(pub);

	const int N = 5;
	int a[] = { 1, 5, -3, 4, 6 };
	int b[] = { 4, 2, 1, 9, -2 };
	// compute correct value
	int sum = 0;
	for (size_t i = 0; i < N; i++) {
		sum += a[i] * b[i];
	}

	std::vector<CipherText> ca(N), cb(N);

	// encrypt each a[] and b[]
	for (size_t i = 0; i < N; i++) {
		pub.enc(ca[i], a[i]);
		pub.enc(cb[i], b[i]);
	}
	CipherText c;
	c.clearAsMultiplied(); // clear as multiplied before using c.add()
	// inner product of encrypted vector
	for (size_t i = 0; i < N; i++) {
		CipherText t;
		CipherText::mul(t, ca[i], cb[i]); // t = ca[i] * cb[i]
		c.add(t); // c += t
	}
	// decode it
	int m = (int)sec.dec(c);
	// verify the value
	if (m == sum) {
		puts("ok");
	} else {
		printf("err correct %d err %d\n", sum, m);
	}
}

void usePrimitiveCipherText()
{
	// init library
	SHE::init();

	SecretKey sec;

	// init secret key by random_device
	sec.setByCSPRNG();

	// set range to decode GT DLP
	SHE::setRangeForGTDLP(100);

	PublicKey pub;
	// get public key
	sec.getPublicKey(pub);

	int a1 = 1, a2 = 2;
	int b1 = 5, b2 = -4;
	CipherTextG1 c1, c2; // size of CipherTextG1 = N * 2 ; N = 256-bit for CurveFp254BNb
	CipherTextG2 d1, d2; // size of CipherTextG2 = N * 4
	pub.enc(c1, a1);
	pub.enc(c2, a2);
	pub.enc(d1, b1);
	pub.enc(d2, b2);
	c1.add(c2); // CipherTextG1 is additive HE
	d1.add(d2); // CipherTextG2 is additive HE
	CipherTextGT cm; // size of CipherTextGT = N * 12 * 4
	CipherTextGT::mul(cm, c1, d1); // cm = c1 * d1
	cm.add(cm); // 2cm
	int m = (int)sec.dec(cm);
	int ok = (a1 + a2) * (b1 + b2) * 2;
	if (m == ok) {
		puts("ok");
	} else {
		printf("err m=%d ok=%d\n", m, ok);
	}
	std::string s;
	s = c1.getStr(mcl::IoSerialize); // serialize
	printf("c1 data size %d byte\n", (int)s.size());

	c2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", c1 == c2 ? "ok" : "ng");

	s = d1.getStr(mcl::IoSerialize); // serialize
	printf("d1 data size %d byte\n", (int)s.size());
	d2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", d1 == d2 ? "ok" : "ng");

	s = cm.getStr(mcl::IoSerialize); // serialize
	printf("cm data size %d byte\n", (int)s.size());
	CipherTextGT cm2;
	cm2.setStr(s, mcl::IoSerialize);
	printf("deserialize %s\n", cm == cm2 ? "ok" : "ng");
}

int main()
	try
{
	miniSample();
	usePrimitiveCipherText();
} catch (std::exception& e) {
	printf("err %s\n", e.what());
	return 1;
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#ifdef OSG_LINUX_TYPES
#include <inttypes.h>
#endif
#include <stdlib.h>
#include <stdio.h>

#include <set>

// CgFX

#include "OSGConfig.h"

#include "OSGCgFXPassChunk.h"
#include "OSGCgFXMaterial.h"
#include "OSGDrawEnv.h"

#if CG_VERSION_NUM < 1500
#error CGFXMaterial2 needs Cg 1.5 or later
#endif

OSG_BEGIN_NAMESPACE

/*! \class osg::CgFXPassChunk

*/

/***************************************************************************\
 *                           Class variables                               *
\***************************************************************************/

// Techniques

/***************************************************************************\
 *                           Class methods                                 *
\***************************************************************************/

void CgFXPassChunk::initMethod(InitPhase ePhase)
{
    Inherited::initMethod(ePhase);
}

/***************************************************************************\
 *                           Instance methods                              *
\***************************************************************************/

/*-------------------------------------------------------------------------*\
 -  private                                                                 -
\*-------------------------------------------------------------------------*/

/*----------------------- constructors & destructors ----------------------*/

CgFXPassChunk::CgFXPassChunk(void) :
     Inherited(    ),
    _pCGPass  (NULL)
{
}

CgFXPassChunk::CgFXPassChunk(const CgFXPassChunk &source) :
     Inherited(source),
    _pCGPass  (NULL  )
{
}

CgFXPassChunk::~CgFXPassChunk(void)
{
}

/*----------------------------- class specific ----------------------------*/

void CgFXPassChunk::changed(ConstFieldMaskArg whichField,
                            UInt32            origin,
                            BitVector         detail)
{
    Inherited::changed(whichField, origin, detail);
}

void CgFXPassChunk::dump(      UInt32    ,
                         const BitVector ) const
{
    SLOG << "Dump CgFXPassChunk NI" << std::endl;
}

bool CgFXPassChunk::isTransparent(void) const
{
    // HACK need to test this!
    return true;
    //return false;
}

void CgFXPassChunk::activate(DrawEnv       *pEnv,
                             State         *pState,
                             StateOverride *pOverride)
{
    cgSetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgSetPassState", NULL);

    pEnv->setActiveShader(TypeTraits<UInt32>::BitsSet);

    updateStateUniforms(pEnv);
}

void CgFXPassChunk::deactivate(DrawEnv       *pEnv,
                               State         *pState,
                               StateOverride *pOverride)
{
    cgResetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgResetPassState", NULL);

    pEnv->setActiveShader(TypeTraits<UInt32>::BitsClear);

    glDepthFunc( GL_LEQUAL );
    glEnable( GL_DEPTH_TEST );
    glEnable( GL_NORMALIZE );
    GLfloat nul[4]={0,0,0,0};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, nul);
    glLightfv(GL_LIGHT0, GL_SPECULAR, nul);
}

void CgFXPassChunk::changeFrom(DrawEnv       *pEnv,
                               State         *pNewState,
                               StateOverride *pNewOverride,
                               State         *pOldState,
                               StateOverride *pOldOverride)
{
    cgSetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgSetPassState", NULL);

    updateStateUniforms(pEnv);
}

void CgFXPassChunk::updateStateUniforms(DrawEnv  *pEnv)
{
    CgFXMaterial *pMat = _sfMaterial.getValue();

    OSG_ASSERT(pMat != NULL);

          CGeffect     pEffect        = pMat->getEffect        ();
          UInt32       uiStateVars    = pMat->getStateVariables();
    const std::string *vStateVarNames = pMat->getStateVarNames ();

          UInt32       uiMask         = 0x0001;

    OSG_ASSERT(pEffect != NULL);

    Matrix mObj2World = pEnv->getObjectToWorld();

    std::string szTmp;

    for(UInt32 i = 0; i < CgFXMaterial::NumStateVars; ++i)
    {
        if(uiStateVars == 0x0000)
            break;

        switch(uiStateVars & uiMask)
        {
            case CgFXMaterial::CgProjectionMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(
                    pMatrixParam,
                    pEnv->_openGLState.getProjection().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc", NULL);
            }
            break;

            case CgFXMaterial::CgModelViewProjectionMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelViewProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mWorld2Scrn = pEnv->getWorldToScreen();

                mWorld2Scrn.mult(mObj2World);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mWorld2Scrn.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // -------------
            // Model | World
            // -------------
            case CgFXMaterial::CgModelMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModel].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mObj2World.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelIMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mModelI = mObj2World;

                mModelI.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mModelI.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelITMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelIT].c_str());

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mModelIT = mObj2World;

                mModelIT.invert   ();
                mModelIT.transpose();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mModelIT.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // ---------------------
            // ModelView | WorldView
            // ---------------------
            case CgFXMaterial::CgModelViewMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelView].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult(mObj2World);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelViewIMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelViewI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult(mObj2World);
                mCameraViewing.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelViewITMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelViewIT].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult     (mObj2World);
                mCameraViewing.invert   (          );
                mCameraViewing.transpose(          );

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // -------------
            // View
            // -------------
            case CgFXMaterial::CgViewMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgView].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         pEnv->getCameraViewing().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewIMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                OSG::Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewITMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewIT].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                OSG::Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.invert   ();
                mCameraViewing.transpose();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewProjectionMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         pEnv->getWorldToScreen().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgTimeMask:
            {
                CGparameter pTime =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgTime].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pTime != NULL);

                cgSetParameter1f(pTime, Real32(OSG::getSystemTime()));
            }
            break;

            default:
                break;
        };

        uiStateVars &= ~uiMask;
        uiMask      =   uiMask << 1;
    }
}

/*-------------------------- Comparison -----------------------------------*/

Real32 CgFXPassChunk::switchCost(StateChunk *OSG_CHECK_ARG(chunk))
{
    return 0;
}

bool CgFXPassChunk::operator < (const StateChunk &other) const
{
    return this < &other;
}

bool CgFXPassChunk::operator == (const StateChunk &other) const
{
    CgFXPassChunk const *tother = dynamic_cast<CgFXPassChunk const*>(&other);

    if(!tother)
        return false;

#if 0
    if(_effectFile != tother->_effectFile)
        return false;
#endif

    return true;
}

bool CgFXPassChunk::operator != (const StateChunk &other) const
{
    return ! (*this == other);
}

OSG_END_NAMESPACE

<commit_msg>Fixed: Issue in CgFXPassChunk where there was a loss of precision with casting from a 64-bit to a 32-bit floating point number for the uniform parameter for Time.<commit_after>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#ifdef OSG_LINUX_TYPES
#include <inttypes.h>
#endif
#include <stdlib.h>
#include <stdio.h>

#include <set>

// CgFX

#include "OSGConfig.h"

#include "OSGCgFXPassChunk.h"
#include "OSGCgFXMaterial.h"
#include "OSGDrawEnv.h"

#if CG_VERSION_NUM < 1500
#error CGFXMaterial2 needs Cg 1.5 or later
#endif

OSG_BEGIN_NAMESPACE

/*! \class osg::CgFXPassChunk

*/

/***************************************************************************\
 *                           Class variables                               *
\***************************************************************************/

// Techniques

/***************************************************************************\
 *                           Class methods                                 *
\***************************************************************************/

void CgFXPassChunk::initMethod(InitPhase ePhase)
{
    Inherited::initMethod(ePhase);
}

/***************************************************************************\
 *                           Instance methods                              *
\***************************************************************************/

/*-------------------------------------------------------------------------*\
 -  private                                                                 -
\*-------------------------------------------------------------------------*/

/*----------------------- constructors & destructors ----------------------*/

CgFXPassChunk::CgFXPassChunk(void) :
     Inherited(    ),
    _pCGPass  (NULL)
{
}

CgFXPassChunk::CgFXPassChunk(const CgFXPassChunk &source) :
     Inherited(source),
    _pCGPass  (NULL  )
{
}

CgFXPassChunk::~CgFXPassChunk(void)
{
}

/*----------------------------- class specific ----------------------------*/

void CgFXPassChunk::changed(ConstFieldMaskArg whichField,
                            UInt32            origin,
                            BitVector         detail)
{
    Inherited::changed(whichField, origin, detail);
}

void CgFXPassChunk::dump(      UInt32    ,
                         const BitVector ) const
{
    SLOG << "Dump CgFXPassChunk NI" << std::endl;
}

bool CgFXPassChunk::isTransparent(void) const
{
    // HACK need to test this!
    return true;
    //return false;
}

void CgFXPassChunk::activate(DrawEnv       *pEnv,
                             State         *pState,
                             StateOverride *pOverride)
{
    cgSetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgSetPassState", NULL);

    pEnv->setActiveShader(TypeTraits<UInt32>::BitsSet);

    updateStateUniforms(pEnv);
}

void CgFXPassChunk::deactivate(DrawEnv       *pEnv,
                               State         *pState,
                               StateOverride *pOverride)
{
    cgResetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgResetPassState", NULL);

    pEnv->setActiveShader(TypeTraits<UInt32>::BitsClear);

    glDepthFunc( GL_LEQUAL );
    glEnable( GL_DEPTH_TEST );
    glEnable( GL_NORMALIZE );
    GLfloat nul[4]={0,0,0,0};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, nul);
    glLightfv(GL_LIGHT0, GL_SPECULAR, nul);
}

void CgFXPassChunk::changeFrom(DrawEnv       *pEnv,
                               State         *pNewState,
                               StateOverride *pNewOverride,
                               State         *pOldState,
                               StateOverride *pOldOverride)
{
    cgSetPassState(_pCGPass);

    CgFXMaterial::checkForCgError("cgSetPassState", NULL);

    updateStateUniforms(pEnv);
}

void CgFXPassChunk::updateStateUniforms(DrawEnv  *pEnv)
{
    CgFXMaterial *pMat = _sfMaterial.getValue();

    OSG_ASSERT(pMat != NULL);

          CGeffect     pEffect        = pMat->getEffect        ();
          UInt32       uiStateVars    = pMat->getStateVariables();
    const std::string *vStateVarNames = pMat->getStateVarNames ();

          UInt32       uiMask         = 0x0001;

    OSG_ASSERT(pEffect != NULL);

    Matrix mObj2World = pEnv->getObjectToWorld();

    std::string szTmp;

    for(UInt32 i = 0; i < CgFXMaterial::NumStateVars; ++i)
    {
        if(uiStateVars == 0x0000)
            break;

        switch(uiStateVars & uiMask)
        {
            case CgFXMaterial::CgProjectionMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(
                    pMatrixParam,
                    pEnv->_openGLState.getProjection().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc", NULL);
            }
            break;

            case CgFXMaterial::CgModelViewProjectionMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelViewProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mWorld2Scrn = pEnv->getWorldToScreen();

                mWorld2Scrn.mult(mObj2World);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mWorld2Scrn.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // -------------
            // Model | World
            // -------------
            case CgFXMaterial::CgModelMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModel].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mObj2World.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelIMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mModelI = mObj2World;

                mModelI.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mModelI.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelITMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgModelIT].c_str());

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mModelIT = mObj2World;

                mModelIT.invert   ();
                mModelIT.transpose();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mModelIT.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // ---------------------
            // ModelView | WorldView
            // ---------------------
            case CgFXMaterial::CgModelViewMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelView].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult(mObj2World);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelViewIMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelViewI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult(mObj2World);
                mCameraViewing.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgModelViewITMask:
            {
                CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[CgFXMaterial::CgModelViewIT].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.mult     (mObj2World);
                mCameraViewing.invert   (          );
                mCameraViewing.transpose(          );

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            // -------------
            // View
            // -------------
            case CgFXMaterial::CgViewMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgView].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         pEnv->getCameraViewing().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewIMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewI].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                OSG::Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.invert();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewITMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewIT].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                OSG::Matrix mCameraViewing = pEnv->getCameraViewing();

                mCameraViewing.invert   ();
                mCameraViewing.transpose();

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         mCameraViewing.getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgViewProjectionMask:
            {
                 CGparameter pMatrixParam =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgViewProjection].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pMatrixParam != NULL);

                cgGLSetMatrixParameterfc(pMatrixParam,
                                         pEnv->getWorldToScreen().getValues());

                CgFXMaterial::checkForCgError("cgGLSetMatrixParameterfc",
                                              NULL);
            }
            break;

            case CgFXMaterial::CgTimeMask:
            {
                CGparameter pTime =
                    cgGetNamedEffectParameter(
                        pEffect,
                        vStateVarNames[
                            CgFXMaterial::CgTime].c_str());

                CgFXMaterial::checkForCgError("cgGetNamedEffectParameter",
                                              NULL);

                OSG_ASSERT(pTime != NULL);

                static const UInt16 MaxLeftDecDigits(4);

                // getSystemTime() returns a time value as a 64-bit floating
                // point number.  But the time value taken by Cg is a 32-bit
                // float.  This can cause a problem with precision when
                // getSystemTime() returns large values, that truncate when cast
                // to a 32-bit float.
                //
                // To deal with this, we are removing the most significant
                // decimal digits left of the decimal points after the
                // MaxLeftDecDigits one

                Time tSysTime(OSG::getSystemTime());

                Time tBase10Shift(osgPow<Time>(10, MaxLeftDecDigits));
                Time tTruncValue(
                    tSysTime -
                    (floor(tSysTime / tBase10Shift) * tBase10Shift));

                cgSetParameter1f(pTime, static_cast<Real32>(TruncValue));
            }
            break;

            default:
                break;
        };

        uiStateVars &= ~uiMask;
        uiMask      =   uiMask << 1;
    }
}

/*-------------------------- Comparison -----------------------------------*/

Real32 CgFXPassChunk::switchCost(StateChunk *OSG_CHECK_ARG(chunk))
{
    return 0;
}

bool CgFXPassChunk::operator < (const StateChunk &other) const
{
    return this < &other;
}

bool CgFXPassChunk::operator == (const StateChunk &other) const
{
    CgFXPassChunk const *tother = dynamic_cast<CgFXPassChunk const*>(&other);

    if(!tother)
        return false;

#if 0
    if(_effectFile != tother->_effectFile)
        return false;
#endif

    return true;
}

bool CgFXPassChunk::operator != (const StateChunk &other) const
{
    return ! (*this == other);
}

OSG_END_NAMESPACE

<|endoftext|>


<commit_before>/**
*	2-D Steady State Conduction without Heat Generation | main.cpp
*
*	@author Samuel0Paul <paulsamuelvishesh@live.com>
**/

#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <cstdint>
#include <chrono>

using std::cout;	using std::endl;
using std::clog;
using std::cin;
using std::make_pair;

using time_ms = std::chrono::milliseconds;
using prec_t = long double;

namespace HMT
{
	template<typename T>
	class Nodes
	{
	public:
		Nodes() = default;
		Nodes(const uint64_t& nodeX, const uint64_t& nodeY);
		virtual ~Nodes() = default;

		void putWallTemp(const T& northTemp, const T& eastTemp, const T& southTemp, const T& westTemp);
		void putHeatSource(const uint64_t& posX, const uint64_t& posY, const T& temp);
		void calculate(const prec_t& epsilon);
		bool hasHeatSource(void) const noexcept(true);
		T getTemp(const uint64_t& posX, const uint64_t& posY) const;

		void testBuffers(void) const;

	protected:
		void initBuffer(void);
		void calculateWThread(const prec_t& epsilon);

	private:
		bool _hasHeatSource, _hasCalculated, _canUseThreads;
		uint64_t _nodeX, _nodeY, _itterCnt;
		std::vector<std::vector<std::pair<T, bool>>> _nodes, _nodesOld;
		std::chrono::time_point<std::chrono::high_resolution_clock> _startTime, _endTime;
	};

	template<typename T>
	void Nodes<T>::testBuffers(void) const
	{
		for (uint64_t i = 0; i < this->_nodeY; ++i) {
			for (uint64_t j = 0; j < this->_nodeX; ++j) {
				cout << this->_nodes[i][j].first << ", ";
			}
			cout << endl;
		}
		for (uint64_t i = 0; i < this->_nodeY; ++i) {
			for (uint64_t j = 0; j < this->_nodeX; ++j) {
				cout << this->_nodesOld[i][j].first << ", ";
			}
			cout << endl;
		}
	}

	template<typename T>
	Nodes<T>::Nodes(const uint64_t& nodeX, const uint64_t& nodeY)
	{
		this->_nodeX = nodeX;
		this->_nodeY = nodeY;
		this->initBuffer();
		this->_hasHeatSource = false;
		this->_hasCalculated = false;
		this->_canUseThreads = false;
	}

	template<typename T>
	void Nodes<T>::initBuffer(void)
	{
		this->_nodes.reserve(this->_nodeY);
		this->_nodesOld.reserve(this->_nodeY);
		for (uint64_t i = 0; i < this->_nodeY; ++i) {
			std::vector<std::pair<T, bool>> tmp;
			tmp.reserve(this->_nodeX);
			for (uint64_t j = 0; j < this->_nodeX; ++j) {
				tmp.push_back(make_pair(static_cast<T>(0), false));
			}
			this->_nodes.push_back(tmp);
			this->_nodesOld.push_back(std::move(tmp));
		}
	}

	template<typename T>
	void Nodes<T>::putWallTemp(const T& northTemp, const T& eastTemp, const T& southTemp, const T& westTemp)
	{
		this->_hasCalculated = false;
		for (uint64_t i = 0; i < this->_nodeY; ++i) {
			this->_nodes[i][0].first = westTemp;
			this->_nodes[i][this->_nodeX - 1].first = eastTemp;
		}
		for (uint64_t i = 0; i < this->_nodeX; ++i) {
			this->_nodes[0][i].first = northTemp;
			this->_nodes[this->_nodeY - 1][i].first = southTemp;
		}
		for (uint64_t i = 0; i < this->_nodeY; i++) {
			this->_nodes[i].shrink_to_fit();
			this->_nodesOld[i].shrink_to_fit();
		}
		this->_nodes.shrink_to_fit();
		this->_nodesOld.shrink_to_fit();
		for (uint64_t i = 1; i < this->_nodeY - 1; ++i) {
			for (uint64_t j = 1; j < this->_nodeX - 1; ++j) {
				this->_nodes[i][j].first = (northTemp + eastTemp + southTemp + westTemp) / 4;
			}
		}
	}

	template<typename T>
	void Nodes<T>::putHeatSource(const uint64_t& posX, const uint64_t& posY, const T& temp)
	{
		this->_hasHeatSource = true;
		this->_hasCalculated = false;
		this->_nodes[posY][posX].first = temp;
		this->_nodes[posY][posX].second = true;
	}

	template<typename T>
	void Nodes<T>::calculate(const prec_t& epsilon)
	{
		if (!this->_hasCalculated) {
			this->_startTime = std::chrono::high_resolution_clock::now();
			if (this->_canUseThreads) {
				this->calculateWThread(epsilon);
			} else {
				this->_itterCnt = 0;
				prec_t diff = epsilon;
				while (epsilon <= diff) {
					++(this->_itterCnt);
					for (uint64_t i = 0; i < this->_nodeY; ++i)
						for (uint64_t j = 0; j < this->_nodeX; ++j)
							this->_nodesOld[i][j] = this->_nodes[i][j];

					for (uint64_t i = 1; i < this->_nodeY - 1; ++i) {
						for (uint64_t j = 1; j < this->_nodeX - 1; ++j) {
							if (this->_nodes[i][j].second != true) {
								this->_nodes[i][j].first = (this->_nodesOld[i - 1][j].first +
															this->_nodesOld[i + 1][j].first +
													 		this->_nodesOld[i][j - 1].first +
													 		this->_nodesOld[i][j + 1].first) / 4;
								if (diff < std::fabs(this->_nodesOld[i][j].first - this->_nodes[i][j].first)) {
									diff = std::fabs(this->_nodesOld[i][j].first - this->_nodes[i][j].first);
								}
							}
						}
					}
				}
			}
			this->_endTime = std::chrono::high_resolution_clock::now();
			clog << "[noi: " << this->_itterCnt << "]" << endl;
			this->_hasCalculated = true;
		}
	}

	template<typename T>
	void Nodes<T>::calculateWThread(const prec_t& epsilon)
	{
		//!TODO implementation with std::thread
	}

	template<typename T>
	T Nodes<T>::getTemp(const uint64_t& posX, const uint64_t& posY) const
	{
		if (this->_hasCalculated)
			return this->_nodes[posY][posX].first;
		else return NULL;
	}
}

int main(int argc, char const *argv[])
{
	cout << std::nounitbuf;
	cout << std::setprecision(4) << std::fixed;
	cout << "############################ HMT Assignment ##########################" << endl
		 << " 2-D Steady State Conduction with Heat Generation" << endl << endl
		 << " Author: Samuel Paul Vishesh [UR11ME145] <paulsamuelvishesh@live.com>" << endl
		 << "######################################################################" << endl << endl;

	std::chrono::time_point<std::chrono::high_resolution_clock> startTime, endTime;
	prec_t	lengthX = 0, lengthY = 0, dx = 0, dy = 0,
			epsilon = 0, diff = 0,
			tempNorth = 0, tempSouth = 0, tempEast = 0, tempWest = 0, tempAvg = 0;
	uint64_t nodeX = 0, nodeY = 0;
	bool hasHeatSource = false;

	cout << "epsilon(give a smaller value for high precision): ";
	cin >> epsilon;
	diff = epsilon;
	cout << "Enter length in x-axix: ";
	cin >> lengthX;
	cout << "Enter length in y-axis: ";
	cin >> lengthY;
	cout << "Enter dist. b/t nodes in x-axis: ";
	cin >> dx;
	cout << "Enter dist. b/t nodes in y-axis: ";
	cin >> dy;

	if (lengthX != 0 && lengthY != 0 && dx != 0 && dy != 0 && epsilon != 0)	{
		nodeX = static_cast<uint64_t>(lengthX / dx);
		nodeY = static_cast<uint64_t>(lengthY / dy);
	} else {
		clog << "Error in intial values entered... (please refer documentation for correct usage)" << endl;
		std::exit(EXIT_FAILURE);
	}
	clog << endl
		 << "[nodeX: " << nodeX << "]" << endl
		 << "[nodeY: " << nodeY << "]" << endl;
/**
	// init cal buffers
	std::vector<std::vector<std::pair<prec_t, bool>>> nodes, nodesOld;
	nodes.reserve(nodeY);
	nodesOld.reserve(nodeY);
	for (uint64_t i = 0; i < nodeY; ++i) {
		std::vector<std::pair<prec_t, bool>> tmp;
		for (uint64_t j = 0; j < nodeX; ++j) {
			tmp.push_back(make_pair(0.0f, false));
		}
		nodes.push_back(tmp);
		nodesOld.push_back(tmp);
	}

	cout << "temp. of northern wall: ";
	cin >> tempNorth;
	cout << "temp. of southern wall: ";
	cin >> tempSouth;
	cout << "temp. of eastern wall: ";
	cin >> tempEast;
	cout << "temp. of western wall: ";
	cin >> tempWest;

	for (uint64_t i = 0; i < nodeY; ++i) {
		nodes[i][0] = make_pair(tempWest, true);
		nodes[i][nodeY - 1] = make_pair(tempEast, true);
	}
	for (uint64_t i = 0; i < nodeX; ++i) {
		nodes[0][i] = make_pair(tempNorth, true);
		nodes[nodeX - 1][i] = make_pair(tempSouth, true);
	}
	tempAvg = (tempWest + tempEast + tempNorth + tempSouth) / 4;

	for (uint64_t i = 1; i < nodeY - 1; ++i) {
		for (uint64_t j = 1; j < nodeX - 1; ++j) {
			nodes[i][j] = make_pair(tempAvg, false);
		}
	}

	for (uint64_t i = 0; i < nodeY; ++i) {
		for (uint64_t j = 0; j < nodeX; ++j)
			cout << nodes[i][j].first << ", ";
		cout << endl;
	}

	{
		char choice = 'y';
		uint64_t posX = 0, posY = 0;
		prec_t sourceTemp = 0.0f;
		while (true) {
			 cout << "Do you want to mark any node(s) as heat source [y/n]: ";
			 cin >> choice;
			 if (!(choice == 'y' || choice == 'Y')) {
			 	hasHeatSource = true;
			 	break;
			 }

			 cout << "posX: ";
			 cin >> posX;
			 cout << "posY: ";
			 cin >> posY;
			 cout << "heat source temp @(" << posX << ", " << posY << "): ";
			 cin >> sourceTemp;

			 nodes[posX - 1][posY - 1].first = sourceTemp;
			 nodes[posX - 1][posY - 1].second = true;
		}
	}

	if (hasHeatSource)
		clog << endl << "[hasHeatSource: " << hasHeatSource << "]" << endl;
	for (auto const &i : nodes) {
		for (auto const &node : i)
			if (node.second == true)
				cout << node.first << ", ";
			else
				cout << "\t, ";
		cout << endl;
	}

	startTime = std::chrono::high_resolution_clock::now();
	size_t iter = 0;
	while (epsilon <= diff) {
		iter++;
		for (uint64_t i = 0; i < nodeY; ++i)
			for (uint64_t j = 0; j < nodeX; ++j)
				nodesOld[i][j] = nodes[i][j];

		diff = 0.0f;
		for (uint64_t i = 1; i < nodeY - 1; ++i)
			for (uint64_t j = 1; j < nodeX - 1; ++j) {
				if (nodes[i][j].second != true) {
					nodes[i][j].first = (nodesOld[i - 1][j].first + nodesOld[i + 1][j].first +
											 nodesOld[i][j - 1].first + nodesOld[i][j + 1].first) / 4;
				}

				if (diff < std::fabs(nodesOld[i][j].first - nodes[i][j].first))
					diff = std::fabs(nodesOld[i][j].first - nodes[i][j].first);
			}
	}
	endTime = std::chrono::high_resolution_clock::now();
	auto elapsedTime = endTime - startTime;

	cout << endl << "######## After iter ..." << endl;

	for (auto const &i : nodes) {
		for (auto const &node : i)
			cout << node.first << ", ";
		cout << endl;
	}

	clog << endl
		 << "[iter: " << iter << "]" << endl
		 << "[time for iter: " << std::chrono::duration_cast<time_ms>(elapsedTime).count() << "ms]" << endl;

	{
		char choice = 'y';
		uint64_t posX = 0, posY = 0;
		while (true)
		{
			cout << "get temp any pos? (n/y): ";
			cin >> choice;
			if (!(choice == 'y' || choice == 'Y'))
				break;

			cout << "posX: ";
			cin >> posX;
			cout << "posY: ";
			cin >> posY;
			cout << "temp @(" << posX << ", " << posY << "): " << nodes[posY - 1][posX - 1].first << endl;
		}
	}**/

	HMT::Nodes<prec_t> nodes{nodeX, nodeY};
	nodes.putWallTemp(500.0f, 100.0f, 100.0f, 100.0f);
	nodes.testBuffers();
	nodes.calculate(0.1f);
	nodes.testBuffers();

	return 0;
}<commit_msg>0.0.1<commit_after><|endoftext|>


<commit_before>namespace dp {

	template < typename T, std::size_t D >
	inline DopeVectorExtent<T, D>::DopeVectorExtent(const std::array<std::size_t, D> &size)
		: DopeVector<T, D>()
		, _arrayPtr(nullptr)
	{
		resize(size);
	}

	template < typename T, std::size_t D >
	inline DopeVectorExtent<T, D> & DopeVectorExtent<T, D>::operator=(const DopeVectorExtent &other)
	{
		if (&other != this) {
			std::array<std::size_t, D> size;
			other.allSizes(size);
			resize(size);
			std::memcpy(_arrayPtr.get(), other._arrayPtr.get(), DopeVector<T, D>::size() * sizeof(T));
		}
		return *this;
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::import(const DopeVector<T, D> &o)
	{
		if (&o == this)
			return;
		try {
			const DopeVectorExtent<T, D> &oo = dynamic_cast<const DopeVectorExtent<T, D> &>(o);
			for (std::size_t d = 0; d < D; ++d)
			if (DopeVector<T, D>::sizeAt(d) != oo.sizeAt(d))
				throw std::out_of_range("Matrixes do not have same size.");
			std::memcpy(_arrayPtr.get(), oo._arrayPtr.get(), DopeVector<T, D>::size() * sizeof(T));
		} catch(std::bad_cast &bc) {
			DopeVector<T, D>::import(o);
		}
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::resize(const std::array<std::size_t, D> &size)
	{
		std::size_t total = size[0];
		for (std::size_t i = 1; i < D; ++i)
			total *= size[i];
		if (total > 0) {
			if (total != DopeVector<T, D>::size())
				_arrayPtr.reset(new T[total]);		// Be aware: data is LOST!
			DopeVector<T, D>::operator=(DopeVector<T, D>(_arrayPtr.get(), 0, size));
		} else {
			clear();
		}
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::clear()
	{
		_arrayPtr.reset(nullptr);
		DopeVector<T, D>::operator=(DopeVector<T, D>());
	}

}
<commit_msg>check for POD data (otherwise it shouldn't be used C's memcpy)<commit_after>#include <type_traits>

namespace dp {

	template < typename T, std::size_t D >
	inline DopeVectorExtent<T, D>::DopeVectorExtent(const std::array<std::size_t, D> &size)
		: DopeVector<T, D>()
		, _arrayPtr(nullptr)
	{
		resize(size);
	}

	template < typename T, std::size_t D >
	inline DopeVectorExtent<T, D> & DopeVectorExtent<T, D>::operator=(const DopeVectorExtent &other)
	{
		if (&other != this) {
			std::array<std::size_t, D> size;
			other.allSizes(size);
			resize(size);
			std::memcpy(_arrayPtr.get(), other._arrayPtr.get(), DopeVector<T, D>::size() * sizeof(T));
		}
		return *this;
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::import(const DopeVector<T, D> &o)
	{
		if (&o == this)
			return;
		try {
			const DopeVectorExtent<T, D> &oo = dynamic_cast<const DopeVectorExtent<T, D> &>(o);
			for (std::size_t d = 0; d < D; ++d)
			if (DopeVector<T, D>::sizeAt(d) != oo.sizeAt(d))
				throw std::out_of_range("Matrixes do not have same size.");
			if (std::is_pod<T>::value)
				std::memcpy(_arrayPtr.get(), oo._arrayPtr.get(), DopeVector<T, D>::size() * sizeof(T));
			else
			for (std::size_t i = 0; i < DopeVector<T, D>::size(); ++i)
				_arrayPtr[i] = oo._arrayPtr[i];
		} catch(std::bad_cast &bc) {
			DopeVector<T, D>::import(o);
		}
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::resize(const std::array<std::size_t, D> &size)
	{
		std::size_t total = size[0];
		for (std::size_t i = 1; i < D; ++i)
			total *= size[i];
		if (total > 0) {
			if (total != DopeVector<T, D>::size())
				_arrayPtr.reset(new T[total]);		// Be aware: data is LOST!
			DopeVector<T, D>::operator=(DopeVector<T, D>(_arrayPtr.get(), 0, size));
		} else {
			clear();
		}
	}

	template < typename T, std::size_t D >
	inline void DopeVectorExtent<T, D>::clear()
	{
		_arrayPtr.reset(nullptr);
		DopeVector<T, D>::operator=(DopeVector<T, D>());
	}

}
<|endoftext|>


<commit_before>/******************************************************************************
The MIT License(MIT)

Embedded Template Library.
https://github.com/ETLCPP/etl

Copyright(c) 2015 jwellbelove

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 <UnitTest++/UnitTest++.h>

#include <string>
#include <ostream>

#include "../optional.h"
#include "../vector.h"
#include "data.h"

typedef TestDataNDC<std::string> Data;

std::ostream& operator << (std::ostream& os, const Data& data)
{
  os << data.value;
  return os;
}

std::ostream& operator << (std::ostream& os, const etl::optional<Data>& data)
{
  os << data.value();
  return os;
}

namespace
{
  SUITE(test_optional)
  {
    //*************************************************************************
    TEST(test_initialisation)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(!bool(data1));
      CHECK(!bool(data2));

      data1 = Data("Hello");
      CHECK(bool(data1));
      CHECK_EQUAL(Data("Hello"), data1);

      data1 = data2;
      CHECK(!bool(data1));
      CHECK(!bool(data2));

      data1 = Data("World");
      data2 = data1;
      CHECK(bool(data1));
      CHECK(bool(data2));

      etl::optional<Data> data3(data1);
      CHECK(bool(data3));
      CHECK_EQUAL(data1, data3);

      etl::optional<Data> data4;
      data4 = Data("Hello");
      data4 = etl::nullopt;
      CHECK(!bool(data4));
    }

    //*************************************************************************
    TEST(test_nullopt)
    {
      etl::optional<Data> data;
      data = Data("Hello");
      data = etl::nullopt;
      CHECK(!bool(data));
    }

    //*************************************************************************
    TEST(test_value_or)
    {
      etl::optional<Data> data;

      Data result = data.value_or(Data("Default"));
      CHECK_EQUAL(Data("Default"), result);

      data = Data("Value");
      result = data.value_or(Data("Default"));
      CHECK_EQUAL(Data("Value"), result);
    }

    //*************************************************************************
    TEST(test_equality)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(data1 == data2);

      data1 = Data("Data1");
      CHECK(!(data1 == data2));

      data1 = etl::nullopt;
      data2 = Data("Data2");
      CHECK(!(data1 == data2));

      data1 = Data("Data1");
      data2 = Data("Data1");
      CHECK(data1 == data2);

      data1 = Data("Data1");
      data2 = Data("Data2");
      CHECK(!(data1 == data2));

      CHECK(data1 == Data("Data1"));
      CHECK(!(data1 == Data("Data2")));
    }

    //*************************************************************************
    TEST(test_less_than)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(!(data1 < data2));

      data1 = Data("Data1");
      CHECK(!(data1 < data2));

      data1 = etl::nullopt;
      data2 = Data("Data2");
      CHECK(data1 < data2);

      data1 = Data("Data1");
      data2 = Data("Data2");
      CHECK(data1 < data2);
      CHECK(!(data2 < data1));

      CHECK(data1 < Data("Data2"));
      CHECK(!(data1 < Data("Data1")));
    }

    //*************************************************************************
    TEST(test_container_of_optional)
    {
      etl::vector<etl::optional<Data>, 10> container;

      container.resize(5, Data("1"));

      CHECK(bool(container[0]));
      CHECK(bool(container[1]));
      CHECK(bool(container[2]));
      CHECK(bool(container[3]));
      CHECK(bool(container[4]));
    }

    //*************************************************************************
    TEST(test_optional_container)
    {
      etl::optional<etl::vector<Data, 10>> container;
      CHECK(!bool(container));

      container = etl::vector<Data, 10>();
      CHECK(bool(container));

      container.value().resize(5, Data("1"));

      CHECK_EQUAL(Data("1"), container.value()[0]);
      CHECK_EQUAL(Data("1"), container.value()[1]);
      CHECK_EQUAL(Data("1"), container.value()[2]);
      CHECK_EQUAL(Data("1"), container.value()[3]);
      CHECK_EQUAL(Data("1"), container.value()[4]);
    }
  };
}
<commit_msg>Added tests for debug exceptions.<commit_after>/******************************************************************************
The MIT License(MIT)

Embedded Template Library.
https://github.com/ETLCPP/etl

Copyright(c) 2015 jwellbelove

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 <UnitTest++/UnitTest++.h>

#include <string>
#include <ostream>

#include "../optional.h"
#include "../vector.h"
#include "data.h"

typedef TestDataNDC<std::string> Data;

std::ostream& operator << (std::ostream& os, const Data& data)
{
  os << data.value;
  return os;
}

std::ostream& operator << (std::ostream& os, const etl::optional<Data>& data)
{
  os << data.value();
  return os;
}

namespace
{
  SUITE(test_optional)
  {
    //*************************************************************************
    TEST(test_initialisation)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(!bool(data1));
      CHECK(!bool(data2));

      data1 = Data("Hello");
      CHECK(bool(data1));
      CHECK_EQUAL(Data("Hello"), data1);

      data1 = data2;
      CHECK(!bool(data1));
      CHECK(!bool(data2));

      data1 = Data("World");
      data2 = data1;
      CHECK(bool(data1));
      CHECK(bool(data2));

      etl::optional<Data> data3(data1);
      CHECK(bool(data3));
      CHECK_EQUAL(data1, data3);

      etl::optional<Data> data4;
      data4 = Data("Hello");
      data4 = etl::nullopt;
      CHECK(!bool(data4));
    }

    //*************************************************************************
    TEST(test_nullopt)
    {
      etl::optional<Data> data;
      data = Data("Hello");
      data = etl::nullopt;
      CHECK(!bool(data));
    }

    //*************************************************************************
    TEST(test_value_or)
    {
      etl::optional<Data> data;

      Data result = data.value_or(Data("Default"));
      CHECK_EQUAL(Data("Default"), result);

      data = Data("Value");
      result = data.value_or(Data("Default"));
      CHECK_EQUAL(Data("Value"), result);
    }

    //*************************************************************************
    TEST(test_equality)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(data1 == data2);

      data1 = Data("Data1");
      CHECK(!(data1 == data2));

      data1 = etl::nullopt;
      data2 = Data("Data2");
      CHECK(!(data1 == data2));

      data1 = Data("Data1");
      data2 = Data("Data1");
      CHECK(data1 == data2);

      data1 = Data("Data1");
      data2 = Data("Data2");
      CHECK(!(data1 == data2));

      CHECK(data1 == Data("Data1"));
      CHECK(!(data1 == Data("Data2")));
    }

    //*************************************************************************
    TEST(test_less_than)
    {
      etl::optional<Data> data1;
      etl::optional<Data> data2;

      CHECK(!(data1 < data2));

      data1 = Data("Data1");
      CHECK(!(data1 < data2));

      data1 = etl::nullopt;
      data2 = Data("Data2");
      CHECK(data1 < data2);

      data1 = Data("Data1");
      data2 = Data("Data2");
      CHECK(data1 < data2);
      CHECK(!(data2 < data1));

      CHECK(data1 < Data("Data2"));
      CHECK(!(data1 < Data("Data1")));
    }

    //*************************************************************************
    TEST(test_container_of_optional)
    {
      etl::vector<etl::optional<Data>, 10> container;

      container.resize(5, Data("1"));

      CHECK(bool(container[0]));
      CHECK(bool(container[1]));
      CHECK(bool(container[2]));
      CHECK(bool(container[3]));
      CHECK(bool(container[4]));
    }

    //*************************************************************************
    TEST(test_optional_container)
    {
      etl::optional<etl::vector<Data, 10>> container;
      CHECK(!bool(container));

      container = etl::vector<Data, 10>();
      CHECK(bool(container));

      container.value().resize(5, Data("1"));

      CHECK_EQUAL(Data("1"), container.value()[0]);
      CHECK_EQUAL(Data("1"), container.value()[1]);
      CHECK_EQUAL(Data("1"), container.value()[2]);
      CHECK_EQUAL(Data("1"), container.value()[3]);
      CHECK_EQUAL(Data("1"), container.value()[4]);
    }

    //*************************************************************************
    TEST(test_exception)
    {
      etl::optional<Data> data1;

      CHECK_THROW(Data d(data1.value()), etl::optional_invalid);
    }
  };
}
<|endoftext|>


<commit_before><commit_msg>remove unused method setDummyUpperLeft<commit_after><|endoftext|>


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

#ifndef SC_MATRIX_HXX
#define SC_MATRIX_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif
#ifndef SC_INTRUREF_HXX
#include "intruref.hxx"
#endif
#ifndef SC_ERRORCODES_HXX
#include "errorcodes.hxx"
#endif

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

class SvStream;
class ScInterpreter;

typedef BYTE ScMatValType;
const ScMatValType SC_MATVAL_VALUE     = 0x00;
const ScMatValType SC_MATVAL_STRING    = 0x01;
const ScMatValType SC_MATVAL_EMPTY     = SC_MATVAL_STRING | 0x02; // STRING plus flag
const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x04;  // EMPTY plus flag

union ScMatrixValue
{
    double fVal;
    String* pS;

    /// Only valid if ScMatrix methods indicate so!
    const String& GetString() const     { return pS ? *pS : EMPTY_STRING; }

    /// Only valid if ScMatrix methods indicate that this is no string!
    USHORT GetError() const         { return GetDoubleErrorValue( fVal); }
};

/** Matrix representation of double values and strings.

    @ATTENTION: optimized for speed and double values.

    Matrix elements are NOT initialized after construction!

    All methods using an SCSIZE nIndex parameter and all Is... methods do NOT
    check the range for validity! However, the Put... and Get... methods using
    nCol/nRow parameters do check the range.

    GetString( SCSIZE nIndex ) does not check if there really is a string, do
    this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
    it and returns and empty string if there is no string. Both GetDouble()
    methods don't check for a string, do this with IsNumeric() or IsString()
    or IsValue() first.

    PutDouble() does not reset an eventual string! Use
    PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
    methods don't reset strings. As a consequence memory leaks may occur if
    used wrong.
 */
class ScMatrix
{
    ScMatrixValue*  pMat;
    ScMatValType*   bIsString;
    ScInterpreter*  pErrorInterpreter;
    ULONG           nRefCnt;     // reference count
    SCSIZE          nColCount;
    SCSIZE          nRowCount;

    void ResetIsString();
    void DeleteIsString();
    void CreateMatrix( SCSIZE nC, SCSIZE nR);

    // pStr may be NULL, bFlag MUST NOT be 0
    void PutStringEntry( const String* pStr, BYTE bFlag, SCSIZE nIndex );

    // only delete via Delete()
    ~ScMatrix();

    // not implemented, prevent usage
    ScMatrix( const ScMatrix& );
    ScMatrix& operator=( const ScMatrix&);

    void SetErrorAtInterpreter( USHORT nError) const;

public:

    /// The maximum number of elements a matrix may have at runtime
    inline static size_t GetElementsMax()
    {
        const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
        const size_t nArbitraryLimit = 0x80000;  // 512k elements ~= 4MB memory
        return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
    }

    /** If nC*nR results in more than GetElementsMax() entries, a 1x1 matrix is
        created instead and a double error value (errStackOverflow) is set.
        Compare nC and nR with a GetDimensions() call to check. */
    ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
    ScMatrix* Clone() const;

    /// disable refcounting forever, may only be deleted via Delete() afterwards
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
    inline  void    IncRef()
    {
        if ( !IsEternalRef() )
            ++nRefCnt;
    }
    inline  void    DecRef()
    {
        if ( nRefCnt > 0 && !IsEternalRef() )
            if ( --nRefCnt == 0 )
                delete this;
    }
    inline  void    Delete()
    {
        if ( nRefCnt == 0 || IsEternalRef() )
            delete this;
        else
            --nRefCnt;
    }

    void SetErrorInterpreter( ScInterpreter* p)
        { pErrorInterpreter = p; }

    ScMatrix( SvStream& rStream);
    void Store( SvStream& rStream) const;

    void GetDimensions( SCSIZE& rC, SCSIZE& rR) const
        { rC = nColCount; rR = nRowCount; };
    SCSIZE GetElementCount() const
        { return nColCount * nRowCount; }
    inline bool ValidColRow( SCSIZE nC, SCSIZE nR) const
        { return nC < nColCount && nR < nRowCount; }
    inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
        { return nC * nRowCount + nR; }

    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
    void PutDouble( double fVal, SCSIZE nIndex)
        { pMat[nIndex].fVal = fVal; }
    void PutDoubleAndResetString( double fVal, SCSIZE nC, SCSIZE nR );
    void PutDoubleAndResetString( double fVal, SCSIZE nIndex );
    void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
    void PutString( const String& rStr, SCSIZE nIndex);
    void PutEmpty( SCSIZE nC, SCSIZE nR);
    void PutEmpty( SCSIZE nIndex);
    /// Jump FALSE without path
    void PutEmptyPath( SCSIZE nC, SCSIZE nR);
    void PutEmptyPath( SCSIZE nIndex);
    void PutError( USHORT nErrorCode, SCSIZE nC, SCSIZE nR )
        { PutDouble( CreateDoubleError( nErrorCode ), nC, nR ); }
    void PutError( USHORT nErrorCode, SCSIZE nIndex )
        { PutDouble( CreateDoubleError( nErrorCode ), nIndex ); }
    void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
    /// lower left triangle
    void FillDoubleLowerLeft( double fVal, SCSIZE nC2 );

    /** Use outside ScInterpreter before obtaining the double value of an
        element and passing it's NAN around.
        @returns 0 if no error, else one of err... constants */
    USHORT GetError( SCSIZE nC, SCSIZE nR) const;
    USHORT GetError( SCSIZE nIndex) const
        { return GetDoubleErrorValue( pMat[nIndex].fVal); }

    /// @return 0.0 if empty
    double GetDouble( SCSIZE nC, SCSIZE nR) const;
    /// @return 0.0 if empty
    double GetDouble( SCSIZE nIndex) const
    {
        if ( pErrorInterpreter )
        {
            USHORT nError = GetDoubleErrorValue( pMat[nIndex].fVal);
            if ( nError )
                SetErrorAtInterpreter( nError);
        }
        return pMat[nIndex].fVal;
    }
    const String& GetString( SCSIZE nC, SCSIZE nR) const;
    const String& GetString( SCSIZE nIndex) const
        { return pMat[nIndex].GetString(); }

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    const ScMatrixValue* Get( SCSIZE nC, SCSIZE nR, ScMatValType& nType) const;

    /// @return <TRUE/> if string or empty
    BOOL IsString( SCSIZE nIndex ) const
        { return bIsString && bIsString[nIndex]; }
    /// @return <TRUE/> if string or empty
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && bIsString[ nC * nRowCount + nR ]; }
    BOOL IsEmpty( SCSIZE nIndex ) const
        { return bIsString && ((bIsString[nIndex] & SC_MATVAL_EMPTY) ==
                SC_MATVAL_EMPTY); }
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && ((bIsString[ nC * nRowCount + nR ] &
                    SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
    BOOL IsEmptyPath( SCSIZE nIndex ) const
        { return bIsString && ((bIsString[nIndex] & SC_MATVAL_EMPTYPATH) ==
                SC_MATVAL_EMPTYPATH); }
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && ((bIsString[ nC * nRowCount + nR ] &
                    SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
    BOOL IsValue( SCSIZE nIndex ) const
        { return !bIsString || !bIsString[nIndex]; }
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
        { return !bIsString || !bIsString[ nC * nRowCount + nR ]; }
    BOOL IsValueOrEmpty( SCSIZE nIndex ) const
        { return !bIsString || !bIsString[nIndex] || ((bIsString[nIndex] &
                    SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
        { return !bIsString || !bIsString[ nC * nRowCount + nR ] ||
            ((bIsString[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
             SC_MATVAL_EMPTY); }

    /// @return <TRUE/> if entire matrix is numeric and no strings are contained
    BOOL IsNumeric() const
        { return bIsString == NULL; }

    void MatTrans( ScMatrix& mRes) const;
    void MatCopy ( ScMatrix& mRes) const;
    /** Copy upper left of this matrix to mRes matrix.
        This matrix's dimensions must be greater than the mRes matrix
        dimensions. */
    void MatCopyUpperLeft( ScMatrix& mRes) const;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    void CompareEqual();
    void CompareNotEqual();
    void CompareLess();
    void CompareGreater();
    void CompareLessEqual();
    void CompareGreaterEqual();

    double And();       // logical AND of all matrix values, or NAN
    double Or();        // logical OR of all matrix values, or NAN

    // All other matrix functions  MatMult, MInv, ...  are in ScInterpreter
    // to be numerically safe.
};

typedef ScSimpleIntrusiveReference< class ScMatrix > ScMatrixRef;

// Old values as used up to SO52.
// The overall elements count had to be <= SC_MAX_MAT_DIM * SC_MAX_MAT_DIM.
// Don't use except maybe for file format compatibility.
// In any other case use ScMatrix::GetElementsMax() instead.
#ifdef WIN
#define SC_OLD_MAX_MAT_DIM            64
#else
#define SC_OLD_MAX_MAT_DIM           128
#endif
#define SC_OLD_MAX_MAT_ELEMENTS     ((SC_OLD_MAX_MAT_DIM) * (SC_OLD_MAX_MAT_DIM))

#endif

<commit_msg>INTEGRATION: CWS calcer (1.4.52); FILE MERGED 2004/11/16 18:24:38 er 1.4.52.1: #i36541# generic ScMatrix::GetString() also for numerical values<commit_after>/*************************************************************************
 *
 *  $RCSfile: scmatrix.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-08 11:28:36 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_MATRIX_HXX
#define SC_MATRIX_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif
#ifndef SC_INTRUREF_HXX
#include "intruref.hxx"
#endif
#ifndef SC_ERRORCODES_HXX
#include "errorcodes.hxx"
#endif

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

class SvStream;
class ScInterpreter;
class SvNumberFormatter;

typedef BYTE ScMatValType;
const ScMatValType SC_MATVAL_VALUE     = 0x00;
const ScMatValType SC_MATVAL_STRING    = 0x01;
const ScMatValType SC_MATVAL_EMPTY     = SC_MATVAL_STRING | 0x02; // STRING plus flag
const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x04;  // EMPTY plus flag

union ScMatrixValue
{
    double fVal;
    String* pS;

    /// Only valid if ScMatrix methods indicate so!
    const String& GetString() const     { return pS ? *pS : EMPTY_STRING; }

    /// Only valid if ScMatrix methods indicate that this is no string!
    USHORT GetError() const         { return GetDoubleErrorValue( fVal); }
};

/** Matrix representation of double values and strings.

    @ATTENTION: optimized for speed and double values.

    Matrix elements are NOT initialized after construction!

    All methods using an SCSIZE nIndex parameter and all Is... methods do NOT
    check the range for validity! However, the Put... and Get... methods using
    nCol/nRow parameters do check the range.

    GetString( SCSIZE nIndex ) does not check if there really is a string, do
    this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
    it and returns and empty string if there is no string. Both GetDouble()
    methods don't check for a string, do this with IsNumeric() or IsString()
    or IsValue() first.

    The GetString( SvNumberFormatter&, ...) methods return the matrix element's
    string if one is present, otherwise the numerical value is formatted as a
    string, or in case of an error the error string is returned.

    PutDouble() does not reset an eventual string! Use
    PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
    methods don't reset strings. As a consequence memory leaks may occur if
    used wrong.
 */
class ScMatrix
{
    ScMatrixValue*  pMat;
    ScMatValType*   bIsString;
    ScInterpreter*  pErrorInterpreter;
    ULONG           nRefCnt;     // reference count
    SCSIZE          nColCount;
    SCSIZE          nRowCount;

    void ResetIsString();
    void DeleteIsString();
    void CreateMatrix( SCSIZE nC, SCSIZE nR);

    // pStr may be NULL, bFlag MUST NOT be 0
    void PutStringEntry( const String* pStr, BYTE bFlag, SCSIZE nIndex );

    // only delete via Delete()
    ~ScMatrix();

    // not implemented, prevent usage
    ScMatrix( const ScMatrix& );
    ScMatrix& operator=( const ScMatrix&);

    void SetErrorAtInterpreter( USHORT nError) const;

public:

    /// The maximum number of elements a matrix may have at runtime
    inline static size_t GetElementsMax()
    {
        const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
        const size_t nArbitraryLimit = 0x80000;  // 512k elements ~= 4MB memory
        return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
    }

    /** If nC*nR results in more than GetElementsMax() entries, a 1x1 matrix is
        created instead and a double error value (errStackOverflow) is set.
        Compare nC and nR with a GetDimensions() call to check. */
    ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
    ScMatrix* Clone() const;

    /// disable refcounting forever, may only be deleted via Delete() afterwards
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
    inline  void    IncRef()
    {
        if ( !IsEternalRef() )
            ++nRefCnt;
    }
    inline  void    DecRef()
    {
        if ( nRefCnt > 0 && !IsEternalRef() )
            if ( --nRefCnt == 0 )
                delete this;
    }
    inline  void    Delete()
    {
        if ( nRefCnt == 0 || IsEternalRef() )
            delete this;
        else
            --nRefCnt;
    }

    void SetErrorInterpreter( ScInterpreter* p)
        { pErrorInterpreter = p; }

    ScMatrix( SvStream& rStream);
    void Store( SvStream& rStream) const;

    void GetDimensions( SCSIZE& rC, SCSIZE& rR) const
        { rC = nColCount; rR = nRowCount; };
    SCSIZE GetElementCount() const
        { return nColCount * nRowCount; }
    inline bool ValidColRow( SCSIZE nC, SCSIZE nR) const
        { return nC < nColCount && nR < nRowCount; }
    inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
        { return nC * nRowCount + nR; }

    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
    void PutDouble( double fVal, SCSIZE nIndex)
        { pMat[nIndex].fVal = fVal; }
    void PutDoubleAndResetString( double fVal, SCSIZE nC, SCSIZE nR );
    void PutDoubleAndResetString( double fVal, SCSIZE nIndex );
    void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
    void PutString( const String& rStr, SCSIZE nIndex);
    void PutEmpty( SCSIZE nC, SCSIZE nR);
    void PutEmpty( SCSIZE nIndex);
    /// Jump FALSE without path
    void PutEmptyPath( SCSIZE nC, SCSIZE nR);
    void PutEmptyPath( SCSIZE nIndex);
    void PutError( USHORT nErrorCode, SCSIZE nC, SCSIZE nR )
        { PutDouble( CreateDoubleError( nErrorCode ), nC, nR ); }
    void PutError( USHORT nErrorCode, SCSIZE nIndex )
        { PutDouble( CreateDoubleError( nErrorCode ), nIndex ); }
    void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
    /// lower left triangle
    void FillDoubleLowerLeft( double fVal, SCSIZE nC2 );

    /** Use outside ScInterpreter before obtaining the double value of an
        element and passing it's NAN around.
        @returns 0 if no error, else one of err... constants */
    USHORT GetError( SCSIZE nC, SCSIZE nR) const;
    USHORT GetError( SCSIZE nIndex) const
        { return GetDoubleErrorValue( pMat[nIndex].fVal); }

    /// @return 0.0 if empty
    double GetDouble( SCSIZE nC, SCSIZE nR) const;
    /// @return 0.0 if empty
    double GetDouble( SCSIZE nIndex) const
    {
        if ( pErrorInterpreter )
        {
            USHORT nError = GetDoubleErrorValue( pMat[nIndex].fVal);
            if ( nError )
                SetErrorAtInterpreter( nError);
        }
        return pMat[nIndex].fVal;
    }
    const String& GetString( SCSIZE nC, SCSIZE nR) const;
    const String& GetString( SCSIZE nIndex) const
        { return pMat[nIndex].GetString(); }

    String GetString( SvNumberFormatter& rFormatter, SCSIZE nIndex) const;
    String GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    const ScMatrixValue* Get( SCSIZE nC, SCSIZE nR, ScMatValType& nType) const;

    /// @return <TRUE/> if string or empty
    BOOL IsString( SCSIZE nIndex ) const
        { return bIsString && bIsString[nIndex]; }
    /// @return <TRUE/> if string or empty
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && bIsString[ nC * nRowCount + nR ]; }
    BOOL IsEmpty( SCSIZE nIndex ) const
        { return bIsString && ((bIsString[nIndex] & SC_MATVAL_EMPTY) ==
                SC_MATVAL_EMPTY); }
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && ((bIsString[ nC * nRowCount + nR ] &
                    SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
    BOOL IsEmptyPath( SCSIZE nIndex ) const
        { return bIsString && ((bIsString[nIndex] & SC_MATVAL_EMPTYPATH) ==
                SC_MATVAL_EMPTYPATH); }
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
        { return bIsString && ((bIsString[ nC * nRowCount + nR ] &
                    SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
    BOOL IsValue( SCSIZE nIndex ) const
        { return !bIsString || !bIsString[nIndex]; }
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
        { return !bIsString || !bIsString[ nC * nRowCount + nR ]; }
    BOOL IsValueOrEmpty( SCSIZE nIndex ) const
        { return !bIsString || !bIsString[nIndex] || ((bIsString[nIndex] &
                    SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
        { return !bIsString || !bIsString[ nC * nRowCount + nR ] ||
            ((bIsString[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
             SC_MATVAL_EMPTY); }

    /// @return <TRUE/> if entire matrix is numeric and no strings are contained
    BOOL IsNumeric() const
        { return bIsString == NULL; }

    void MatTrans( ScMatrix& mRes) const;
    void MatCopy ( ScMatrix& mRes) const;
    /** Copy upper left of this matrix to mRes matrix.
        This matrix's dimensions must be greater than the mRes matrix
        dimensions. */
    void MatCopyUpperLeft( ScMatrix& mRes) const;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    void CompareEqual();
    void CompareNotEqual();
    void CompareLess();
    void CompareGreater();
    void CompareLessEqual();
    void CompareGreaterEqual();

    double And();       // logical AND of all matrix values, or NAN
    double Or();        // logical OR of all matrix values, or NAN

    // All other matrix functions  MatMult, MInv, ...  are in ScInterpreter
    // to be numerically safe.
};

typedef ScSimpleIntrusiveReference< class ScMatrix > ScMatrixRef;

// Old values as used up to SO52.
// The overall elements count had to be <= SC_MAX_MAT_DIM * SC_MAX_MAT_DIM.
// Don't use except maybe for file format compatibility.
// In any other case use ScMatrix::GetElementsMax() instead.
#ifdef WIN
#define SC_OLD_MAX_MAT_DIM            64
#else
#define SC_OLD_MAX_MAT_DIM           128
#endif
#define SC_OLD_MAX_MAT_ELEMENTS     ((SC_OLD_MAX_MAT_DIM) * (SC_OLD_MAX_MAT_DIM))

#endif

<|endoftext|>