<commit_before>
#include "../../Flare.h"
#include "FlareHUDMenu.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareHUDMenu"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareHUDMenu::Construct(const FArguments& InArgs)
{
	// Data
	OwnerHUD = InArgs._OwnerHUD;
	TargetShip = NULL;
	Overheating = false;
	Burning = false;
	PowerOutage = false;
	PresentationFlashTime = 0.2f;
	TimeSinceOverheatChanged = PresentationFlashTime;
	TimeSinceOutageChanged = PresentationFlashTime;
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(OwnerHUD->GetOwner());

	// Style
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	.Padding(FMargin(0))
	[
		SNew(SVerticalBox)

		// Text notification box
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Fill)
		.VAlign(VAlign_Top)
		[
			SNew(SVerticalBox)

			// Overheating progress bar
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Top)
			[
				SNew(SHorizontalBox)

				// Icon
				+ SHorizontalBox::Slot()
				.AutoWidth()
				.Padding(Theme.ContentPadding)
				[
					SNew(SImage)
					.Image(FFlareStyleSet::GetIcon("Temperature"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColorNoAlpha)
				]

				// Bar
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SBox)
					.MinDesiredWidth(500)
					.HAlign(HAlign_Fill)
					.VAlign(VAlign_Center)
					[
						SNew(SProgressBar)
						.Style(&Theme.TemperatureBarStyle)
						.Percent(this, &SFlareHUDMenu::GetTemperatureProgress)
						.FillColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColorNoAlpha)
					]
				]

				// Text
				+ SHorizontalBox::Slot()
				.Padding(Theme.ContentPadding)
				[
					SNew(SBox)
					.MinDesiredWidth(100)
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.TextStyle(&Theme.NameFont)
						.Text(this, &SFlareHUDMenu::GetTemperature)
						.ColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColor)
					]
				]
			]

			// Overheating box
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			[
				SNew(SHorizontalBox)

				// Overheating icon
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SImage)
					.Image(FFlareStyleSet::GetIcon("HUD_Temperature"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOverheatColor, false)
				]

				// Overheating text
				+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock)
					.TextStyle(&Theme.TitleFont)
					.Text(LOCTEXT("Overheating", "OVERHEATING"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOverheatColor, true)
				]
			]

			// Outage box
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			[
				SNew(SVerticalBox)

				+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SHorizontalBox)

					// Outage icon
					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SImage)
						.Image(FFlareStyleSet::GetIcon("HUD_Power"))
						.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, false)
					]

					// Outage text
					+ SHorizontalBox::Slot()
					.AutoWidth()
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.TextStyle(&Theme.TitleFont)
						.Text(LOCTEXT("PowerOutage", "POWER OUTAGE"))
						.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, true)
					]
				]

				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Center)
				[
					SNew(STextBlock)
					.Text(this, &SFlareHUDMenu::GetOutageText)
					.TextStyle(&Theme.SubTitleFont)
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, true)
				]
			]
		]

		// Weapon panel
		+ SVerticalBox::Slot()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Bottom)
		.Padding(FMargin(0, 0, 0, 100))
		[
			SAssignNew(WeaponContainer, SVerticalBox)
		]

		// Status panel
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Bottom)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(TemperatureStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Temperature)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(PowerStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Power)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(PropulsionStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Propulsion)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(RCSStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_RCS)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(LifeSupportStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_LifeSupport)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(WeaponStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Weapon)
			]
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareHUDMenu::SetTargetShip(IFlareSpacecraftInterface* Target)
{
	// Set targets
	TargetShip = Target;
	TemperatureStatus->SetTargetShip(Target);
	PowerStatus->SetTargetShip(Target);
	PropulsionStatus->SetTargetShip(Target);
	RCSStatus->SetTargetShip(Target);
	LifeSupportStatus->SetTargetShip(Target);
	WeaponStatus->SetTargetShip(Target);
	AFlareSpacecraft* PlayerShip = Cast<AFlareSpacecraft>(Target);
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Update weapon list
	if (PlayerShip)
	{
		TArray<FFlareWeaponGroup*>& WeaponGroupList = PlayerShip->GetWeaponsSystem()->GetWeaponGroupList();
		TSharedPtr<SFlareSubsystemStatus> Temp;
		WeaponContainer->ClearChildren();

		// Add weapon indicators
		for (int32 i = 0; i < WeaponGroupList.Num(); i++)
		{
			WeaponContainer->AddSlot()
			.AutoHeight()
			[
				SNew(SFlareWeaponStatus)
				.PlayerShip(PlayerShip)
				.TargetWeaponGroupIndex(i)
			];
		}

		// No weapon
		WeaponContainer->AddSlot()
		.AutoHeight()
		[
			SNew(SFlareWeaponStatus)
			.PlayerShip(PlayerShip)
			.TargetWeaponGroupIndex(-1)
		];

		WeaponContainer->SetVisibility(EVisibility::Visible);
	}
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareHUDMenu::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	if (TargetShip)
	{
		// Is alive ?
		SetVisibility(TargetShip->GetDamageSystem()->IsAlive() ? EVisibility::Visible : EVisibility::Collapsed);

		// Overheating status
		TimeSinceOverheatChanged += InDeltaTime;
		Temperature = TargetShip->GetDamageSystem()->GetTemperature();
		OverheatTemperature = TargetShip->GetDamageSystem()->GetOverheatTemperature();

		// Alert the player if the ship is near the overheat temperature
		bool NewOverheating = (TargetShip->GetDamageSystem()->GetTemperature() > TargetShip->GetDamageSystem()->GetOverheatTemperature() * 0.95);
		if (NewOverheating != Overheating)
		{
			TimeSinceOverheatChanged = 0;
		}
		Overheating = NewOverheating;
		Burning = (TargetShip->GetDamageSystem()->GetTemperature() > TargetShip->GetDamageSystem()->GetBurnTemperature());

		// Outage status
		TimeSinceOutageChanged += InDeltaTime;
		bool NewPowerOutage = TargetShip->GetDamageSystem()->HasPowerOutage();
		if (NewPowerOutage != PowerOutage)
		{
			TimeSinceOutageChanged = 0;
		}
		PowerOutage = NewPowerOutage;
	}
}

TOptional<float> SFlareHUDMenu::GetTemperatureProgress() const
{
	float WidgetMin = 500.0f;
	float WidgetRange = OverheatTemperature - WidgetMin;
	return ((Temperature - WidgetMin) / WidgetRange);
}

FSlateColor SFlareHUDMenu::GetTemperatureColor() const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	float Distance = Temperature - 0.9f * OverheatTemperature;
	float Ratio = FMath::Clamp(FMath::Abs(Distance) / 10.0f, 0.0f, 1.0f);

	if (Distance < 0)
	{
		Ratio = 0.0f;
	}

	FLinearColor Color = FMath::Lerp(Theme.NeutralColor, Theme.EnemyColor, Ratio);
	Color.A = Theme.DefaultAlpha;
	return Color;
}

FSlateColor SFlareHUDMenu::GetTemperatureColorNoAlpha() const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	float Distance = Temperature - 0.9f * OverheatTemperature;
	float Ratio = FMath::Clamp(FMath::Abs(Distance) / 10.0f, 0.0f, 1.0f);

	if (Distance < 0)
	{
		Ratio = 0.0f;
	}

	return FMath::Lerp(Theme.NeutralColor, Theme.EnemyColor, Ratio);
}

FText SFlareHUDMenu::GetTemperature() const
{
	return FText::FromString(FString::Printf(TEXT("%4s K"), *FString::FromInt(Temperature)));
}

FSlateColor SFlareHUDMenu::GetOverheatColor(bool Text) const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	FLinearColor Color = Theme.EnemyColor;
	float Ratio = FMath::Clamp(TimeSinceOverheatChanged / PresentationFlashTime, 0.0f, 1.0f);
	Color.A *= (Overheating ? Ratio : (1 - Ratio));

	if (Text)
	{
		Color.A *= Theme.DefaultAlpha;
	}

	return Color;
}

FSlateColor SFlareHUDMenu::GetOutageColor(bool Text) const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	FLinearColor Color = Theme.NeutralColor;
	float Ratio = FMath::Clamp(TimeSinceOutageChanged / PresentationFlashTime, 0.0f, 1.0f);
	Color.A *= (PowerOutage ? Ratio : (1 - Ratio));

	if (Text)
	{
		Color.A *= Theme.DefaultAlpha;
	}

	return Color;
}

FText SFlareHUDMenu::GetOutageText() const
{
	if (TargetShip)
	{
		return FText::FromString(LOCTEXT("PwBackIn", "Back in ").ToString() + FString::FromInt(TargetShip->GetDamageSystem()->GetPowerOutageDuration() + 1) + " s");
	}
	else
	{
		return FText::FromString("");
	}
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Fixed weapon ordering on the HUD<commit_after>
#include "../../Flare.h"
#include "FlareHUDMenu.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareHUDMenu"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareHUDMenu::Construct(const FArguments& InArgs)
{
	// Data
	OwnerHUD = InArgs._OwnerHUD;
	TargetShip = NULL;
	Overheating = false;
	Burning = false;
	PowerOutage = false;
	PresentationFlashTime = 0.2f;
	TimeSinceOverheatChanged = PresentationFlashTime;
	TimeSinceOutageChanged = PresentationFlashTime;
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(OwnerHUD->GetOwner());

	// Style
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	.Padding(FMargin(0))
	[
		SNew(SVerticalBox)

		// Text notification box
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Fill)
		.VAlign(VAlign_Top)
		[
			SNew(SVerticalBox)

			// Overheating progress bar
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Top)
			[
				SNew(SHorizontalBox)

				// Icon
				+ SHorizontalBox::Slot()
				.AutoWidth()
				.Padding(Theme.ContentPadding)
				[
					SNew(SImage)
					.Image(FFlareStyleSet::GetIcon("Temperature"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColorNoAlpha)
				]

				// Bar
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SBox)
					.MinDesiredWidth(500)
					.HAlign(HAlign_Fill)
					.VAlign(VAlign_Center)
					[
						SNew(SProgressBar)
						.Style(&Theme.TemperatureBarStyle)
						.Percent(this, &SFlareHUDMenu::GetTemperatureProgress)
						.FillColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColorNoAlpha)
					]
				]

				// Text
				+ SHorizontalBox::Slot()
				.Padding(Theme.ContentPadding)
				[
					SNew(SBox)
					.MinDesiredWidth(100)
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.TextStyle(&Theme.NameFont)
						.Text(this, &SFlareHUDMenu::GetTemperature)
						.ColorAndOpacity(this, &SFlareHUDMenu::GetTemperatureColor)
					]
				]
			]

			// Overheating box
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			[
				SNew(SHorizontalBox)

				// Overheating icon
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SImage)
					.Image(FFlareStyleSet::GetIcon("HUD_Temperature"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOverheatColor, false)
				]

				// Overheating text
				+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock)
					.TextStyle(&Theme.TitleFont)
					.Text(LOCTEXT("Overheating", "OVERHEATING"))
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOverheatColor, true)
				]
			]

			// Outage box
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign(HAlign_Center)
			[
				SNew(SVerticalBox)

				+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SHorizontalBox)

					// Outage icon
					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SImage)
						.Image(FFlareStyleSet::GetIcon("HUD_Power"))
						.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, false)
					]

					// Outage text
					+ SHorizontalBox::Slot()
					.AutoWidth()
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.TextStyle(&Theme.TitleFont)
						.Text(LOCTEXT("PowerOutage", "POWER OUTAGE"))
						.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, true)
					]
				]

				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Center)
				[
					SNew(STextBlock)
					.Text(this, &SFlareHUDMenu::GetOutageText)
					.TextStyle(&Theme.SubTitleFont)
					.ColorAndOpacity(this, &SFlareHUDMenu::GetOutageColor, true)
				]
			]
		]

		// Weapon panel
		+ SVerticalBox::Slot()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Bottom)
		.Padding(FMargin(0, 0, 0, 100))
		[
			SAssignNew(WeaponContainer, SVerticalBox)
		]

		// Status panel
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Bottom)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(TemperatureStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Temperature)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(PowerStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Power)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(PropulsionStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Propulsion)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(RCSStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_RCS)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(LifeSupportStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_LifeSupport)
			]

			+ SHorizontalBox::Slot().AutoWidth()
			[
				SAssignNew(WeaponStatus, SFlareSubsystemStatus).Subsystem(EFlareSubsystem::SYS_Weapon)
			]
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareHUDMenu::SetTargetShip(IFlareSpacecraftInterface* Target)
{
	// Set targets
	TargetShip = Target;
	TemperatureStatus->SetTargetShip(Target);
	PowerStatus->SetTargetShip(Target);
	PropulsionStatus->SetTargetShip(Target);
	RCSStatus->SetTargetShip(Target);
	LifeSupportStatus->SetTargetShip(Target);
	WeaponStatus->SetTargetShip(Target);
	AFlareSpacecraft* PlayerShip = Cast<AFlareSpacecraft>(Target);
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Update weapon list
	if (PlayerShip)
	{
		TArray<FFlareWeaponGroup*>& WeaponGroupList = PlayerShip->GetWeaponsSystem()->GetWeaponGroupList();
		TSharedPtr<SFlareSubsystemStatus> Temp;
		WeaponContainer->ClearChildren();

		// Add weapon indicators
		for (int32 i = WeaponGroupList.Num() - 1; i >= 0; i--)
		{
			WeaponContainer->AddSlot()
			.AutoHeight()
			[
				SNew(SFlareWeaponStatus)
				.PlayerShip(PlayerShip)
				.TargetWeaponGroupIndex(i)
			];
		}

		// No weapon
		WeaponContainer->AddSlot()
		.AutoHeight()
		[
			SNew(SFlareWeaponStatus)
			.PlayerShip(PlayerShip)
			.TargetWeaponGroupIndex(-1)
		];

		WeaponContainer->SetVisibility(EVisibility::Visible);
	}
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareHUDMenu::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	if (TargetShip)
	{
		// Is alive ?
		SetVisibility(TargetShip->GetDamageSystem()->IsAlive() ? EVisibility::Visible : EVisibility::Collapsed);

		// Overheating status
		TimeSinceOverheatChanged += InDeltaTime;
		Temperature = TargetShip->GetDamageSystem()->GetTemperature();
		OverheatTemperature = TargetShip->GetDamageSystem()->GetOverheatTemperature();

		// Alert the player if the ship is near the overheat temperature
		bool NewOverheating = (TargetShip->GetDamageSystem()->GetTemperature() > TargetShip->GetDamageSystem()->GetOverheatTemperature() * 0.95);
		if (NewOverheating != Overheating)
		{
			TimeSinceOverheatChanged = 0;
		}
		Overheating = NewOverheating;
		Burning = (TargetShip->GetDamageSystem()->GetTemperature() > TargetShip->GetDamageSystem()->GetBurnTemperature());

		// Outage status
		TimeSinceOutageChanged += InDeltaTime;
		bool NewPowerOutage = TargetShip->GetDamageSystem()->HasPowerOutage();
		if (NewPowerOutage != PowerOutage)
		{
			TimeSinceOutageChanged = 0;
		}
		PowerOutage = NewPowerOutage;
	}
}

TOptional<float> SFlareHUDMenu::GetTemperatureProgress() const
{
	float WidgetMin = 500.0f;
	float WidgetRange = OverheatTemperature - WidgetMin;
	return ((Temperature - WidgetMin) / WidgetRange);
}

FSlateColor SFlareHUDMenu::GetTemperatureColor() const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	float Distance = Temperature - 0.9f * OverheatTemperature;
	float Ratio = FMath::Clamp(FMath::Abs(Distance) / 10.0f, 0.0f, 1.0f);

	if (Distance < 0)
	{
		Ratio = 0.0f;
	}

	FLinearColor Color = FMath::Lerp(Theme.NeutralColor, Theme.EnemyColor, Ratio);
	Color.A = Theme.DefaultAlpha;
	return Color;
}

FSlateColor SFlareHUDMenu::GetTemperatureColorNoAlpha() const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	float Distance = Temperature - 0.9f * OverheatTemperature;
	float Ratio = FMath::Clamp(FMath::Abs(Distance) / 10.0f, 0.0f, 1.0f);

	if (Distance < 0)
	{
		Ratio = 0.0f;
	}

	return FMath::Lerp(Theme.NeutralColor, Theme.EnemyColor, Ratio);
}

FText SFlareHUDMenu::GetTemperature() const
{
	return FText::FromString(FString::Printf(TEXT("%4s K"), *FString::FromInt(Temperature)));
}

FSlateColor SFlareHUDMenu::GetOverheatColor(bool Text) const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	FLinearColor Color = Theme.EnemyColor;
	float Ratio = FMath::Clamp(TimeSinceOverheatChanged / PresentationFlashTime, 0.0f, 1.0f);
	Color.A *= (Overheating ? Ratio : (1 - Ratio));

	if (Text)
	{
		Color.A *= Theme.DefaultAlpha;
	}

	return Color;
}

FSlateColor SFlareHUDMenu::GetOutageColor(bool Text) const
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	FLinearColor Color = Theme.NeutralColor;
	float Ratio = FMath::Clamp(TimeSinceOutageChanged / PresentationFlashTime, 0.0f, 1.0f);
	Color.A *= (PowerOutage ? Ratio : (1 - Ratio));

	if (Text)
	{
		Color.A *= Theme.DefaultAlpha;
	}

	return Color;
}

FText SFlareHUDMenu::GetOutageText() const
{
	if (TargetShip)
	{
		return FText::FromString(LOCTEXT("PwBackIn", "Back in ").ToString() + FString::FromInt(TargetShip->GetDamageSystem()->GetPowerOutageDuration() + 1) + " s");
	}
	else
	{
		return FText::FromString("");
	}
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>
#pragma once

#include "journal/method.hpp"

#include <list>

#include "glog/logging.h"
#include "journal/recorder.hpp"

namespace principia {
namespace journal {

template<typename Profile>
Method<Profile>::Method() {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    LogMethodIfDebug();
  }
}

template<typename Profile>
template<typename P, typename>
Method<Profile>::Method(typename P::In const& in) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    Profile::Fill(in, message_.get());
    LogMethodIfDebug();
  }
}

template <typename Profile>
template <typename P, typename>
Method<Profile>::Method(typename P::Out const& out) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    out_filler_ = [this, out]() { Profile::Fill(out, message_.get()); };
    LogMethodIfDebug();
  }
}

template<typename Profile>
template<typename P, typename, typename>
Method<Profile>::Method(typename P::In const& in, typename P::Out const& out) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    out_filler_ = [this, out]() { Profile::Fill(out, message_.get()); };
    Profile::Fill(in, message_.get());
    LogMethodIfDebug();
  }
}

template<typename Profile>
Method<Profile>::~Method() {
  CHECK(returned_);
  if (Recorder::active_recorder_ != nullptr) {
    if (out_filler_ != nullptr) {
      out_filler_();
    }
    serialization::Method method;
    method.SetAllocatedExtension(
        Profile::Message::extension, message_.release());
    Recorder::active_recorder_->Write(method);
  }
}

template<typename Profile>
void Method<Profile>::Return() {
  CHECK(!returned_);
  returned_ = true;
}

template<typename Profile>
template<typename P, typename>
typename P::Return Method<Profile>::Return(
    typename P::Return const& result) {
  CHECK(!returned_);
  returned_ = true;
  if (Recorder::active_recorder_ != nullptr) {
    Profile::Fill(result, message_.get());
  }
  return result;
}

template<typename Profile>
void Method<Profile>::LogMethodIfDebug() {
  if (Recorder::active_recorder_->verbose_) {
    LOG(INFO) << message_->GetDescriptor()->name() << "\n"
              << message_->DebugString();
    google::FlushLogFiles(google::INFO);
  }
}

}  // namespace journal
}  // namespace principia
<commit_msg>Spaces.<commit_after>
#pragma once

#include "journal/method.hpp"

#include <list>

#include "glog/logging.h"
#include "journal/recorder.hpp"

namespace principia {
namespace journal {

template<typename Profile>
Method<Profile>::Method() {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    LogMethodIfDebug();
  }
}

template<typename Profile>
template<typename P, typename>
Method<Profile>::Method(typename P::In const& in) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    Profile::Fill(in, message_.get());
    LogMethodIfDebug();
  }
}

template<typename Profile>
template<typename P, typename>
Method<Profile>::Method(typename P::Out const& out) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    out_filler_ = [this, out]() { Profile::Fill(out, message_.get()); };
    LogMethodIfDebug();
  }
}

template<typename Profile>
template<typename P, typename, typename>
Method<Profile>::Method(typename P::In const& in, typename P::Out const& out) {
  if (Recorder::active_recorder_ != nullptr) {
    message_ = std::make_unique<typename Profile::Message>();
    out_filler_ = [this, out]() { Profile::Fill(out, message_.get()); };
    Profile::Fill(in, message_.get());
    LogMethodIfDebug();
  }
}

template<typename Profile>
Method<Profile>::~Method() {
  CHECK(returned_);
  if (Recorder::active_recorder_ != nullptr) {
    if (out_filler_ != nullptr) {
      out_filler_();
    }
    serialization::Method method;
    method.SetAllocatedExtension(
        Profile::Message::extension, message_.release());
    Recorder::active_recorder_->Write(method);
  }
}

template<typename Profile>
void Method<Profile>::Return() {
  CHECK(!returned_);
  returned_ = true;
}

template<typename Profile>
template<typename P, typename>
typename P::Return Method<Profile>::Return(
    typename P::Return const& result) {
  CHECK(!returned_);
  returned_ = true;
  if (Recorder::active_recorder_ != nullptr) {
    Profile::Fill(result, message_.get());
  }
  return result;
}

template<typename Profile>
void Method<Profile>::LogMethodIfDebug() {
  if (Recorder::active_recorder_->verbose_) {
    LOG(INFO) << message_->GetDescriptor()->name() << "\n"
              << message_->DebugString();
    google::FlushLogFiles(google::INFO);
  }
}

}  // namespace journal
}  // namespace principia
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: prnsave.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:49:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_PRNSAVE_HXX
#define SC_PRNSAVE_HXX

#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

#include <vector>

class ScRange;

class ScPrintSaverTab
{
    typedef ::std::vector< ScRange > ScRangeVec;

    ScRangeVec  maPrintRanges;      // Array
    ScRange*    mpRepeatCol;        // einzeln
    ScRange*    mpRepeatRow;        // einzeln
    BOOL        mbEntireSheet;

public:
            ScPrintSaverTab();
            ~ScPrintSaverTab();

    void            SetAreas( const ScRangeVec& rRanges, BOOL bEntireSheet );
    void            SetRepeat( const ScRange* pCol, const ScRange* pRow );

    const ScRangeVec&   GetPrintRanges() const  { return maPrintRanges; }
    BOOL                IsEntireSheet() const   { return mbEntireSheet; }
    const ScRange*      GetRepeatCol() const    { return mpRepeatCol; }
    const ScRange*      GetRepeatRow() const    { return mpRepeatRow; }

    BOOL    operator==( const ScPrintSaverTab& rCmp ) const;
};

class ScPrintRangeSaver
{
    SCTAB               nTabCount;
    ScPrintSaverTab*    pData;      // Array

public:
            ScPrintRangeSaver( SCTAB nCount );
            ~ScPrintRangeSaver();

    SCTAB                   GetTabCount() const     { return nTabCount; }
    ScPrintSaverTab&        GetTabData(SCTAB nTab);
    const ScPrintSaverTab&  GetTabData(SCTAB nTab) const;

    BOOL    operator==( const ScPrintRangeSaver& rCmp ) const;
};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.4.700); FILE MERGED 2008/04/01 15:29:39 thb 1.4.700.3: #i85898# Stripping all external header guards 2008/04/01 12:36:00 thb 1.4.700.2: #i85898# Stripping all external header guards 2008/03/31 17:13:33 rt 1.4.700.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: prnsave.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SC_PRNSAVE_HXX
#define SC_PRNSAVE_HXX

#include "address.hxx"
#include <tools/solar.h>

#include <vector>

class ScRange;

class ScPrintSaverTab
{
    typedef ::std::vector< ScRange > ScRangeVec;

    ScRangeVec  maPrintRanges;      // Array
    ScRange*    mpRepeatCol;        // einzeln
    ScRange*    mpRepeatRow;        // einzeln
    BOOL        mbEntireSheet;

public:
            ScPrintSaverTab();
            ~ScPrintSaverTab();

    void            SetAreas( const ScRangeVec& rRanges, BOOL bEntireSheet );
    void            SetRepeat( const ScRange* pCol, const ScRange* pRow );

    const ScRangeVec&   GetPrintRanges() const  { return maPrintRanges; }
    BOOL                IsEntireSheet() const   { return mbEntireSheet; }
    const ScRange*      GetRepeatCol() const    { return mpRepeatCol; }
    const ScRange*      GetRepeatRow() const    { return mpRepeatRow; }

    BOOL    operator==( const ScPrintSaverTab& rCmp ) const;
};

class ScPrintRangeSaver
{
    SCTAB               nTabCount;
    ScPrintSaverTab*    pData;      // Array

public:
            ScPrintRangeSaver( SCTAB nCount );
            ~ScPrintRangeSaver();

    SCTAB                   GetTabCount() const     { return nTabCount; }
    ScPrintSaverTab&        GetTabData(SCTAB nTab);
    const ScPrintSaverTab&  GetTabData(SCTAB nTab) const;

    BOOL    operator==( const ScPrintRangeSaver& rCmp ) const;
};

#endif

<|endoftext|>


<commit_before>//===- NativeFormatting.cpp - Low level formatting helpers -------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/NativeFormatting.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Format.h"

using namespace llvm;

template<typename T, std::size_t N>
static int format_to_buffer(T Value, char (&Buffer)[N]) {
  char *EndPtr = std::end(Buffer);
  char *CurPtr = EndPtr;

  do {
    *--CurPtr = '0' + char(Value % 10);
    Value /= 10;
  } while (Value);
  return EndPtr - CurPtr;
}

static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
  assert(!Buffer.empty());

  ArrayRef<char> ThisGroup;
  int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
  ThisGroup = Buffer.take_front(InitialDigits);
  S.write(ThisGroup.data(), ThisGroup.size());

  Buffer = Buffer.drop_front(InitialDigits);
  assert(Buffer.size() % 3 == 0);
  while (!Buffer.empty()) {
    S << ',';
    ThisGroup = Buffer.take_front(3);
    S.write(ThisGroup.data(), 3);
    Buffer = Buffer.drop_front(3);
  }
}

template <typename T>
static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
                                IntegerStyle Style, bool IsNegative) {
  static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");

  char NumberBuffer[128];
  std::memset(NumberBuffer, '0', sizeof(NumberBuffer));

  size_t Len = 0;
  Len = format_to_buffer(N, NumberBuffer);

  if (IsNegative)
    S << '-';

  if (Len < MinDigits && Style != IntegerStyle::Number) {
    for (size_t I = Len; I < MinDigits; ++I)
      S << '0';
  }

  if (Style == IntegerStyle::Number) {
    writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
  } else {
    S.write(std::end(NumberBuffer) - Len, Len);
  }
}

template <typename T>
static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
                           IntegerStyle Style, bool IsNegative = false) {
  // Output using 32-bit div/mod if possible.
  if (N == static_cast<uint32_t>(N))
    write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
                        IsNegative);
  else
    write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
}

template <typename T>
static void write_signed(raw_ostream &S, T N, size_t MinDigits,
                         IntegerStyle Style) {
  static_assert(std::is_signed<T>::value, "Value is not signed!");

  using UnsignedT = typename std::make_unsigned<T>::type;

  if (N >= 0) {
    write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
    return;
  }

  UnsignedT UN = -(UnsignedT)N;
  write_unsigned(S, UN, MinDigits, Style, true);
}

void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
                     Optional<size_t> Width) {
  const size_t kMaxWidth = 128u;

  size_t W = std::min(kMaxWidth, Width.getValueOr(0u));

  unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
  bool Prefix = (Style == HexPrintStyle::PrefixLower ||
                 Style == HexPrintStyle::PrefixUpper);
  bool Upper =
      (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
  unsigned PrefixChars = Prefix ? 2 : 0;
  unsigned NumChars =
      std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);

  char NumberBuffer[kMaxWidth];
  ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
  if (Prefix)
    NumberBuffer[1] = 'x';
  char *EndPtr = NumberBuffer + NumChars;
  char *CurPtr = EndPtr;
  while (N) {
    unsigned char x = static_cast<unsigned char>(N) % 16;
    *--CurPtr = hexdigit(x, !Upper);
    N /= 16;
  }

  S.write(NumberBuffer, NumChars);
}

void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
                        Optional<size_t> Precision) {
  size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));

  if (std::isnan(N)) {
    S << "nan";
    return;
  } else if (std::isinf(N)) {
    S << "INF";
    return;
  }

  char Letter;
  if (Style == FloatStyle::Exponent)
    Letter = 'e';
  else if (Style == FloatStyle::ExponentUpper)
    Letter = 'E';
  else
    Letter = 'f';

  SmallString<8> Spec;
  llvm::raw_svector_ostream Out(Spec);
  Out << "%." << Prec << Letter;

  if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
#ifdef _WIN32
// On MSVCRT and compatible, output of %e is incompatible to Posix
// by default. Number of exponent digits should be at least 2. "%+03d"
// FIXME: Implement our formatter to here or Support/Format.h!
#if defined(__MINGW32__)
    // FIXME: It should be generic to C++11.
    if (N == 0.0 && std::signbit(N)) {
      char NegativeZero[] = "-0.000000e+00";
      if (Style == FloatStyle::ExponentUpper)
        NegativeZero[strlen(NegativeZero) - 4] = 'E';
      S << NegativeZero;
      return;
    }
#else
    int fpcl = _fpclass(N);

    // negative zero
    if (fpcl == _FPCLASS_NZ) {
      char NegativeZero[] = "-0.000000e+00";
      if (Style == FloatStyle::ExponentUpper)
        NegativeZero[strlen(NegativeZero) - 4] = 'E';
      S << NegativeZero;
      return;
    }
#endif

    char buf[32];
    unsigned len;
    len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
    if (len <= sizeof(buf) - 2) {
      if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
          buf[len - 3] == '0') {
        int cs = buf[len - 4];
        if (cs == '+' || cs == '-') {
          int c1 = buf[len - 2];
          int c0 = buf[len - 1];
          if (isdigit(static_cast<unsigned char>(c1)) &&
              isdigit(static_cast<unsigned char>(c0))) {
            // Trim leading '0': "...e+012" -> "...e+12\0"
            buf[len - 3] = c1;
            buf[len - 2] = c0;
            buf[--len] = 0;
          }
        }
      }
      S << buf;
      return;
    }
#endif
  }

  if (Style == FloatStyle::Percent)
    N *= 100.0;

  char Buf[32];
  unsigned Len;
  Len = format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
  if (Style == FloatStyle::Percent)
    ++Len;
  S << Buf;
  if (Style == FloatStyle::Percent)
    S << '%';
}

bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
  return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
}

size_t llvm::getDefaultPrecision(FloatStyle Style) {
  switch (Style) {
  case FloatStyle::Exponent:
  case FloatStyle::ExponentUpper:
    return 6; // Number of decimal places.
  case FloatStyle::Fixed:
  case FloatStyle::Percent:
    return 2; // Number of decimal places.
  }
  LLVM_BUILTIN_UNREACHABLE;
}
<commit_msg>Cherry-pick r322885 from LLVM.<commit_after>//===- NativeFormatting.cpp - Low level formatting helpers -------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/NativeFormatting.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Format.h"

#include <float.h>

using namespace llvm;

template<typename T, std::size_t N>
static int format_to_buffer(T Value, char (&Buffer)[N]) {
  char *EndPtr = std::end(Buffer);
  char *CurPtr = EndPtr;

  do {
    *--CurPtr = '0' + char(Value % 10);
    Value /= 10;
  } while (Value);
  return EndPtr - CurPtr;
}

static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
  assert(!Buffer.empty());

  ArrayRef<char> ThisGroup;
  int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
  ThisGroup = Buffer.take_front(InitialDigits);
  S.write(ThisGroup.data(), ThisGroup.size());

  Buffer = Buffer.drop_front(InitialDigits);
  assert(Buffer.size() % 3 == 0);
  while (!Buffer.empty()) {
    S << ',';
    ThisGroup = Buffer.take_front(3);
    S.write(ThisGroup.data(), 3);
    Buffer = Buffer.drop_front(3);
  }
}

template <typename T>
static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
                                IntegerStyle Style, bool IsNegative) {
  static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");

  char NumberBuffer[128];
  std::memset(NumberBuffer, '0', sizeof(NumberBuffer));

  size_t Len = 0;
  Len = format_to_buffer(N, NumberBuffer);

  if (IsNegative)
    S << '-';

  if (Len < MinDigits && Style != IntegerStyle::Number) {
    for (size_t I = Len; I < MinDigits; ++I)
      S << '0';
  }

  if (Style == IntegerStyle::Number) {
    writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
  } else {
    S.write(std::end(NumberBuffer) - Len, Len);
  }
}

template <typename T>
static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
                           IntegerStyle Style, bool IsNegative = false) {
  // Output using 32-bit div/mod if possible.
  if (N == static_cast<uint32_t>(N))
    write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
                        IsNegative);
  else
    write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
}

template <typename T>
static void write_signed(raw_ostream &S, T N, size_t MinDigits,
                         IntegerStyle Style) {
  static_assert(std::is_signed<T>::value, "Value is not signed!");

  using UnsignedT = typename std::make_unsigned<T>::type;

  if (N >= 0) {
    write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
    return;
  }

  UnsignedT UN = -(UnsignedT)N;
  write_unsigned(S, UN, MinDigits, Style, true);
}

void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_unsigned(S, N, MinDigits, Style);
}

void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
                         IntegerStyle Style) {
  write_signed(S, N, MinDigits, Style);
}

void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
                     Optional<size_t> Width) {
  const size_t kMaxWidth = 128u;

  size_t W = std::min(kMaxWidth, Width.getValueOr(0u));

  unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
  bool Prefix = (Style == HexPrintStyle::PrefixLower ||
                 Style == HexPrintStyle::PrefixUpper);
  bool Upper =
      (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
  unsigned PrefixChars = Prefix ? 2 : 0;
  unsigned NumChars =
      std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);

  char NumberBuffer[kMaxWidth];
  ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
  if (Prefix)
    NumberBuffer[1] = 'x';
  char *EndPtr = NumberBuffer + NumChars;
  char *CurPtr = EndPtr;
  while (N) {
    unsigned char x = static_cast<unsigned char>(N) % 16;
    *--CurPtr = hexdigit(x, !Upper);
    N /= 16;
  }

  S.write(NumberBuffer, NumChars);
}

void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
                        Optional<size_t> Precision) {
  size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));

  if (std::isnan(N)) {
    S << "nan";
    return;
  } else if (std::isinf(N)) {
    S << "INF";
    return;
  }

  char Letter;
  if (Style == FloatStyle::Exponent)
    Letter = 'e';
  else if (Style == FloatStyle::ExponentUpper)
    Letter = 'E';
  else
    Letter = 'f';

  SmallString<8> Spec;
  llvm::raw_svector_ostream Out(Spec);
  Out << "%." << Prec << Letter;

  if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
#ifdef _WIN32
// On MSVCRT and compatible, output of %e is incompatible to Posix
// by default. Number of exponent digits should be at least 2. "%+03d"
// FIXME: Implement our formatter to here or Support/Format.h!
#if defined(__MINGW32__)
    // FIXME: It should be generic to C++11.
    if (N == 0.0 && std::signbit(N)) {
      char NegativeZero[] = "-0.000000e+00";
      if (Style == FloatStyle::ExponentUpper)
        NegativeZero[strlen(NegativeZero) - 4] = 'E';
      S << NegativeZero;
      return;
    }
#else
    int fpcl = _fpclass(N);

    // negative zero
    if (fpcl == _FPCLASS_NZ) {
      char NegativeZero[] = "-0.000000e+00";
      if (Style == FloatStyle::ExponentUpper)
        NegativeZero[strlen(NegativeZero) - 4] = 'E';
      S << NegativeZero;
      return;
    }
#endif

    char buf[32];
    unsigned len;
    len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
    if (len <= sizeof(buf) - 2) {
      if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
          buf[len - 3] == '0') {
        int cs = buf[len - 4];
        if (cs == '+' || cs == '-') {
          int c1 = buf[len - 2];
          int c0 = buf[len - 1];
          if (isdigit(static_cast<unsigned char>(c1)) &&
              isdigit(static_cast<unsigned char>(c0))) {
            // Trim leading '0': "...e+012" -> "...e+12\0"
            buf[len - 3] = c1;
            buf[len - 2] = c0;
            buf[--len] = 0;
          }
        }
      }
      S << buf;
      return;
    }
#endif
  }

  if (Style == FloatStyle::Percent)
    N *= 100.0;

  char Buf[32];
  unsigned Len;
  Len = format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
  if (Style == FloatStyle::Percent)
    ++Len;
  S << Buf;
  if (Style == FloatStyle::Percent)
    S << '%';
}

bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
  return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
}

size_t llvm::getDefaultPrecision(FloatStyle Style) {
  switch (Style) {
  case FloatStyle::Exponent:
  case FloatStyle::ExponentUpper:
    return 6; // Number of decimal places.
  case FloatStyle::Fixed:
  case FloatStyle::Percent:
    return 2; // Number of decimal places.
  }
  LLVM_BUILTIN_UNREACHABLE;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2006 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csutil/memheap.h"
#include "csutil/scopedlock.h"
#include "csutil/sysfunc.h"

namespace CS
{
  namespace Memory
  {
    // dlmalloc functions
    extern "C"
    {
      typedef void* mspace;
      mspace create_mspace(size_t capacity, int locked);
      size_t destroy_mspace(mspace msp);
      void* mspace_malloc(mspace msp, size_t bytes);
      void mspace_free(mspace msp, void* mem);
      void* mspace_realloc(mspace msp, void* mem, size_t newsize);
      int mspace_trim(mspace msp, size_t pad);
      size_t mspace_footprint(mspace msp);
    };

    Heap::Heap()
    {
      mspace = create_mspace (0, 1);
    }
    Heap::~Heap()
    {
      destroy_mspace (mspace);
    }

    void* Heap::Alloc (const size_t n)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_malloc (mspace, n);
    }
    void Heap::Free (void* p)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_free (mspace, p);
    }
    void* Heap::Realloc (void* p, size_t newSize)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_realloc (mspace, p, newSize);
    }
    void Heap::Trim (size_t pad)
    {
      mspace_trim (mspace, pad);
    }
    size_t Heap::Footprint ()
    {
      return mspace_footprint (mspace);
    }
  } // namespace Memory
} // namespace CS

<commit_msg>Also lock CS::Memory::Heap during Trim() and Footprint()<commit_after>/*
    Copyright (C) 2006 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csutil/memheap.h"
#include "csutil/scopedlock.h"
#include "csutil/sysfunc.h"

namespace CS
{
  namespace Memory
  {
    // dlmalloc functions
    extern "C"
    {
      typedef void* mspace;
      mspace create_mspace(size_t capacity, int locked);
      size_t destroy_mspace(mspace msp);
      void* mspace_malloc(mspace msp, size_t bytes);
      void mspace_free(mspace msp, void* mem);
      void* mspace_realloc(mspace msp, void* mem, size_t newsize);
      int mspace_trim(mspace msp, size_t pad);
      size_t mspace_footprint(mspace msp);
    };

    Heap::Heap()
    {
      mspace = create_mspace (0, 1);
    }
    Heap::~Heap()
    {
      destroy_mspace (mspace);
    }

    void* Heap::Alloc (const size_t n)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_malloc (mspace, n);
    }
    void Heap::Free (void* p)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_free (mspace, p);
    }
    void* Heap::Realloc (void* p, size_t newSize)
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_realloc (mspace, p, newSize);
    }
    void Heap::Trim (size_t pad)
    {
      csScopedLock<SpinLock> foo (lock);
      mspace_trim (mspace, pad);
    }
    size_t Heap::Footprint ()
    {
      csScopedLock<SpinLock> foo (lock);
      return mspace_footprint (mspace);
    }
  } // namespace Memory
} // namespace CS

<|endoftext|>


<commit_before>#include <gtest/gtest.h> // TEST_F
#include <sober/network/Engine.hpp>
#include <sober/network/http/Stream.hpp>
#include <sober/network/http/delegate/Retry.hpp>
#include <thread> // std::this_thread

namespace sober {
namespace network {
namespace unittest {

class Long: public ::testing::Test {
 public:
  Long(): stream_(engine_) {
  }

 protected:
  network::Engine engine_;
  network::http::Stream stream_;
};

TEST_F(Long, queries_with_timeout) {
  http::delegate::Retry delegate(1, boost::posix_time::milliseconds(0));

  stream_.set_endpoint("http://pastebin.com/raw.php");
  stream_.set_delegate(delegate);

  // first request
  stream_.set_query("i", "A8wzq8s3");
  stream_.push_request();
  engine_.run();

  ASSERT_TRUE(stream_.response_valid());
  ASSERT_STREQ(stream_.response_body().c_str(), "Hello, request!");

  std::this_thread::sleep_for(std::chrono::seconds(60));

  stream_.clear_statistic();
  ASSERT_EQ(stream_.statistic().get_restarted(), 0);

  engine_.run();

  ASSERT_GE(stream_.statistic().get_restarted(), 1);

  // second request (repeat connect expected)
  stream_.set_query("i", "zUyXrfcz");
  stream_.push_request();
  engine_.run();

  ASSERT_TRUE(stream_.response_valid());
  ASSERT_STREQ(stream_.response_body().c_str(), "! One more time");
}

TEST_F(Long, operation_timeout) {
  stream_.set_endpoint("http://111.22.33.33");
  stream_.push_request();

  engine_.run();

  ASSERT_FALSE(stream_.response_valid());
}

} // namespace unittest
} // namespace network
} // namespace sober
<commit_msg>Update Long unittest<commit_after>#include <gtest/gtest.h> // TEST_F
#include <sober/network/Engine.hpp>
#include <sober/network/http/Stream.hpp>
#include <sober/network/http/delegate/Retry.hpp>
#include <sober/network/http/sink/String.hpp>
#include <sober/utils/Test.hpp>
#include <thread> // std::this_thread

namespace sober {
namespace network {
namespace unittest {

class Long: public utils::Test {
 public:
  static const std::size_t BUFFER_SIZE = 1024;

  Long(): response_(BUFFER_SIZE, sink_), stream_(engine_, request_, response_) {
  }

 protected:
  http::sink::String sink_;
  http::Response response_;
  http::Request request_;
  network::Engine engine_;
  network::http::Stream stream_;
};

TEST_F(Long, queries_with_timeout) {
  http::delegate::Retry delegate(1, boost::posix_time::milliseconds(0));

  stream_.set_endpoint("http://pastebin.com/raw.php");
  stream_.set_delegate(delegate);

  // first request
  request_.set_query("i", "A8wzq8s3");
  stream_.async_start();

  engine_.run();

  ASSERT_TRUE(sink_.ready());
  ASSERT_STREQ(sink_.body().c_str(), "Hello, request!");

  std::this_thread::sleep_for(std::chrono::seconds(60));

  stream_.clear_statistic();
  ASSERT_EQ(stream_.statistic().get_restarted(), 0);

  // second request (expected connect repeating)
  request_.set_query("i", "zUyXrfcz");
  stream_.async_start();

  engine_.run();

  ASSERT_GE(stream_.statistic().get_restarted(), 1);

  ASSERT_TRUE(sink_.ready());
  ASSERT_STREQ(sink_.body().c_str(), "! One more time");
}

TEST_F(Long, operation_timeout) {
  stream_.set_endpoint("http://111.22.33.33");
  stream_.async_start();

  engine_.run();

  ASSERT_FALSE(sink_.ready());
}

} // namespace unittest
} // namespace network
} // namespace sober
<|endoftext|>


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

#ifndef SC_XMLWRAP_HXX
#define SC_XMLWRAP_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

class ScDocument;
class SfxMedium;
class ScMySharedData;

#include <tools/errcode.hxx>

namespace com { namespace sun { namespace star {
    namespace beans { struct PropertyValue; }
    namespace frame { class XModel; }
    namespace task { class XStatusIndicator; }
    namespace lang { class XMultiServiceFactory; }
    namespace uno { class XInterface; }
    namespace embed { class XStorage; }
    namespace xml {
        namespace sax { struct InputSource; } }
} } }

class ScXMLImportWrapper
{
    ScDocument&     rDoc;
    SfxMedium*      pMedium;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xStorage;

    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator> GetStatusIndicator(
        com::sun::star::uno::Reference< com::sun::star::frame::XModel >& rModel);
    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator> GetStatusIndicator();

    sal_uInt32 ImportFromComponent(com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceFactory,
        com::sun::star::uno::Reference<com::sun::star::frame::XModel>& xModel,
        com::sun::star::uno::Reference<com::sun::star::uno::XInterface>& xXMLParser,
        com::sun::star::xml::sax::InputSource& aParserInput,
        const rtl::OUString& sComponentName, const rtl::OUString& sDocName, const rtl::OUString& sOldDocName,
        com::sun::star::uno::Sequence<com::sun::star::uno::Any>& aArgs,
        sal_Bool bMustBeSuccessfull);

    sal_Bool ExportToComponent(com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceFactory,
        com::sun::star::uno::Reference<com::sun::star::frame::XModel>& xModel,
        com::sun::star::uno::Reference<com::sun::star::uno::XInterface>& xWriter,
        com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aDescriptor,
        const rtl::OUString& sName, const rtl::OUString& sMediaType, const rtl::OUString& sComponentName,
        const sal_Bool bPlainText, com::sun::star::uno::Sequence<com::sun::star::uno::Any>& aArgs,
        ScMySharedData*& pSharedData);

public:
    ScXMLImportWrapper(ScDocument& rD, SfxMedium* pM, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >&);
    BOOL Import(sal_Bool bStylesOnly, ErrCode& );
    BOOL Export(sal_Bool bStylesOnly);
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.14.174); FILE MERGED 2005/09/05 15:01:07 rt 1.14.174.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlwrap.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:04:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_XMLWRAP_HXX
#define SC_XMLWRAP_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

class ScDocument;
class SfxMedium;
class ScMySharedData;

#include <tools/errcode.hxx>

namespace com { namespace sun { namespace star {
    namespace beans { struct PropertyValue; }
    namespace frame { class XModel; }
    namespace task { class XStatusIndicator; }
    namespace lang { class XMultiServiceFactory; }
    namespace uno { class XInterface; }
    namespace embed { class XStorage; }
    namespace xml {
        namespace sax { struct InputSource; } }
} } }

class ScXMLImportWrapper
{
    ScDocument&     rDoc;
    SfxMedium*      pMedium;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xStorage;

    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator> GetStatusIndicator(
        com::sun::star::uno::Reference< com::sun::star::frame::XModel >& rModel);
    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator> GetStatusIndicator();

    sal_uInt32 ImportFromComponent(com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceFactory,
        com::sun::star::uno::Reference<com::sun::star::frame::XModel>& xModel,
        com::sun::star::uno::Reference<com::sun::star::uno::XInterface>& xXMLParser,
        com::sun::star::xml::sax::InputSource& aParserInput,
        const rtl::OUString& sComponentName, const rtl::OUString& sDocName, const rtl::OUString& sOldDocName,
        com::sun::star::uno::Sequence<com::sun::star::uno::Any>& aArgs,
        sal_Bool bMustBeSuccessfull);

    sal_Bool ExportToComponent(com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceFactory,
        com::sun::star::uno::Reference<com::sun::star::frame::XModel>& xModel,
        com::sun::star::uno::Reference<com::sun::star::uno::XInterface>& xWriter,
        com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aDescriptor,
        const rtl::OUString& sName, const rtl::OUString& sMediaType, const rtl::OUString& sComponentName,
        const sal_Bool bPlainText, com::sun::star::uno::Sequence<com::sun::star::uno::Any>& aArgs,
        ScMySharedData*& pSharedData);

public:
    ScXMLImportWrapper(ScDocument& rD, SfxMedium* pM, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >&);
    BOOL Import(sal_Bool bStylesOnly, ErrCode& );
    BOOL Export(sal_Bool bStylesOnly);
};

#endif

<|endoftext|>


<commit_before>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<int> in;
  set<int> out;
  set<int> all;
  RSplit() = default;
  RSplit(const set<int>& i, const set<int>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
int merge_components(int c1, int c2, map<int,int>& component, map<int,list<int>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(int i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].end(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<int>& x, const set<int>& y)
{
  std::set<int>::const_iterator i = x.begin();
  std::set<int>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const std::set<int>& tips, const vector<const RSplit*>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  map<int,int> component;      // element   -> component
  map<int,list<int>> elements; // component -> elements
  for(int i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    int c1 = -1;
    for(int i: split->in)
    {
      int c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  int first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<int,set<int>> subtips;
  for(int c: tips)
  {
    if (c != component[c]) continue;

    set<int>& s = subtips[c];
    for(int l: elements[c])
      s.insert(l);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<int,vector<const RSplit*>> subsplits;
  for(const auto& split: splits)
  {
    int first = *split->in.begin();
    int c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split->out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  clearAndfillDesIdSets(*tree);

  for(auto n1: iter_post(*tree))
    for(auto n2: iter_post(*taxonomy))
      if (n1->getData().desIds == n2->getData().desIds)
	n1->setName( n2->getName());
}

set<int> remap_ids(const set<long>& s1, const map<long,int>& id_map)
{
  set<int> s2;
  for(auto x: s1)
  {
    auto it = id_map.find(x);
    assert(it != id_map.end());
    s2.insert(it->second);
  }
  return s2;
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // 0. Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // index -> id
  vector<long> ids;
  // id -> index
  map<long,int> id_map;
  for(long id: all_leaves)
  {
    int i = ids.size();
    id_map[id] = i;
    ids.push_back(id);

    assert(id_map[ids[i]] == i);
    assert(ids[id_map[id]] == id);
  }
  auto remap = [&id_map](const set<long>& ids) {return remap_ids(ids,id_map);};
  auto all_leaves_indices = remap(all_leaves);

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    const auto leafTaxaIndices = remap(leafTaxa);
    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = remap(nd->getData().desIds);
      RSplit split{descendants, leafTaxaIndices};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }
  vector<const RSplit*> split_ptrs;
  for(const auto& split: splits)
    split_ptrs.push_back(&split);

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<const RSplit*> consistent;
  for(const auto& split: split_ptrs)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves_indices, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<*split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<*split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves_indices, consistent);
  for(auto nd: iter_pre(*tree))
    if (nd->isTip())
    {
      int index = nd->getOttId();
      nd->setOttId(ids[index]);
    }

  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

unique_ptr<Tree_t> make_unresolved_tree(const vector<unique_ptr<Tree_t>>& trees, bool use_ids)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (use_ids)
  {
    map<long,string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	{
	  long id = nd->getOttId();
	  auto it = names.find(id);
	  if (it == names.end())
	    names[id] = nd->getName();
	}

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setOttId(n.first);
      node->setName(n.second);
    }
    clearAndfillDesIdSets(*tree);
  }
  else
  {
    set<string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	  names.insert(nd->getName());

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setName(n);
    }
  }

  return tree;
}

string newick(const Tree_t &t)
{
  std::ostringstream s;
  writeTreeAsNewick(s, t);
  return s.str();
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "Takes at series of tree files, with possibly mulitple trees per file.\n"
                "Files are concatenated and the combined list treated as a single subproblem.\n"
                "Trees should occur in order of priority, with the taxonomy last.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);

    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);

    otCLI.addFlag('T',
		  "Synthesize an unresolved taxonomy from all mentioned tips.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  false);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    bool requireOttIds = otCLI.getParsingRules().requireOttIds;
    if (synthesize_taxonomy)
    {
      trees.push_back(make_unresolved_tree(trees,requireOttIds));
      LOG(DEBUG)<<"taxonomy = "<<newick(*trees.back())<<"\n";
    }

    // Add fake Ott Ids to tips and compute desIds
    if (not requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<commit_msg>Don't do so many map lookups.<commit_after>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<int> in;
  set<int> out;
  set<int> all;
  RSplit() = default;
  RSplit(const set<int>& i, const set<int>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
int merge_components(int c1, int c2, vector<int>& component, vector<list<int>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(int i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].end(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<int>& x, const set<int>& y)
{
  std::set<int>::const_iterator i = x.begin();
  std::set<int>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

bool empty_intersection(const set<int>& xs, const vector<int>& ys)
{
  for(int y: ys)
    if (xs.count(y))
      return false;
  return true;
}

vector<int> indices;

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const vector<int>& tips, const vector<const RSplit*>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  vector<int> component;       // element index  -> component
  vector<list<int>> elements;  // component -> element indices
  for(int i=0;i<tips.size();i++)
  {
    indices[tips[i]] = i;
    component.push_back(i);
    elements.push_back({i});
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    int c1 = -1;
    for(int i: split->in)
    {
      int j = indices[i];
      int c2 = component[j];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[j];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  if (elements[component[0]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<int,vector<int>> subtips;
  for(int c=0;c<tips.size();c++)
  {
    if (c != component[c]) continue;

    vector<int>& s = subtips[c];
    for(int i: elements[c])
      s.push_back(tips[i]);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<int,vector<const RSplit*>> subsplits;
  for(const auto& split: splits)
  {
    int first = indices[*split->in.begin()];
    assert(first >= 0);
    int c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split->out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // Clear our map from id -> index
  for(int id: tips)
    indices[id] = -1;

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  clearAndfillDesIdSets(*tree);

  for(auto n1: iter_post(*tree))
    for(auto n2: iter_post(*taxonomy))
      if (n1->getData().desIds == n2->getData().desIds)
	n1->setName( n2->getName());
}

set<int> remap_ids(const set<long>& s1, const map<long,int>& id_map)
{
  set<int> s2;
  for(auto x: s1)
  {
    auto it = id_map.find(x);
    assert(it != id_map.end());
    s2.insert(it->second);
  }
  return s2;
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // 0. Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // index -> id
  vector<long> ids;
  // id -> index
  map<long,int> id_map;
  for(long id: all_leaves)
  {
    int i = ids.size();
    id_map[id] = i;
    ids.push_back(id);

    assert(id_map[ids[i]] == i);
    assert(ids[id_map[id]] == id);
  }
  auto remap = [&id_map](const set<long>& ids) {return remap_ids(ids,id_map);};
  vector<int> all_leaves_indices;
  for(int i=0;i<all_leaves.size();i++)
    all_leaves_indices.push_back(i);

  indices.resize(all_leaves.size());
  for(auto& i: indices)
    i=-1;

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    const auto leafTaxaIndices = remap(leafTaxa);
    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = remap(nd->getData().desIds);
      RSplit split{descendants, leafTaxaIndices};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }
  vector<const RSplit*> split_ptrs;
  for(const auto& split: splits)
    split_ptrs.push_back(&split);

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<const RSplit*> consistent;
  for(const auto& split: split_ptrs)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves_indices, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<*split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<*split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves_indices, consistent);
  for(auto nd: iter_pre(*tree))
    if (nd->isTip())
    {
      int index = nd->getOttId();
      nd->setOttId(ids[index]);
    }

  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

unique_ptr<Tree_t> make_unresolved_tree(const vector<unique_ptr<Tree_t>>& trees, bool use_ids)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (use_ids)
  {
    map<long,string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	{
	  long id = nd->getOttId();
	  auto it = names.find(id);
	  if (it == names.end())
	    names[id] = nd->getName();
	}

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setOttId(n.first);
      node->setName(n.second);
    }
    clearAndfillDesIdSets(*tree);
  }
  else
  {
    set<string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	  names.insert(nd->getName());

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setName(n);
    }
  }

  return tree;
}

string newick(const Tree_t &t)
{
  std::ostringstream s;
  writeTreeAsNewick(s, t);
  return s.str();
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "Takes at series of tree files, with possibly mulitple trees per file.\n"
                "Files are concatenated and the combined list treated as a single subproblem.\n"
                "Trees should occur in order of priority, with the taxonomy last.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);

    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);

    otCLI.addFlag('T',
		  "Synthesize an unresolved taxonomy from all mentioned tips.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  false);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    bool requireOttIds = otCLI.getParsingRules().requireOttIds;
    if (synthesize_taxonomy)
    {
      trees.push_back(make_unresolved_tree(trees,requireOttIds));
      LOG(DEBUG)<<"taxonomy = "<<newick(*trees.back())<<"\n";
    }

    // Add fake Ott Ids to tips and compute desIds
    if (not requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<|endoftext|>


<commit_before>#include <cpu/CPUDenseGraphBFSolver.h>
#include <cpu/CPURandom.h>
#include <iostream>
#include <chrono>

namespace sq = sqaod;

#ifdef SQAOD_CUDA_ENABLED
#  include <cuda/CUDADenseGraphBFSolver.h>
namespace sqcuda = sqaod_cuda;
#endif

template<class real>
sq::MatrixType<real> symmetricMatrix(sq::SizeType dim) {
    sq::CPURandom random;
    random.seed(0);
    sq::MatrixType<real> mat(dim, dim);
    for (sq::SizeType irow = 0; irow < dim; ++irow) {
        for (sq::SizeType icol = irow; icol < dim; ++icol) {
            mat(icol, irow) = mat(irow, icol) = random.random<real>() - 0.5f;
        }
    }
    return mat;
}

int main() {

    typedef double real;

    int N = 20;

    sq::MatrixType<real> W = symmetricMatrix<real>(N);

    sq::CPUDenseGraphBFSolver<real> cpuSolver;
    cpuSolver.setProblem(W);
    cpuSolver.setTileSize(1 << std::min(N, 18));

    auto start = std::chrono::system_clock::now();
    cpuSolver.search();
    auto end = std::chrono::system_clock::now();

    std::cout << cpuSolver.get_E().min() << std::endl;

    auto diff = end - start;
    std::cout << "elapsed time = "
              << std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() << " msec."
              << std::endl;

#ifdef SQAOD_CUDA_ENABLED
    sqcuda::Device device;
    device.initialize();

    sqcuda::CUDADenseGraphBFSolver<real> cudaSolver(device);
    cudaSolver.setProblem(W);
    cudaSolver.setTileSize(1 << std::min(N, 18));

    start = std::chrono::system_clock::now();
    cudaSolver.search();
    end = std::chrono::system_clock::now();

    std::cout << cudaSolver.get_E().min() << std::endl;
    device.finalize();

    diff = end - start;
    std::cout << "elapsed time = "
              << std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() << " msec."
              << std::endl;
#endif
}
<commit_msg>Adding code to run CUDADenseGraphAnnealer.<commit_after>#include <cpu/CPUDenseGraphBFSolver.h>
#include <cpu/CPUDenseGraphAnnealer.h>
#include <cpu/CPURandom.h>
#include <iostream>
#include <chrono>

namespace sq = sqaod;

#ifdef SQAOD_CUDA_ENABLED
#  include <cuda/CUDADenseGraphBFSolver.h>
#  include <cuda/CUDADenseGraphAnnealer.h>
namespace sqcuda = sqaod_cuda;
#endif

template<class T>
void showDuration(const T &duration) {
    std::cout << "elapsed time = "
              << std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() << " msec."
              << std::endl;
}

template<class real>
sq::MatrixType<real> symmetricMatrix(sq::SizeType dim) {
    sq::CPURandom random;
    random.seed(0);
    sq::MatrixType<real> mat(dim, dim);
    for (sq::SizeType irow = 0; irow < dim; ++irow) {
        for (sq::SizeType icol = irow; icol < dim; ++icol) {
            mat(icol, irow) = mat(irow, icol) = random.random<real>() - 0.5f;
        }
    }
    return mat;
}

template<class real>
void denseGraphBFSearch(int N) {

    sq::MatrixType<real> W = symmetricMatrix<real>(N);

    sq::CPUDenseGraphBFSolver<real> cpuSolver;
    cpuSolver.setProblem(W);
    cpuSolver.setTileSize(1 << std::min(N, 18));

    auto start = std::chrono::system_clock::now();
    cpuSolver.search();
    auto end = std::chrono::system_clock::now();

    std::cout << cpuSolver.get_E().min() << std::endl;

    showDuration(end - start);

#ifdef SQAOD_CUDA_ENABLED
    sqcuda::Device device;
    device.initialize();

    sqcuda::CUDADenseGraphBFSolver<real> cudaSolver(device);
    cudaSolver.setProblem(W);
    cudaSolver.setTileSize(1 << std::min(N, 18));

    start = std::chrono::system_clock::now();
    cudaSolver.search();
    end = std::chrono::system_clock::now();

    std::cout << cudaSolver.get_E().min() << std::endl;
    device.finalize();

    showDuration(end - start);
#endif
}

template<class real, template<class real> class A>
void anneal(A<real> &an, real Ginit, real Gfin, real kT, real tau) {

    an.initAnneal();
    an.randomize_q();
    real G = Ginit;
    while (Gfin < G) {
        an.annealOneStep(G, kT);
        G = G * tau;
        std::cerr << ".";
    }
    an.finAnneal();
    std::cerr << std::endl;
    const sq::VectorType<real> &E = an.get_E();
    std::cerr << "Energy : " << E.min() << std::endl;
}

template<class real>
void denseGraphAnnealer(int N) {

    real Ginit = 5.;
    real Gfin = 0.01;
    real kT = 0.02;
    real tau = 0.99;

    sq::MatrixType<real> W = symmetricMatrix<real>(N);

    sq::CPUDenseGraphAnnealer<real> cpuAnnealer;
    cpuAnnealer.setProblem(W);
    cpuAnnealer.setNumTrotters(N / 2);

    auto start = std::chrono::system_clock::now();
    anneal(cpuAnnealer, Ginit, Gfin, kT, tau);
    auto end = std::chrono::system_clock::now();

    std::cout << cpuAnnealer.get_E().min() << std::endl;

    showDuration(end - start);

#ifdef SQAOD_CUDA_ENABLED
    sqcuda::Device device;
    device.initialize();

    sqcuda::CUDADenseGraphAnnealer<real> cudaAnnealer(device);
    cudaAnnealer.setProblem(W);
    cudaAnnealer.setNumTrotters(N / 2);

    start = std::chrono::system_clock::now();
    anneal(cudaAnnealer, Ginit, Gfin, kT, tau);
    end = std::chrono::system_clock::now();

    std::cout << cudaAnnealer.get_E().min() << std::endl;
    device.finalize();

    showDuration(end - start);
#endif
}

int main() {
    int N = 20;
    denseGraphBFSearch<double>(N);
    denseGraphBFSearch<float>(N);

    N = 100;
    denseGraphAnnealer<double>(N);
    denseGraphAnnealer<float>(N);
}
<|endoftext|>