<commit_before>#include <fstream>
#include <iostream>
#include <math.h>

#include "ChargeProcess.hpp"
#include "DCCon_in.hpp"
#include "DCCon_out.hpp"
#include "HEESTimer.hpp"
#include "LoadApp.hpp"
#include "SuperCap.hpp"
#include "main.hpp"

using namespace std;
using namespace std::tr1;

extern HEESTimer HTimer;

double dc_super_cap_energy = 0.0;
double bank_res_energy = 0.0;

ChargeProcess::ChargeProcess() :
	vcti(0.0), icti(0.0),
	super_cap_iin(0.0), super_cap_qacc(0.0), super_cap_voc(0.0), super_cap_vcc(0.0), dc_load_power(0.0),
	dc_super_cap_vout(super_cap_vcc), dc_super_cap_iout(super_cap_iin), dc_super_cap_vin(vcti), dc_super_cap_iin(0.0), dc_super_cap_power(0.0),
	dc_load_vin(vcti), dc_load_iin(icti), dc_load_vout(1.0), dc_load_iout(1.0),
	power_input(0.0),
	time_elapsed(0.0), time_index(0),
	output_file("OverallProcess.txt") {

	ofstream output(output_file.c_str());
	output << "Pinput\tVCTI\tVcap_oc\tVcap_cc\tQacc\tIsup\tPdcsup\tPdcload\tPrbank\tEsup\tCacc" << endl;
	output.close();
}

void ChargeProcess::compute_dc_bank_iin() {
	// Compute the current Icti on CTI from bank to load
	dc_load.ConverterModel(dc_load_vin, dc_load_vout, dc_load_iout, dc_load_iin, dc_load_power);

	dc_super_cap_iin = power_input/vcti - dc_load_iin;

	// Test if the supply power is large enough
	if (dc_super_cap_iin < 0) {
		power_status = POWER_NOT_ENOUGH_FOR_LOAD;
	} else {
		power_status = POWER_NORMAL;
	}
}

void ChargeProcess::charge_policy_our_policy(ees_bank *bank) {

	// Set the VCTI to the load vdd;
	if (power_status == POWER_INIT) {
		if (fixed_vcti > 0.0)
			vcti = fixed_vcti;
		else
			vcti = dc_load_vout;
		compute_dc_bank_iin();
	}

	if (power_status == POWER_NORMAL) {
		dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		// Reconfig if necessary
		// while ((dc_super_cap_vout > dc_super_cap_vin) && supcap_reconfig_return && bank_reconfig_enable) {
			// supcap_reconfig_return = bank->EESBankOperating(dc_super_cap_iin, dc_super_cap_vout, -100.0);
			// supcap_reconfig_return = bank->EESBankReconfiguration(dc_super_cap_iin, dc_super_cap_vout, &dc_super_cap);
			// dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		// }
		if ((dc_super_cap_vout > dc_super_cap_vin) && supcap_reconfig_return && bank_reconfig_enable) {
			supcap_reconfig_return = bank->EESBankReconfiguration(dc_super_cap_iin, dc_super_cap_vout, &dc_super_cap);
			dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		}
	}

	return;
}

void ChargeProcess::charge_policy_optimal_vcti(ees_bank *bank) {
	if (time_index % recompute_vcti_time_index == 0) {
		vcti = sel_vcti.bestVCTI(power_input, dc_load_iout, dc_load_vout, "out_SupCap", bank);
	}

	compute_dc_bank_iin();
	if (power_status == POWER_NORMAL) {
		dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
	}

	return;
}

int ChargeProcess::ChargeProcessOptimalVcti(ees_bank *bank, lionbat *lb, loadApplication *load) {

	this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
	power_status = POWER_INIT;

	// Bind to optimal vcti policy
	charge_policy = bind(&ChargeProcess::charge_policy_optimal_vcti, this, placeholders::_1);

	return ChargeProcessApplyPolicy(bank, lb, load);
}

int ChargeProcess::ChargeProcessOurPolicy(ees_bank *bank, lionbat *lb, loadApplication *load) {

	this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
	power_status = POWER_INIT;

	supcap_reconfig_return = true;

	// Bind to our policy
	charge_policy = bind(&ChargeProcess::charge_policy_our_policy, this, placeholders::_1);

	return ChargeProcessApplyPolicy(bank, lb, load);
}

int ChargeProcess::ChargeProcessApplyPolicy(ees_bank *bank, lionbat *lb, loadApplication *load) {

	// DC-DC converter for the load
	dc_load_vout = load->get_vdd();
	dc_load_iout = load->get_idd();

	// Task info and timer stuff
	time_elapsed = 0.0;
	time_index = 0;

	// Output file
	ofstream output(output_file.c_str(), ios_base::app);
	if (!output.good()) {
		cerr << "Can not open files!" << endl;
	}

	while (fabs(load->CurrentTaskRemainingTime()) > 1e-3) {

		// Every second, update the power input
		if (time_index % 10 == 0) {
			this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
			power_status = POWER_INIT;
		}
		charge_policy(bank);

		// Check if we need to break because the power_input is not enough
		if (power_status == POWER_NOT_ENOUGH_FOR_LOAD) {
			time_index = -1;
			break;
		}

		// Record the current status of the super capacitor
		if (HTimer.HEESTimerGetCurrentTimeIndex() % delta_energy_steps == 0)
			print_super_cap_info(output, bank, power_input);

		bank->EESBankCharge(super_cap_iin, dc_super_cap_vout, min_time_interval, super_cap_vcc, super_cap_qacc);

		time_elapsed += min_time_interval;
		++time_index;
		HTimer.HEESTimerAdvancdTimerIndex(1, bank);
		load->AdvanceLoadProgress(min_time_interval);

		// Recorde the wasted energy on dcdc and bank resistance
		dc_super_cap_energy += min_time_interval * dc_super_cap_power;
		bank_res_energy += min_time_interval * super_cap_iin * super_cap_iin *bank->EESBankGetRacc();

		if (HTimer.HEESTimerGetCurrentTimeIndex() > MAX_TIME_INDEX)
			break;
	}

	output.close();
	// After charging, reset the power status to POWER_INIT
	power_status = POWER_INIT;

	return time_index;
}

void ChargeProcess::print_super_cap_info(ofstream &output, ees_bank *bank, double power_input) {
	// Output the status to a file
	super_cap_voc = bank->EESBankGetVoc();
	super_cap_qacc = bank->EESBankGetQacc();
	output.precision(5);
	output.setf(ios::fixed,ios::floatfield);
	output << power_input << "\t"
			<< vcti << "\t"
			<< super_cap_voc << "\t"
			<< super_cap_vcc << "\t"
			<< super_cap_qacc << "\t"
			<< super_cap_iin << "\t"
			<< dc_super_cap_power << "\t"
			<< dc_load_power << "\t"
			<< super_cap_iin*super_cap_iin*bank->EESBankGetRacc() << "\t"
			<< bank->EESBankGetEnergy() << "\t"
			<< bank->EESBankGetCacc() << endl;

	return;
}
<commit_msg>Print out SupCap Bank DC-DC Iout in log<commit_after>#include <fstream>
#include <iostream>
#include <math.h>

#include "ChargeProcess.hpp"
#include "DCCon_in.hpp"
#include "DCCon_out.hpp"
#include "HEESTimer.hpp"
#include "LoadApp.hpp"
#include "SuperCap.hpp"
#include "main.hpp"

using namespace std;
using namespace std::tr1;

extern HEESTimer HTimer;

double dc_super_cap_energy = 0.0;
double bank_res_energy = 0.0;

ChargeProcess::ChargeProcess() :
	vcti(0.0), icti(0.0),
	super_cap_iin(0.0), super_cap_qacc(0.0), super_cap_voc(0.0), super_cap_vcc(0.0), dc_load_power(0.0),
	dc_super_cap_vout(super_cap_vcc), dc_super_cap_iout(super_cap_iin), dc_super_cap_vin(vcti), dc_super_cap_iin(0.0), dc_super_cap_power(0.0),
	dc_load_vin(vcti), dc_load_iin(icti), dc_load_vout(1.0), dc_load_iout(1.0),
	power_input(0.0),
	time_elapsed(0.0), time_index(0),
	output_file("OverallProcess.txt") {

	ofstream output(output_file.c_str());
	output << "Pinput\tVCTI\tVcap_oc\tVcap_cc\tQacc\t\tIsup\tPdcsup\tPdcsupIin\tPdcload\tPrbank\tEsup\tCacc" << endl;
	output.close();
}

void ChargeProcess::compute_dc_bank_iin() {
	// Compute the current Icti on CTI from bank to load
	dc_load.ConverterModel(dc_load_vin, dc_load_vout, dc_load_iout, dc_load_iin, dc_load_power);

	dc_super_cap_iin = power_input/vcti - dc_load_iin;

	// Test if the supply power is large enough
	if (dc_super_cap_iin < 0) {
		power_status = POWER_NOT_ENOUGH_FOR_LOAD;
	} else {
		power_status = POWER_NORMAL;
	}
}

void ChargeProcess::charge_policy_our_policy(ees_bank *bank) {

	// Set the VCTI to the load vdd;
	if (power_status == POWER_INIT) {
		if (fixed_vcti > 0.0)
			vcti = fixed_vcti;
		else
			vcti = dc_load_vout;
		compute_dc_bank_iin();
	}

	if (power_status == POWER_NORMAL) {
		dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		// Reconfig if necessary
		// while ((dc_super_cap_vout > dc_super_cap_vin) && supcap_reconfig_return && bank_reconfig_enable) {
			// supcap_reconfig_return = bank->EESBankOperating(dc_super_cap_iin, dc_super_cap_vout, -100.0);
			// supcap_reconfig_return = bank->EESBankReconfiguration(dc_super_cap_iin, dc_super_cap_vout, &dc_super_cap);
			// dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		// }
		if ((dc_super_cap_vout > dc_super_cap_vin) && supcap_reconfig_return && bank_reconfig_enable) {
			supcap_reconfig_return = bank->EESBankReconfiguration(dc_super_cap_iin, dc_super_cap_vout, &dc_super_cap);
			dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
		}
	}

	return;
}

void ChargeProcess::charge_policy_optimal_vcti(ees_bank *bank) {
	if (time_index % recompute_vcti_time_index == 0) {
		vcti = sel_vcti.bestVCTI(power_input, dc_load_iout, dc_load_vout, "out_SupCap", bank);
	}

	compute_dc_bank_iin();
	if (power_status == POWER_NORMAL) {
		dc_super_cap.ConverterModel_EESBank(dc_super_cap_vin, dc_super_cap_iin, dc_super_cap_vout, dc_super_cap_iout, dc_super_cap_power, bank);
	}

	return;
}

int ChargeProcess::ChargeProcessOptimalVcti(ees_bank *bank, lionbat *lb, loadApplication *load) {

	this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
	power_status = POWER_INIT;

	// Bind to optimal vcti policy
	charge_policy = bind(&ChargeProcess::charge_policy_optimal_vcti, this, placeholders::_1);

	return ChargeProcessApplyPolicy(bank, lb, load);
}

int ChargeProcess::ChargeProcessOurPolicy(ees_bank *bank, lionbat *lb, loadApplication *load) {

	this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
	power_status = POWER_INIT;

	supcap_reconfig_return = true;

	// Bind to our policy
	charge_policy = bind(&ChargeProcess::charge_policy_our_policy, this, placeholders::_1);

	return ChargeProcessApplyPolicy(bank, lb, load);
}

int ChargeProcess::ChargeProcessApplyPolicy(ees_bank *bank, lionbat *lb, loadApplication *load) {

	// DC-DC converter for the load
	dc_load_vout = load->get_vdd();
	dc_load_iout = load->get_idd();

	// Task info and timer stuff
	time_elapsed = 0.0;
	time_index = 0;

	// Output file
	ofstream output(output_file.c_str(), ios_base::app);
	if (!output.good()) {
		cerr << "Can not open files!" << endl;
	}

	while (fabs(load->CurrentTaskRemainingTime()) > 1e-3) {

		// Every second, update the power input
		if (time_index % 10 == 0) {
			this->power_input = power_source_func(HTimer.HEESTimerGetCurrentTimeInSecond());
			power_status = POWER_INIT;
		}
		charge_policy(bank);

		// Check if we need to break because the power_input is not enough
		if (power_status == POWER_NOT_ENOUGH_FOR_LOAD) {
			time_index = -1;
			break;
		}

		// Record the current status of the super capacitor
		if (HTimer.HEESTimerGetCurrentTimeIndex() % delta_energy_steps == 0)
			print_super_cap_info(output, bank, power_input);

		bank->EESBankCharge(super_cap_iin, dc_super_cap_vout, min_time_interval, super_cap_vcc, super_cap_qacc);

		time_elapsed += min_time_interval;
		++time_index;
		HTimer.HEESTimerAdvancdTimerIndex(1, bank);
		load->AdvanceLoadProgress(min_time_interval);

		// Recorde the wasted energy on dcdc and bank resistance
		dc_super_cap_energy += min_time_interval * dc_super_cap_power;
		bank_res_energy += min_time_interval * super_cap_iin * super_cap_iin *bank->EESBankGetRacc();

		if (HTimer.HEESTimerGetCurrentTimeIndex() > MAX_TIME_INDEX)
			break;
	}

	output.close();
	// After charging, reset the power status to POWER_INIT
	power_status = POWER_INIT;

	return time_index;
}

void ChargeProcess::print_super_cap_info(ofstream &output, ees_bank *bank, double power_input) {
	// Output the status to a file
	super_cap_voc = bank->EESBankGetVoc();
	super_cap_qacc = bank->EESBankGetQacc();
	output.precision(5);
	output.setf(ios::fixed,ios::floatfield);
	output << power_input << "\t"
			<< vcti << "\t"
			<< super_cap_voc << "\t"
			<< super_cap_vcc << "\t"
			<< super_cap_qacc << "\t"
			<< super_cap_iin << "\t"
			<< dc_super_cap_power << "\t"
			<< dc_super_cap_iin << "\t\t"
			<< dc_load_power << "\t"
			<< super_cap_iin*super_cap_iin*bank->EESBankGetRacc() << "\t"
			<< bank->EESBankGetEnergy() << "\t"
			<< bank->EESBankGetCacc() << endl;

	return;
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 <memory>

#include "Examples/ExampleStapling/StaplerBehavior.h"
#include "SurgSim/Blocks/KeyboardTogglesGraphicsBehavior.h"
#include "SurgSim/Blocks/TransferPhysicsToGraphicsMeshBehavior.h"
#include "SurgSim/Blocks/VisualizeContactsBehavior.h"
#include "SurgSim/Framework/BasicSceneElement.h"
#include "SurgSim/Framework/BehaviorManager.h"
#include "SurgSim/Framework/FrameworkConvert.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Devices/IdentityPoseDevice/IdentityPoseDevice.h"
#include "SurgSim/Graphics/OsgManager.h"
#include "SurgSim/Graphics/OsgMeshRepresentation.h"
#include "SurgSim/Graphics/OsgSceneryRepresentation.h"
#include "SurgSim/Graphics/OsgView.h"
#include "SurgSim/Graphics/OsgViewElement.h"
#include "SurgSim/Input/InputManager.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/FixedRepresentation.h"
#include "SurgSim/Physics/PhysicsManager.h"
#include "SurgSim/Physics/VirtualToolCoupler.h"

using SurgSim::Device::IdentityPoseDevice;
using SurgSim::Framework::BehaviorManager;
using SurgSim::Framework::Runtime;
using SurgSim::Framework::SceneElement;
using SurgSim::Graphics::OsgManager;
using SurgSim::Graphics::OsgView;
using SurgSim::Graphics::OsgViewElement;
using SurgSim::Input::InputManager;
using SurgSim::Math::Vector3d;
using SurgSim::Input::DeviceInterface;
using SurgSim::Physics::PhysicsManager;

template <typename Type>
std::shared_ptr<Type> getComponentChecked(std::shared_ptr<SurgSim::Framework::SceneElement> sceneElement,
										  const std::string& name)
{
	std::shared_ptr<SurgSim::Framework::Component> component = sceneElement->getComponent(name);
	SURGSIM_ASSERT(component != nullptr) << "Failed to get Component named '" << name << "'.";

	std::shared_ptr<Type> result = std::dynamic_pointer_cast<Type>(component);
	SURGSIM_ASSERT(result != nullptr) << "Failed to convert Component to requested type.";

	return result;
}

int main(int argc, char* argv[])
{
	const std::string deviceName = "MultiAxisDevice";

	std::shared_ptr<BehaviorManager> behaviorManager = std::make_shared<BehaviorManager>();
	std::shared_ptr<OsgManager> graphicsManager = std::make_shared<OsgManager>();
	std::shared_ptr<InputManager> inputManager = std::make_shared<InputManager>();
	std::shared_ptr<PhysicsManager> physicsManager = std::make_shared<PhysicsManager>();

	std::shared_ptr<Runtime> runtime = std::make_shared<Runtime>("config.txt");
	runtime->addManager(behaviorManager);
	runtime->addManager(graphicsManager);
	runtime->addManager(inputManager);
	runtime->addManager(physicsManager);

	std::shared_ptr<DeviceInterface> device;
	device = std::make_shared<IdentityPoseDevice>(deviceName);
	inputManager->addDevice(device);

	YAML::Node node = YAML::LoadFile("Data/Stapling/StaplingDemo.yaml");

	runtime->getScene()->decode(node);

	std::shared_ptr<SceneElement> arm = runtime->getScene()->getSceneElement("arm");
	std::shared_ptr<SceneElement> wound = runtime->getScene()->getSceneElement("wound");
	std::shared_ptr<SceneElement> stapler = runtime->getScene()->getSceneElement("stapler");
	std::shared_ptr<SceneElement> view = runtime->getScene()->getSceneElement("StaplingDemoView");
	auto osgView = std::dynamic_pointer_cast<OsgView>(view->getComponent("StaplingDemoView View"));
	SURGSIM_ASSERT(nullptr != osgView) << "No OsgView held by SceneElement StaplingDemoView.";
	inputManager->addDevice(osgView->getKeyboardDevice());

	// Exclude collision between certain Collision::Representations
	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "VirtualToothCollision0"));

	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "VirtualToothCollision1"));

	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(wound, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(arm, "Collision"));

	runtime->execute();

	return 0;
}<commit_msg>Add MultiAxisDevice device support in SerializableStapling example<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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 <memory>

#include "Examples/ExampleStapling/StaplerBehavior.h"
#include "SurgSim/Blocks/KeyboardTogglesGraphicsBehavior.h"
#include "SurgSim/Blocks/TransferPhysicsToGraphicsMeshBehavior.h"
#include "SurgSim/Blocks/VisualizeContactsBehavior.h"
#include "SurgSim/Devices/MultiAxis/MultiAxisDevice.h"
#include "SurgSim/Framework/BasicSceneElement.h"
#include "SurgSim/Framework/BehaviorManager.h"
#include "SurgSim/Framework/FrameworkConvert.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Devices/IdentityPoseDevice/IdentityPoseDevice.h"
#include "SurgSim/Graphics/OsgManager.h"
#include "SurgSim/Graphics/OsgMeshRepresentation.h"
#include "SurgSim/Graphics/OsgSceneryRepresentation.h"
#include "SurgSim/Graphics/OsgView.h"
#include "SurgSim/Graphics/OsgViewElement.h"
#include "SurgSim/Input/InputManager.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/FixedRepresentation.h"
#include "SurgSim/Physics/PhysicsManager.h"
#include "SurgSim/Physics/VirtualToolCoupler.h"

using SurgSim::Device::IdentityPoseDevice;
using SurgSim::Device::MultiAxisDevice;
using SurgSim::Framework::BehaviorManager;
using SurgSim::Framework::Runtime;
using SurgSim::Framework::SceneElement;
using SurgSim::Graphics::OsgManager;
using SurgSim::Graphics::OsgView;
using SurgSim::Graphics::OsgViewElement;
using SurgSim::Input::InputManager;
using SurgSim::Math::Vector3d;
using SurgSim::Input::DeviceInterface;
using SurgSim::Physics::PhysicsManager;

template <typename Type>
std::shared_ptr<Type> getComponentChecked(std::shared_ptr<SurgSim::Framework::SceneElement> sceneElement,
										  const std::string& name)
{
	std::shared_ptr<SurgSim::Framework::Component> component = sceneElement->getComponent(name);
	SURGSIM_ASSERT(component != nullptr) << "Failed to get Component named '" << name << "'.";

	std::shared_ptr<Type> result = std::dynamic_pointer_cast<Type>(component);
	SURGSIM_ASSERT(result != nullptr) << "Failed to convert Component to requested type.";

	return result;
}

int main(int argc, char* argv[])
{
	const std::string deviceName = "MultiAxisDevice";

	std::shared_ptr<BehaviorManager> behaviorManager = std::make_shared<BehaviorManager>();
	std::shared_ptr<OsgManager> graphicsManager = std::make_shared<OsgManager>();
	std::shared_ptr<InputManager> inputManager = std::make_shared<InputManager>();
	std::shared_ptr<PhysicsManager> physicsManager = std::make_shared<PhysicsManager>();

	std::shared_ptr<Runtime> runtime = std::make_shared<Runtime>("config.txt");
	runtime->addManager(behaviorManager);
	runtime->addManager(graphicsManager);
	runtime->addManager(inputManager);
	runtime->addManager(physicsManager);

	std::shared_ptr<DeviceInterface> device;
	device = std::make_shared<MultiAxisDevice>(deviceName);
	if (!device->initialize())
	{
		SURGSIM_LOG_WARNING(SurgSim::Framework::Logger::getDefaultLogger())
			<< "Could not initialize device " << device->getName() << " for the tool.";

		device = std::make_shared<IdentityPoseDevice>(deviceName);
	}
	inputManager->addDevice(device);

	YAML::Node node = YAML::LoadFile("Data/Stapling/StaplingDemo.yaml");

	runtime->getScene()->decode(node);

	std::shared_ptr<SceneElement> arm = runtime->getScene()->getSceneElement("arm");
	std::shared_ptr<SceneElement> wound = runtime->getScene()->getSceneElement("wound");
	std::shared_ptr<SceneElement> stapler = runtime->getScene()->getSceneElement("stapler");
	std::shared_ptr<SceneElement> view = runtime->getScene()->getSceneElement("StaplingDemoView");
	auto osgView = std::dynamic_pointer_cast<OsgView>(view->getComponent("StaplingDemoView View"));
	SURGSIM_ASSERT(nullptr != osgView) << "No OsgView held by SceneElement StaplingDemoView.";
	inputManager->addDevice(osgView->getKeyboardDevice());

	// Exclude collision between certain Collision::Representations
	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "VirtualToothCollision0"));

	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(stapler, "VirtualToothCollision1"));

	physicsManager->addExcludedCollisionPair(
		getComponentChecked<SurgSim::Collision::Representation>(wound, "Collision"),
		getComponentChecked<SurgSim::Collision::Representation>(arm, "Collision"));

	runtime->execute();

	return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include "vtkDoubleArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkMultiCorrelativeStatistics.h"

//=============================================================================
int TestMultiCorrelativeStatistics( int, char *[] )
{
  int testStatus = 0;

  /* */
  double mingledData[] =
    {
    46, 45,
    47, 49,
    46, 47,
    46, 46,
    47, 46,
    47, 49,
    49, 49,
    47, 45,
    50, 50,
    46, 46,
    51, 50,
    48, 48,
    52, 54,
    48, 47,
    52, 52,
    49, 49,
    53, 54,
    50, 50,
    53, 54,
    50, 52,
    53, 53,
    50, 51,
    54, 54,
    49, 49,
    52, 52,
    50, 51,
    52, 52,
    49, 47,
    48, 48,
    48, 50,
    46, 48,
    47, 47
    };
  int nVals = 32;
  /*
  double mingledData[] =
    {
    1,
    5,
    11,
    10,
    9,
    7,
    11,
    11
    };
  int nVals = 4;
  */

  const char m0Name[] = "M0";
  vtkDoubleArray* dataset1Arr = vtkDoubleArray::New();
  dataset1Arr->SetNumberOfComponents( 1 );
  dataset1Arr->SetName( m0Name );

  const char m1Name[] = "M1";
  vtkDoubleArray* dataset2Arr = vtkDoubleArray::New();
  dataset2Arr->SetNumberOfComponents( 1 );
  dataset2Arr->SetName( m1Name );

  const char m2Name[] = "M2";
  vtkDoubleArray* dataset3Arr = vtkDoubleArray::New();
  dataset3Arr->SetNumberOfComponents( 1 );
  dataset3Arr->SetName( m2Name );

  for ( int i = 0; i < nVals; ++ i )
    {
    int ti = i << 1;
    dataset1Arr->InsertNextValue( mingledData[ti] );
    dataset2Arr->InsertNextValue( mingledData[ti + 1] );
    dataset3Arr->InsertNextValue( i != 12 ? -1. : -1.001 );
    }

  vtkTable* datasetTable = vtkTable::New();
  datasetTable->AddColumn( dataset1Arr );
  dataset1Arr->Delete();
  datasetTable->AddColumn( dataset2Arr );
  dataset2Arr->Delete();
  datasetTable->AddColumn( dataset3Arr );
  dataset3Arr->Delete();

  /*
  int nMetricPairs = 3;
  vtkStdString columnPairs[] = { m0Name, m1Name, m1Name, m0Name, m2Name, m1Name };
  double centers[] = { 49.2188, 49.5 };
  double covariance[] = { 5.98286, 7.54839, 6.14516 };
  double threshold = 4.;
  */

  vtkMultiCorrelativeStatistics* haruspex = vtkMultiCorrelativeStatistics::New();
  haruspex->SetInput( 0, datasetTable );

  datasetTable->Delete();

  // -- Select Column Pairs of Interest ( Learn Mode ) --
  haruspex->SetColumnStatus( m0Name, 1 );
  haruspex->SetColumnStatus( m1Name, 1 );
  haruspex->RequestSelectedColumns();
  haruspex->ResetAllColumnStates();
  haruspex->SetColumnStatus( m0Name, 1 );
  haruspex->SetColumnStatus( m1Name, 1 );
  haruspex->SetColumnStatus( m2Name, 1 );
  haruspex->SetColumnStatus( m2Name, 0 );
  haruspex->SetColumnStatus( m2Name, 1 );
  haruspex->RequestSelectedColumns();
  haruspex->RequestSelectedColumns(); // Try a duplicate entry. This should have no effect.
  haruspex->SetColumnStatus( m0Name, 0 );
  haruspex->SetColumnStatus( m2Name, 0 );
  haruspex->SetColumnStatus( "Metric 3", 1 ); // An invalid name. This should result in a request for metric 1's self-correlation.
  // haruspex->RequestSelectedColumns(); will get called in RequestData()

  // -- Test Learn Mode --
  haruspex->SetLearn( true );
  haruspex->SetDerive( true );
  haruspex->SetAssess( false );

  haruspex->Update();
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( haruspex->GetOutputDataObject( 1 ) );
  for ( unsigned int b = 0; b < outputMetaDS->GetNumberOfBlocks(); ++ b )
    {
    vtkTable* outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( b ) );
    //vtkIdType n = haruspex->GetSampleSize();
    if ( b == 0 )
      {
      cout << "Raw sums\n";
      }
    else
      {
      cout << "Request " << ( b - 1 ) << "\n";
      }

  /*
  cout << "## Calculated the following statistics ( "
       << n
       << " entries per column ):\n";
  for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
    {
    cout << "   (X, Y) = ("
         << outputMeta->GetValue( r, 0 ).ToString().c_str()
         << ", "
         << outputMeta->GetValue( r, 1 ).ToString().c_str()
         << ")";

    for ( int i = 2; i < 3; ++ i )
      {
      cout << ", "
           << outputMeta->GetColumnName( i )
           << "="
           << outputMeta->GetValue( r, i ).ToDouble();
      }
    cout << "\n";
    / * * /
    if ( outputMeta->GetValueByName( r,  "Linear Correlation" ).ToString() == vtkStdString( "valid" ) )
      {
      cout << "\n   Y = "
           << outputMeta->GetValueByName( r, "Slope Y/X" ).ToDouble()
           << " * X + "
           << outputMeta->GetValueByName( r, "Intersect Y/X" ).ToDouble()
           << ", X = "
           << outputMeta->GetValueByName( r, "Slope X/Y" ).ToDouble()
           << " * Y + "
           << outputMeta->GetValueByName( r, "Intersect X/Y" ).ToDouble()
           << ", corr. coeff.: "
           << outputMeta->GetValueByName( r, "Pearson r" ).ToDouble()
           << "\n";
      }
    else
      {
      cout << "\n   Degenerate input, linear correlation was not calculated.\n";
      }
      / * * /
    }
*/
    outputMeta->Dump();
    }

#if 0
  // -- Select Column Pairs of Interest ( Assess Mode ) --
  haruspex->ResetColumnPairs(); // Clear existing pairs
  haruspex->AddColumnPair( columnPairs[0], columnPairs[1] ); // A valid pair
#endif // 0

  // -- Test Assess Mode --
  vtkMultiBlockDataSet* paramsTables = vtkMultiBlockDataSet::New();
  paramsTables->ShallowCopy( outputMetaDS );

  haruspex->SetInput( 1, paramsTables );
  paramsTables->Delete();
  haruspex->SetLearn( false );
  haruspex->SetDerive( false ); // Do not recalculate nor rederive a model
  haruspex->SetAssess( true );
  haruspex->Update();

  vtkTable* outputData = haruspex->GetOutput();
  outputData->Dump();
#if 0
  int nOutliers = 0;
  int tableIdx[] = { 0, 1, 3 };
  cout << "   Found the following outliers:\n";
  for ( int i = 0; i < 3; ++ i )
    {
    cout << "   "
         << outputData->GetColumnName( tableIdx[i] );
    }
  cout << "\n";

  for ( vtkIdType r = 0; r < outputData->GetNumberOfRows(); ++ r )
    {
    if ( outputData->GetValue( r, tableIdx[2] ).ToDouble() > threshold )
      {
      ++ nOutliers;

      for ( int i = 0; i < 3; ++ i )
        {
        cout << "     "
             << outputData->GetValue( r,  tableIdx[i] ).ToString()
             << "    ";
        }
      cout << "\n";
      }
    }

  if ( nOutliers != 3 )
    {
    cout << "Error: Expected 3 outliers, found " << nOutliers << ".\n";
    testStatus = 1;
    }

  paramsTable->Delete();
#endif // 0

  haruspex->Delete();

  return testStatus;
}

<commit_msg>STYLE: use GenericMacros instead of couts in case of errors<commit_after>/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include "vtkDoubleArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkMultiCorrelativeStatistics.h"

//=============================================================================
int TestMultiCorrelativeStatistics( int, char *[] )
{
  int testStatus = 0;

  /* */
  double mingledData[] =
    {
    46, 45,
    47, 49,
    46, 47,
    46, 46,
    47, 46,
    47, 49,
    49, 49,
    47, 45,
    50, 50,
    46, 46,
    51, 50,
    48, 48,
    52, 54,
    48, 47,
    52, 52,
    49, 49,
    53, 54,
    50, 50,
    53, 54,
    50, 52,
    53, 53,
    50, 51,
    54, 54,
    49, 49,
    52, 52,
    50, 51,
    52, 52,
    49, 47,
    48, 48,
    48, 50,
    46, 48,
    47, 47
    };
  int nVals = 32;
  /*
  double mingledData[] =
    {
    1,
    5,
    11,
    10,
    9,
    7,
    11,
    11
    };
  int nVals = 4;
  */

  const char m0Name[] = "M0";
  vtkDoubleArray* dataset1Arr = vtkDoubleArray::New();
  dataset1Arr->SetNumberOfComponents( 1 );
  dataset1Arr->SetName( m0Name );

  const char m1Name[] = "M1";
  vtkDoubleArray* dataset2Arr = vtkDoubleArray::New();
  dataset2Arr->SetNumberOfComponents( 1 );
  dataset2Arr->SetName( m1Name );

  const char m2Name[] = "M2";
  vtkDoubleArray* dataset3Arr = vtkDoubleArray::New();
  dataset3Arr->SetNumberOfComponents( 1 );
  dataset3Arr->SetName( m2Name );

  for ( int i = 0; i < nVals; ++ i )
    {
    int ti = i << 1;
    dataset1Arr->InsertNextValue( mingledData[ti] );
    dataset2Arr->InsertNextValue( mingledData[ti + 1] );
    dataset3Arr->InsertNextValue( i != 12 ? -1. : -1.001 );
    }

  vtkTable* datasetTable = vtkTable::New();
  datasetTable->AddColumn( dataset1Arr );
  dataset1Arr->Delete();
  datasetTable->AddColumn( dataset2Arr );
  dataset2Arr->Delete();
  datasetTable->AddColumn( dataset3Arr );
  dataset3Arr->Delete();

  /*
  int nMetricPairs = 3;
  vtkStdString columnPairs[] = { m0Name, m1Name, m1Name, m0Name, m2Name, m1Name };
  double centers[] = { 49.2188, 49.5 };
  double covariance[] = { 5.98286, 7.54839, 6.14516 };
  double threshold = 4.;
  */

  vtkMultiCorrelativeStatistics* haruspex = vtkMultiCorrelativeStatistics::New();
  haruspex->SetInput( 0, datasetTable );

  datasetTable->Delete();

  // -- Select Column Pairs of Interest ( Learn Mode ) --
  haruspex->SetColumnStatus( m0Name, 1 );
  haruspex->SetColumnStatus( m1Name, 1 );
  haruspex->RequestSelectedColumns();
  haruspex->ResetAllColumnStates();
  haruspex->SetColumnStatus( m0Name, 1 );
  haruspex->SetColumnStatus( m1Name, 1 );
  haruspex->SetColumnStatus( m2Name, 1 );
  haruspex->SetColumnStatus( m2Name, 0 );
  haruspex->SetColumnStatus( m2Name, 1 );
  haruspex->RequestSelectedColumns();
  haruspex->RequestSelectedColumns(); // Try a duplicate entry. This should have no effect.
  haruspex->SetColumnStatus( m0Name, 0 );
  haruspex->SetColumnStatus( m2Name, 0 );
  haruspex->SetColumnStatus( "Metric 3", 1 ); // An invalid name. This should result in a request for metric 1's self-correlation.
  // haruspex->RequestSelectedColumns(); will get called in RequestData()

  // -- Test Learn Mode --
  haruspex->SetLearn( true );
  haruspex->SetDerive( true );
  haruspex->SetAssess( false );

  haruspex->Update();
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( haruspex->GetOutputDataObject( 1 ) );
  for ( unsigned int b = 0; b < outputMetaDS->GetNumberOfBlocks(); ++ b )
    {
    vtkTable* outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( b ) );
    //vtkIdType n = haruspex->GetSampleSize();
    if ( b == 0 )
      {
      cout << "Raw sums\n";
      }
    else
      {
      cout << "Request " << ( b - 1 ) << "\n";
      }

  /*
  cout << "## Calculated the following statistics ( "
       << n
       << " entries per column ):\n";
  for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
    {
    cout << "   (X, Y) = ("
         << outputMeta->GetValue( r, 0 ).ToString().c_str()
         << ", "
         << outputMeta->GetValue( r, 1 ).ToString().c_str()
         << ")";

    for ( int i = 2; i < 3; ++ i )
      {
      cout << ", "
           << outputMeta->GetColumnName( i )
           << "="
           << outputMeta->GetValue( r, i ).ToDouble();
      }
    cout << "\n";
    / * * /
    if ( outputMeta->GetValueByName( r,  "Linear Correlation" ).ToString() == vtkStdString( "valid" ) )
      {
      cout << "\n   Y = "
           << outputMeta->GetValueByName( r, "Slope Y/X" ).ToDouble()
           << " * X + "
           << outputMeta->GetValueByName( r, "Intersect Y/X" ).ToDouble()
           << ", X = "
           << outputMeta->GetValueByName( r, "Slope X/Y" ).ToDouble()
           << " * Y + "
           << outputMeta->GetValueByName( r, "Intersect X/Y" ).ToDouble()
           << ", corr. coeff.: "
           << outputMeta->GetValueByName( r, "Pearson r" ).ToDouble()
           << "\n";
      }
    else
      {
      cout << "\n   Degenerate input, linear correlation was not calculated.\n";
      }
      / * * /
    }
*/
    outputMeta->Dump();
    }

#if 0
  // -- Select Column Pairs of Interest ( Assess Mode ) --
  haruspex->ResetColumnPairs(); // Clear existing pairs
  haruspex->AddColumnPair( columnPairs[0], columnPairs[1] ); // A valid pair
#endif // 0

  // -- Test Assess Mode --
  vtkMultiBlockDataSet* paramsTables = vtkMultiBlockDataSet::New();
  paramsTables->ShallowCopy( outputMetaDS );

  haruspex->SetInput( 1, paramsTables );
  paramsTables->Delete();
  haruspex->SetLearn( false );
  haruspex->SetDerive( false ); // Do not recalculate nor rederive a model
  haruspex->SetAssess( true );
  haruspex->Update();

  vtkTable* outputData = haruspex->GetOutput();
  outputData->Dump();
#if 0
  int nOutliers = 0;
  int tableIdx[] = { 0, 1, 3 };
  cout << "   Found the following outliers:\n";
  for ( int i = 0; i < 3; ++ i )
    {
    cout << "   "
         << outputData->GetColumnName( tableIdx[i] );
    }
  cout << "\n";

  for ( vtkIdType r = 0; r < outputData->GetNumberOfRows(); ++ r )
    {
    if ( outputData->GetValue( r, tableIdx[2] ).ToDouble() > threshold )
      {
      ++ nOutliers;

      for ( int i = 0; i < 3; ++ i )
        {
        cout << "     "
             << outputData->GetValue( r,  tableIdx[i] ).ToString()
             << "    ";
        }
      cout << "\n";
      }
    }

  if ( nOutliers != 3 )
    {
    vtkGenericWarningMacro("Expected 3 outliers, found " << nOutliers << ".");
    testStatus = 1;
    }

  paramsTable->Delete();
#endif // 0

  haruspex->Delete();

  return testStatus;
}

<|endoftext|>


<commit_before>#include "bulkDataNTSenderFlow.h"
#include <iostream>
#include <ace/Get_Opt.h>

using namespace AcsBulkdata;

int main(int argc, char *argv[])
{
	char c;
	double send_time;
	unsigned int sleepPeriod=0;
	unsigned int dataSize=65000;
	ACE_Time_Value start_time, elapsed_time;

	LoggingProxy m_logger(0, 0, 31, 0);

	LoggingProxy::init (&m_logger);
    ACS_CHECK_LOGGER;

	// Parse the args
    ACE_Get_Opt get_opts (argc, argv, "w:s:");
    while(( c = get_opts()) != -1 ) {
    	switch(c) {
    	case 'w':
    		sleepPeriod = atoi(get_opts.opt_arg());
    		break;
    	case 's':
    		dataSize = atoi(get_opts.opt_arg());
    		break;
    	}
    }//while

	BulkDataNTSenderStream senderStream1("DefaultStream");

	BulkDataNTSenderFlow* flow0 = senderStream1.createFlow("00");
	BulkDataNTSenderFlow* flow1 = senderStream1.createFlow("01");

	sleep(1); //here we should wait for at least one receiver
	//std::cout << "press a key to start.." << std::endl;
	//getchar();

	unsigned char parm[]="123";

	flow0->startSend(parm, 3);

	//unsigned char data[]="Hello wrold !!!!";
	unsigned char *data= new unsigned char[dataSize];
	for (unsigned int i=0; i<dataSize; i++)
			data[i]=i;

	ACS_SHORT_LOG((LM_INFO, "Going to send: %d Bytes", dataSize));
	start_time = ACE_OS::gettimeofday();
	flow0->sendData(data, dataSize);
	elapsed_time = ACE_OS::gettimeofday() - start_time;
	send_time = (elapsed_time.sec()+( elapsed_time.usec() / 1000000. ));
	ACS_SHORT_LOG((LM_INFO, "Transfer rate: %f", (dataSize/(1024*1024))/send_time));

	flow1->sendData(data, dataSize);

	for (unsigned int i=0; i<dataSize; i++)
				data[i]=i%10;
	flow0->sendData(data, dataSize);
	flow1->sendData(data, dataSize);

	sleep(2);
	//std::cout << "press a key to send stop.." << std::endl;
	//getchar();
	flow0->stopSend();
	flow1->stopSend();

	if (sleepPeriod>0)
	{
		sleep(sleepPeriod);
	}
	else
	{
		std::cout << "press a key to exit.." << std::endl;
		getchar();
	}

	delete flow0;
// flow1 will be deleted when senderStream1 is deleted

}
<commit_msg>added comment that startSend is not called for state machine test purpose<commit_after>#include "bulkDataNTSenderFlow.h"
#include <iostream>
#include <ace/Get_Opt.h>

using namespace AcsBulkdata;

int main(int argc, char *argv[])
{
	char c;
	double send_time;
	unsigned int sleepPeriod=0;
	unsigned int dataSize=65000;
	ACE_Time_Value start_time, elapsed_time;

	LoggingProxy m_logger(0, 0, 31, 0);

	LoggingProxy::init (&m_logger);
    ACS_CHECK_LOGGER;

	// Parse the args
    ACE_Get_Opt get_opts (argc, argv, "w:s:");
    while(( c = get_opts()) != -1 ) {
    	switch(c) {
    	case 'w':
    		sleepPeriod = atoi(get_opts.opt_arg());
    		break;
    	case 's':
    		dataSize = atoi(get_opts.opt_arg());
    		break;
    	}
    }//while

	BulkDataNTSenderStream senderStream1("DefaultStream");

	BulkDataNTSenderFlow* flow0 = senderStream1.createFlow("00");
	BulkDataNTSenderFlow* flow1 = senderStream1.createFlow("01");

	sleep(1); //here we should wait for at least one receiver
	//std::cout << "press a key to start.." << std::endl;
	//getchar();

	unsigned char parm[]="123";

	flow0->startSend(parm, 3);

// for test purpose we do not invoke startSend
//	strcpy(parm, "abc");
//	flow1->startSend(parm, 3);

	//unsigned char data[]="Hello wrold !!!!";
	unsigned char *data= new unsigned char[dataSize];
	for (unsigned int i=0; i<dataSize; i++)
			data[i]=i;

	ACS_SHORT_LOG((LM_INFO, "Going to send: %d Bytes", dataSize));
	start_time = ACE_OS::gettimeofday();
	flow0->sendData(data, dataSize);
	elapsed_time = ACE_OS::gettimeofday() - start_time;
	send_time = (elapsed_time.sec()+( elapsed_time.usec() / 1000000. ));
	ACS_SHORT_LOG((LM_INFO, "Transfer rate: %f", (dataSize/(1024*1024))/send_time));

	flow1->sendData(data, dataSize);

	for (unsigned int i=0; i<dataSize; i++)
				data[i]=i%10;
	flow0->sendData(data, dataSize);
	flow1->sendData(data, dataSize);

	sleep(2);
	//std::cout << "press a key to send stop.." << std::endl;
	//getchar();
	flow0->stopSend();
	flow1->stopSend();

	if (sleepPeriod>0)
	{
		sleep(sleepPeriod);
	}
	else
	{
		std::cout << "press a key to exit.." << std::endl;
		getchar();
	}

	delete flow0;
// flow1 will be deleted when senderStream1 is deleted

}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Range_inl_
#define _Stroika_Foundation_Traversal_Range_inl_

#include    "../Debug/Assertions.h"
#include    "../Math/Overlap.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            /*
             ********************************************************************************
             RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_StaticDataMember_Buggy
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound   =   MIN;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound   =   MAX;
#endif

            /*
             ********************************************************************************
             ****************** RangeTraits::DefaultRangeTraits<T> **************************
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_StaticDataMember_Buggy
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kLowerBound   =   numeric_limits<T>::lowest ();
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kUpperBound   =   numeric_limits<T>::max ();
#endif

            /*
             ********************************************************************************
             ***************************** Range<T, TRAITS> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range ()
                : Range (TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const Range<T2, TRAITS>& src)
                : Range (src.GetLowerBound (), src.GetUpperBound (), src.GetLowerBoundOpenness (), src.GetUpperBoundOpenness ())
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end)
                : Range (begin, end, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (TRAITS::kUpperBound)
                , fEnd_ (TRAITS::kLowerBound)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end, Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (begin)
                , fEnd_ (end)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require  (TRAITS::kLowerBound <= TRAITS::kUpperBound);    // always required for class
                Require (TRAITS::kLowerBound <= begin);
                Require (begin <= end);
                Require (end <= TRAITS::kUpperBound);
#endif
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end, Openness lhsOpen, Openness rhsOpen)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, lhsOpen, rhsOpen)
            {
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Range<T, TRAITS>    Range<T, TRAITS>::FullRange ()
            {
                return Range<T, TRAITS> (
                           TraitsType::kLowerBound, TraitsType::kUpperBound,
                           TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
                       );
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::empty () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    fBegin_ > fEnd_ ?
                    true :
                    ((fBegin_ == fEnd_) ?
                     (fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen) :
                     false
                    )
                    ;
#else
                if (fBegin_ > fEnd_) {
                    // internal hack done in Range<T, TRAITS>::Range() - empty range - otherwise not possible to create this situation
                    return true;
                }
                else if (fBegin_ == fEnd_) {
                    return fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   typename Range<T, TRAITS>::UnsignedDifferenceType    Range<T, TRAITS>::GetDistanceSpanned () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    static_cast<UnsignedDifferenceType> (0) :
                    (fEnd_ - fBegin_)
                    ;
#else
                if (empty ()) {
                    return static_cast<UnsignedDifferenceType> (0);
                }
                return fEnd_ - fBegin_;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetMidpoint () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return GetLowerBound () + GetDistanceSpanned () / 2;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::Contains (const T& r) const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    false :
                    (
                        (fBegin_ < r and r < fEnd_) or
                        (fBeginOpenness_ == Openness::eClosed and r == fBegin_) or
                        (fEndOpenness_ == Openness::eClosed and r == fEnd_)
                    )
                    ;
#else
                if (empty ()) {
                    return false;
                }
                if (fBegin_ < r and r < fEnd_) {
                    return true;
                }
                if (fBeginOpenness_ == Openness::eClosed and r == fBegin_) {
                    return true;
                }
                if (fEndOpenness_ == Openness::eClosed and r == fEnd_) {
                    return true;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            inline  bool    Range<T, TRAITS>::Equals (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty ()) {
                    return rhs.empty ();
                }
                return fBegin_ == rhs.fBegin_ and fEnd_ == rhs.fEnd_ and fBeginOpenness_ == rhs.fBeginOpenness_ and fBeginOpenness_ == rhs.fBeginOpenness_;
            }
#if 0
            template    <typename T, typename TRAITS>
            bool    Range<T, TRAITS>::Overlaps (const Range<T, TRAITS>& rhs) const
            {
                /*
                 *  @todo   RETHINK - because Range has semantics of exclude end - make sure overlap usuage
                 *          here is correct??? Unsure -- LGP 2013-07-05
                 */
                return Math::Overlaps (
                           pair<T, T> (fBegin_, fEnd_),
                           pair<T, T> (rhs.fBegin_, rhs.fEnd_)
                       );
            }
#endif
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            bool    Range<T, TRAITS>::Intersects (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return false;
                }
                T   l   =   max (fBegin_, rhs.fBegin_);
                T   r   =   min (fEnd_, rhs.fEnd_);
                if (l < r) {
                    return true;
                }
                else if (l == r) {
                    // must check if the end that has 'l' for each Range that that end is closed. Contains()
                    // is a shortcut for that
                    return Contains (l) and rhs.Contains (l);
                }
                else {
                    return false;
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::Intersection (const Range<T, TRAITS>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return Range ();
                }
                T   l   =   max (fBegin_, rhs.fBegin_);
                T   r   =   min (fEnd_, rhs.fEnd_);
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    return Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                else {
                    return Range ();
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::UnionBounds (const Range<T, TRAITS>& rhs) const
            {
                if (empty ()) {
                    return rhs;
                }
                if (rhs.empty ()) {
                    return *this;
                }
                T   l   =   min (GetLowerBound (), rhs.GetLowerBound ());
                T   r   =   max (GetUpperBound (), rhs.GetUpperBound ());
                Range<T, TRAITS>   result;
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    result = Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                Ensure (result.GetLowerBound () <= GetLowerBound ());
                Ensure (result.GetLowerBound () <= GetUpperBound ());
                Ensure (result.GetLowerBound () <= rhs.GetLowerBound ());
                Ensure (result.GetLowerBound () <= rhs.GetUpperBound ());
                Ensure (result.GetUpperBound () >= GetLowerBound ());
                Ensure (result.GetUpperBound () >= GetUpperBound ());
                Ensure (result.GetUpperBound () >= rhs.GetLowerBound ());
                Ensure (result.GetUpperBound () >= rhs.GetUpperBound ());
                return result;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetLowerBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fBegin_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetLowerBoundOpenness () const
            {
                return fBeginOpenness_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetUpperBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fEnd_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetUpperBoundOpenness () const
            {
                return fEndOpenness_;
            }
            template    <typename T, typename TRAITS>
            template    <typename... ARGS>
            inline  Characters::String  Range<T, TRAITS>::Format (ARGS&& ... args) const
            {
                if (GetLowerBound () == GetUpperBound ()) {
                    return GetLowerBound ().Format (forward<ARGS> (args)...);
                }
                else {
                    return GetLowerBound ().Format (forward<ARGS> (args)...) + L" - " + GetUpperBound  ().Format (forward<ARGS> (args)...);
                }
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator== (const Range<T, TRAITS>& rhs) const
            {
                return Equals (rhs);
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator!= (const Range<T, TRAITS>& rhs) const
            {
                return not Equals (rhs);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Range_inl_ */
<commit_msg>fixed bug with Range() CTOR - from other template - accesses other type, so must use accessor<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Range_inl_
#define _Stroika_Foundation_Traversal_Range_inl_

#include    "../Debug/Assertions.h"
#include    "../Math/Overlap.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            /*
             ********************************************************************************
             RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_StaticDataMember_Buggy
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kLowerBound   =   MIN;
            template    <typename T, T MIN, T MAX , Openness LOWER_BOUND_OPEN, Openness UPPER_BOUND_OPEN, typename SIGNED_DIFF_TYPE, typename UNSIGNED_DIFF_TYPE>
            const T RangeTraits::ExplicitRangeTraits_Integral<T, MIN, MAX, LOWER_BOUND_OPEN, UPPER_BOUND_OPEN, SIGNED_DIFF_TYPE, UNSIGNED_DIFF_TYPE>::kUpperBound   =   MAX;
#endif

            /*
             ********************************************************************************
             ****************** RangeTraits::DefaultRangeTraits<T> **************************
             ********************************************************************************
             */
#if     qCompilerAndStdLib_constexpr_StaticDataMember_Buggy
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kLowerBound   =   numeric_limits<T>::lowest ();
            template    <typename T>
            const T RangeTraits::DefaultRangeTraits<T>::kUpperBound   =   numeric_limits<T>::max ();
#endif

            /*
             ********************************************************************************
             ***************************** Range<T, TRAITS> *********************************
             ********************************************************************************
             */
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range ()
                : Range (TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const Range<T2, TRAITS>& src)
                : Range (src.GetLowerBound (), src.GetUpperBound (), src.GetLowerBoundOpenness (), src.GetUpperBoundOpenness ())
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end)
                : Range (begin, end, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, TRAITS::kLowerBoundOpenness, TRAITS::kUpperBoundOpenness)
            {
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (TRAITS::kUpperBound)
                , fEnd_ (TRAITS::kLowerBound)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Ensure (empty ());
#endif
            }
            template    <typename T, typename TRAITS>
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            inline  Range<T, TRAITS>::Range (const T& begin, const T& end, Openness lhsOpen, Openness rhsOpen)
                : fBegin_ (begin)
                , fEnd_ (end)
                , fBeginOpenness_ (lhsOpen)
                , fEndOpenness_ (rhsOpen)
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require  (TRAITS::kLowerBound <= TRAITS::kUpperBound);    // always required for class
                Require (TRAITS::kLowerBound <= begin);
                Require (begin <= end);
                Require (end <= TRAITS::kUpperBound);
#endif
            }
            template    <typename T, typename TRAITS>
            inline  Range<T, TRAITS>::Range (const Memory::Optional<T>& begin, const Memory::Optional<T>& end, Openness lhsOpen, Openness rhsOpen)
                : Range (begin.IsPresent () ? *begin : TRAITS::kLowerBound, end.IsPresent () ? *end : TRAITS::kUpperBound, lhsOpen, rhsOpen)
            {
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Range<T, TRAITS>    Range<T, TRAITS>::FullRange ()
            {
                return Range<T, TRAITS> (
                           TraitsType::kLowerBound, TraitsType::kUpperBound,
                           TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
                       );
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::empty () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    fBegin_ > fEnd_ ?
                    true :
                    ((fBegin_ == fEnd_) ?
                     (fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen) :
                     false
                    )
                    ;
#else
                if (fBegin_ > fEnd_) {
                    // internal hack done in Range<T, TRAITS>::Range() - empty range - otherwise not possible to create this situation
                    return true;
                }
                else if (fBegin_ == fEnd_) {
                    return fBeginOpenness_ == Openness::eOpen and fEndOpenness_ == Openness::eOpen;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   typename Range<T, TRAITS>::UnsignedDifferenceType    Range<T, TRAITS>::GetDistanceSpanned () const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    static_cast<UnsignedDifferenceType> (0) :
                    (fEnd_ - fBegin_)
                    ;
#else
                if (empty ()) {
                    return static_cast<UnsignedDifferenceType> (0);
                }
                return fEnd_ - fBegin_;
#endif
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetMidpoint () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return GetLowerBound () + GetDistanceSpanned () / 2;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   bool    Range<T, TRAITS>::Contains (const T& r) const
            {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                return
                    empty () ?
                    false :
                    (
                        (fBegin_ < r and r < fEnd_) or
                        (fBeginOpenness_ == Openness::eClosed and r == fBegin_) or
                        (fEndOpenness_ == Openness::eClosed and r == fEnd_)
                    )
                    ;
#else
                if (empty ()) {
                    return false;
                }
                if (fBegin_ < r and r < fEnd_) {
                    return true;
                }
                if (fBeginOpenness_ == Openness::eClosed and r == fBegin_) {
                    return true;
                }
                if (fEndOpenness_ == Openness::eClosed and r == fEnd_) {
                    return true;
                }
                return false;
#endif
            }
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            inline  bool    Range<T, TRAITS>::Equals (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty ()) {
                    return rhs.empty ();
                }
                return fBegin_ == rhs.fBegin_ and fEnd_ == rhs.fEnd_ and fBeginOpenness_ == rhs.fBeginOpenness_ and fBeginOpenness_ == rhs.fBeginOpenness_;
            }
#if 0
            template    <typename T, typename TRAITS>
            bool    Range<T, TRAITS>::Overlaps (const Range<T, TRAITS>& rhs) const
            {
                /*
                 *  @todo   RETHINK - because Range has semantics of exclude end - make sure overlap usuage
                 *          here is correct??? Unsure -- LGP 2013-07-05
                 */
                return Math::Overlaps (
                           pair<T, T> (fBegin_, fEnd_),
                           pair<T, T> (rhs.fBegin_, rhs.fEnd_)
                       );
            }
#endif
            template    <typename T, typename TRAITS>
            template    <typename T2, typename TRAITS2>
            bool    Range<T, TRAITS>::Intersects (const Range<T2, TRAITS2>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return false;
                }
                T   l   =   max (fBegin_, rhs.GetLowerBound ());
                T   r   =   min (fEnd_, rhs.GetUpperBound ());
                if (l < r) {
                    return true;
                }
                else if (l == r) {
                    // must check if the end that has 'l' for each Range that that end is closed. Contains()
                    // is a shortcut for that
                    return Contains (l) and rhs.Contains (l);
                }
                else {
                    return false;
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::Intersection (const Range<T, TRAITS>& rhs) const
            {
                if (empty () or rhs.empty ()) {
                    return Range ();
                }
                T   l   =   max (fBegin_, rhs.fBegin_);
                T   r   =   min (fEnd_, rhs.fEnd_);
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    return Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                else {
                    return Range ();
                }
            }
            template    <typename T, typename TRAITS>
            Range<T, TRAITS> Range<T, TRAITS>::UnionBounds (const Range<T, TRAITS>& rhs) const
            {
                if (empty ()) {
                    return rhs;
                }
                if (rhs.empty ()) {
                    return *this;
                }
                T   l   =   min (GetLowerBound (), rhs.GetLowerBound ());
                T   r   =   max (GetUpperBound (), rhs.GetUpperBound ());
                Range<T, TRAITS>   result;
                if (l <= r) {
                    // lhs/rhs ends are closed iff BOTH lhs/rhs contains that point
                    Openness lhsO = Contains (l) and rhs.Contains (l) ? Openness::eClosed : Openness::eOpen;
                    Openness rhsO = Contains (r) and rhs.Contains (r) ? Openness::eClosed : Openness::eOpen;
                    result = Range<T, TRAITS> (l, r, lhsO, rhsO);
                }
                Ensure (result.GetLowerBound () <= GetLowerBound ());
                Ensure (result.GetLowerBound () <= GetUpperBound ());
                Ensure (result.GetLowerBound () <= rhs.GetLowerBound ());
                Ensure (result.GetLowerBound () <= rhs.GetUpperBound ());
                Ensure (result.GetUpperBound () >= GetLowerBound ());
                Ensure (result.GetUpperBound () >= GetUpperBound ());
                Ensure (result.GetUpperBound () >= rhs.GetLowerBound ());
                Ensure (result.GetUpperBound () >= rhs.GetUpperBound ());
                return result;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetLowerBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fBegin_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetLowerBoundOpenness () const
            {
                return fBeginOpenness_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   T    Range<T, TRAITS>::GetUpperBound () const
            {
#if     !qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (not empty ());
#endif
                return fEnd_;
            }
            template    <typename T, typename TRAITS>
            inline  constexpr   Openness    Range<T, TRAITS>::GetUpperBoundOpenness () const
            {
                return fEndOpenness_;
            }
            template    <typename T, typename TRAITS>
            template    <typename... ARGS>
            inline  Characters::String  Range<T, TRAITS>::Format (ARGS&& ... args) const
            {
                if (GetLowerBound () == GetUpperBound ()) {
                    return GetLowerBound ().Format (forward<ARGS> (args)...);
                }
                else {
                    return GetLowerBound ().Format (forward<ARGS> (args)...) + L" - " + GetUpperBound  ().Format (forward<ARGS> (args)...);
                }
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator== (const Range<T, TRAITS>& rhs) const
            {
                return Equals (rhs);
            }
            template    <typename T, typename TRAITS>
            inline  bool    Range<T, TRAITS>::operator!= (const Range<T, TRAITS>& rhs) const
            {
                return not Equals (rhs);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Range_inl_ */
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This benchmark attempts to measure the time to do a fullscreen clear, an axis-aligned partial
// clear, and a clear restricted to an axis-aligned rounded rect. The fullscreen and axis-aligned
// partial clears on the GPU should follow a fast path that maps to backend-specialized clear
// operations, whereas the rounded-rect clear cannot be.

#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkRRect.h"

class ClearBench : public Benchmark {
public:
    enum ClearType {
        kFull_ClearType,
        kPartial_ClearType,
        kComplex_ClearType
    };

    ClearBench(ClearType type) : fType(type) {}

protected:
    const char* onGetName() override {
        switch(fType) {
        case kFull_ClearType:
            return "Clear-Full";
        case kPartial_ClearType:
            return "Clear-Partial";
        case kComplex_ClearType:
            return "Clear-Complex";
        }
        SkASSERT(false);
        return "Unreachable";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        const SkColor color = SK_ColorBLUE;
        const SkRect partialClip = SkRect::MakeLTRB(50, 50, 400, 400);
        const SkRRect complexClip = SkRRect::MakeRectXY(partialClip, 15, 15);

        // TODO (michaelludwig): Any benefit to changing the clip geometry?
        for (int i = 0; i < loops; i++) {
            canvas->save();
            switch(fType) {
                case kPartial_ClearType:
                    canvas->clipRect(partialClip);
                    break;
                case kComplex_ClearType:
                    canvas->clipRRect(complexClip);
                    break;
                case kFull_ClearType:
                    // Don't add any extra clipping, since it defaults to the entire "device"
                    break;
            }

            canvas->clear(color);
            canvas->restore();
        }
    }

private:
    ClearType fType;
};

DEF_BENCH( return new ClearBench(ClearBench::kFull_ClearType); )
DEF_BENCH( return new ClearBench(ClearBench::kPartial_ClearType); )
DEF_BENCH( return new ClearBench(ClearBench::kComplex_ClearType); )
<commit_msg>Prevent op batching in clear benchmark<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This benchmark attempts to measure the time to do a fullscreen clear, an axis-aligned partial
// clear, and a clear restricted to an axis-aligned rounded rect. The fullscreen and axis-aligned
// partial clears on the GPU should follow a fast path that maps to backend-specialized clear
// operations, whereas the rounded-rect clear cannot be.

#include "Benchmark.h"

#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkRRect.h"

#include "GrRenderTargetContext.h"

static sk_sp<SkShader> make_shader() {
    static const SkPoint kPts[] = {{0, 0}, {10, 10}};
    static const SkColor kColors[] = {SK_ColorBLUE, SK_ColorWHITE};
    return SkGradientShader::MakeLinear(kPts, kColors, nullptr, 2, SkShader::kClamp_TileMode);
}

class ClearBench : public Benchmark {
public:
    enum ClearType {
        kFull_ClearType,
        kPartial_ClearType,
        kComplex_ClearType
    };

    ClearBench(ClearType type) : fType(type) {}

protected:
    const char* onGetName() override {
        switch(fType) {
        case kFull_ClearType:
            return "Clear-Full";
        case kPartial_ClearType:
            return "Clear-Partial";
        case kComplex_ClearType:
            return "Clear-Complex";
        }
        SkASSERT(false);
        return "Unreachable";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        static const SkRect kPartialClip = SkRect::MakeLTRB(50, 50, 400, 400);
        static const SkRRect kComplexClip = SkRRect::MakeRectXY(kPartialClip, 15, 15);
        // Small to limit fill cost, but intersects the clips to confound batching
        static const SkRect kInterruptRect = SkRect::MakeXYWH(200, 200, 3, 3);

        // For the draw that sits between consecutive clears, use a shader that is simple but
        // requires local coordinates so that Ganesh does not convert it into a solid color rect,
        // which could then turn into a scissored-clear behind the scenes.
        SkPaint interruptPaint;
        interruptPaint.setShader(make_shader());

        GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
        if (rtc) {
            // Tricks the GrRenderTargetOpList into thinking it cannot reset its draw op list on
            // a fullscreen clear. If we don't do this, fullscreen clear ops would be created and
            // constantly discard the previous iteration's op so execution would only invoke one
            // actual clear on the GPU (not what we want to measure).
            rtc->setNeedsStencil();
        }

        for (int i = 0; i < loops; i++) {
            canvas->save();
            switch(fType) {
                case kPartial_ClearType:
                    canvas->clipRect(kPartialClip);
                    break;
                case kComplex_ClearType:
                    canvas->clipRRect(kComplexClip);
                    break;
                case kFull_ClearType:
                    // Don't add any extra clipping, since it defaults to the entire "device"
                    break;
            }

            // The clear we care about measuring
            canvas->clear(SK_ColorBLUE);
            canvas->restore();

            // Perform as minimal a draw as possible that intersects with the clear region in
            // order to prevent the clear ops from being batched together.
            canvas->drawRect(kInterruptRect, interruptPaint);
        }
    }

private:
    ClearType fType;
};

DEF_BENCH( return new ClearBench(ClearBench::kFull_ClearType); )
DEF_BENCH( return new ClearBench(ClearBench::kPartial_ClearType); )
DEF_BENCH( return new ClearBench(ClearBench::kComplex_ClearType); )
<|endoftext|>