<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "config.h"

#ifndef DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
# define DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING 0
#endif

#include <string>
#include <vector>
#include <map>
#include <random>
#include <fstream>
#include <limits>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/float_cmp.hh>
# include <dune/common/fvector.hh>
# include <dune/common/fmatrix.hh>
# include <dune/common/parallel/mpihelper.hh>

# if HAVE_DUNE_FEM
#   include <dune/fem/misc/mpimanager.hh>
# endif
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/test/gtest/gtest.h>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/timedlogging.hh>
#include <dune/stuff/common/convergence-study.hh>

#include "common.hh"

#if HAVE_TBB
# include <thread>
# include <tbb/task_scheduler_init.h>
#endif

class
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
      errors_are_not_as_expected
  : public Dune::Exception
{};

std::vector< double >
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
                      truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > ret(size);
    for (size_t ii = 0; ii < size; ++ii)
      ret[ii] = in[ii];
    return ret;
  }
} // ... truncate_vector(...)

int main(int argc, char** argv)
{
#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  try {
#endif

    testing::InitGoogleTest(&argc, argv);
    DSC_CONFIG.read_options(argc, argv);
#if HAVE_DUNE_FEM
    Dune::Fem::MPIManager::initialize(argc, argv);
#else
    Dune::MPIHelper::instance(argc, argv);
#endif

    DSC::Logger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_DEBUG | DSC::LOG_ERROR
#elif DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_ERROR
#else
                         DSC::LOG_CONSOLE | DSC::LOG_ERROR
#endif
                                                                                , "", "", "");

    DSC::TimedLogger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                              std::numeric_limits< ssize_t >::max(),
#else
                              -1,
#endif
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                                                                    std::numeric_limits< ssize_t >::max()
#else
                                                                    -1
#endif
                                                                                );
#if HAVE_TBB
    tbb::task_scheduler_init tbb_init(DSC_CONFIG_GET("threading.max_count", 1));
#endif
    return RUN_ALL_TESTS();

#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
#endif // DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
} // ... main(...)

<commit_msg>[test.main] circumvent unconditional warning output<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "config.h"

#ifndef DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
# define DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING 0
#endif

#include <string>
#include <vector>
#include <map>
#include <random>
#include <fstream>
#include <limits>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/float_cmp.hh>
# include <dune/common/fvector.hh>
# include <dune/common/fmatrix.hh>
# include <dune/common/parallel/mpihelper.hh>

# if HAVE_DUNE_FEM
#   include <dune/fem/misc/mpimanager.hh>
# endif
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/test/gtest/gtest.h>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/timedlogging.hh>
#include <dune/stuff/common/convergence-study.hh>

#include "common.hh"

#if HAVE_TBB
# include <thread>
# include <tbb/task_scheduler_init.h>
#endif

class
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
      errors_are_not_as_expected
  : public Dune::Exception
{};

std::vector< double >
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
                      truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > ret(size);
    for (size_t ii = 0; ii < size; ++ii)
      ret[ii] = in[ii];
    return ret;
  }
} // ... truncate_vector(...)

int main(int argc, char** argv)
{
#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  try {
#endif

    testing::InitGoogleTest(&argc, argv);
    DSC_CONFIG.read_options(argc, argv);
#if HAVE_DUNE_FEM
    Dune::Fem::MPIManager::initialize(argc, argv);
#else
    Dune::MPIHelper::instance(argc, argv);
#endif

    DSC::Logger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_DEBUG | DSC::LOG_ERROR
#elif DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_ERROR
#else
                         DSC::LOG_CONSOLE | DSC::LOG_ERROR
#endif
                                                                                , "", "", "");

    DSC::TimedLogger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                              std::numeric_limits< ssize_t >::max(),
#else
                              -1,
#endif
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                                                                    std::numeric_limits< ssize_t >::max()
#else
                                                                    -1
#endif
                                                                                );
#if HAVE_TBB
    tbb::task_scheduler_init tbb_init(DSC_CONFIG.has_key("threading.max_count")      // <- doing this so complicated to
                                      ? DSC_CONFIG.get< int >("threading.max_count") //    silence the WARNING: ...
                                      : 1);
#endif
    return RUN_ALL_TESTS();

#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
#endif // DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
} // ... main(...)

<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// Source file for project BoxOfRox.
//
// Authors: Viranga and Naor
///////////////////////////////////////////////////////////////////////////////

#include "ARSS.h"
#include "BoxOfRox.h"

// Request lint level warnings with the LINT macro on Microsoft compilers
#ifdef LINT
#pragma warning(push,4)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif

int main(int argc, char** argv)
{

#ifdef _DEBUG
	cout << "***DEBUG BUILD***" << endl;
#endif

	ncc::whoami();

	InitRun(argc,argv);
	InitGlut(argc,argv);
	InitHUD();
	InitDevIL();
	InitPhysX();
	InitCUDA();
	InitExperiment();
	glutMainLoop(); // enter event processing

	return 0; // never actually reached.
}

void CustomizeRun(int,char**)
{
	// Read experiment-specific program options from file.
	if (!ConfigExperimentOptions())
	{ncc__warning("Could not find ARSS config file. Attempting to continue with all default options.\a");}
}
bool ConfigExperimentOptions()
{
	// First check that an options file exists
	ifstream fp(gRun.iniFile.c_str());
	bool success = fp.good();
	fp.close();

	// Read in parameters by group, file.ini style
	char buf[MAX_CHARS_PER_NAME];

	// Experiment parameters
	ncc::GetStrPropertyFromINIFile("experiment","experiment_type","",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if		(strcmp(buf,"fill_box")==0)
		rox::eExperimentType = rox::eFILL_BOX;
	else if (strcmp(buf,"shake_box")==0)
		rox::eExperimentType = rox::eSHAKE_BOX;
	else
		rox::eExperimentType = rox::eBAD_EXPERIMENT_TYPE;

	ncc::GetStrPropertyFromINIFile("experiment","shake_magnitude","0",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::params.shakeMagnitude = atof(buf);

	// Parameters for the box
	ncc::GetStrPropertyFromINIFile("box","box_unit_size","100",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::params.boxSize = atof(buf);
	ncc::GetStrPropertyFromINIFile("box","box_design","",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if (strcmp(buf,"AOSAT1")==0)
		rox::eBoxDesign = rox::eAOSAT1;
	else
		rox::eBoxDesign = rox::eBAD_BOX_DESIGN;

	// Parameters for the regolith
	ncc::GetStrPropertyFromINIFile("regolith","grain_type","uniform",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if		(strcmp(buf,"uniform")==0)
		rox::regolith.type = rox::regolith.eGRAIN_UNIFORM;
	else if	(strcmp(buf,"bimodal")==0)
		rox::regolith.type = rox::regolith.eGRAIN_BIMODAL;
	else
		rox::regolith.type = rox::regolith.eBAD_GRAIN_TYPE;

	ncc::GetStrPropertyFromINIFile("regolith","grain_size1","1",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::regolith.size1 = atof(buf);
	ncc::GetStrPropertyFromINIFile("regolith","grain_size2","1",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::regolith.size2 = atof(buf);

	rox::regolith.totalNumber = ncc::GetIntPropertyFromINIFile("regolith","grain_total_number",0,gRun.iniFile.c_str());

	// Code units and scaling
	ncc::GetStrPropertyFromINIFile("units","big_g","0",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::units.bigG = atof(buf);

	return success;
}
void CustomizeScene(PxSceneDesc &sceneDesc)
{
	sceneDesc.gravity = PxVec3(0);
}
void CustomizeGLUT()
{

}
void CustomizeHUD()
{

}
void RefreshCustomHUDElements()
{

}
void FireAction()
{

}
void LogExperiment()
{

}
void PrintDebug()
{
}
void ApplyCustomInteractions()
{
	rox::GravitateSelf();
}
void RenderOtherStuff()
{

}
void CreateExperiment()
{
	gDebug.bXYGridOn=true;
	switch (rox::eExperimentType)
	{
	case rox::eFILL_BOX:
		rox::CreateFillBoxExperiment();
		break;
	case rox::eBAD_EXPERIMENT_TYPE: // intentional fall through
	default:
		ncc__error("Unknown experiment type. Experiment aborted.\a");
	}

	// Start the action
	gSim.isRunning=true;
	gSim.bPause=false;
	RefreshHUD();
}
void RebootExperiment()
{
	gSim.isRunning=false;
	DestroyPhysX();
	InitPhysX();
	CreateExperiment();
}
void LoadExperiment()
{

}
void UpArrowAction()
{

}
void DownArrowAction()
{

}
void LeftArrowAction()
{

}
void RightArrowAction()
{

}

// BoxOfRox namespace functions
void rox::CreateTheBox()
{
	switch (rox::eBoxDesign)
	{
	case rox::eAOSAT1:
		rox::CreateAOSAT1();
		break;
	case rox::eBAD_BOX_DESIGN: // intentional fall through
	default:
		ncc__error("Unknown box design\a");
	}
}
void rox::CreateFillBoxExperiment()
{
	rox::CreateTheBox();
	gCamera.pos = PxVec3(0,rox::params.boxSize,3*rox::params.boxSize);
}
void rox::GravitateSelf()
{
	if (gCUDA.cudaCapable)
		rox::GravitateOnDevice();
	else
		rox::GravitateOnHost();
}
void rox::GravitateOnDevice()
{
	rox::GravitateOnHost(); //TODO: include device implementation when needed, for speed
}
void rox::GravitateOnHost()
/*
 * This is a semi-optimized all-pairs gravity calculation in a single host thread. Not
 * usually the best option, but a necessary fall back option.
*/
{
	// Prepare
	PxU32 nbActors = gPhysX.mScene->getActors(gPhysX.roles.dynamics,gPhysX.cast,MAX_ACTORS_PER_SCENE);
	if (nbActors<2) return;
	float *bodies = new float[4*nbActors];
	float *forces = new float[3*nbActors];
	if (bodies==NULL || forces==NULL)
		ncc__error("Error allocating memory for body/forces arrays.");

	// Linearize actor positions
	for (PxU32 k=0; k<nbActors; k++)
	{
		PxRigidDynamic* actor = gPhysX.cast[k]->isRigidDynamic();
		PxTransform pose = actor->getGlobalPose().transform(actor->getCMassLocalPose());
		PxVec3 pos = pose.p;
		bodies[4*k+0] = actor->getMass();
		bodies[4*k+1] = pos.x;
		bodies[4*k+2] = pos.y;
		bodies[4*k+3] = pos.z;
	}

	// And now, the N^2 double loop.
	for (PxU32 j=0; j<nbActors; j++)
	{
		forces[3*j+0] = forces[3*j+1] = forces[3*j+2] = 0.0f;
		for (PxU32 k=0; k<j; k++)
		{
			PxReal x = bodies[4*k+1] - bodies[4*j+1];
			PxReal y = bodies[4*k+2] - bodies[4*j+2];
			PxReal z = bodies[4*k+3] - bodies[4*j+3];

			float distSqr = x*x + y*y + z*z;
			float distSix = distSqr*distSqr*distSqr;
			float invDistCube = 1.0f/sqrtf(distSix);

			float s = rox::units.bigG * bodies[4*j+0] * bodies[4*k+0] * invDistCube;

			forces[3*j+0] += x*s;
			forces[3*j+1] += y*s;
			forces[3*j+2] += z*s;
			forces[3*k+0] -= x*s;
			forces[3*k+1] -= y*s;
			forces[3*k+2] -= z*s;
		}
	}

	// Add accumulated forces to actors
	for (PxU32 k=0; k<nbActors; k++)
	{
		PxRigidDynamic* actor = gPhysX.cast[k]->isRigidDynamic();
		PxVec3 F(forces[3*k+0],forces[3*k+1],forces[3*k+2]);
		actor->addForce(F);
	}

	// Clean up
	delete [] bodies;
	delete [] forces;

	return;
}
void rox::CreateAOSAT1()
{
	// Define wall dimension and thickness
	PxReal U = rox::params.boxSize;
	PxReal t = 0.02*U;

	// We'll make the containment with a kinematic actor
	PxRigidDynamic* theBox = gPhysX.mPhysics->createRigidDynamic(PxTransform(PxVec3(0)));
	if (!theBox)
		ncc__error("actor creation failed!");
	theBox->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);

	// Define sides
	PxBoxGeometry box_side(U/2,t/2,U/2);
	PxBoxGeometry minibox_side(U/10,t/4,U/2);
	PxMaterial* defmat=gPhysX.mDefaultMaterial;

	// Attach the sides
	// Middle Chamber
	theBox->createShape(box_side,*defmat); // middle chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U,0))); // middle chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U/2,U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // middle chamber left wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U/2,U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // middle chamber right wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // middle chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // middle chamber front wall

	// Left Chamber
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,0,0))); // left chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U,0))); // left chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // left chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // left chamber front wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-(3*U/2),U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // left chamber left wall

	// Right Chamber
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,0,0))); // right chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U,0))); // right chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // right chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // right chamber front wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3((3*U/2),U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // right chamber right wall

	// Mini Boxes
	theBox->createShape(minibox_side,*defmat,PxTransform(PxVec3(-(3*U/5),U/2,-(3*U/10)),PxQuat(PxPi/2,PxVec3(1,0,0)))); // left chamber minibox
	theBox->createShape(minibox_side,*defmat,PxTransform(PxVec3((3*U/5),U/2,-(3*U/10)),PxQuat(PxPi/2,PxVec3(1,0,0)))); // right chamber minibox

	// Name, color, and register the box
	theBox->setName("#the_box");
	gColors.colorBucket.push_back(vector<GLubyte>(3));
	gColors.colorBucket.back()[0] = ncc::rgb::yLightYellow[0];
	gColors.colorBucket.back()[1] = ncc::rgb::yLightYellow[1];
	gColors.colorBucket.back()[2] = ncc::rgb::yLightYellow[2];
	theBox->userData = &(gColors.colorBucket.back()[0]);
	gPhysX.mScene->addActor(*theBox);
	rox::VIPs.theBox = theBox;
}

// End lint level warnings
#ifdef LINT
#pragma warning(pop)
#endif
<commit_msg>added minibox regolith containers to CreateAOSAT1<commit_after>///////////////////////////////////////////////////////////////////////////////
// Source file for project BoxOfRox.
//
// Authors: Viranga and Naor
///////////////////////////////////////////////////////////////////////////////

#include "ARSS.h"
#include "BoxOfRox.h"

// Request lint level warnings with the LINT macro on Microsoft compilers
#ifdef LINT
#pragma warning(push,4)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif

int main(int argc, char** argv)
{

#ifdef _DEBUG
	cout << "***DEBUG BUILD***" << endl;
#endif

	ncc::whoami();

	InitRun(argc,argv);
	InitGlut(argc,argv);
	InitHUD();
	InitDevIL();
	InitPhysX();
	InitCUDA();
	InitExperiment();
	glutMainLoop(); // enter event processing

	return 0; // never actually reached.
}

void CustomizeRun(int,char**)
{
	// Read experiment-specific program options from file.
	if (!ConfigExperimentOptions())
	{ncc__warning("Could not find ARSS config file. Attempting to continue with all default options.\a");}
}
bool ConfigExperimentOptions()
{
	// First check that an options file exists
	ifstream fp(gRun.iniFile.c_str());
	bool success = fp.good();
	fp.close();

	// Read in parameters by group, file.ini style
	char buf[MAX_CHARS_PER_NAME];

	// Experiment parameters
	ncc::GetStrPropertyFromINIFile("experiment","experiment_type","",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if		(strcmp(buf,"fill_box")==0)
		rox::eExperimentType = rox::eFILL_BOX;
	else if (strcmp(buf,"shake_box")==0)
		rox::eExperimentType = rox::eSHAKE_BOX;
	else
		rox::eExperimentType = rox::eBAD_EXPERIMENT_TYPE;

	ncc::GetStrPropertyFromINIFile("experiment","shake_magnitude","0",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::params.shakeMagnitude = atof(buf);

	// Parameters for the box
	ncc::GetStrPropertyFromINIFile("box","box_unit_size","100",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::params.boxSize = atof(buf);
	ncc::GetStrPropertyFromINIFile("box","box_design","",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if (strcmp(buf,"AOSAT1")==0)
		rox::eBoxDesign = rox::eAOSAT1;
	else
		rox::eBoxDesign = rox::eBAD_BOX_DESIGN;

	// Parameters for the regolith
	ncc::GetStrPropertyFromINIFile("regolith","grain_type","uniform",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	if		(strcmp(buf,"uniform")==0)
		rox::regolith.type = rox::regolith.eGRAIN_UNIFORM;
	else if	(strcmp(buf,"bimodal")==0)
		rox::regolith.type = rox::regolith.eGRAIN_BIMODAL;
	else
		rox::regolith.type = rox::regolith.eBAD_GRAIN_TYPE;

	ncc::GetStrPropertyFromINIFile("regolith","grain_size1","1",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::regolith.size1 = atof(buf);
	ncc::GetStrPropertyFromINIFile("regolith","grain_size2","1",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::regolith.size2 = atof(buf);

	rox::regolith.totalNumber = ncc::GetIntPropertyFromINIFile("regolith","grain_total_number",0,gRun.iniFile.c_str());

	// Code units and scaling
	ncc::GetStrPropertyFromINIFile("units","big_g","0",buf,MAX_CHARS_PER_NAME,gRun.iniFile.c_str());
	rox::units.bigG = atof(buf);

	return success;
}
void CustomizeScene(PxSceneDesc &sceneDesc)
{
	sceneDesc.gravity = PxVec3(0);
}
void CustomizeGLUT()
{

}
void CustomizeHUD()
{

}
void RefreshCustomHUDElements()
{

}
void FireAction()
{

}
void LogExperiment()
{

}
void PrintDebug()
{
}
void ApplyCustomInteractions()
{
	rox::GravitateSelf();
}
void RenderOtherStuff()
{

}
void CreateExperiment()
{
	gDebug.bXYGridOn=true;
	switch (rox::eExperimentType)
	{
	case rox::eFILL_BOX:
		rox::CreateFillBoxExperiment();
		break;
	case rox::eBAD_EXPERIMENT_TYPE: // intentional fall through
	default:
		ncc__error("Unknown experiment type. Experiment aborted.\a");
	}

	// Start the action
	gSim.isRunning=true;
	gSim.bPause=false;
	RefreshHUD();
}
void RebootExperiment()
{
	gSim.isRunning=false;
	DestroyPhysX();
	InitPhysX();
	CreateExperiment();
}
void LoadExperiment()
{

}
void UpArrowAction()
{

}
void DownArrowAction()
{

}
void LeftArrowAction()
{

}
void RightArrowAction()
{

}

// BoxOfRox namespace functions
void rox::CreateTheBox()
{
	switch (rox::eBoxDesign)
	{
	case rox::eAOSAT1:
		rox::CreateAOSAT1();
		break;
	case rox::eBAD_BOX_DESIGN: // intentional fall through
	default:
		ncc__error("Unknown box design\a");
	}
}
void rox::CreateFillBoxExperiment()
{
	rox::CreateTheBox();
	gCamera.pos = PxVec3(0,rox::params.boxSize,3*rox::params.boxSize);
}
void rox::GravitateSelf()
{
	if (gCUDA.cudaCapable)
		rox::GravitateOnDevice();
	else
		rox::GravitateOnHost();
}
void rox::GravitateOnDevice()
{
	rox::GravitateOnHost(); //TODO: include device implementation when needed, for speed
}
void rox::GravitateOnHost()
/*
 * This is a semi-optimized all-pairs gravity calculation in a single host thread. Not
 * usually the best option, but a necessary fall back option.
*/
{
	// Prepare
	PxU32 nbActors = gPhysX.mScene->getActors(gPhysX.roles.dynamics,gPhysX.cast,MAX_ACTORS_PER_SCENE);
	if (nbActors<2) return;
	float *bodies = new float[4*nbActors];
	float *forces = new float[3*nbActors];
	if (bodies==NULL || forces==NULL)
		ncc__error("Error allocating memory for body/forces arrays.");

	// Linearize actor positions
	for (PxU32 k=0; k<nbActors; k++)
	{
		PxRigidDynamic* actor = gPhysX.cast[k]->isRigidDynamic();
		PxTransform pose = actor->getGlobalPose().transform(actor->getCMassLocalPose());
		PxVec3 pos = pose.p;
		bodies[4*k+0] = actor->getMass();
		bodies[4*k+1] = pos.x;
		bodies[4*k+2] = pos.y;
		bodies[4*k+3] = pos.z;
	}

	// And now, the N^2 double loop.
	for (PxU32 j=0; j<nbActors; j++)
	{
		forces[3*j+0] = forces[3*j+1] = forces[3*j+2] = 0.0f;
		for (PxU32 k=0; k<j; k++)
		{
			PxReal x = bodies[4*k+1] - bodies[4*j+1];
			PxReal y = bodies[4*k+2] - bodies[4*j+2];
			PxReal z = bodies[4*k+3] - bodies[4*j+3];

			float distSqr = x*x + y*y + z*z;
			float distSix = distSqr*distSqr*distSqr;
			float invDistCube = 1.0f/sqrtf(distSix);

			float s = rox::units.bigG * bodies[4*j+0] * bodies[4*k+0] * invDistCube;

			forces[3*j+0] += x*s;
			forces[3*j+1] += y*s;
			forces[3*j+2] += z*s;
			forces[3*k+0] -= x*s;
			forces[3*k+1] -= y*s;
			forces[3*k+2] -= z*s;
		}
	}

	// Add accumulated forces to actors
	for (PxU32 k=0; k<nbActors; k++)
	{
		PxRigidDynamic* actor = gPhysX.cast[k]->isRigidDynamic();
		PxVec3 F(forces[3*k+0],forces[3*k+1],forces[3*k+2]);
		actor->addForce(F);
	}

	// Clean up
	delete [] bodies;
	delete [] forces;

	return;
}
void rox::CreateAOSAT1()
{
	// Define wall dimension and thickness
	PxReal U = rox::params.boxSize;
	PxReal t = 0.02*U;

	// We'll make the containment with a kinematic actor
	PxRigidDynamic* theBox = gPhysX.mPhysics->createRigidDynamic(PxTransform(PxVec3(0)));
	if (!theBox)
		ncc__error("actor creation failed!");
	theBox->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);

	// Define sides
	PxBoxGeometry box_side(U/2,t/2,U/2);
	PxBoxGeometry minibox_side(t/2,U/2,U/2-U/10);
	PxMaterial* defmat=gPhysX.mDefaultMaterial;

	// Attach the sides
	// Middle Chamber
	theBox->createShape(box_side,*defmat); // middle chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U,0))); // middle chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U/2,U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // middle chamber left wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U/2,U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // middle chamber right wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // middle chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(0,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // middle chamber front wall

	// Left Chamber
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,0,0))); // left chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U,0))); // left chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // left chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-U,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // left chamber front wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(-(3*U/2),U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // left chamber left wall

	// Right Chamber
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,0,0))); // right chamber bottom wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U,0))); // right chamber top wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U/2,-U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // right chamber back wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3(U,U/2,U/2),PxQuat(PxPi/2,PxVec3(1,0,0)))); // right chamber front wall
	theBox->createShape(box_side,*defmat,PxTransform(PxVec3((3*U/2),U/2,0),PxQuat(PxPi/2,PxVec3(0,0,1)))); // right chamber right wall

	// Mini Boxes (regolith containment)
	PxShape* mini = theBox->createShape(minibox_side,*defmat,PxTransform(PxVec3(-(7*U/10),U/2,-U/10))); // left chamber minibox
	gColors.colorBucket.push_back(vector<GLubyte>(3));
	gColors.colorBucket.back()[0] = ncc::rgb::rRed[0];
	gColors.colorBucket.back()[1] = ncc::rgb::rRed[1];
	gColors.colorBucket.back()[2] = ncc::rgb::rRed[2];
	mini->userData = &(gColors.colorBucket.back()[0]);
	mini = theBox->createShape(minibox_side,*defmat,PxTransform(PxVec3((7*U/10),U/2,-U/10))); // right chamber minibox
	mini->userData = &(gColors.colorBucket.back()[0]);

	// Name, color, and register the box
	theBox->setName("#the_box");
	gColors.colorBucket.push_back(vector<GLubyte>(3));
	gColors.colorBucket.back()[0] = ncc::rgb::yLightYellow[0];
	gColors.colorBucket.back()[1] = ncc::rgb::yLightYellow[1];
	gColors.colorBucket.back()[2] = ncc::rgb::yLightYellow[2];
	theBox->userData = &(gColors.colorBucket.back()[0]);
	gPhysX.mScene->addActor(*theBox);
	rox::VIPs.theBox = theBox;
}

// End lint level warnings
#ifdef LINT
#pragma warning(pop)
#endif
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2003-2012
  \file      app/rdo_studio/src/style.cpp
  \author    Урусов Андрей (rdo@rk9.bmstu.ru)
  \date      27.03.2003
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "app/rdo_studio/pch/stdpch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "app/rdo_studio/src/style.h"
#include "thirdparty/scintilla/include/Scintilla.h"
// --------------------------------------------------------------------------------

namespace rdo { namespace gui { namespace style {

// --------------------------------------------------------------------------------
// -------------------- StyleFont
// --------------------------------------------------------------------------------
StyleFont::StyleFont()
{
	name = "Courier New";
	size = 10;
}

StyleFont::~StyleFont()
{}

StyleFont& StyleFont::operator =( const StyleFont& font )
{
	name = font.name;
	size = font.size;

	return *this;
}

rbool StyleFont::operator ==( const StyleFont& font ) const
{
	return name == font.name &&
	       size == font.size;
}

rbool StyleFont::operator !=( const StyleFont& font ) const
{
	return !(*this == font);
}

void StyleFont::load(QSettings& settings)
{
	settings >> *this;
}

void StyleFont::save(QSettings& settings) const
{
	settings << *this;
}

StyleFont StyleFont::getDefaultFont()
{
	StyleFont font;
	return font;
}

StyleFont StyleFont::getClassicFont()
{
	StyleFont font;
	font.name = "Fixedsys";

	return font;
}

StyleFont StyleFont::getTracerLogFont()
{
	StyleFont font;
	font.name = "Courier";

	return font;
}

StyleFont StyleFont::getChartViewFont()
{
	StyleFont font;
	font.name = "Tahoma";

	return font;
}

StyleFont StyleFont::getFrameFont()
{
	StyleFont font;

	font.name = "Verdana";
	font.size = 8;

	return font;
}

QSettings& operator<< (QSettings& settings, const StyleFont& font)
{
	settings.setValue("name", QString::fromStdString(font.name));
	settings.setValue("size", font.size);
	return settings;
}

QSettings& operator>> (QSettings& settings, StyleFont& font)
{
	font.name = settings.value("name", QString::fromStdString(font.name)).toString().toStdString();
	font.size = settings.value("size", font.size).toInt();
	return settings;
}

// --------------------------------------------------------------------------------
// -------------------- StyleBase
// --------------------------------------------------------------------------------
StyleBase::StyleBase()
	: font()
{
	defaultColor    = QColor( 0x00, 0x00, 0x00 );
	backgroundColor = QColor( 0xFF, 0xFF, 0xFF );
	defaultStyle = StyleFont::NONE;
}

StyleBase::~StyleBase()
{
}

StyleBase& StyleBase::operator =( const StyleBase& style )
{
	font            = style.font;
	defaultStyle    = style.defaultStyle;
	defaultColor    = style.defaultColor;
	backgroundColor = style.backgroundColor;
	return *this;
}

rbool StyleBase::operator ==( const StyleBase& style ) const
{
	return
		font            == style.font &&
		defaultColor    == style.defaultColor &&
		backgroundColor == style.backgroundColor &&
		defaultStyle    == style.defaultStyle;
}

rbool StyleBase::operator !=( const StyleBase& style ) const
{
	return !(*this == style);
}

QSettings& operator<< (QSettings& settings, const StyleBase& style)
{
	settings.beginGroup("font");
	settings << style.font;
	settings.endGroup();

	settings.beginGroup("theme");
	settings.setValue("default_color", style.defaultColor.name());
	settings.setValue("background_color", style.backgroundColor.name());
	settings.setValue("default_style", style.defaultStyle);
	settings.endGroup();

	return settings;
}

QSettings& operator>> (QSettings& settings, StyleBase& style)
{
	settings.beginGroup("font");
	settings >> style.font;
	settings.endGroup();

	settings.beginGroup("theme");
	style.defaultColor    = QColor(settings.value("default_color", style.defaultColor.name()).toString());
	style.backgroundColor = QColor(settings.value("background_color", style.backgroundColor.name()).toString());
	style.defaultStyle    = static_cast<StyleFont::style>(settings.value("default_style", style.defaultStyle).toInt());
	settings.endGroup();

	return settings;
}

}}} // namespace rdo::gui::style
<commit_msg> - подобран стиль в Линуксе<commit_after>/*!
  \copyright (c) RDO-Team, 2003-2012
  \file      app/rdo_studio/src/style.cpp
  \author    Урусов Андрей (rdo@rk9.bmstu.ru)
  \date      27.03.2003
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "app/rdo_studio/pch/stdpch.h"
// ----------------------------------------------------------------------- INCLUDES
#include <QtGlobal>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/static_assert.h"
#include "app/rdo_studio/src/style.h"
#include "thirdparty/scintilla/include/Scintilla.h"
// --------------------------------------------------------------------------------

namespace rdo { namespace gui { namespace style {

// --------------------------------------------------------------------------------
// -------------------- StyleFont
// --------------------------------------------------------------------------------
StyleFont::StyleFont()
	: size(10)
{
#if defined(Q_OS_WIN)
	name = "Courier New";
	size = 10;
#elif defined(Q_OS_LINUX)
	name = "Courier";
	size = 11;
#else
	STATIC_ASSERT(UndefinedOS);
#endif
}

StyleFont::~StyleFont()
{}

StyleFont& StyleFont::operator =( const StyleFont& font )
{
	name = font.name;
	size = font.size;

	return *this;
}

rbool StyleFont::operator ==( const StyleFont& font ) const
{
	return name == font.name &&
	       size == font.size;
}

rbool StyleFont::operator !=( const StyleFont& font ) const
{
	return !(*this == font);
}

void StyleFont::load(QSettings& settings)
{
	settings >> *this;
}

void StyleFont::save(QSettings& settings) const
{
	settings << *this;
}

StyleFont StyleFont::getDefaultFont()
{
	StyleFont font;
	return font;
}

StyleFont StyleFont::getClassicFont()
{
	StyleFont font;
	font.name = "Fixedsys";

	return font;
}

StyleFont StyleFont::getTracerLogFont()
{
	StyleFont font;
	font.name = "Courier";

	return font;
}

StyleFont StyleFont::getChartViewFont()
{
	StyleFont font;
	font.name = "Tahoma";

	return font;
}

StyleFont StyleFont::getFrameFont()
{
	StyleFont font;

	font.name = "Verdana";
	font.size = 8;

	return font;
}

QSettings& operator<< (QSettings& settings, const StyleFont& font)
{
	settings.setValue("name", QString::fromStdString(font.name));
	settings.setValue("size", font.size);
	return settings;
}

QSettings& operator>> (QSettings& settings, StyleFont& font)
{
	font.name = settings.value("name", QString::fromStdString(font.name)).toString().toStdString();
	font.size = settings.value("size", font.size).toInt();
	return settings;
}

// --------------------------------------------------------------------------------
// -------------------- StyleBase
// --------------------------------------------------------------------------------
StyleBase::StyleBase()
	: font()
{
	defaultColor    = QColor( 0x00, 0x00, 0x00 );
	backgroundColor = QColor( 0xFF, 0xFF, 0xFF );
	defaultStyle = StyleFont::NONE;
}

StyleBase::~StyleBase()
{
}

StyleBase& StyleBase::operator =( const StyleBase& style )
{
	font            = style.font;
	defaultStyle    = style.defaultStyle;
	defaultColor    = style.defaultColor;
	backgroundColor = style.backgroundColor;
	return *this;
}

rbool StyleBase::operator ==( const StyleBase& style ) const
{
	return
		font            == style.font &&
		defaultColor    == style.defaultColor &&
		backgroundColor == style.backgroundColor &&
		defaultStyle    == style.defaultStyle;
}

rbool StyleBase::operator !=( const StyleBase& style ) const
{
	return !(*this == style);
}

QSettings& operator<< (QSettings& settings, const StyleBase& style)
{
	settings.beginGroup("font");
	settings << style.font;
	settings.endGroup();

	settings.beginGroup("theme");
	settings.setValue("default_color", style.defaultColor.name());
	settings.setValue("background_color", style.backgroundColor.name());
	settings.setValue("default_style", style.defaultStyle);
	settings.endGroup();

	return settings;
}

QSettings& operator>> (QSettings& settings, StyleBase& style)
{
	settings.beginGroup("font");
	settings >> style.font;
	settings.endGroup();

	settings.beginGroup("theme");
	style.defaultColor    = QColor(settings.value("default_color", style.defaultColor.name()).toString());
	style.backgroundColor = QColor(settings.value("background_color", style.backgroundColor.name()).toString());
	style.defaultStyle    = static_cast<StyleFont::style>(settings.value("default_style", style.defaultStyle).toInt());
	settings.endGroup();

	return settings;
}

}}} // namespace rdo::gui::style
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdocommon.cpp
  \authors
  \authors     (rdo@rk9.bmstu.ru)
  \authors     (lord.tiran@gmail.com)
  \date      13.06.2009
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- PLATFORM
#include "utils/platform.h"
// ----------------------------------------------------------------------- INCLUDES
#include <locale>
#include <stdio.h>
#include <stdarg.h>

#ifdef COMPILER_VISUAL_STUDIO
#	include <windows.h>
#	include <io.h>
#else
#	include <stdarg.h>
#	include <wchar.h>
#endif
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdocommon.h"
// --------------------------------------------------------------------------------

#ifdef COMPILER_VISUAL_STUDIO
#	pragma warning(disable : 4786)
#endif

OPEN_RDO_NAMESPACE

tstring format(CPTR(tchar) str, ...)
{
	va_list params;
	va_start( params, str );
	tstring res = format( str, params );
	va_end( params );
	return res;
}

tstring format( CPTR(tchar) str, REF(va_list) params )
{
	std::vector< tchar > s;
	s.resize( 256 );
	int size = -1;
	while ( size == -1 ) {
#ifdef COMPILER_VISUAL_STUDIO
#	pragma warning(disable: 4996)
#ifdef UNICODE
		size = _vsnwprintf( &s[0], s.size(), str, params );
#else
		size = _vsnprintf( &s[0], s.size(), str, params );
#endif
#	pragma warning(default: 4996)
#endif  // COMPILER_VISUAL_STUDIO

#ifdef COMPILER_GCC
#ifdef UNICODE
		size = vswprintf( &s[0], s.size(), str, params );
#else
		size = vsnprintf( &s[0], s.size(), str, params );
#endif
#endif // COMPILER_GCC
		if ( size == -1 )
		{
			s.resize( s.size() + 256 );
		}
	}
	s.resize( size );
	return tstring( s.begin(), s.end() );
}

#ifdef COMPILER_VISUAL_STUDIO
tstring format(ruint resource, ...)
{
	va_list params;
	va_start( params, resource );
	tstring res = format( resource, params );
	va_end( params );
	return res;
}

tstring format(ruint resource, REF(va_list) params)
{
	tchar buffer[1024];
	HMODULE hModule = ::GetModuleHandle(NULL);
	if (hModule)
	{
		if (LoadString(hModule, resource, buffer, sizeof(buffer)/sizeof(tchar)))
		return format(buffer, params);
	}
	return _T("");
}
#endif // COMPILER_VISUAL_STUDIO

wstring toUnicode(CREF(astring) str)
{
	wstring result;

	try
	{
		std::wostringstream wstm;
		//! @todo        ? ..   ?
		wstm.imbue(std::locale("rus"));
		CREF(std::ctype<wchar_t>) ctfacet =	std::use_facet<std::ctype<wchar_t> >(wstm.getloc());
		for (std::size_t i = 0; i < str.size(); ++i)
		{
			wstm << ctfacet.widen(str[i]);
		}
		result = wstm.str();
	}
	catch (CREF(std::runtime_error))
	{}

	return result;
}

CLOSE_RDO_NAMESPACE
<commit_msg> - забытый инклюд<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdocommon.cpp
  \authors
  \authors     (rdo@rk9.bmstu.ru)
  \authors     (lord.tiran@gmail.com)
  \date      13.06.2009
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- PLATFORM
#include "utils/platform.h"
// ----------------------------------------------------------------------- INCLUDES
#include <locale>
#include <stdio.h>
#include <stdarg.h>
#include <stdexcept>

#ifdef COMPILER_VISUAL_STUDIO
#	include <windows.h>
#	include <io.h>
#else
#	include <stdarg.h>
#	include <wchar.h>
#endif
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdocommon.h"
// --------------------------------------------------------------------------------

#ifdef COMPILER_VISUAL_STUDIO
#	pragma warning(disable : 4786)
#endif

OPEN_RDO_NAMESPACE

tstring format(CPTR(tchar) str, ...)
{
	va_list params;
	va_start( params, str );
	tstring res = format( str, params );
	va_end( params );
	return res;
}

tstring format( CPTR(tchar) str, REF(va_list) params )
{
	std::vector< tchar > s;
	s.resize( 256 );
	int size = -1;
	while ( size == -1 ) {
#ifdef COMPILER_VISUAL_STUDIO
#	pragma warning(disable: 4996)
#ifdef UNICODE
		size = _vsnwprintf( &s[0], s.size(), str, params );
#else
		size = _vsnprintf( &s[0], s.size(), str, params );
#endif
#	pragma warning(default: 4996)
#endif  // COMPILER_VISUAL_STUDIO

#ifdef COMPILER_GCC
#ifdef UNICODE
		size = vswprintf( &s[0], s.size(), str, params );
#else
		size = vsnprintf( &s[0], s.size(), str, params );
#endif
#endif // COMPILER_GCC
		if ( size == -1 )
		{
			s.resize( s.size() + 256 );
		}
	}
	s.resize( size );
	return tstring( s.begin(), s.end() );
}

#ifdef COMPILER_VISUAL_STUDIO
tstring format(ruint resource, ...)
{
	va_list params;
	va_start( params, resource );
	tstring res = format( resource, params );
	va_end( params );
	return res;
}

tstring format(ruint resource, REF(va_list) params)
{
	tchar buffer[1024];
	HMODULE hModule = ::GetModuleHandle(NULL);
	if (hModule)
	{
		if (LoadString(hModule, resource, buffer, sizeof(buffer)/sizeof(tchar)))
		return format(buffer, params);
	}
	return _T("");
}
#endif // COMPILER_VISUAL_STUDIO

wstring toUnicode(CREF(astring) str)
{
	wstring result;

	try
	{
		std::wostringstream wstm;
		//! @todo        ? ..   ?
		wstm.imbue(std::locale("rus"));
		CREF(std::ctype<wchar_t>) ctfacet =	std::use_facet<std::ctype<wchar_t> >(wstm.getloc());
		for (std::size_t i = 0; i < str.size(); ++i)
		{
			wstm << ctfacet.widen(str[i]);
		}
		result = wstm.str();
	}
	catch (CREF(std::runtime_error))
	{}

	return result;
}

CLOSE_RDO_NAMESPACE
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <iosfwd>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema_fwd.hh"
#include "dht/i_partitioner.hh"
#include "hashing.hh"
#include "mutation_fragment.hh"
#include "mutation_consumer_concepts.hh"

#include <seastar/util/optimized_optional.hh>

template<typename Result>
struct mutation_consume_result {
    stop_iteration stop;
    Result result;
};

template<>
struct mutation_consume_result<void> {
    stop_iteration stop;
};

enum class consume_in_reverse {
    no = 0,
    yes,
};

class mutation final {
private:
    struct data {
        schema_ptr _schema;
        dht::decorated_key _dk;
        mutation_partition _p;

        data(dht::decorated_key&& key, schema_ptr&& schema);
        data(partition_key&& key, schema_ptr&& schema);
        data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp);
        data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp);
    };
    std::unique_ptr<data> _ptr;
private:
    mutation() = default;
    explicit operator bool() const { return bool(_ptr); }
    friend class optimized_optional<mutation>;
public:
    mutation(schema_ptr schema, dht::decorated_key key)
        : _ptr(std::make_unique<data>(std::move(key), std::move(schema)))
    { }
    mutation(schema_ptr schema, partition_key key_)
        : _ptr(std::make_unique<data>(std::move(key_), std::move(schema)))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, const mutation_partition& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), mp))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition&& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), std::move(mp)))
    { }
    mutation(const mutation& m)
        : _ptr(std::make_unique<data>(schema_ptr(m.schema()), dht::decorated_key(m.decorated_key()), m.partition()))
    { }
    mutation(mutation&&) = default;
    mutation& operator=(mutation&& x) = default;
    mutation& operator=(const mutation& m);

    void set_static_cell(const column_definition& def, atomic_cell_or_collection&& value);
    void set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value);
    void set_cell(const clustering_key_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const clustering_key_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);

    // Upgrades this mutation to a newer schema. The new schema must
    // be obtained using only valid schema transformation:
    //  * primary key column count must not change
    //  * column types may only change to those with compatible representations
    //
    // After upgrade, mutation's partition should only be accessed using the new schema. User must
    // ensure proper isolation of accesses.
    //
    // Strong exception guarantees.
    //
    // Note that the conversion may lose information, it's possible that m1 != m2 after:
    //
    //   auto m2 = m1;
    //   m2.upgrade(s2);
    //   m2.upgrade(m1.schema());
    //
    void upgrade(const schema_ptr&);

    const partition_key& key() const { return _ptr->_dk._key; };
    const dht::decorated_key& decorated_key() const { return _ptr->_dk; };
    dht::ring_position ring_position() const { return { decorated_key() }; }
    const dht::token& token() const { return _ptr->_dk._token; }
    const schema_ptr& schema() const { return _ptr->_schema; }
    const mutation_partition& partition() const { return _ptr->_p; }
    mutation_partition& partition() { return _ptr->_p; }
    const utils::UUID& column_family_id() const { return _ptr->_schema->id(); }
    // Consistent with hash<canonical_mutation>
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    // Consumes the mutation's content.
    //
    // The mutation is in a moved-from alike state after consumption.
    template<FlattenedConsumer Consumer>
    auto consume(Consumer& consumer, consume_in_reverse reverse) && -> mutation_consume_result<decltype(consumer.consume_end_of_stream())>;

    // See mutation_partition::live_row_count()
    uint64_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;

    void apply(mutation&&);
    void apply(const mutation&);
    void apply(const mutation_fragment&);

    mutation operator+(const mutation& other) const;
    mutation& operator+=(const mutation& other);
    mutation& operator+=(mutation&& other);

    // Returns a subset of this mutation holding only information relevant for given clustering ranges.
    // Range tombstones will be trimmed to the boundaries of the clustering ranges.
    mutation sliced(const query::clustering_row_ranges&) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

namespace {

template<consume_in_reverse reverse, FlattenedConsumer Consumer>
stop_iteration consume_clustering_fragments(const schema& s, mutation_partition& partition, Consumer& consumer) {
    using crs_type = mutation_partition::rows_type;
    using crs_iterator_type = std::conditional_t<reverse == consume_in_reverse::yes, crs_type::reverse_iterator, crs_type::iterator>;
    using rts_type = range_tombstone::container_type;
    using rts_iterator_type = std::conditional_t<reverse == consume_in_reverse::yes, rts_type::reverse_iterator, rts_type::iterator>;

    crs_iterator_type crs_it, crs_end;
    rts_iterator_type rts_it, rts_end;
    if constexpr (reverse == consume_in_reverse::yes) {
        crs_it = partition.clustered_rows().rbegin();
        crs_end = partition.clustered_rows().rend();
        rts_it = partition.row_tombstones().rbegin();
        rts_end = partition.row_tombstones().rend();
    } else {
        crs_it = partition.clustered_rows().begin();
        crs_end = partition.clustered_rows().end();
        rts_it = partition.row_tombstones().begin();
        rts_end = partition.row_tombstones().end();
    }

    stop_iteration stop = stop_iteration::no;

    position_in_partition::tri_compare cmp(s);

    while (!stop && (crs_it != crs_end || rts_it != rts_end)) {
        bool emit_rt;
        if (crs_it != crs_end && rts_it != rts_end) {
            const auto cmp_res = cmp(rts_it->position(), crs_it->position());
            if constexpr (reverse == consume_in_reverse::yes) {
                emit_rt = cmp_res > 0;
            } else {
                emit_rt = cmp_res < 0;
            }
        } else {
            emit_rt = rts_it != rts_end;
        }
        if (emit_rt) {
            stop = consumer.consume(std::move(*rts_it));
            ++rts_it;
        } else {
            stop = consumer.consume(clustering_row(std::move(*crs_it)));
            ++crs_it;
        }
    }

    return stop;
}

} // anonymous namespace

template<FlattenedConsumer Consumer>
auto mutation::consume(Consumer& consumer, consume_in_reverse reverse) && -> mutation_consume_result<decltype(consumer.consume_end_of_stream())> {
    consumer.consume_new_partition(_ptr->_dk);

    auto& partition = _ptr->_p;

    if (partition.partition_tombstone()) {
        consumer.consume(partition.partition_tombstone());
    }

    stop_iteration stop = stop_iteration::no;
    if (!partition.static_row().empty()) {
        stop = consumer.consume(static_row(std::move(partition.static_row().get_existing())));
    }

    if (reverse == consume_in_reverse::yes) {
        stop = consume_clustering_fragments<consume_in_reverse::yes>(*_ptr->_schema, partition, consumer);
    } else {
        stop = consume_clustering_fragments<consume_in_reverse::no>(*_ptr->_schema, partition, consumer);
    }

    const auto stop_consuming = consumer.consume_end_of_partition();
    using consume_res_type = decltype(consumer.consume_end_of_stream());
    if constexpr (std::is_same_v<consume_res_type, void>) {
        consumer.consume_end_of_stream();
        return mutation_consume_result<void>{stop_consuming};
    } else {
        return mutation_consume_result<consume_res_type>{stop_consuming, consumer.consume_end_of_stream()};
    }
}

struct mutation_equals_by_key {
    bool operator()(const mutation& m1, const mutation& m2) const {
        return m1.schema() == m2.schema()
                && m1.decorated_key().equal(*m1.schema(), m2.decorated_key());
    }
};

struct mutation_hash_by_key {
    size_t operator()(const mutation& m) const {
        auto dk_hash = std::hash<dht::decorated_key>();
        return dk_hash(m.decorated_key());
    }
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

using mutation_opt = optimized_optional<mutation>;

// Consistent with operator==()
// Consistent across the cluster, so should not rely on particular
// serialization format, only on actual data stored.
template<>
struct appending_hash<mutation> {
    template<typename Hasher>
    void operator()(Hasher& h, const mutation& m) const {
        const schema& s = *m.schema();
        feed_hash(h, m.key(), s);
        m.partition().feed_hash(h, s);
    }
};

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->apply(std::move(src));
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const dht::partition_range&);

class flat_mutation_reader;

// Reads a single partition from a reader. Returns empty optional if there are no more partitions to be read.
future<mutation_opt> read_mutation_from_flat_mutation_reader(flat_mutation_reader& reader, db::timeout_clock::time_point timeout);
<commit_msg>mutation: Keep range tombstone in tree when consuming<commit_after>/*
 * Copyright (C) 2014-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <iosfwd>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema_fwd.hh"
#include "dht/i_partitioner.hh"
#include "hashing.hh"
#include "mutation_fragment.hh"
#include "mutation_consumer_concepts.hh"

#include <seastar/util/optimized_optional.hh>

template<typename Result>
struct mutation_consume_result {
    stop_iteration stop;
    Result result;
};

template<>
struct mutation_consume_result<void> {
    stop_iteration stop;
};

enum class consume_in_reverse {
    no = 0,
    yes,
};

class mutation final {
private:
    struct data {
        schema_ptr _schema;
        dht::decorated_key _dk;
        mutation_partition _p;

        data(dht::decorated_key&& key, schema_ptr&& schema);
        data(partition_key&& key, schema_ptr&& schema);
        data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp);
        data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp);
    };
    std::unique_ptr<data> _ptr;
private:
    mutation() = default;
    explicit operator bool() const { return bool(_ptr); }
    friend class optimized_optional<mutation>;
public:
    mutation(schema_ptr schema, dht::decorated_key key)
        : _ptr(std::make_unique<data>(std::move(key), std::move(schema)))
    { }
    mutation(schema_ptr schema, partition_key key_)
        : _ptr(std::make_unique<data>(std::move(key_), std::move(schema)))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, const mutation_partition& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), mp))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition&& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), std::move(mp)))
    { }
    mutation(const mutation& m)
        : _ptr(std::make_unique<data>(schema_ptr(m.schema()), dht::decorated_key(m.decorated_key()), m.partition()))
    { }
    mutation(mutation&&) = default;
    mutation& operator=(mutation&& x) = default;
    mutation& operator=(const mutation& m);

    void set_static_cell(const column_definition& def, atomic_cell_or_collection&& value);
    void set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value);
    void set_cell(const clustering_key_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const clustering_key_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);

    // Upgrades this mutation to a newer schema. The new schema must
    // be obtained using only valid schema transformation:
    //  * primary key column count must not change
    //  * column types may only change to those with compatible representations
    //
    // After upgrade, mutation's partition should only be accessed using the new schema. User must
    // ensure proper isolation of accesses.
    //
    // Strong exception guarantees.
    //
    // Note that the conversion may lose information, it's possible that m1 != m2 after:
    //
    //   auto m2 = m1;
    //   m2.upgrade(s2);
    //   m2.upgrade(m1.schema());
    //
    void upgrade(const schema_ptr&);

    const partition_key& key() const { return _ptr->_dk._key; };
    const dht::decorated_key& decorated_key() const { return _ptr->_dk; };
    dht::ring_position ring_position() const { return { decorated_key() }; }
    const dht::token& token() const { return _ptr->_dk._token; }
    const schema_ptr& schema() const { return _ptr->_schema; }
    const mutation_partition& partition() const { return _ptr->_p; }
    mutation_partition& partition() { return _ptr->_p; }
    const utils::UUID& column_family_id() const { return _ptr->_schema->id(); }
    // Consistent with hash<canonical_mutation>
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    // Consumes the mutation's content.
    //
    // The mutation is in a moved-from alike state after consumption.
    template<FlattenedConsumer Consumer>
    auto consume(Consumer& consumer, consume_in_reverse reverse) && -> mutation_consume_result<decltype(consumer.consume_end_of_stream())>;

    // See mutation_partition::live_row_count()
    uint64_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;

    void apply(mutation&&);
    void apply(const mutation&);
    void apply(const mutation_fragment&);

    mutation operator+(const mutation& other) const;
    mutation& operator+=(const mutation& other);
    mutation& operator+=(mutation&& other);

    // Returns a subset of this mutation holding only information relevant for given clustering ranges.
    // Range tombstones will be trimmed to the boundaries of the clustering ranges.
    mutation sliced(const query::clustering_row_ranges&) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

namespace {

template<consume_in_reverse reverse, FlattenedConsumer Consumer>
stop_iteration consume_clustering_fragments(const schema& s, mutation_partition& partition, Consumer& consumer) {
    using crs_type = mutation_partition::rows_type;
    using crs_iterator_type = std::conditional_t<reverse == consume_in_reverse::yes, crs_type::reverse_iterator, crs_type::iterator>;
    using rts_type = range_tombstone::container_type;
    using rts_iterator_type = std::conditional_t<reverse == consume_in_reverse::yes, rts_type::reverse_iterator, rts_type::iterator>;

    crs_iterator_type crs_it, crs_end;
    rts_iterator_type rts_it, rts_end;
    if constexpr (reverse == consume_in_reverse::yes) {
        crs_it = partition.clustered_rows().rbegin();
        crs_end = partition.clustered_rows().rend();
        rts_it = partition.row_tombstones().rbegin();
        rts_end = partition.row_tombstones().rend();
    } else {
        crs_it = partition.clustered_rows().begin();
        crs_end = partition.clustered_rows().end();
        rts_it = partition.row_tombstones().begin();
        rts_end = partition.row_tombstones().end();
    }

    stop_iteration stop = stop_iteration::no;

    position_in_partition::tri_compare cmp(s);

    while (!stop && (crs_it != crs_end || rts_it != rts_end)) {
        bool emit_rt;
        if (crs_it != crs_end && rts_it != rts_end) {
            const auto cmp_res = cmp(rts_it->position(), crs_it->position());
            if constexpr (reverse == consume_in_reverse::yes) {
                emit_rt = cmp_res > 0;
            } else {
                emit_rt = cmp_res < 0;
            }
        } else {
            emit_rt = rts_it != rts_end;
        }
        if (emit_rt) {
            stop = consumer.consume(range_tombstone(std::move(*rts_it), range_tombstone::without_link{}));
            ++rts_it;
        } else {
            stop = consumer.consume(clustering_row(std::move(*crs_it)));
            ++crs_it;
        }
    }

    return stop;
}

} // anonymous namespace

template<FlattenedConsumer Consumer>
auto mutation::consume(Consumer& consumer, consume_in_reverse reverse) && -> mutation_consume_result<decltype(consumer.consume_end_of_stream())> {
    consumer.consume_new_partition(_ptr->_dk);

    auto& partition = _ptr->_p;

    if (partition.partition_tombstone()) {
        consumer.consume(partition.partition_tombstone());
    }

    stop_iteration stop = stop_iteration::no;
    if (!partition.static_row().empty()) {
        stop = consumer.consume(static_row(std::move(partition.static_row().get_existing())));
    }

    if (reverse == consume_in_reverse::yes) {
        stop = consume_clustering_fragments<consume_in_reverse::yes>(*_ptr->_schema, partition, consumer);
    } else {
        stop = consume_clustering_fragments<consume_in_reverse::no>(*_ptr->_schema, partition, consumer);
    }

    const auto stop_consuming = consumer.consume_end_of_partition();
    using consume_res_type = decltype(consumer.consume_end_of_stream());
    if constexpr (std::is_same_v<consume_res_type, void>) {
        consumer.consume_end_of_stream();
        return mutation_consume_result<void>{stop_consuming};
    } else {
        return mutation_consume_result<consume_res_type>{stop_consuming, consumer.consume_end_of_stream()};
    }
}

struct mutation_equals_by_key {
    bool operator()(const mutation& m1, const mutation& m2) const {
        return m1.schema() == m2.schema()
                && m1.decorated_key().equal(*m1.schema(), m2.decorated_key());
    }
};

struct mutation_hash_by_key {
    size_t operator()(const mutation& m) const {
        auto dk_hash = std::hash<dht::decorated_key>();
        return dk_hash(m.decorated_key());
    }
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

using mutation_opt = optimized_optional<mutation>;

// Consistent with operator==()
// Consistent across the cluster, so should not rely on particular
// serialization format, only on actual data stored.
template<>
struct appending_hash<mutation> {
    template<typename Hasher>
    void operator()(Hasher& h, const mutation& m) const {
        const schema& s = *m.schema();
        feed_hash(h, m.key(), s);
        m.partition().feed_hash(h, s);
    }
};

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->apply(std::move(src));
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const dht::partition_range&);

class flat_mutation_reader;

// Reads a single partition from a reader. Returns empty optional if there are no more partitions to be read.
future<mutation_opt> read_mutation_from_flat_mutation_reader(flat_mutation_reader& reader, db::timeout_clock::time_point timeout);
<|endoftext|>


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

#include "google/cloud/spanner/client.h"
#include <iostream>
#include <stdexcept>

const std::string kTableName = "Singers";
const std::string kUpdateColumnName = "Age";
const std::string kBaseColumnName = "DefaultAge";
// const std::string kCustomDml = "UPDATE Singers SET Age = DefaultAge+10 WHERE Age IS NULL";
const std::string kCustomDml = "UPDATE TestModels SET ExpirationTime = TIMESTAMP_ADD(TrainingTime, INTERVAL 60 DAY) WHERE ExpirationTime IS NULL";

void DmlPartitionedUpdate(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  auto result = client.ExecutePartitionedDml(
      spanner::SqlStatement(kCustomDml));
  if (!result) throw std::runtime_error(result.status().message());
  std::cout << "Update was successful [spanner_dml_partitioned_update]\n";
}

void ReadWriteTransaction(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  using ::google::cloud::StatusOr;

  // A helper to read a single Singers DefaultAge.
  auto get_default_age =
      [](spanner::Client client, spanner::Transaction txn,
         std::int64_t id) -> StatusOr<std::int64_t> {
    auto key = spanner::KeySet().AddKey(spanner::MakeKey(id));
    auto rows = client.Read(std::move(txn), "Singers", std::move(key),
                            {"DefaultAge"});
    using RowType = std::tuple<std::int64_t>;
    auto row = spanner::GetSingularRow(spanner::StreamOf<RowType>(rows));
    if (!row) return std::move(row).status();
    return std::get<0>(*std::move(row));
  };

  // A helper to read a single Singers Age
  auto get_current_age =
      [](spanner::Client client, spanner::Transaction txn,
         std::int64_t id) -> StatusOr<std::int64_t> {
    auto key = spanner::KeySet().AddKey(spanner::MakeKey(id));
    auto rows = client.Read(std::move(txn), "Singers", std::move(key),
                            {"Age"});
    using RowType = std::tuple<std::int64_t>;
    auto row = spanner::GetSingularRow(spanner::StreamOf<RowType>(rows));
    if (!row) return std::move(row).status();
    return std::get<0>(*std::move(row));
  };

  auto commit = client.Commit(
      [&client, &get_default_age, &get_current_age](
          spanner::Transaction const& txn) -> StatusOr<spanner::Mutations> {
        std::int64_t id = 1;
        auto defaultAge = get_default_age(client, txn, id);
        if (!defaultAge) return std::move(defaultAge).status();
        auto age = get_current_age(client, txn, id);

	if(age) {
             std::int64_t ageGap = *age - *defaultAge;
	     if(ageGap != 100) {
	     	return google::cloud::Status(
		    google::cloud::StatusCode::kUnknown,
		    "Age gap is wrong for Singer ID " + std::to_string(id));
	     }
	     std::cout << "No need to update for Singer ID " + std::to_string(id) + "\n";
	     return spanner::Mutations{};
	}
	std::cout << "Update Age for Singer ID " + std::to_string(id) + "\n";
        std::int64_t ageGap = 100;
        return spanner::Mutations{
            spanner::UpdateMutationBuilder(
                "Singers", {"SingerId", "Age"})
                .EmplaceRow(id, *defaultAge + ageGap)
                .Build()};
      });

  if (!commit) throw std::runtime_error(commit.status().message());

  std::cout << "Update was successful [spanner_read_write_transaction]\n";
}

int main(int argc, char* argv[]) try {
  if (argc != 4) {
    std::cerr << "Usage: " << argv[0]
              << " project-id instance-id database-id\n";
    return 1;
  }

  namespace spanner = ::google::cloud::spanner;
  spanner::Client client(
      spanner::MakeConnection(spanner::Database(argv[1], argv[2], argv[3])));
  // DmlPartitionedUpdate(client);
  ReadWriteTransaction(client);
  return 1;

  /*
  auto rows =
      client.ExecuteQuery(spanner::SqlStatement("SELECT 'Hello World'"));

  for (auto const& row : spanner::StreamOf<std::tuple<std::string>>(rows)) {
    if (!row) throw std::runtime_error(row.status().message());
    std::cout << std::get<0>(*row) << "\n";
  }

  return 0;
  */
  } catch (std::exception const& ex) {
  std::cerr << "Standard exception raised: " << ex.what() << "\n";
  return 1;
}
<commit_msg>remove dml update function<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "google/cloud/spanner/client.h"
#include <iostream>
#include <stdexcept>

const std::string kTableName = "Singers";
const std::string kUpdateColumnName = "Age";
const std::string kBaseColumnName = "DefaultAge";

void ReadWriteTransaction(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  using ::google::cloud::StatusOr;

  // A helper to read a single Singers DefaultAge.
  auto get_default_age =
      [](spanner::Client client, spanner::Transaction txn,
         std::int64_t id) -> StatusOr<std::int64_t> {
    auto key = spanner::KeySet().AddKey(spanner::MakeKey(id));
    auto rows = client.Read(std::move(txn), "Singers", std::move(key),
                            {"DefaultAge"});
    using RowType = std::tuple<std::int64_t>;
    auto row = spanner::GetSingularRow(spanner::StreamOf<RowType>(rows));
    if (!row) return std::move(row).status();
    return std::get<0>(*std::move(row));
  };

  // A helper to read a single Singers Age
  auto get_current_age =
      [](spanner::Client client, spanner::Transaction txn,
         std::int64_t id) -> StatusOr<std::int64_t> {
    auto key = spanner::KeySet().AddKey(spanner::MakeKey(id));
    auto rows = client.Read(std::move(txn), "Singers", std::move(key),
                            {"Age"});
    using RowType = std::tuple<std::int64_t>;
    auto row = spanner::GetSingularRow(spanner::StreamOf<RowType>(rows));
    if (!row) return std::move(row).status();
    return std::get<0>(*std::move(row));
  };

  auto commit = client.Commit(
      [&client, &get_default_age, &get_current_age](
          spanner::Transaction const& txn) -> StatusOr<spanner::Mutations> {
        std::int64_t id = 1;
        auto defaultAge = get_default_age(client, txn, id);
        if (!defaultAge) return std::move(defaultAge).status();
        auto age = get_current_age(client, txn, id);

	if(age) {
             std::int64_t ageGap = *age - *defaultAge;
	     if(ageGap != 100) {
	     	return google::cloud::Status(
		    google::cloud::StatusCode::kUnknown,
		    "Age gap is wrong for Singer ID " + std::to_string(id));
	     }
	     std::cout << "No need to update for Singer ID " + std::to_string(id) + "\n";
	     return spanner::Mutations{};
	}
	std::cout << "Update Age for Singer ID " + std::to_string(id) + "\n";
        std::int64_t ageGap = 100;
        return spanner::Mutations{
            spanner::UpdateMutationBuilder(
                "Singers", {"SingerId", "Age"})
                .EmplaceRow(id, *defaultAge + ageGap)
                .Build()};
      });

  if (!commit) throw std::runtime_error(commit.status().message());

  std::cout << "Update was successful [spanner_read_write_transaction]\n";
}

int main(int argc, char* argv[]) try {
  if (argc != 4) {
    std::cerr << "Usage: " << argv[0]
              << " project-id instance-id database-id\n";
    return 1;
  }

  namespace spanner = ::google::cloud::spanner;
  spanner::Client client(
      spanner::MakeConnection(spanner::Database(argv[1], argv[2], argv[3])));
  // DmlPartitionedUpdate(client);
  ReadWriteTransaction(client);
  return 1;

  /*
  auto rows =
      client.ExecuteQuery(spanner::SqlStatement("SELECT 'Hello World'"));

  for (auto const& row : spanner::StreamOf<std::tuple<std::string>>(rows)) {
    if (!row) throw std::runtime_error(row.status().message());
    std::cout << std::get<0>(*row) << "\n";
  }

  return 0;
  */
  } catch (std::exception const& ex) {
  std::cerr << "Standard exception raised: " << ex.what() << "\n";
  return 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1999 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $"
#endif

# include "config.h"

/*
 * This functor scans the design looking for dangling objects and
 * excess local signals. These deletions are not necessarily required
 * for proper functioning of anything, but they can clean up the
 * appearance of design files that are generated.
 */
# include  "functor.h"
# include  "netlist.h"
# include  "compiler.h"

class nodangle_f  : public functor_t {
    public:
      void event(Design*des, NetEvent*ev);
      void signal(Design*des, NetNet*sig);

      unsigned count_;
      unsigned stotal, etotal;
};

void nodangle_f::event(Design*des, NetEvent*ev)
{
	/* If there are no references to this event, then go right
	   ahead and delete in. There is no use looking further at
	   it. */
      if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
	    delete ev;
	    etotal += 1;
	    return;
      }

	/* Try to remove duplicate probes from the event. */
      for (unsigned idx = 0 ;  idx < ev->nprobe() ;  idx += 1) {
	    unsigned jdx = idx + 1;
	    while (jdx < ev->nprobe()) {
		  NetEvProbe*ip = ev->probe(idx);
		  NetEvProbe*jp = ev->probe(jdx);

		  if (ip->edge() != jp->edge()) {
			jdx += 1;
			continue;
		  }

		  bool fully_connected = true;
		  for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
			unsigned ipin = 0;
			bool connected_flag = false;
			for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
			      if (connected(ip->pin(ipin), jp->pin(jpin))) {
				    connected_flag = true;
				    break;
			      }

			if (!connected_flag) {
			      fully_connected = false;
			      break;
			}
		  }

		  if (fully_connected) {
			delete jp;
		  } else {
			jdx += 1;
		  }
	    }
      }

	/* Try to find all the events that are similar to me, and
	   replace their references with references to me. */
      list<NetEvent*> match;
      ev->find_similar_event(match);
      for (list<NetEvent*>::iterator idx = match.begin()
		 ; idx != match.end() ;  idx ++) {

	    NetEvent*tmp = *idx;
	    assert(tmp != ev);
	    tmp ->replace_event(ev);
      }

}

void nodangle_f::signal(Design*des, NetNet*sig)
{
	/* Cannot delete signals referenced in an expression
	   or an l-value. */
      if (sig->get_refs() > 0)
	    return;

	/* Cannot delete the ports of tasks or functions. There are
	   too many places where they are referenced. */
      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->type() == NetScope::TASK))
	    return;

      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->type() == NetScope::FUNC))
	    return;

	/* Can't delete ports of cells. */
      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->attribute(perm_string::literal("ivl_synthesis_cell")) != verinum()))
	    return;

	/* Check to see if the signal is completely unconnected. If
	   all the bits are unlinked, then delete it. */
      bool linked_flag = false;
      for (unsigned idx =  0 ;  idx < sig->pin_count() ;  idx += 1)
	    if (sig->pin(idx).is_linked()) {
		  linked_flag = true;
		  break;
	    }

      if (! linked_flag) {
	    delete sig;
	    stotal += 1;
	    return;
      }

	/* The remaining things can only be done to synthesized
	   signals, not ones that appear in the original Verilog. */
      if (! sig->local_flag())
	    return;

	/* Check to see if there is some significant signal connected
	   to every pin of this signal. */
      unsigned significant_flags = 0;
      for (unsigned idx = 0 ;  idx < sig->pin_count() ;  idx += 1) {
	    Nexus*nex = sig->pin(idx).nexus();

	    for (Link*cur = nex->first_nlink()
		       ; cur ;  cur = cur->next_nlink()) {

		  if (cur == &sig->pin(idx))
			continue;

		  NetNet*cursig = dynamic_cast<NetNet*>(cur->get_obj());
		  if (cursig == 0)
			continue;

		  if (cursig->local_flag())
			continue;

		  significant_flags += 1;
		  break;
	    }

	    if (significant_flags <= idx)
		  break;
      }

	/* If every pin is connected to another significant signal,
	   then I can delete this one. */
      if (significant_flags == sig->pin_count()) {
	    count_ += 1;
	    delete sig;
	    stotal += 1;
      }
}

void nodangle(Design*des)
{
      nodangle_f fun;
      unsigned count_iterations = 0;
      fun.stotal = 0;
      fun.etotal = 0;

      do {
	    fun.count_ = 0;
	    des->functor(&fun);
	    count_iterations += 1;

	    if (verbose_flag) {
		  cout << " ... " << count_iterations << " iterations"
		       << " deleted " << fun.stotal << " dangling signals"
		       << " and " << fun.etotal << " events."
		       << " (count=" << fun.count_ << ")" << endl;
	    }

      } while (fun.count_ > 0);

}

/*
 * $Log: nodangle.cc,v $
 * Revision 1.21  2004/02/20 18:53:35  steve
 *  Addtrbute keys are perm_strings.
 *
 * Revision 1.20  2004/01/15 06:04:19  steve
 *  Remove duplicate NetEvProbe objects in nodangle.
 *
 * Revision 1.19  2003/06/25 04:46:03  steve
 *  Do not elide ports of cells.
 *
 * Revision 1.18  2003/04/22 04:48:30  steve
 *  Support event names as expressions elements.
 *
 * Revision 1.17  2002/08/12 01:35:00  steve
 *  conditional ident string using autoconfig.
 *
 * Revision 1.16  2002/07/24 16:24:45  steve
 *  Rewrite find_similar_event to support doing
 *  all event matching and replacement in one
 *  shot, saving time in the scans.
 *
 * Revision 1.15  2002/05/26 01:39:02  steve
 *  Carry Verilog 2001 attributes with processes,
 *  all the way through to the ivl_target API.
 *
 *  Divide signal reference counts between rval
 *  and lval references.
 *
 * Revision 1.14  2002/02/02 06:13:38  steve
 *  event find_similar should not find self.
 *
 * Revision 1.13  2001/07/27 02:41:55  steve
 *  Fix binding of dangling function ports. do not elide them.
 *
 * Revision 1.12  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.11  2001/02/17 05:14:35  steve
 *  Cannot elide task ports.
 *
 * Revision 1.10  2000/11/19 20:48:53  steve
 *  Killing some signals might make others killable.
 *
 * Revision 1.9  2000/11/18 05:12:45  steve
 *  Delete unreferenced signals no matter what.
 *
 * Revision 1.8  2000/06/25 19:59:42  steve
 *  Redesign Links to include the Nexus class that
 *  carries properties of the connected set of links.
 *
 * Revision 1.7  2000/05/31 02:26:49  steve
 *  Globally merge redundant event objects.
 *
 * Revision 1.6  2000/05/07 04:37:56  steve
 *  Carry strength values from Verilog source to the
 *  pform and netlist for gates.
 *
 *  Change vvm constants to use the driver_t to drive
 *  a constant value. This works better if there are
 *  multiple drivers on a signal.
 *
 * Revision 1.5  2000/04/28 21:00:29  steve
 *  Over agressive signal elimination in constant probadation.
 *
 * Revision 1.4  2000/04/18 04:50:20  steve
 *  Clean up unneeded NetEvent objects.
 *
 * Revision 1.3  2000/02/23 02:56:55  steve
 *  Macintosh compilers do not support ident.
 *
 * Revision 1.2  1999/11/28 23:42:02  steve
 *  NetESignal object no longer need to be NetNode
 *  objects. Let them keep a pointer to NetNet objects.
 *
 * Revision 1.1  1999/11/18 03:52:20  steve
 *  Turn NetTmp objects into normal local NetNet objects,
 *  and add the nodangle functor to clean up the local
 *  symbols generated by elaboration and other steps.
 *
 */

<commit_msg>Bias storage of events towards static scopes.<commit_after>/*
 * Copyright (c) 1999 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $"
#endif

# include "config.h"

/*
 * This functor scans the design looking for dangling objects and
 * excess local signals. These deletions are not necessarily required
 * for proper functioning of anything, but they can clean up the
 * appearance of design files that are generated.
 */
# include  "functor.h"
# include  "netlist.h"
# include  "compiler.h"

class nodangle_f  : public functor_t {
    public:
      void event(Design*des, NetEvent*ev);
      void signal(Design*des, NetNet*sig);

      unsigned iteration;
      unsigned stotal, etotal;
      bool scontinue, econtinue;
      bool scomplete, ecomplete;
};

void nodangle_f::event(Design*des, NetEvent*ev)
{
      if (ecomplete) return;

	/* If there are no references to this event, then go right
	   ahead and delete it. There is no use looking further at
	   it. */
      if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
	    delete ev;
	    etotal += 1;
	    return;
      }

      if (iteration == 0) {
              /* Try to remove duplicate probes from the event. This
                 is done as a separate initial pass to ensure similar
                 events are detected as soon as possible in subsequent
                 iterations. */
            for (unsigned idx = 0 ;  idx < ev->nprobe() ;  idx += 1) {
                  unsigned jdx = idx + 1;
                  while (jdx < ev->nprobe()) {
                        NetEvProbe*ip = ev->probe(idx);
                        NetEvProbe*jp = ev->probe(jdx);

                        if (ip->edge() != jp->edge()) {
                              jdx += 1;
                              continue;
                        }

                        bool fully_connected = true;
                        for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
                              unsigned ipin = 0;
                              bool connected_flag = false;
                              for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
                                    if (connected(ip->pin(ipin), jp->pin(jpin))) {
                                          connected_flag = true;
                                          break;
                                    }

                              if (!connected_flag) {
                                    fully_connected = false;
                                    break;
                              }
                        }

                        if (fully_connected) {
                              delete jp;
                        } else {
                              jdx += 1;
                        }
                  }
            }
            econtinue = true;
      } else {
              /* Postpone examining events in an automatic scope until the
                 third (optional) pass. This will mean similar events are
                 biased towards being stored in static scopes. */
            if (ev->scope()->is_auto()) {
                  if (iteration == 1) {
                        econtinue = true;
                        return;
                  }
            } else {
                  if (iteration == 2) {
                        return;
                  }
            }

              /* Try to find all the events that are similar to me, and
                 replace their references with references to me. */
            list<NetEvent*> match;
            ev->find_similar_event(match);
            for (list<NetEvent*>::iterator idx = match.begin()
                       ; idx != match.end() ;  idx ++) {

                  NetEvent*tmp = *idx;
                  assert(tmp != ev);
                  tmp ->replace_event(ev);
            }
      }
}

void nodangle_f::signal(Design*des, NetNet*sig)
{
      if (scomplete) return;

	/* Cannot delete signals referenced in an expression
	   or an l-value. */
      if (sig->get_refs() > 0)
	    return;

	/* Cannot delete the ports of tasks or functions. There are
	   too many places where they are referenced. */
      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->type() == NetScope::TASK))
	    return;

      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->type() == NetScope::FUNC))
	    return;

	/* Can't delete ports of cells. */
      if ((sig->port_type() != NetNet::NOT_A_PORT)
	  && (sig->scope()->attribute(perm_string::literal("ivl_synthesis_cell")) != verinum()))
	    return;

	/* Check to see if the signal is completely unconnected. If
	   all the bits are unlinked, then delete it. */
      bool linked_flag = false;
      for (unsigned idx =  0 ;  idx < sig->pin_count() ;  idx += 1)
	    if (sig->pin(idx).is_linked()) {
		  linked_flag = true;
		  break;
	    }

      if (! linked_flag) {
	    delete sig;
	    stotal += 1;
	    return;
      }

	/* The remaining things can only be done to synthesized
	   signals, not ones that appear in the original Verilog. */
      if (! sig->local_flag())
	    return;

	/* Check to see if there is some significant signal connected
	   to every pin of this signal. */
      unsigned significant_flags = 0;
      for (unsigned idx = 0 ;  idx < sig->pin_count() ;  idx += 1) {
	    Nexus*nex = sig->pin(idx).nexus();

	    for (Link*cur = nex->first_nlink()
		       ; cur ;  cur = cur->next_nlink()) {

		  if (cur == &sig->pin(idx))
			continue;

		  NetNet*cursig = dynamic_cast<NetNet*>(cur->get_obj());
		  if (cursig == 0)
			continue;

		  if (cursig->local_flag())
			continue;

		  significant_flags += 1;
		  break;
	    }

	    if (significant_flags <= idx)
		  break;
      }

	/* If every pin is connected to another significant signal,
	   then I can delete this one. */
      if (significant_flags == sig->pin_count()) {
	    scontinue = true;
	    delete sig;
	    stotal += 1;
      }
}

void nodangle(Design*des)
{
      nodangle_f fun;
      fun.iteration = 0;
      fun.stotal = 0;
      fun.etotal = 0;
      fun.scomplete = false;
      fun.ecomplete = false;
      do {
            fun.scontinue = false;
            fun.econtinue = false;
	    des->functor(&fun);
	    fun.iteration += 1;
            fun.scomplete = !fun.scontinue;
            fun.ecomplete = !fun.econtinue;

	    if (verbose_flag) {
		  cout << " ... " << fun.iteration << " iterations"
		       << " deleted " << fun.stotal << " dangling signals"
		       << " and " << fun.etotal << " events." << endl;
	    }

      } while (fun.scontinue || fun.econtinue);

}

/*
 * $Log: nodangle.cc,v $
 * Revision 1.21  2004/02/20 18:53:35  steve
 *  Addtrbute keys are perm_strings.
 *
 * Revision 1.20  2004/01/15 06:04:19  steve
 *  Remove duplicate NetEvProbe objects in nodangle.
 *
 * Revision 1.19  2003/06/25 04:46:03  steve
 *  Do not elide ports of cells.
 *
 * Revision 1.18  2003/04/22 04:48:30  steve
 *  Support event names as expressions elements.
 *
 * Revision 1.17  2002/08/12 01:35:00  steve
 *  conditional ident string using autoconfig.
 *
 * Revision 1.16  2002/07/24 16:24:45  steve
 *  Rewrite find_similar_event to support doing
 *  all event matching and replacement in one
 *  shot, saving time in the scans.
 *
 * Revision 1.15  2002/05/26 01:39:02  steve
 *  Carry Verilog 2001 attributes with processes,
 *  all the way through to the ivl_target API.
 *
 *  Divide signal reference counts between rval
 *  and lval references.
 *
 * Revision 1.14  2002/02/02 06:13:38  steve
 *  event find_similar should not find self.
 *
 * Revision 1.13  2001/07/27 02:41:55  steve
 *  Fix binding of dangling function ports. do not elide them.
 *
 * Revision 1.12  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.11  2001/02/17 05:14:35  steve
 *  Cannot elide task ports.
 *
 * Revision 1.10  2000/11/19 20:48:53  steve
 *  Killing some signals might make others killable.
 *
 * Revision 1.9  2000/11/18 05:12:45  steve
 *  Delete unreferenced signals no matter what.
 *
 * Revision 1.8  2000/06/25 19:59:42  steve
 *  Redesign Links to include the Nexus class that
 *  carries properties of the connected set of links.
 *
 * Revision 1.7  2000/05/31 02:26:49  steve
 *  Globally merge redundant event objects.
 *
 * Revision 1.6  2000/05/07 04:37:56  steve
 *  Carry strength values from Verilog source to the
 *  pform and netlist for gates.
 *
 *  Change vvm constants to use the driver_t to drive
 *  a constant value. This works better if there are
 *  multiple drivers on a signal.
 *
 * Revision 1.5  2000/04/28 21:00:29  steve
 *  Over agressive signal elimination in constant probadation.
 *
 * Revision 1.4  2000/04/18 04:50:20  steve
 *  Clean up unneeded NetEvent objects.
 *
 * Revision 1.3  2000/02/23 02:56:55  steve
 *  Macintosh compilers do not support ident.
 *
 * Revision 1.2  1999/11/28 23:42:02  steve
 *  NetESignal object no longer need to be NetNode
 *  objects. Let them keep a pointer to NetNet objects.
 *
 * Revision 1.1  1999/11/18 03:52:20  steve
 *  Turn NetTmp objects into normal local NetNet objects,
 *  and add the nodangle functor to clean up the local
 *  symbols generated by elaboration and other steps.
 *
 */
<|endoftext|>