<commit_before>/*
 * Copyright (c) 2009, Piotr Korzuszek
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "OptionsScene.h"

#include "common.h"
#include "common/Properties.h"
#include "gfx/Stage.h"

const int LABEL_WIDTH = 80;
const int LABEL_HEIGHT = 20;

const int ERROR_LABEL_WIDTH = 200;
const int ERROR_LABEL_HEIGHT = 20;

const int EDIT_WIDTH = 200;
const int EDIT_HEIGHT = 20;

const int BUTTON_WIDTH = 100;
const int BUTTON_HEIGHT = 20;

const int COMBOBOX_WIDTH = 200;
const int COMBOBOX_HEIGHT = 20;

const int CHECKBOX_WIDTH = 200;
const int CHECKBOX_HEIGHT = 20;

const int SLIDER_WIDTH = 200;
const int SLIDER_HEIGHT = 20;

const int H_MARGIN = 20;
const int V_MARGIN = 40;

OptionScene::OptionScene(CL_GUIComponent *p_parent) :
	GuiScene(p_parent),
    m_controller(this),
	m_nameLabel(this),
	m_nameLineEdit(this),
	m_resolutionLabel(this),
	m_resolutionComboBox(this),
	m_fullScreenCheckBox(this),
	m_soundLabel(this),
	m_soundValueLabel(this),
	m_wsadCheckBox(this),
	m_soundSlider(this),
	m_errorLabel(this),
	m_cancelButton(this),
    m_okButton(this),
	m_menu(),
	m_resolutions()
{
	set_class_name("OptionScene");

	static const int START_X = 240;
	static const int START_Y = V_MARGIN;

	int x = START_X;
	int y = START_Y;

	m_nameLabel.set_text(_("Player's name"));
	m_nameLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	m_nameLineEdit.set_geometry(CL_Rect(x, y, x + EDIT_WIDTH, y + EDIT_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_resolutionLabel.set_text(_("Resolution"));
	m_resolutionLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	addResolution(800, 600);
	addResolution(1024, 768);
	m_resolutionComboBox.set_geometry(CL_Rect(x, y, x + COMBOBOX_WIDTH, y + COMBOBOX_HEIGHT));
	m_resolutionComboBox.set_selected_item(0);

	x = START_X;
	y += V_MARGIN;

	m_fullScreenCheckBox.set_text(_("Full screen"));
	m_fullScreenCheckBox.set_geometry(CL_Rect(x, y, x + CHECKBOX_WIDTH, y + CHECKBOX_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_wsadCheckBox.set_text(_("Use WASD"));
	m_wsadCheckBox.set_geometry(CL_Rect(x, y, x + CHECKBOX_WIDTH, y + CHECKBOX_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_soundLabel.set_text(_("Sound"));
	m_soundLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	m_soundSlider.set_min(0);
	m_soundSlider.set_max(100);
	m_soundSlider.set_geometry(CL_Rect(x, y, x + SLIDER_WIDTH, y + SLIDER_HEIGHT));

	x += SLIDER_WIDTH + H_MARGIN;

	m_soundValueLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));
	setSliderLabelValue();

	x = (Gfx::Stage::getWidth() - (2 * BUTTON_WIDTH + H_MARGIN)) / 2;
	y = Gfx::Stage::getHeight() - (BUTTON_HEIGHT + V_MARGIN + ERROR_LABEL_HEIGHT);

	m_errorLabel.set_geometry(CL_Rect(x, y, x + ERROR_LABEL_WIDTH, y + ERROR_LABEL_HEIGHT));

    x = (Gfx::Stage::getWidth() - (2 * BUTTON_WIDTH + H_MARGIN)) / 2;
    y = Gfx::Stage::getHeight() - (BUTTON_HEIGHT + V_MARGIN);

    m_okButton.set_text(_("Ok"));
    m_okButton.set_geometry(CL_Rect(x, y, x + BUTTON_WIDTH, y + BUTTON_HEIGHT));

    x += V_MARGIN + BUTTON_WIDTH;

    m_cancelButton.set_text(_("Cancel"));
    m_cancelButton.set_geometry(CL_Rect(x, y, x + BUTTON_WIDTH, y + BUTTON_HEIGHT));

	m_soundSlider.func_value_changed().set(this, &OptionScene::onSliderValueChange);
	m_okButton.func_clicked().set(this, &OptionScene::onOkClick);
	m_cancelButton.func_clicked().set(this, &OptionScene::onCancelClick);
}

OptionScene::~OptionScene()
{
}

void OptionScene::draw(CL_GraphicContext &p_gc)
{
	CL_Draw::fill(p_gc, 0.0f, 0.0f, get_width(), get_height(), CL_Colorf::white);

	GuiScene::draw(p_gc);
}

void OptionScene::addResolution(int p_width, int p_height)
{
	m_resolutions.push_back(CL_Size(p_width, p_height));

	CL_String resolution = CL_StringHelp::int_to_local8(p_width) + "x" + CL_StringHelp::int_to_local8(p_height);
	m_menu.insert_item(resolution);

	m_resolutionComboBox.set_popup_menu(m_menu);
}

void OptionScene::displayError(const CL_String& p_message)
{
	CL_Font font(get_gc(), "helvetica", 14);
	CL_SpanLayout span;
	span.add_text(p_message, font, CL_Colorf::red);
	m_errorLabel.set_span(span);
}

void OptionScene::pushed()
{
	m_errorLabel.set_text("");

	if (Properties::getPropertyAsString("opt_player_name", "") != "")
	{
		int width = Properties::getPropertyAsInt("opt_screen_width", -1);
		int height = Properties::getPropertyAsInt("opt_screen_height", -1);
		m_resolutionComboBox.set_selected_item(searchResolution(width, height));

		m_nameLineEdit.set_text(Properties::getPropertyAsString("opt_player_name", ""));
		m_fullScreenCheckBox.set_checked(Properties::getPropertyAsBool("opt_fullscreen", false));
		m_wsadCheckBox.set_checked(Properties::getPropertyAsBool("opt_use_wasd", false));
		m_soundSlider.set_position(Properties::getPropertyAsInt("opt_sound_volume", 100));
		setSliderLabelValue();
	}
	else
	{
		useDefaultSetings();
	}

	GuiScene::pushed();
}

int OptionScene::searchResolution(const int& p_searchWidth, const int& p_searchHeight)
{
	for (unsigned i = 0; i < m_resolutions.size(); ++i)
	{
		if (m_resolutions[i].width == p_searchWidth && m_resolutions[i].height == p_searchHeight)
		{
			return i;
		}
	}

	return -1;
}

void OptionScene::onCancelClick()
{
    INVOKE_0(cancelClicked);
}

void OptionScene::onOkClick()
{
    INVOKE_0(okClicked);
}

void OptionScene::onSliderValueChange()
{
	setSliderLabelValue();
}

void OptionScene::setSliderLabelValue()
{
	m_soundValueLabel.set_text(CL_StringHelp::int_to_local8(m_soundSlider.get_position()));
	m_soundValueLabel.paint();
}

void OptionScene::useDefaultSetings()
{
	m_nameLineEdit.set_text("");
	m_resolutionComboBox.set_selected_item(0);
	m_fullScreenCheckBox.set_checked(false);
	m_wsadCheckBox.set_checked(false);
	m_soundSlider.set_position(100);
	setSliderLabelValue();
	m_errorLabel.set_text("");
}

const CL_String& OptionScene::getPlayersName() const
{
	return m_nameLineEdit.get_text();
}

int OptionScene::getResolutionWidth() const
{
	return m_resolutions[m_resolutionComboBox.get_selected_item()].width;
}

int OptionScene::getResolutionHeight() const
{
	return m_resolutions[m_resolutionComboBox.get_selected_item()].height;
}

bool OptionScene::getFullScreen() const
{
	return m_fullScreenCheckBox.is_checked();
}

int OptionScene::getSound() const
{
	return m_soundSlider.get_position();
}

bool OptionScene::getWASD() const
{
	return m_wsadCheckBox.is_checked();
}
<commit_msg>obsługa błędu braku odpowiedniej rozdzielczości<commit_after>/*
 * Copyright (c) 2009, Piotr Korzuszek
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "OptionsScene.h"

#include "common.h"
#include "common/Properties.h"
#include "gfx/Stage.h"

const int LABEL_WIDTH = 80;
const int LABEL_HEIGHT = 20;

const int ERROR_LABEL_WIDTH = 200;
const int ERROR_LABEL_HEIGHT = 20;

const int EDIT_WIDTH = 200;
const int EDIT_HEIGHT = 20;

const int BUTTON_WIDTH = 100;
const int BUTTON_HEIGHT = 20;

const int COMBOBOX_WIDTH = 200;
const int COMBOBOX_HEIGHT = 20;

const int CHECKBOX_WIDTH = 200;
const int CHECKBOX_HEIGHT = 20;

const int SLIDER_WIDTH = 200;
const int SLIDER_HEIGHT = 20;

const int H_MARGIN = 20;
const int V_MARGIN = 40;

OptionScene::OptionScene(CL_GUIComponent *p_parent) :
	GuiScene(p_parent),
    m_controller(this),
	m_nameLabel(this),
	m_nameLineEdit(this),
	m_resolutionLabel(this),
	m_resolutionComboBox(this),
	m_fullScreenCheckBox(this),
	m_soundLabel(this),
	m_soundValueLabel(this),
	m_wsadCheckBox(this),
	m_soundSlider(this),
	m_errorLabel(this),
	m_cancelButton(this),
    m_okButton(this),
	m_menu(),
	m_resolutions()
{
	set_class_name("OptionScene");

	static const int START_X = 240;
	static const int START_Y = V_MARGIN;

	int x = START_X;
	int y = START_Y;

	m_nameLabel.set_text(_("Player's name"));
	m_nameLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	m_nameLineEdit.set_geometry(CL_Rect(x, y, x + EDIT_WIDTH, y + EDIT_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_resolutionLabel.set_text(_("Resolution"));
	m_resolutionLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	addResolution(800, 600);
	addResolution(1024, 768);
	m_resolutionComboBox.set_geometry(CL_Rect(x, y, x + COMBOBOX_WIDTH, y + COMBOBOX_HEIGHT));
	m_resolutionComboBox.set_selected_item(0);

	x = START_X;
	y += V_MARGIN;

	m_fullScreenCheckBox.set_text(_("Full screen"));
	m_fullScreenCheckBox.set_geometry(CL_Rect(x, y, x + CHECKBOX_WIDTH, y + CHECKBOX_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_wsadCheckBox.set_text(_("Use WASD"));
	m_wsadCheckBox.set_geometry(CL_Rect(x, y, x + CHECKBOX_WIDTH, y + CHECKBOX_HEIGHT));

	x = START_X;
	y += V_MARGIN;

	m_soundLabel.set_text(_("Sound"));
	m_soundLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));

	x += LABEL_WIDTH + H_MARGIN;

	m_soundSlider.set_min(0);
	m_soundSlider.set_max(100);
	m_soundSlider.set_geometry(CL_Rect(x, y, x + SLIDER_WIDTH, y + SLIDER_HEIGHT));

	x += SLIDER_WIDTH + H_MARGIN;

	m_soundValueLabel.set_geometry(CL_Rect(x, y, x + LABEL_WIDTH, y + LABEL_HEIGHT));
	setSliderLabelValue();

	x = (Gfx::Stage::getWidth() - (2 * BUTTON_WIDTH + H_MARGIN)) / 2;
	y = Gfx::Stage::getHeight() - (BUTTON_HEIGHT + V_MARGIN + ERROR_LABEL_HEIGHT);

	m_errorLabel.set_geometry(CL_Rect(x, y, x + ERROR_LABEL_WIDTH, y + ERROR_LABEL_HEIGHT));

    x = (Gfx::Stage::getWidth() - (2 * BUTTON_WIDTH + H_MARGIN)) / 2;
    y = Gfx::Stage::getHeight() - (BUTTON_HEIGHT + V_MARGIN);

    m_okButton.set_text(_("Ok"));
    m_okButton.set_geometry(CL_Rect(x, y, x + BUTTON_WIDTH, y + BUTTON_HEIGHT));

    x += V_MARGIN + BUTTON_WIDTH;

    m_cancelButton.set_text(_("Cancel"));
    m_cancelButton.set_geometry(CL_Rect(x, y, x + BUTTON_WIDTH, y + BUTTON_HEIGHT));

	m_soundSlider.func_value_changed().set(this, &OptionScene::onSliderValueChange);
	m_okButton.func_clicked().set(this, &OptionScene::onOkClick);
	m_cancelButton.func_clicked().set(this, &OptionScene::onCancelClick);
}

OptionScene::~OptionScene()
{
}

void OptionScene::draw(CL_GraphicContext &p_gc)
{
	CL_Draw::fill(p_gc, 0.0f, 0.0f, get_width(), get_height(), CL_Colorf::white);

	GuiScene::draw(p_gc);
}

void OptionScene::addResolution(int p_width, int p_height)
{
	m_resolutions.push_back(CL_Size(p_width, p_height));

	CL_String resolution = CL_StringHelp::int_to_local8(p_width) + "x" + CL_StringHelp::int_to_local8(p_height);
	m_menu.insert_item(resolution);

	m_resolutionComboBox.set_popup_menu(m_menu);
}

void OptionScene::displayError(const CL_String& p_message)
{
	CL_Font font(get_gc(), "helvetica", 14);
	CL_SpanLayout span;
	span.add_text(p_message, font, CL_Colorf::red);
	m_errorLabel.set_span(span);
}

void OptionScene::pushed()
{
	m_errorLabel.set_text("");

	if (Properties::getPropertyAsString("opt_player_name", "") != "")
	{
		int width = Properties::getPropertyAsInt("opt_screen_width", -1);
		int height = Properties::getPropertyAsInt("opt_screen_height", -1);
		int index = 0;
		if ((index = searchResolution(width, height)) == -1)
		{
			index = 0;
		}
		m_resolutionComboBox.set_selected_item(index);

		m_nameLineEdit.set_text(Properties::getPropertyAsString("opt_player_name", ""));
		m_fullScreenCheckBox.set_checked(Properties::getPropertyAsBool("opt_fullscreen", false));
		m_wsadCheckBox.set_checked(Properties::getPropertyAsBool("opt_use_wasd", false));
		m_soundSlider.set_position(Properties::getPropertyAsInt("opt_sound_volume", 100));
		setSliderLabelValue();
	}
	else
	{
		useDefaultSetings();
	}

	GuiScene::pushed();
}

int OptionScene::searchResolution(const int& p_searchWidth, const int& p_searchHeight)
{
	for (unsigned i = 0; i < m_resolutions.size(); ++i)
	{
		if (m_resolutions[i].width == p_searchWidth && m_resolutions[i].height == p_searchHeight)
		{
			return i;
		}
	}

	return -1;
}

void OptionScene::onCancelClick()
{
    INVOKE_0(cancelClicked);
}

void OptionScene::onOkClick()
{
    INVOKE_0(okClicked);
}

void OptionScene::onSliderValueChange()
{
	setSliderLabelValue();
}

void OptionScene::setSliderLabelValue()
{
	m_soundValueLabel.set_text(CL_StringHelp::int_to_local8(m_soundSlider.get_position()));
	m_soundValueLabel.paint();
}

void OptionScene::useDefaultSetings()
{
	m_nameLineEdit.set_text("");
	m_resolutionComboBox.set_selected_item(0);
	m_fullScreenCheckBox.set_checked(false);
	m_wsadCheckBox.set_checked(false);
	m_soundSlider.set_position(100);
	setSliderLabelValue();
	m_errorLabel.set_text("");
}

const CL_String& OptionScene::getPlayersName() const
{
	return m_nameLineEdit.get_text();
}

int OptionScene::getResolutionWidth() const
{
	return m_resolutions[m_resolutionComboBox.get_selected_item()].width;
}

int OptionScene::getResolutionHeight() const
{
	return m_resolutions[m_resolutionComboBox.get_selected_item()].height;
}

bool OptionScene::getFullScreen() const
{
	return m_fullScreenCheckBox.is_checked();
}

int OptionScene::getSound() const
{
	return m_soundSlider.get_position();
}

bool OptionScene::getWASD() const
{
	return m_wsadCheckBox.is_checked();
}
<|endoftext|>


<commit_before>#include <reversed.hpp>

#include <array>
#include <string>
#include <utility>
#include <vector>

#include "catch.hpp"

#define DECLARE_REVERSE_ITERATOR
#include "helpers.hpp"
#undef DECLARE_REVERSE_ITERATOR

using iter::reversed;
using Vec = const std::vector<int>;

TEST_CASE("reversed: can reverse a vector", "[reversed]") {
  Vec ns = {10, 20, 30, 40};
  std::vector<int> v;
  SECTION("Normal call") {
    auto r = reversed(ns);
    v.assign(std::begin(r), std::end(r));
  }
  SECTION("Pipe") {
    auto r = ns | reversed;
    v.assign(std::begin(r), std::end(r));
  }

  Vec vc = {40, 30, 20, 10};

  REQUIRE(v == vc);
}

#if 0
TEST_CASE("reversed: Works with different begin and end types",
    "[reversed]") {
  CharRange cr{'d'};
  auto r = reversed(cr);
  Vec v(r.begin(), r.end());
  Vec vc{'c', 'b', 'a'};
  REQUIRE(v == vc);
}
#endif

TEST_CASE("reversed: can reverse an array", "[reversed]") {
  int ns[] = {10, 20, 30, 40};
  auto r = reversed(ns);

  Vec v(std::begin(r), std::end(r));
  Vec vc = {40, 30, 20, 10};

  REQUIRE(v == vc);
}

TEST_CASE("reversed: empty when iterable is empty", "[reversed]") {
  Vec emp{};
  auto r = reversed(emp);
  REQUIRE(std::begin(r) == std::end(r));
}

TEST_CASE("reversed: moves rvalues and binds to lvalues", "[reversed]") {
  itertest::BasicIterable<int> bi{1, 2};
  itertest::BasicIterable<int> bi2{1, 2};
  reversed(bi);
  REQUIRE_FALSE(bi.was_moved_from());

  reversed(std::move(bi2));
  REQUIRE(bi2.was_moved_from());
}

TEST_CASE("reversed: doesn't move or copy elements of array", "[reversed]") {
  constexpr itertest::SolidInt arr[] = {{6}, {7}, {8}};
  for (auto&& i : reversed(arr)) {
    (void)i;
  }
}

TEST_CASE("reversed: with iterable doesn't move or copy elems", "[reversed]") {
  constexpr std::array<itertest::SolidInt, 3> arr{{{6}, {7}, {8}}};
  for (auto&& i : reversed(arr)) {
    (void)i;
  }
}

TEST_CASE("reversed: iterator meets requirements", "[reversed]") {
  Vec v;
  auto r = reversed(v);
  REQUIRE(itertest::IsIterator<decltype(std::begin(r))>::value);

  int a[1];
  auto ra = reversed(a);
  REQUIRE(itertest::IsIterator<decltype(std::begin(ra))>::value);
}

template <typename T>
using ImpT = decltype(reversed(std::declval<T>()));
TEST_CASE("reversed: has correct ctor and assign ops", "[reversed]") {
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string&>>::value);
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string>>::value);
}
<commit_msg>Test reversed with const iteration<commit_after>#include <reversed.hpp>

#include <array>
#include <string>
#include <utility>
#include <vector>

#include "catch.hpp"

#define DECLARE_REVERSE_ITERATOR
#include "helpers.hpp"
#undef DECLARE_REVERSE_ITERATOR

using iter::reversed;
using Vec = const std::vector<int>;

TEST_CASE("reversed: can reverse a vector", "[reversed]") {
  Vec ns = {10, 20, 30, 40};
  std::vector<int> v;
  SECTION("Normal call") {
    auto r = reversed(ns);
    v.assign(std::begin(r), std::end(r));
  }
  SECTION("Pipe") {
    auto r = ns | reversed;
    v.assign(std::begin(r), std::end(r));
  }

  Vec vc = {40, 30, 20, 10};

  REQUIRE(v == vc);
}

TEST_CASE("reversed: const iteration", "[reversed][const]") {
  Vec ns = {10, 20, 30, 40};
  const auto r = reversed(ns);
  Vec v(std::begin(r), std::end(r));
  Vec vc = {40, 30, 20, 10};
  REQUIRE(v == vc);
}

TEST_CASE("reversed: const iterators can be compared to non-const iterators",
    "[reversed][const]") {
  auto r = reversed(Vec{});
  const auto& cr = r;
  (void)(std::begin(r) == std::end(cr));
}

#if 0
TEST_CASE("reversed: Works with different begin and end types",
    "[reversed]") {
  CharRange cr{'d'};
  auto r = reversed(cr);
  Vec v(r.begin(), r.end());
  Vec vc{'c', 'b', 'a'};
  REQUIRE(v == vc);
}
#endif

TEST_CASE("reversed: can reverse an array", "[reversed]") {
  int ns[] = {10, 20, 30, 40};
  auto r = reversed(ns);

  Vec v(std::begin(r), std::end(r));
  Vec vc = {40, 30, 20, 10};

  REQUIRE(v == vc);
}

TEST_CASE("reversed: empty when iterable is empty", "[reversed]") {
  Vec emp{};
  auto r = reversed(emp);
  REQUIRE(std::begin(r) == std::end(r));
}

TEST_CASE("reversed: moves rvalues and binds to lvalues", "[reversed]") {
  itertest::BasicIterable<int> bi{1, 2};
  itertest::BasicIterable<int> bi2{1, 2};
  reversed(bi);
  REQUIRE_FALSE(bi.was_moved_from());

  reversed(std::move(bi2));
  REQUIRE(bi2.was_moved_from());
}

TEST_CASE("reversed: doesn't move or copy elements of array", "[reversed]") {
  constexpr itertest::SolidInt arr[] = {{6}, {7}, {8}};
  for (auto&& i : reversed(arr)) {
    (void)i;
  }
}

TEST_CASE("reversed: with iterable doesn't move or copy elems", "[reversed]") {
  constexpr std::array<itertest::SolidInt, 3> arr{{{6}, {7}, {8}}};
  for (auto&& i : reversed(arr)) {
    (void)i;
  }
}

TEST_CASE("reversed: iterator meets requirements", "[reversed]") {
  Vec v;
  auto r = reversed(v);
  REQUIRE(itertest::IsIterator<decltype(std::begin(r))>::value);

  int a[1];
  auto ra = reversed(a);
  REQUIRE(itertest::IsIterator<decltype(std::begin(ra))>::value);
}

template <typename T>
using ImpT = decltype(reversed(std::declval<T>()));
TEST_CASE("reversed: has correct ctor and assign ops", "[reversed]") {
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string&>>::value);
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string>>::value);
}
<|endoftext|>


<commit_before>/**  @file gsAffineFunction.hpp

    @brief Implements an affine function.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Bressan
    Created on:  2014-11-27
*/

namespace gismo {

template <typename T>
gsAffineFunction<T>::gsAffineFunction(const gsVector<index_t> &dir, const gsVector<bool> &o, const gsMatrix<T> &box1, const gsMatrix<T> &box2)
{
    GISMO_ASSERT(box1.rows()==box2.rows(),
                 "The two boxes must be subset of Rn for the same n (same number of rows)");
    GISMO_ASSERT(box1.cols()==2 && 2==box2.cols(),
                 "The two boxes must be described by the lower and upper corner, the matrices must have two columns");

    const index_t dim = box1.rows();
    const gsVector<T> size1= box1.col(1) - box1.col(0);
    const gsVector<T> size2= box2.col(1) - box2.col(0);
    m_mat.setZero(dim,dim);
    m_trans.resize(dim);
    for (index_t i=0; i<dim; ++i)
    {
        const T ratio = size1(i)==0 ? T(1) : size2(dir(i))/size1(i);
        m_mat(dir(i),i) = o(i) ? ratio : -ratio;
        m_trans(dir(i)) = o(i) ? box2(dir(i),0) : box2(dir(i),1);
    }
    m_trans -= m_mat * box1.col(0);
}

template <typename T>
gsAffineFunction<T>::gsAffineFunction(const gsMatrix<T> mat, const gsVector<T> trans)
    : m_mat(mat), m_trans(trans)
{
    GISMO_ASSERT(m_mat.rows()==m_trans.rows(),
                 "Incompatible linear map and translation in affine map");
}

template <typename T>
int gsAffineFunction<T>::domainDim() const
{
    return m_mat.cols();
}

template <typename T>
int gsAffineFunction<T>::targetDim() const
{
    return m_mat.rows();
}

template <typename T>
void gsAffineFunction<T>::eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    result = (m_mat*u).colwise()+m_trans;
}

template <typename T>
void gsAffineFunction<T>::eval_component_into(const gsMatrix<T>& u,
                                                      const index_t comp,
                                                      gsMatrix<T>& result) const
{
    gsMatrix<T> temp;
    eval_into(u,temp);
    result=temp.row(comp);
}

template <typename T>
void gsAffineFunction<T>::deriv_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    result.resize(m_mat.rows()* m_mat.cols(), u.cols());
    if (!u.cols())
    {
        return;
    }
    for (index_t col=0;col<m_mat.cols();++col)
    {
        result.block(m_mat.rows()*col,0,m_mat.rows(),1)=m_mat.col(col);
    }
    for (index_t col=1; col<result.cols();++col)
    {
        result.col(col)=result.col(0);
    }
}

template <typename T>
void gsAffineFunction<T>::deriv2_into( const gsMatrix<T>& u, gsMatrix<T>& result ) const
{
    const index_t rows = domainDim()*domainDim()*targetDim();
    result.setZero(rows,u.cols());
}

} // namespace gismo
<commit_msg>warn fix<commit_after>/**  @file gsAffineFunction.hpp

    @brief Implements an affine function.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Bressan
    Created on:  2014-11-27
*/

namespace gismo {

template <typename T>
gsAffineFunction<T>::gsAffineFunction(const gsVector<index_t> &dir, const gsVector<bool> &o, const gsMatrix<T> &box1, const gsMatrix<T> &box2)
{
    GISMO_ASSERT(box1.rows()==box2.rows(),
                 "The two boxes must be subset of Rn for the same n (same number of rows)");
    GISMO_ASSERT(box1.cols()==2 && 2==box2.cols(),
                 "The two boxes must be described by the lower and upper corner, the matrices must have two columns");

    const index_t dim = box1.rows();
    const gsVector<T> size1 = box1.col(1) - box1.col(0);
    const gsVector<T> size2 = box2.col(1) - box2.col(0);
    m_mat.setZero(dim,dim);
    m_trans.resize(dim);
    for (index_t i=0; i<dim; ++i)
    {
        const T ratio = size1[i]==0 ? T(1) : size2(dir[i])/size1[i];
        m_mat(dir(i),i) = o[i] ? ratio : -ratio;
        m_trans(dir(i)) = o[i] ? box2(dir[i],0) : box2(dir[i],1);
    }
    m_trans -= m_mat * box1.col(0);
}

template <typename T>
gsAffineFunction<T>::gsAffineFunction(const gsMatrix<T> mat, const gsVector<T> trans)
    : m_mat(mat), m_trans(trans)
{
    GISMO_ASSERT(m_mat.rows()==m_trans.rows(),
                 "Incompatible linear map and translation in affine map");
}

template <typename T>
int gsAffineFunction<T>::domainDim() const
{
    return m_mat.cols();
}

template <typename T>
int gsAffineFunction<T>::targetDim() const
{
    return m_mat.rows();
}

template <typename T>
void gsAffineFunction<T>::eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    result = (m_mat*u).colwise()+m_trans;
}

template <typename T>
void gsAffineFunction<T>::eval_component_into(const gsMatrix<T>& u,
                                                      const index_t comp,
                                                      gsMatrix<T>& result) const
{
    gsMatrix<T> temp;
    eval_into(u,temp);
    result=temp.row(comp);
}

template <typename T>
void gsAffineFunction<T>::deriv_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    result.resize(m_mat.rows()* m_mat.cols(), u.cols());
    if (!u.cols())
    {
        return;
    }
    for (index_t col=0;col<m_mat.cols();++col)
    {
        result.block(m_mat.rows()*col,0,m_mat.rows(),1)=m_mat.col(col);
    }
    for (index_t col=1; col<result.cols();++col)
    {
        result.col(col)=result.col(0);
    }
}

template <typename T>
void gsAffineFunction<T>::deriv2_into( const gsMatrix<T>& u, gsMatrix<T>& result ) const
{
    const index_t rows = domainDim()*domainDim()*targetDim();
    result.setZero(rows,u.cols());
}

} // namespace gismo
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------
//      $Id$
//    Version: $Name$
//
//    Copyright (C) 2005, 2006, 2008 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/utilities.h>
#include <base/exceptions.h>

#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cerrno>
#include <cmath>
#include <unistd.h>
#include <sys/types.h>
#include <sstream>

#ifdef HAVE_STD_NUMERIC_LIMITS
#  include <limits>
#else
#  include <limits.h>
#endif

DEAL_II_NAMESPACE_OPEN

namespace Utilities
{

  DeclException2 (ExcInvalidNumber2StringConversersion,
		  unsigned int, unsigned int,
		  << "When trying to convert " << arg1
		  << " to a string with " << arg2 << " digits");
  DeclException1 (ExcInvalidNumber,
		  unsigned int,
		  << "Invalid number " << arg1);
  DeclException1 (ExcCantConvertString,
		  std::string,
		  << "Can't convert the string " << arg1
                  << " to the desired type");

  std::string
  int_to_string (const unsigned int i,
		 const unsigned int digits)
  {
				     // if second argument is invalid, then do
				     // not pad the resulting string at all
    if (digits == numbers::invalid_unsigned_int)
      return int_to_string (i, needed_digits(i));

    AssertThrow ( ! ((digits==1 && i>=10)   ||
		     (digits==2 && i>=100)  ||
		     (digits==3 && i>=1000) ||
		     (digits==4 && i>=10000)||
		     (digits==5 && i>=100000)||
		     (i>=1000000)),
		  ExcInvalidNumber2StringConversersion(i, digits));

    std::string s;
    switch (digits)
      {
	case 6:
	      s += '0' + i/100000;
	case 5:
	      s += '0' + (i%100000)/10000;
	case 4:
	      s += '0' + (i%10000)/1000;
	case 3:
	      s += '0' + (i%1000)/100;
	case 2:
	      s += '0' + (i%100)/10;
	case 1:
	      s += '0' + i%10;
	      break;
	default:
	      s += "invalid digits information";
      };
    return s;
  }

  unsigned int
  needed_digits (const unsigned int max_number)
  {
    if (max_number < 10)
      return 1;
    if (max_number < 100)
      return 2;
    if (max_number < 1000)
      return 3;
    if (max_number < 10000)
      return 4;
    if (max_number < 100000)
      return 5;
    if (max_number < 1000000)
      return 6;
    AssertThrow (false, ExcInvalidNumber(max_number));
    return 0;
  }

  int
  string_to_int (const std::string &s)
  {
    std::istringstream ss(s);

#ifdef HAVE_STD_NUMERIC_LIMITS
    static const int max_int = std::numeric_limits<int>::max();
#else
    static const int max_int = INT_MAX;
#endif

    int i = max_int;
    ss >> i;

                                     // check for errors
    AssertThrow (i != max_int, ExcCantConvertString (s));

    return i;
  }

  std::vector<int>
  string_to_int (const std::vector<std::string> &s)
  {
    std::vector<int> tmp (s.size());
    for (unsigned int i=0; i<s.size(); ++i)
      tmp[i] = string_to_int (s[i]);
    return tmp;
  }

  std::vector<std::string>
  split_string_list (const std::string &s,
                     const char         delimiter)
  {
    std::string tmp = s;
    std::vector<std::string> split_list;
    split_list.reserve (std::count (tmp.begin(), tmp.end(), delimiter)+1);

				     // split the input list
    while (tmp.length() != 0)
      {
        std::string name;
	name = tmp;

	if (name.find(delimiter) != std::string::npos)
	  {
	    name.erase (name.find(delimiter), std::string::npos);
	    tmp.erase (0, tmp.find(delimiter)+1);
	  }
	else
	  tmp = "";

	while ((name.length() != 0) &&
	       (name[0] == ' '))
	  name.erase (0,1);

	while (name[name.length()-1] == ' ')
	  name.erase (name.length()-1, 1);

	split_list.push_back (name);
      }

    return split_list;
  }

  std::vector<std::string>
  break_text_into_lines (const std::string &original_text,
                         const unsigned int width,
                         const char delimiter)
  {
    std::string              text = original_text;
    std::vector<std::string> lines;

                                     // remove trailing spaces
    while ((text.length() != 0) && (text[text.length()-1] == delimiter))
      text.erase(text.length()-1,1);

                                     // then split the text into lines
    while (text.length() != 0)
      {
                                         // in each iteration, first remove
                                         // leading spaces
        while ((text.length() != 0) && (text[0] == delimiter))
          text.erase(0, 1);

                                         // if we can fit everything into one
                                         // line, then do so. otherwise, we have
                                         // to keep breaking
        if (text.length() < width)
          {
            lines.push_back (text);
            text = "";
          }
        else
          {
                                             // starting at position width, find the
                                             // location of the previous space, so
                                             // that we can break around there
            int location = std::min<int>(width,text.length()-1);
            for (; location>0; --location)
              if (text[location] == delimiter)
                break;

                                             // if there are no spaces, then try if
                                             // there are spaces coming up
            if (location == 0)
              for (location = std::min<int>(width,text.length()-1);
                   location<static_cast<int>(text.length());
                   ++location)
                if (text[location] == delimiter)
                  break;

                                             // now take the text up to the found
                                             // location and put it into a single
                                             // line, and remove it from 'text'
            lines.push_back (std::string (text, 0, location));
            text.erase (0, location);
          }
      }

    return lines;
  }

  bool
  match_at_string_start (const std::string &name,
			 const std::string &pattern)
  {
    if (pattern.size() > name.size())
      return false;

    for (unsigned int i=0; i<pattern.size(); ++i)
      if (pattern[i] != name[i])
	return false;

    return true;
  }

  std::pair<int, unsigned int>
  get_integer_at_position (const std::string &name,
			   const unsigned int position)
  {
    Assert (position < name.size(), ExcInternalError());

    const std::string test_string (name.begin()+position,
				   name.end());

    std::istringstream str(test_string);

    int i;
    if (str >> i)
      {
					 // compute the number of
					 // digits of i. assuming it
					 // is less than 8 is likely
					 // ok
	if (i<10)
	  return std::make_pair (i, 1U);
	else if (i<100)
	  return std::make_pair (i, 2U);
	else if (i<1000)
	  return std::make_pair (i, 3U);
	else if (i<10000)
	  return std::make_pair (i, 4U);
	else if (i<100000)
	  return std::make_pair (i, 5U);
	else if (i<1000000)
	  return std::make_pair (i, 6U);
	else if (i<10000000)
	  return std::make_pair (i, 7U);
	else
	  {
	    Assert (false, ExcNotImplemented());
	    return std::make_pair (-1, numbers::invalid_unsigned_int);
	  }
      }
    else
      return std::make_pair (-1, numbers::invalid_unsigned_int);
  }

  double
  generate_normal_random_number (const double a,
				 const double sigma)
  {
				     // if no noise: return now
    if (sigma == 0)
      return a;

#ifdef HAVE_RAND_R
    static unsigned int seed = 0xabcd1234;
    const double y = 1.0*rand_r(&seed)/RAND_MAX;
#else
    const double y = 1.0*rand()/RAND_MAX;
#endif

				     // find x such that y=erf(x). do so
				     // using a Newton method to find
				     // the zero of F(x)=erf(x)-y. start
				     // at x=0
    double x = 0;
    unsigned int iteration = 0;
    while (true)
      {
	const double residual = 0.5+erf(x/std::sqrt(2.)/sigma)/2-y;
	if (std::fabs(residual) < 1e-7)
	  break;
	const double F_prime = 1./std::sqrt(2*3.1415926536)/sigma *
			       std::exp(-x*x/sigma/sigma/2);
	x += -residual / F_prime;

					 // make sure that we don't
					 // recurse endlessly
	++iteration;
	Assert (iteration < 20, ExcInternalError());
      };
    return x+a;
  }

  namespace System
  {
#if defined(__linux__)

    double get_cpu_load ()
    {
      std::ifstream cpuinfo;
      cpuinfo.open("/proc/loadavg");

      AssertThrow(cpuinfo, ExcIO());

      double load;
      cpuinfo >> load;

      return load;
    }

#else

    double get_cpu_load ()
    {
      return 0.;
    }

#endif

    std::string get_hostname ()
    {
      const unsigned int N=1024;
      char hostname[N];
      gethostname (&(hostname[0]), N-1);
      return hostname;
    }

    std::string get_time ()
    {
      std::time_t  time1= std::time (0);
      std::tm     *time = std::localtime(&time1);

      std::ostringstream o;
      o << time->tm_hour << ":"
        << (time->tm_min < 10 ? "0" : "") << time->tm_min << ":"
        << (time->tm_sec < 10 ? "0" : "") << time->tm_sec;

      return o.str();
    }

#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
                                // Unfortunately, we have to work
                                // around an oddity in the way PETSc
                                // and some gcc versions interact. If
                                // we use PETSc's MPI dummy
                                // implementation, it expands the
                                // calls to the two MPI functions
                                // basically as ``(n_jobs=1, 0)'',
                                // i.e. it assigns the number one to
                                // the variable holding the number of
                                // jobs, and then uses the comma
                                // operator to let the entire
                                // expression have the value zero. The
                                // latter is important, since
                                // ``MPI_Comm_size'' returns an error
                                // code that we may want to check (we
                                // don't here, but one could in
                                // principle), and the trick with the
                                // comma operator makes sure that both
                                // the number of jobs is correctly
                                // assigned, and the return value is
                                // zero. Unfortunately, if some recent
                                // versions of gcc detect that the
                                // comma expression just stands by
                                // itself, i.e. the result is not
                                // assigned to another variable, then
                                // they warn ``right-hand operand of
                                // comma has no effect''. This
                                // unwanted side effect can be
                                // suppressed by casting the result of
                                // the entire expression to type
                                // ``void'' -- not beautiful, but
                                // helps calming down unwarranted
                                // compiler warnings...
    unsigned int get_n_mpi_processes (
      const MPI_Comm &mpi_communicator)
    {
      int n_jobs=1;
      (void) MPI_Comm_size (mpi_communicator, &n_jobs);

      return n_jobs;
    }

    unsigned int get_this_mpi_process (
      const MPI_Comm &mpi_communicator)
    {
      int rank=0;
      (void) MPI_Comm_rank (mpi_communicator, &rank);

      return rank;
    }
#else
    unsigned int get_n_mpi_processes (const MPI_Comm &)
    {
      return 1;
    }

    unsigned int get_this_mpi_process (const MPI_Comm &)
    {
      return 0;
    }
#endif
  }

#ifdef DEAL_II_USE_TRILINOS

  TrilinosTools::TrilinosTools (int* argc, char*** argv)
                      :
                      owns_mpi (true),
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
		      use_mpi (true)
#else
		      use_mpi (false)
#endif
  {
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
    int MPI_has_been_started = 0;
    MPI_Initialized(&MPI_has_been_started);
    Assert (MPI_has_been_started == 0,
	    ExcMessage ("MPI error. You can only start MPI once!"));

    int mpi_err;
    mpi_err = MPI_Init (argc, argv);
    Assert (mpi_err == 0,
	    ExcMessage ("MPI could not be initialized."));

    communicator = Teuchos::rcp (new Epetra_MpiComm (MPI_COMM_WORLD), true);
#else
    communicator = Teuchos::rcp (new Epetra_SerialComm (MPI_COMM_WORLD), true);
#endif
  }

  TrilinosTools::TrilinosTools (const TrilinosTools &InputTrilinos)
                      :
                      owns_mpi (false),
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
		      use_mpi (true),
#else
		      use_mpi (false),
#endif
		      communicator (&*InputTrilinos.communicator, false)
  {}

  TrilinosTools::~TrilinosTools()
  {
    int mpi_err = 0;

#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
    if (use_mpi == true && owns_mpi == true)
      mpi_err = MPI_Finalize();
#endif

    Assert (mpi_err == 0,
	    ExcMessage ("An error occurred while calling MPI_Finalize()"));
  }

  const Epetra_Comm&
  TrilinosTools::comm() const
  {
    return *communicator;
  }

  bool
  TrilinosTools::trilinos_uses_mpi () const
  {
    return use_mpi;
  }

#endif

}

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Corrected one error.<commit_after>//---------------------------------------------------------------------------
//      $Id$
//    Version: $Name$
//
//    Copyright (C) 2005, 2006, 2008 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/utilities.h>
#include <base/exceptions.h>

#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cerrno>
#include <cmath>
#include <unistd.h>
#include <sys/types.h>
#include <sstream>

#ifdef HAVE_STD_NUMERIC_LIMITS
#  include <limits>
#else
#  include <limits.h>
#endif

DEAL_II_NAMESPACE_OPEN

namespace Utilities
{

  DeclException2 (ExcInvalidNumber2StringConversersion,
		  unsigned int, unsigned int,
		  << "When trying to convert " << arg1
		  << " to a string with " << arg2 << " digits");
  DeclException1 (ExcInvalidNumber,
		  unsigned int,
		  << "Invalid number " << arg1);
  DeclException1 (ExcCantConvertString,
		  std::string,
		  << "Can't convert the string " << arg1
                  << " to the desired type");

  std::string
  int_to_string (const unsigned int i,
		 const unsigned int digits)
  {
				     // if second argument is invalid, then do
				     // not pad the resulting string at all
    if (digits == numbers::invalid_unsigned_int)
      return int_to_string (i, needed_digits(i));

    AssertThrow ( ! ((digits==1 && i>=10)   ||
		     (digits==2 && i>=100)  ||
		     (digits==3 && i>=1000) ||
		     (digits==4 && i>=10000)||
		     (digits==5 && i>=100000)||
		     (i>=1000000)),
		  ExcInvalidNumber2StringConversersion(i, digits));

    std::string s;
    switch (digits)
      {
	case 6:
	      s += '0' + i/100000;
	case 5:
	      s += '0' + (i%100000)/10000;
	case 4:
	      s += '0' + (i%10000)/1000;
	case 3:
	      s += '0' + (i%1000)/100;
	case 2:
	      s += '0' + (i%100)/10;
	case 1:
	      s += '0' + i%10;
	      break;
	default:
	      s += "invalid digits information";
      };
    return s;
  }

  unsigned int
  needed_digits (const unsigned int max_number)
  {
    if (max_number < 10)
      return 1;
    if (max_number < 100)
      return 2;
    if (max_number < 1000)
      return 3;
    if (max_number < 10000)
      return 4;
    if (max_number < 100000)
      return 5;
    if (max_number < 1000000)
      return 6;
    AssertThrow (false, ExcInvalidNumber(max_number));
    return 0;
  }

  int
  string_to_int (const std::string &s)
  {
    std::istringstream ss(s);

#ifdef HAVE_STD_NUMERIC_LIMITS
    static const int max_int = std::numeric_limits<int>::max();
#else
    static const int max_int = INT_MAX;
#endif

    int i = max_int;
    ss >> i;

                                     // check for errors
    AssertThrow (i != max_int, ExcCantConvertString (s));

    return i;
  }

  std::vector<int>
  string_to_int (const std::vector<std::string> &s)
  {
    std::vector<int> tmp (s.size());
    for (unsigned int i=0; i<s.size(); ++i)
      tmp[i] = string_to_int (s[i]);
    return tmp;
  }

  std::vector<std::string>
  split_string_list (const std::string &s,
                     const char         delimiter)
  {
    std::string tmp = s;
    std::vector<std::string> split_list;
    split_list.reserve (std::count (tmp.begin(), tmp.end(), delimiter)+1);

				     // split the input list
    while (tmp.length() != 0)
      {
        std::string name;
	name = tmp;

	if (name.find(delimiter) != std::string::npos)
	  {
	    name.erase (name.find(delimiter), std::string::npos);
	    tmp.erase (0, tmp.find(delimiter)+1);
	  }
	else
	  tmp = "";

	while ((name.length() != 0) &&
	       (name[0] == ' '))
	  name.erase (0,1);

	while (name[name.length()-1] == ' ')
	  name.erase (name.length()-1, 1);

	split_list.push_back (name);
      }

    return split_list;
  }

  std::vector<std::string>
  break_text_into_lines (const std::string &original_text,
                         const unsigned int width,
                         const char delimiter)
  {
    std::string              text = original_text;
    std::vector<std::string> lines;

                                     // remove trailing spaces
    while ((text.length() != 0) && (text[text.length()-1] == delimiter))
      text.erase(text.length()-1,1);

                                     // then split the text into lines
    while (text.length() != 0)
      {
                                         // in each iteration, first remove
                                         // leading spaces
        while ((text.length() != 0) && (text[0] == delimiter))
          text.erase(0, 1);

                                         // if we can fit everything into one
                                         // line, then do so. otherwise, we have
                                         // to keep breaking
        if (text.length() < width)
          {
            lines.push_back (text);
            text = "";
          }
        else
          {
                                             // starting at position width, find the
                                             // location of the previous space, so
                                             // that we can break around there
            int location = std::min<int>(width,text.length()-1);
            for (; location>0; --location)
              if (text[location] == delimiter)
                break;

                                             // if there are no spaces, then try if
                                             // there are spaces coming up
            if (location == 0)
              for (location = std::min<int>(width,text.length()-1);
                   location<static_cast<int>(text.length());
                   ++location)
                if (text[location] == delimiter)
                  break;

                                             // now take the text up to the found
                                             // location and put it into a single
                                             // line, and remove it from 'text'
            lines.push_back (std::string (text, 0, location));
            text.erase (0, location);
          }
      }

    return lines;
  }

  bool
  match_at_string_start (const std::string &name,
			 const std::string &pattern)
  {
    if (pattern.size() > name.size())
      return false;

    for (unsigned int i=0; i<pattern.size(); ++i)
      if (pattern[i] != name[i])
	return false;

    return true;
  }

  std::pair<int, unsigned int>
  get_integer_at_position (const std::string &name,
			   const unsigned int position)
  {
    Assert (position < name.size(), ExcInternalError());

    const std::string test_string (name.begin()+position,
				   name.end());

    std::istringstream str(test_string);

    int i;
    if (str >> i)
      {
					 // compute the number of
					 // digits of i. assuming it
					 // is less than 8 is likely
					 // ok
	if (i<10)
	  return std::make_pair (i, 1U);
	else if (i<100)
	  return std::make_pair (i, 2U);
	else if (i<1000)
	  return std::make_pair (i, 3U);
	else if (i<10000)
	  return std::make_pair (i, 4U);
	else if (i<100000)
	  return std::make_pair (i, 5U);
	else if (i<1000000)
	  return std::make_pair (i, 6U);
	else if (i<10000000)
	  return std::make_pair (i, 7U);
	else
	  {
	    Assert (false, ExcNotImplemented());
	    return std::make_pair (-1, numbers::invalid_unsigned_int);
	  }
      }
    else
      return std::make_pair (-1, numbers::invalid_unsigned_int);
  }

  double
  generate_normal_random_number (const double a,
				 const double sigma)
  {
				     // if no noise: return now
    if (sigma == 0)
      return a;

#ifdef HAVE_RAND_R
    static unsigned int seed = 0xabcd1234;
    const double y = 1.0*rand_r(&seed)/RAND_MAX;
#else
    const double y = 1.0*rand()/RAND_MAX;
#endif

				     // find x such that y=erf(x). do so
				     // using a Newton method to find
				     // the zero of F(x)=erf(x)-y. start
				     // at x=0
    double x = 0;
    unsigned int iteration = 0;
    while (true)
      {
	const double residual = 0.5+erf(x/std::sqrt(2.)/sigma)/2-y;
	if (std::fabs(residual) < 1e-7)
	  break;
	const double F_prime = 1./std::sqrt(2*3.1415926536)/sigma *
			       std::exp(-x*x/sigma/sigma/2);
	x += -residual / F_prime;

					 // make sure that we don't
					 // recurse endlessly
	++iteration;
	Assert (iteration < 20, ExcInternalError());
      };
    return x+a;
  }

  namespace System
  {
#if defined(__linux__)

    double get_cpu_load ()
    {
      std::ifstream cpuinfo;
      cpuinfo.open("/proc/loadavg");

      AssertThrow(cpuinfo, ExcIO());

      double load;
      cpuinfo >> load;

      return load;
    }

#else

    double get_cpu_load ()
    {
      return 0.;
    }

#endif

    std::string get_hostname ()
    {
      const unsigned int N=1024;
      char hostname[N];
      gethostname (&(hostname[0]), N-1);
      return hostname;
    }

    std::string get_time ()
    {
      std::time_t  time1= std::time (0);
      std::tm     *time = std::localtime(&time1);

      std::ostringstream o;
      o << time->tm_hour << ":"
        << (time->tm_min < 10 ? "0" : "") << time->tm_min << ":"
        << (time->tm_sec < 10 ? "0" : "") << time->tm_sec;

      return o.str();
    }

#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
                                // Unfortunately, we have to work
                                // around an oddity in the way PETSc
                                // and some gcc versions interact. If
                                // we use PETSc's MPI dummy
                                // implementation, it expands the
                                // calls to the two MPI functions
                                // basically as ``(n_jobs=1, 0)'',
                                // i.e. it assigns the number one to
                                // the variable holding the number of
                                // jobs, and then uses the comma
                                // operator to let the entire
                                // expression have the value zero. The
                                // latter is important, since
                                // ``MPI_Comm_size'' returns an error
                                // code that we may want to check (we
                                // don't here, but one could in
                                // principle), and the trick with the
                                // comma operator makes sure that both
                                // the number of jobs is correctly
                                // assigned, and the return value is
                                // zero. Unfortunately, if some recent
                                // versions of gcc detect that the
                                // comma expression just stands by
                                // itself, i.e. the result is not
                                // assigned to another variable, then
                                // they warn ``right-hand operand of
                                // comma has no effect''. This
                                // unwanted side effect can be
                                // suppressed by casting the result of
                                // the entire expression to type
                                // ``void'' -- not beautiful, but
                                // helps calming down unwarranted
                                // compiler warnings...
    unsigned int get_n_mpi_processes (
      const MPI_Comm &mpi_communicator)
    {
      int n_jobs=1;
      (void) MPI_Comm_size (mpi_communicator, &n_jobs);

      return n_jobs;
    }

    unsigned int get_this_mpi_process (
      const MPI_Comm &mpi_communicator)
    {
      int rank=0;
      (void) MPI_Comm_rank (mpi_communicator, &rank);

      return rank;
    }
#else
    unsigned int get_n_mpi_processes (const MPI_Comm &)
    {
      return 1;
    }

    unsigned int get_this_mpi_process (const MPI_Comm &)
    {
      return 0;
    }
#endif
  }

#ifdef DEAL_II_USE_TRILINOS

  TrilinosTools::TrilinosTools (int* argc, char*** argv)
                      :
                      owns_mpi (true),
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
		      use_mpi (true)
#else
		      use_mpi (false)
#endif
  {
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
    int MPI_has_been_started = 0;
    MPI_Initialized(&MPI_has_been_started);
    Assert (MPI_has_been_started == 0,
	    ExcMessage ("MPI error. You can only start MPI once!"));

    int mpi_err;
    mpi_err = MPI_Init (argc, argv);
    Assert (mpi_err == 0,
	    ExcMessage ("MPI could not be initialized."));

    communicator = Teuchos::rcp (new Epetra_MpiComm (MPI_COMM_WORLD), true);
#else
    communicator = Teuchos::rcp (new Epetra_SerialComm (), true);
#endif
  }

  TrilinosTools::TrilinosTools (const TrilinosTools &InputTrilinos)
                      :
                      owns_mpi (false),
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
		      use_mpi (true),
#else
		      use_mpi (false),
#endif
		      communicator (&*InputTrilinos.communicator, false)
  {}

  TrilinosTools::~TrilinosTools()
  {
    int mpi_err = 0;

#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
    if (use_mpi == true && owns_mpi == true)
      mpi_err = MPI_Finalize();
#endif

    Assert (mpi_err == 0,
	    ExcMessage ("An error occurred while calling MPI_Finalize()"));
  }

  const Epetra_Comm&
  TrilinosTools::comm() const
  {
    return *communicator;
  }

  bool
  TrilinosTools::trilinos_uses_mpi () const
  {
    return use_mpi;
  }

#endif

}

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before>#include "aquila/global.h"
#include "aquila/source/generator/SineGenerator.h"
#include "aquila/source/Sum.h"
#include "aquila/transform/FftFactory.h"
#include "aquila/tools/TextPlot.h"
#include <algorithm>
#include <functional>
#include <memory>

int main()
{
    // input signal parameters
    const std::size_t SIZE = 64;
    const Aquila::FrequencyType sampleFreq = 2000;
    const Aquila::FrequencyType f1 = 96, f2 = 813;
    const Aquila::FrequencyType f_lp = 500;

    Aquila::SineGenerator sineGenerator1(sampleFreq);
    sineGenerator1.setAmplitude(32).setFrequency(f1).generate(SIZE);
    Aquila::SineGenerator sineGenerator2(sampleFreq);
    sineGenerator2.setAmplitude(8).setFrequency(f2).setPhase(0.75).generate(SIZE);
    Aquila::Sum sum(sineGenerator1, sineGenerator2);

    Aquila::TextPlot plt("Signal waveform before filtration");
    plt.plot(sum);

    // calculate the FFT
    auto fft = Aquila::FftFactory::getFft(SIZE);
    Aquila::ComplexType spectrum[SIZE];
    fft->fft(sum.toArray(), spectrum);
    plt.setTitle("Signal spectrum before filtration");
    plt.plotSpectrum(spectrum, SIZE);

    // generate a low-pass filter spectrum
    Aquila::ComplexType filterSpectrum[SIZE];
    for (std::size_t i = 0; i < SIZE; ++i)
    {
        if (i < (SIZE * f_lp / sampleFreq))
        {
            // passband
            filterSpectrum[i] = 1.0;
        }
        else
        {
            // stopband
            filterSpectrum[i] = 0.0;
        }
    }
    plt.setTitle("Filter spectrum");
    plt.plotSpectrum(filterSpectrum, SIZE);

    // the following line does the multiplication of two spectra
    // (which is complementary to convolution in time domain)
    typedef Aquila::ComplexType cplx;
    std::transform(spectrum, spectrum + SIZE, filterSpectrum, spectrum,
                   [] (cplx x, cplx y) { return x * y; });
    plt.setTitle("Signal spectrum after filtration");
    plt.plotSpectrum(spectrum, SIZE);

    // Inverse FFT moves us back to time domain
    double x1[SIZE];
    fft->ifft(spectrum, x1);
    plt.setTitle("Signal waveform after filtration");
    plt.plot(x1, SIZE);

    return 0;
}
<commit_msg>Updated frequency-domain filtering example.<commit_after>#include "aquila/global.h"
#include "aquila/source/generator/SineGenerator.h"
#include "aquila/source/Sum.h"
#include "aquila/transform/FftFactory.h"
#include "aquila/tools/TextPlot.h"
#include <algorithm>
#include <functional>
#include <memory>

int main()
{
    // input signal parameters
    const std::size_t SIZE = 64;
    const Aquila::FrequencyType sampleFreq = 2000;
    const Aquila::FrequencyType f1 = 96, f2 = 813;
    const Aquila::FrequencyType f_lp = 500;

    Aquila::SineGenerator sineGenerator1(sampleFreq);
    sineGenerator1.setAmplitude(32).setFrequency(f1).generate(SIZE);
    Aquila::SineGenerator sineGenerator2(sampleFreq);
    sineGenerator2.setAmplitude(8).setFrequency(f2).setPhase(0.75).generate(SIZE);
    Aquila::Sum sum(sineGenerator1, sineGenerator2);

    Aquila::TextPlot plt("Signal waveform before filtration");
    plt.plot(sum);

    // calculate the FFT
    auto fft = Aquila::FftFactory::getFft(SIZE);
    Aquila::SpectrumType spectrum = fft->fft(sum.toArray());
    plt.setTitle("Signal spectrum before filtration");
    plt.plotSpectrum(spectrum);

    // generate a low-pass filter spectrum
    Aquila::SpectrumType filterSpectrum(SIZE);
    for (std::size_t i = 0; i < SIZE; ++i)
    {
        if (i < (SIZE * f_lp / sampleFreq))
        {
            // passband
            filterSpectrum[i] = 1.0;
        }
        else
        {
            // stopband
            filterSpectrum[i] = 0.0;
        }
    }
    plt.setTitle("Filter spectrum");
    plt.plotSpectrum(filterSpectrum);

    // the following line does the multiplication of two spectra
    // (which is complementary to convolution in time domain)
    typedef Aquila::ComplexType cplx;
    std::transform(
        std::begin(spectrum),
        std::end(spectrum),
        std::begin(filterSpectrum),
        std::begin(spectrum),
        [] (cplx x, cplx y) { return x * y; }
    );
    plt.setTitle("Signal spectrum after filtration");
    plt.plotSpectrum(spectrum);

    // Inverse FFT moves us back to time domain
    double x1[SIZE];
    fft->ifft(&spectrum[0], x1);
    plt.setTitle("Signal waveform after filtration");
    plt.plot(x1, SIZE);

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2019-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <logging.h>
#include <logging/timer.h>
#include <test/util/setup_common.h>
#include <util/string.h>

#include <chrono>
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <utility>
#include <vector>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(logging_tests, BasicTestingSetup)

struct LogSetup : public BasicTestingSetup {
    fs::path prev_log_path;
    fs::path tmp_log_path;
    bool prev_reopen_file;
    bool prev_print_to_file;
    bool prev_log_timestamps;
    bool prev_log_threadnames;
    bool prev_log_sourcelocations;
    std::unordered_map<BCLog::LogFlags, BCLog::Level> prev_category_levels;
    BCLog::Level prev_log_level;

    LogSetup() : prev_log_path{LogInstance().m_file_path},
                 tmp_log_path{m_args.GetDataDirBase() / "tmp_debug.log"},
                 prev_reopen_file{LogInstance().m_reopen_file},
                 prev_print_to_file{LogInstance().m_print_to_file},
                 prev_log_timestamps{LogInstance().m_log_timestamps},
                 prev_log_threadnames{LogInstance().m_log_threadnames},
                 prev_log_sourcelocations{LogInstance().m_log_sourcelocations},
                 prev_category_levels{LogInstance().CategoryLevels()},
                 prev_log_level{LogInstance().LogLevel()}
    {
        LogInstance().m_file_path = tmp_log_path;
        LogInstance().m_reopen_file = true;
        LogInstance().m_print_to_file = true;
        LogInstance().m_log_timestamps = false;
        LogInstance().m_log_threadnames = false;

        // Prevent tests from failing when the line number of the logs changes.
        LogInstance().m_log_sourcelocations = false;

        LogInstance().SetLogLevel(BCLog::Level::Debug);
        LogInstance().SetCategoryLogLevel({});
    }

    ~LogSetup()
    {
        LogInstance().m_file_path = prev_log_path;
        LogPrintf("Sentinel log to reopen log file\n");
        LogInstance().m_print_to_file = prev_print_to_file;
        LogInstance().m_reopen_file = prev_reopen_file;
        LogInstance().m_log_timestamps = prev_log_timestamps;
        LogInstance().m_log_threadnames = prev_log_threadnames;
        LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
        LogInstance().SetLogLevel(prev_log_level);
        LogInstance().SetCategoryLogLevel(prev_category_levels);
    }
};

BOOST_AUTO_TEST_CASE(logging_timer)
{
    SetMockTime(1);
    auto micro_timer = BCLog::Timer<std::chrono::microseconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(micro_timer.LogMsg("test micros"), "tests: test micros (1000000μs)");

    SetMockTime(1);
    auto ms_timer = BCLog::Timer<std::chrono::milliseconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(ms_timer.LogMsg("test ms"), "tests: test ms (1000.00ms)");

    SetMockTime(1);
    auto sec_timer = BCLog::Timer<std::chrono::seconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(sec_timer.LogMsg("test secs"), "tests: test secs (1.00s)");
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintf_, LogSetup)
{
    LogInstance().m_log_sourcelocations = true;
    LogPrintf_("fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug, "foo1: %s", "bar1\n");
    LogPrintf_("fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::None, "foo2: %s", "bar2\n");
    LogPrintf_("fn3", "src3", 3, BCLog::LogFlags::NONE, BCLog::Level::Debug, "foo3: %s", "bar3\n");
    LogPrintf_("fn4", "src4", 4, BCLog::LogFlags::NONE, BCLog::Level::None, "foo4: %s", "bar4\n");
    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    std::vector<std::string> expected = {
        "[src1:1] [fn1] [net:debug] foo1: bar1",
        "[src2:2] [fn2] [net] foo2: bar2",
        "[src3:3] [fn3] [debug] foo3: bar3",
        "[src4:4] [fn4] foo4: bar4",
    };
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
{
    LogPrintf("foo5: %s\n", "bar5");
    LogPrint(BCLog::NET, "foo6: %s\n", "bar6");
    LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo7: %s\n", "bar7");
    LogPrintLevel(BCLog::NET, BCLog::Level::Info, "foo8: %s\n", "bar8");
    LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo9: %s\n", "bar9");
    LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo10: %s\n", "bar10");
    LogPrintfCategory(BCLog::VALIDATION, "foo11: %s\n", "bar11");
    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    std::vector<std::string> expected = {
        "foo5: bar5",
        "[net] foo6: bar6",
        "[net:debug] foo7: bar7",
        "[net:info] foo8: bar8",
        "[net:warning] foo9: bar9",
        "[net:error] foo10: bar10",
        "[validation] foo11: bar11",
    };
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros_CategoryName, LogSetup)
{
    LogInstance().EnableCategory(BCLog::LogFlags::ALL);
    const auto concatenated_category_names = LogInstance().LogCategoriesString();
    std::vector<std::pair<BCLog::LogFlags, std::string>> expected_category_names;
    const auto category_names = SplitString(concatenated_category_names, ',');
    for (const auto& category_name : category_names) {
        BCLog::LogFlags category;
        const auto trimmed_category_name = TrimString(category_name);
        BOOST_REQUIRE(GetLogCategory(category, trimmed_category_name));
        expected_category_names.emplace_back(category, trimmed_category_name);
    }

    std::vector<std::string> expected;
    for (const auto& [category, name] : expected_category_names) {
        LogPrint(category, "foo: %s\n", "bar");
        std::string expected_log = "[";
        expected_log += name;
        expected_log += "] foo: bar";
        expected.push_back(expected_log);
    }

    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Unit test coverage for log severity levels<commit_after>// Copyright (c) 2019-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <logging.h>
#include <logging/timer.h>
#include <test/util/setup_common.h>
#include <util/string.h>

#include <chrono>
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <utility>
#include <vector>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(logging_tests, BasicTestingSetup)

struct LogSetup : public BasicTestingSetup {
    fs::path prev_log_path;
    fs::path tmp_log_path;
    bool prev_reopen_file;
    bool prev_print_to_file;
    bool prev_log_timestamps;
    bool prev_log_threadnames;
    bool prev_log_sourcelocations;
    std::unordered_map<BCLog::LogFlags, BCLog::Level> prev_category_levels;
    BCLog::Level prev_log_level;

    LogSetup() : prev_log_path{LogInstance().m_file_path},
                 tmp_log_path{m_args.GetDataDirBase() / "tmp_debug.log"},
                 prev_reopen_file{LogInstance().m_reopen_file},
                 prev_print_to_file{LogInstance().m_print_to_file},
                 prev_log_timestamps{LogInstance().m_log_timestamps},
                 prev_log_threadnames{LogInstance().m_log_threadnames},
                 prev_log_sourcelocations{LogInstance().m_log_sourcelocations},
                 prev_category_levels{LogInstance().CategoryLevels()},
                 prev_log_level{LogInstance().LogLevel()}
    {
        LogInstance().m_file_path = tmp_log_path;
        LogInstance().m_reopen_file = true;
        LogInstance().m_print_to_file = true;
        LogInstance().m_log_timestamps = false;
        LogInstance().m_log_threadnames = false;

        // Prevent tests from failing when the line number of the logs changes.
        LogInstance().m_log_sourcelocations = false;

        LogInstance().SetLogLevel(BCLog::Level::Debug);
        LogInstance().SetCategoryLogLevel({});
    }

    ~LogSetup()
    {
        LogInstance().m_file_path = prev_log_path;
        LogPrintf("Sentinel log to reopen log file\n");
        LogInstance().m_print_to_file = prev_print_to_file;
        LogInstance().m_reopen_file = prev_reopen_file;
        LogInstance().m_log_timestamps = prev_log_timestamps;
        LogInstance().m_log_threadnames = prev_log_threadnames;
        LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
        LogInstance().SetLogLevel(prev_log_level);
        LogInstance().SetCategoryLogLevel(prev_category_levels);
    }
};

BOOST_AUTO_TEST_CASE(logging_timer)
{
    SetMockTime(1);
    auto micro_timer = BCLog::Timer<std::chrono::microseconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(micro_timer.LogMsg("test micros"), "tests: test micros (1000000μs)");

    SetMockTime(1);
    auto ms_timer = BCLog::Timer<std::chrono::milliseconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(ms_timer.LogMsg("test ms"), "tests: test ms (1000.00ms)");

    SetMockTime(1);
    auto sec_timer = BCLog::Timer<std::chrono::seconds>("tests", "end_msg");
    SetMockTime(2);
    BOOST_CHECK_EQUAL(sec_timer.LogMsg("test secs"), "tests: test secs (1.00s)");
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintf_, LogSetup)
{
    LogInstance().m_log_sourcelocations = true;
    LogPrintf_("fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug, "foo1: %s", "bar1\n");
    LogPrintf_("fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::None, "foo2: %s", "bar2\n");
    LogPrintf_("fn3", "src3", 3, BCLog::LogFlags::NONE, BCLog::Level::Debug, "foo3: %s", "bar3\n");
    LogPrintf_("fn4", "src4", 4, BCLog::LogFlags::NONE, BCLog::Level::None, "foo4: %s", "bar4\n");
    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    std::vector<std::string> expected = {
        "[src1:1] [fn1] [net:debug] foo1: bar1",
        "[src2:2] [fn2] [net] foo2: bar2",
        "[src3:3] [fn3] [debug] foo3: bar3",
        "[src4:4] [fn4] foo4: bar4",
    };
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
{
    LogPrintf("foo5: %s\n", "bar5");
    LogPrint(BCLog::NET, "foo6: %s\n", "bar6");
    LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo7: %s\n", "bar7");
    LogPrintLevel(BCLog::NET, BCLog::Level::Info, "foo8: %s\n", "bar8");
    LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo9: %s\n", "bar9");
    LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo10: %s\n", "bar10");
    LogPrintfCategory(BCLog::VALIDATION, "foo11: %s\n", "bar11");
    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    std::vector<std::string> expected = {
        "foo5: bar5",
        "[net] foo6: bar6",
        "[net:debug] foo7: bar7",
        "[net:info] foo8: bar8",
        "[net:warning] foo9: bar9",
        "[net:error] foo10: bar10",
        "[validation] foo11: bar11",
    };
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros_CategoryName, LogSetup)
{
    LogInstance().EnableCategory(BCLog::LogFlags::ALL);
    const auto concatenated_category_names = LogInstance().LogCategoriesString();
    std::vector<std::pair<BCLog::LogFlags, std::string>> expected_category_names;
    const auto category_names = SplitString(concatenated_category_names, ',');
    for (const auto& category_name : category_names) {
        BCLog::LogFlags category;
        const auto trimmed_category_name = TrimString(category_name);
        BOOST_REQUIRE(GetLogCategory(category, trimmed_category_name));
        expected_category_names.emplace_back(category, trimmed_category_name);
    }

    std::vector<std::string> expected;
    for (const auto& [category, name] : expected_category_names) {
        LogPrint(category, "foo: %s\n", "bar");
        std::string expected_log = "[";
        expected_log += name;
        expected_log += "] foo: bar";
        expected.push_back(expected_log);
    }

    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_FIXTURE_TEST_CASE(logging_SeverityLevels, LogSetup)
{
    LogInstance().EnableCategory(BCLog::LogFlags::ALL);

    LogInstance().SetLogLevel(BCLog::Level::Info);
    LogInstance().SetCategoryLogLevel(/*category_str=*/"net", /*level_str=*/"info");

    // Global log level
    LogPrintLevel(BCLog::HTTP, BCLog::Level::Info, "foo1: %s\n", "bar1");
    LogPrintLevel(BCLog::MEMPOOL, BCLog::Level::Debug, "foo2: %s. This log level is lower than the global one.\n", "bar2");
    LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Warning, "foo3: %s\n", "bar3");
    LogPrintLevel(BCLog::RPC, BCLog::Level::Error, "foo4: %s\n", "bar4");

    // Category-specific log level
    LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo5: %s\n", "bar5");
    LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo6: %s. This log level is lower than the category-specific one.\n", "bar6");
    LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo7: %s\n", "bar7");

    std::vector<std::string> expected = {
        "[http:info] foo1: bar1",
        "[validation:warning] foo3: bar3",
        "[rpc:error] foo4: bar4",
        "[net:warning] foo5: bar5",
        "[net:error] foo7: bar7",
    };
    std::ifstream file{tmp_log_path};
    std::vector<std::string> log_lines;
    for (std::string log; std::getline(file, log);) {
        log_lines.push_back(log);
    }
    BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkArray.cxx

-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkArray.h"
#include "vtkDenseArray.h"
#include "vtkSparseArray.h"
#include <vtkVariant.h>

#include <vtkstd/algorithm>

//
// Standard functions
//

//----------------------------------------------------------------------------

vtkArray::vtkArray()
{
}

//----------------------------------------------------------------------------

vtkArray::~vtkArray()
{
}

//----------------------------------------------------------------------------

void vtkArray::PrintSelf(ostream &os, vtkIndent indent)
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Name: " << this->Name << endl;

  os << indent << "Dimensions: " << this->GetDimensions() << endl;
  os << indent << "Extents: " << this->GetExtents() << endl;

  os << indent << "DimensionLabels:";
  for(DimensionT i = 0; i != this->GetDimensions(); ++i)
    os << " " << this->GetDimensionLabel(i);
  os << endl;

  os << indent << "Size: " << this->GetSize() << endl;
  os << indent << "NonNullSize: " << this->GetNonNullSize() << endl;
}

vtkArray* vtkArray::CreateArray(int StorageType, int ValueType)
{
  switch(StorageType)
    {
    case DENSE:
      {
      switch(ValueType)
        {
        case VTK_CHAR:
          return vtkDenseArray<char>::New();
        case VTK_SIGNED_CHAR:
          return vtkDenseArray<signed char>::New();
        case VTK_UNSIGNED_CHAR:
          return vtkDenseArray<unsigned char>::New();
        case VTK_SHORT:
          return vtkDenseArray<short>::New();
        case VTK_UNSIGNED_SHORT:
          return vtkDenseArray<unsigned short>::New();
        case VTK_INT:
          return vtkDenseArray<int>::New();
        case VTK_UNSIGNED_INT:
          return vtkDenseArray<unsigned int>::New();
        case VTK_LONG:
          return vtkDenseArray<long>::New();
        case VTK_UNSIGNED_LONG:
          return vtkDenseArray<unsigned long>::New();
#if defined(VTK_TYPE_USE_LONG_LONG)
        case VTK_LONG_LONG:
          return vtkDenseArray<long long>::New();
        case VTK_UNSIGNED_LONG_LONG:
          return vtkDenseArray<unsigned long long>::New();
#endif
#if defined(VTK_TYPE_USE___INT64)
        case VTK___INT64:
          return vtkDenseArray<__int64>::New();
        case VTK_UNSIGNED___INT64:
          return vtkDenseArray<unsigned __int64>::New();
#endif
        case VTK_FLOAT:
          return vtkDenseArray<float>::New();
        case VTK_DOUBLE:
          return vtkDenseArray<double>::New();
        case VTK_ID_TYPE:
          return vtkDenseArray<vtkIdType>::New();
        case VTK_STRING:
          return vtkDenseArray<vtkStdString>::New();
        case VTK_UNICODE_STRING:
          return vtkDenseArray<vtkUnicodeString>::New();
        case VTK_VARIANT:
          return vtkDenseArray<vtkVariant>::New();
        }
      vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown value type: " << vtkImageScalarTypeNameMacro(ValueType));
      return 0;
      }
    case SPARSE:
      {
      switch(ValueType)
        {
        case VTK_CHAR:
          return vtkSparseArray<char>::New();
        case VTK_SIGNED_CHAR:
          return vtkSparseArray<signed char>::New();
        case VTK_UNSIGNED_CHAR:
          return vtkSparseArray<unsigned char>::New();
        case VTK_SHORT:
          return vtkSparseArray<short>::New();
        case VTK_UNSIGNED_SHORT:
          return vtkSparseArray<unsigned short>::New();
        case VTK_INT:
          return vtkSparseArray<int>::New();
        case VTK_UNSIGNED_INT:
          return vtkSparseArray<unsigned int>::New();
        case VTK_LONG:
          return vtkSparseArray<long>::New();
        case VTK_UNSIGNED_LONG:
          return vtkSparseArray<unsigned long>::New();
#if defined(VTK_TYPE_USE_LONG_LONG)
        case VTK_LONG_LONG:
          return vtkSparseArray<long long>::New();
        case VTK_UNSIGNED_LONG_LONG:
          return vtkSparseArray<unsigned long long>::New();
#endif
#if defined(VTK_TYPE_USE___INT64)
        case VTK___INT64:
          return vtkSparseArray<__int64>::New();
        case VTK_UNSIGNED___INT64:
          return vtkSparseArray<unsigned __int64>::New();
#endif
        case VTK_FLOAT:
          return vtkSparseArray<float>::New();
        case VTK_DOUBLE:
          return vtkSparseArray<double>::New();
        case VTK_ID_TYPE:
          return vtkSparseArray<vtkIdType>::New();
        case VTK_STRING:
          return vtkSparseArray<vtkStdString>::New();
        case VTK_UNICODE_STRING:
          return vtkDenseArray<vtkUnicodeString>::New();
        case VTK_VARIANT:
          return vtkSparseArray<vtkVariant>::New();
        }
      vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown value type: " << vtkImageScalarTypeNameMacro(ValueType));
      return 0;
      }
    }

    vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown storage type: " << StorageType);
    return 0;
}

void vtkArray::Resize(const CoordinateT i)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i)));
}

void vtkArray::Resize(const vtkArrayRange& i)
{
  this->Resize(vtkArrayExtents(i));
}

void vtkArray::Resize(const CoordinateT i, const CoordinateT j)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i), vtkArrayRange(0, j)));
}

void vtkArray::Resize(const vtkArrayRange& i, const vtkArrayRange& j)
{
  this->Resize(vtkArrayExtents(i, j));
}

void vtkArray::Resize(const CoordinateT i, const CoordinateT j, const CoordinateT k)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i), vtkArrayRange(0, j), vtkArrayRange(0, k)));
}

void vtkArray::Resize(const vtkArrayRange& i, const vtkArrayRange& j, const vtkArrayRange& k)
{
  this->Resize(vtkArrayExtents(i, j, k));
}

void vtkArray::Resize(const vtkArrayExtents& extents)
{
  this->InternalResize(extents);
}

const vtkArrayRange vtkArray::GetExtent(DimensionT dimension)
{
  return this->GetExtents()[dimension];
}

vtkArray::DimensionT vtkArray::GetDimensions()
{
  return this->GetExtents().GetDimensions();
}

vtkTypeUInt64 vtkArray::GetSize()
{
  return this->GetExtents().GetSize();
}

void vtkArray::SetName(const vtkStdString& raw_name)
{
  // Don't allow newlines in array names ...
  vtkStdString name(raw_name);
  name.erase(vtkstd::remove(name.begin(), name.end(), '\r'), name.end());
  name.erase(vtkstd::remove(name.begin(), name.end(), '\n'), name.end());

  this->Name = name;
}

vtkStdString vtkArray::GetName()
{
  return this->Name;
}

void vtkArray::SetDimensionLabel(DimensionT i, const vtkStdString& raw_label)
{
  if(i < 0 || i >= this->GetDimensions())
    {
    vtkErrorMacro("Cannot set label for dimension " << i << " of a " << this->GetDimensions() << "-way array");
    return;
    }

  // Don't allow newlines in dimension labels ...
  vtkStdString label(raw_label);
  label.erase(vtkstd::remove(label.begin(), label.end(), '\r'), label.end());
  label.erase(vtkstd::remove(label.begin(), label.end(), '\n'), label.end());

  this->InternalSetDimensionLabel(i, label);
}

vtkStdString vtkArray::GetDimensionLabel(DimensionT i)
{
  if(i < 0 || i >= this->GetDimensions())
    {
    vtkErrorMacro("Cannot get label for dimension " << i << " of a " << this->GetDimensions() << "-way array");
    return "";
    }

  return this->InternalGetDimensionLabel(i);
}
<commit_msg>BUG: Fix typo in last commit.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkArray.cxx

-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkArray.h"
#include "vtkDenseArray.h"
#include "vtkSparseArray.h"
#include <vtkVariant.h>

#include <vtkstd/algorithm>

//
// Standard functions
//

//----------------------------------------------------------------------------

vtkArray::vtkArray()
{
}

//----------------------------------------------------------------------------

vtkArray::~vtkArray()
{
}

//----------------------------------------------------------------------------

void vtkArray::PrintSelf(ostream &os, vtkIndent indent)
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Name: " << this->Name << endl;

  os << indent << "Dimensions: " << this->GetDimensions() << endl;
  os << indent << "Extents: " << this->GetExtents() << endl;

  os << indent << "DimensionLabels:";
  for(DimensionT i = 0; i != this->GetDimensions(); ++i)
    os << " " << this->GetDimensionLabel(i);
  os << endl;

  os << indent << "Size: " << this->GetSize() << endl;
  os << indent << "NonNullSize: " << this->GetNonNullSize() << endl;
}

vtkArray* vtkArray::CreateArray(int StorageType, int ValueType)
{
  switch(StorageType)
    {
    case DENSE:
      {
      switch(ValueType)
        {
        case VTK_CHAR:
          return vtkDenseArray<char>::New();
        case VTK_SIGNED_CHAR:
          return vtkDenseArray<signed char>::New();
        case VTK_UNSIGNED_CHAR:
          return vtkDenseArray<unsigned char>::New();
        case VTK_SHORT:
          return vtkDenseArray<short>::New();
        case VTK_UNSIGNED_SHORT:
          return vtkDenseArray<unsigned short>::New();
        case VTK_INT:
          return vtkDenseArray<int>::New();
        case VTK_UNSIGNED_INT:
          return vtkDenseArray<unsigned int>::New();
        case VTK_LONG:
          return vtkDenseArray<long>::New();
        case VTK_UNSIGNED_LONG:
          return vtkDenseArray<unsigned long>::New();
#if defined(VTK_TYPE_USE_LONG_LONG)
        case VTK_LONG_LONG:
          return vtkDenseArray<long long>::New();
        case VTK_UNSIGNED_LONG_LONG:
          return vtkDenseArray<unsigned long long>::New();
#endif
#if defined(VTK_TYPE_USE___INT64)
        case VTK___INT64:
          return vtkDenseArray<__int64>::New();
        case VTK_UNSIGNED___INT64:
          return vtkDenseArray<unsigned __int64>::New();
#endif
        case VTK_FLOAT:
          return vtkDenseArray<float>::New();
        case VTK_DOUBLE:
          return vtkDenseArray<double>::New();
        case VTK_ID_TYPE:
          return vtkDenseArray<vtkIdType>::New();
        case VTK_STRING:
          return vtkDenseArray<vtkStdString>::New();
        case VTK_UNICODE_STRING:
          return vtkDenseArray<vtkUnicodeString>::New();
        case VTK_VARIANT:
          return vtkDenseArray<vtkVariant>::New();
        }
      vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown value type: " << vtkImageScalarTypeNameMacro(ValueType));
      return 0;
      }
    case SPARSE:
      {
      switch(ValueType)
        {
        case VTK_CHAR:
          return vtkSparseArray<char>::New();
        case VTK_SIGNED_CHAR:
          return vtkSparseArray<signed char>::New();
        case VTK_UNSIGNED_CHAR:
          return vtkSparseArray<unsigned char>::New();
        case VTK_SHORT:
          return vtkSparseArray<short>::New();
        case VTK_UNSIGNED_SHORT:
          return vtkSparseArray<unsigned short>::New();
        case VTK_INT:
          return vtkSparseArray<int>::New();
        case VTK_UNSIGNED_INT:
          return vtkSparseArray<unsigned int>::New();
        case VTK_LONG:
          return vtkSparseArray<long>::New();
        case VTK_UNSIGNED_LONG:
          return vtkSparseArray<unsigned long>::New();
#if defined(VTK_TYPE_USE_LONG_LONG)
        case VTK_LONG_LONG:
          return vtkSparseArray<long long>::New();
        case VTK_UNSIGNED_LONG_LONG:
          return vtkSparseArray<unsigned long long>::New();
#endif
#if defined(VTK_TYPE_USE___INT64)
        case VTK___INT64:
          return vtkSparseArray<__int64>::New();
        case VTK_UNSIGNED___INT64:
          return vtkSparseArray<unsigned __int64>::New();
#endif
        case VTK_FLOAT:
          return vtkSparseArray<float>::New();
        case VTK_DOUBLE:
          return vtkSparseArray<double>::New();
        case VTK_ID_TYPE:
          return vtkSparseArray<vtkIdType>::New();
        case VTK_STRING:
          return vtkSparseArray<vtkStdString>::New();
        case VTK_UNICODE_STRING:
          return vtkSparseArray<vtkUnicodeString>::New();
        case VTK_VARIANT:
          return vtkSparseArray<vtkVariant>::New();
        }
      vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown value type: " << vtkImageScalarTypeNameMacro(ValueType));
      return 0;
      }
    }

    vtkGenericWarningMacro(<< "vtkArrary::CreateArray() cannot create array with unknown storage type: " << StorageType);
    return 0;
}

void vtkArray::Resize(const CoordinateT i)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i)));
}

void vtkArray::Resize(const vtkArrayRange& i)
{
  this->Resize(vtkArrayExtents(i));
}

void vtkArray::Resize(const CoordinateT i, const CoordinateT j)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i), vtkArrayRange(0, j)));
}

void vtkArray::Resize(const vtkArrayRange& i, const vtkArrayRange& j)
{
  this->Resize(vtkArrayExtents(i, j));
}

void vtkArray::Resize(const CoordinateT i, const CoordinateT j, const CoordinateT k)
{
  this->Resize(vtkArrayExtents(vtkArrayRange(0, i), vtkArrayRange(0, j), vtkArrayRange(0, k)));
}

void vtkArray::Resize(const vtkArrayRange& i, const vtkArrayRange& j, const vtkArrayRange& k)
{
  this->Resize(vtkArrayExtents(i, j, k));
}

void vtkArray::Resize(const vtkArrayExtents& extents)
{
  this->InternalResize(extents);
}

const vtkArrayRange vtkArray::GetExtent(DimensionT dimension)
{
  return this->GetExtents()[dimension];
}

vtkArray::DimensionT vtkArray::GetDimensions()
{
  return this->GetExtents().GetDimensions();
}

vtkTypeUInt64 vtkArray::GetSize()
{
  return this->GetExtents().GetSize();
}

void vtkArray::SetName(const vtkStdString& raw_name)
{
  // Don't allow newlines in array names ...
  vtkStdString name(raw_name);
  name.erase(vtkstd::remove(name.begin(), name.end(), '\r'), name.end());
  name.erase(vtkstd::remove(name.begin(), name.end(), '\n'), name.end());

  this->Name = name;
}

vtkStdString vtkArray::GetName()
{
  return this->Name;
}

void vtkArray::SetDimensionLabel(DimensionT i, const vtkStdString& raw_label)
{
  if(i < 0 || i >= this->GetDimensions())
    {
    vtkErrorMacro("Cannot set label for dimension " << i << " of a " << this->GetDimensions() << "-way array");
    return;
    }

  // Don't allow newlines in dimension labels ...
  vtkStdString label(raw_label);
  label.erase(vtkstd::remove(label.begin(), label.end(), '\r'), label.end());
  label.erase(vtkstd::remove(label.begin(), label.end(), '\n'), label.end());

  this->InternalSetDimensionLabel(i, label);
}

vtkStdString vtkArray::GetDimensionLabel(DimensionT i)
{
  if(i < 0 || i >= this->GetDimensions())
    {
    vtkErrorMacro("Cannot get label for dimension " << i << " of a " << this->GetDimensions() << "-way array");
    return "";
    }

  return this->InternalGetDimensionLabel(i);
}
<|endoftext|>