<commit_before>/*************************************************************************/
/*  navigation_link_2d.cpp                                               */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "navigation_link_2d.h"

#include "core/math/geometry_2d.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"

void NavigationLink2D::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);

	ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
	ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);

	ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink2D::set_navigation_layers);
	ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink2D::get_navigation_layers);

	ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink2D::set_navigation_layer_value);
	ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink2D::get_navigation_layer_value);

	ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink2D::set_start_location);
	ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink2D::get_start_location);

	ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink2D::set_end_location);
	ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink2D::get_end_location);

	ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost);
	ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost);

	ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink2D::set_travel_cost);
	ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink2D::get_travel_cost);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_location"), "set_start_location", "get_start_location");
	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "end_location"), "set_end_location", "get_end_location");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}

void NavigationLink2D::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			if (enabled) {
				NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());

				// Update global positions for the link.
				Transform2D gt = get_global_transform();
				NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
				NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
			}
		} break;
		case NOTIFICATION_TRANSFORM_CHANGED: {
			// Update global positions for the link.
			Transform2D gt = get_global_transform();
			NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
			NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
		} break;
		case NOTIFICATION_EXIT_TREE: {
			NavigationServer2D::get_singleton()->link_set_map(link, RID());
		} break;
		case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
			if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
				Color color;
				if (enabled) {
					color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
				} else {
					color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
				}

				real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

				draw_line(get_start_location(), get_end_location(), color);
				draw_arc(get_start_location(), radius, 0, Math_TAU, 10, color);
				draw_arc(get_end_location(), radius, 0, Math_TAU, 10, color);
			}
#endif // DEBUG_ENABLED
		} break;
	}
}

#ifdef TOOLS_ENABLED
Rect2 NavigationLink2D::_edit_get_rect() const {
	real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

	Rect2 rect(get_start_location(), Size2());
	rect.expand_to(get_end_location());
	rect.grow_by(radius);
	return rect;
}

bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
	Point2 segment[2] = { get_start_location(), get_end_location() };

	Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, segment);
	return p_point.distance_to(closest_point) < p_tolerance;
}
#endif // TOOLS_ENABLED

void NavigationLink2D::set_enabled(bool p_enabled) {
	if (enabled == p_enabled) {
		return;
	}

	enabled = p_enabled;

	if (!is_inside_tree()) {
		return;
	}

	if (!enabled) {
		NavigationServer2D::get_singleton()->link_set_map(link, RID());
	} else {
		NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
	}

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		update();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
	if (bidirectional == p_bidirectional) {
		return;
	}

	bidirectional = p_bidirectional;

	NavigationServer2D::get_singleton()->link_set_bidirectional(link, bidirectional);
}

void NavigationLink2D::set_navigation_layers(uint32_t p_navigation_layers) {
	if (navigation_layers == p_navigation_layers) {
		return;
	}

	navigation_layers = p_navigation_layers;

	NavigationServer2D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
}

void NavigationLink2D::set_navigation_layer_value(int p_layer_number, bool p_value) {
	ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
	ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");

	uint32_t _navigation_layers = get_navigation_layers();

	if (p_value) {
		_navigation_layers |= 1 << (p_layer_number - 1);
	} else {
		_navigation_layers &= ~(1 << (p_layer_number - 1));
	}

	set_navigation_layers(_navigation_layers);
}

bool NavigationLink2D::get_navigation_layer_value(int p_layer_number) const {
	ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
	ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");

	return get_navigation_layers() & (1 << (p_layer_number - 1));
}

void NavigationLink2D::set_start_location(Vector2 p_location) {
	if (start_location.is_equal_approx(p_location)) {
		return;
	}

	start_location = p_location;

	if (!is_inside_tree()) {
		return;
	}

	Transform2D gt = get_global_transform();
	NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));

	update_configuration_warnings();

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		update();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_end_location(Vector2 p_location) {
	if (end_location.is_equal_approx(p_location)) {
		return;
	}

	end_location = p_location;

	if (!is_inside_tree()) {
		return;
	}

	Transform2D gt = get_global_transform();
	NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));

	update_configuration_warnings();

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		update();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_enter_cost(real_t p_enter_cost) {
	ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
	if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
		return;
	}

	enter_cost = p_enter_cost;

	NavigationServer2D::get_singleton()->link_set_enter_cost(link, enter_cost);
}

void NavigationLink2D::set_travel_cost(real_t p_travel_cost) {
	ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
	if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
		return;
	}

	travel_cost = p_travel_cost;

	NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost);
}

TypedArray<String> NavigationLink2D::get_configuration_warnings() const {
	TypedArray<String> warnings = Node::get_configuration_warnings();

	if (start_location.is_equal_approx(end_location)) {
		warnings.push_back(RTR("NavigationLink2D start location should be different than the end location to be useful."));
	}

	return warnings;
}

NavigationLink2D::NavigationLink2D() {
	link = NavigationServer2D::get_singleton()->link_create();
	set_notify_transform(true);
}

NavigationLink2D::~NavigationLink2D() {
	NavigationServer2D::get_singleton()->free(link);
	link = RID();
}
<commit_msg>Fix build after merge of #63479<commit_after>/*************************************************************************/
/*  navigation_link_2d.cpp                                               */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "navigation_link_2d.h"

#include "core/math/geometry_2d.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"

void NavigationLink2D::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);

	ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
	ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);

	ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink2D::set_navigation_layers);
	ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink2D::get_navigation_layers);

	ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink2D::set_navigation_layer_value);
	ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink2D::get_navigation_layer_value);

	ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink2D::set_start_location);
	ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink2D::get_start_location);

	ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink2D::set_end_location);
	ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink2D::get_end_location);

	ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost);
	ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost);

	ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink2D::set_travel_cost);
	ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink2D::get_travel_cost);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_location"), "set_start_location", "get_start_location");
	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "end_location"), "set_end_location", "get_end_location");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
}

void NavigationLink2D::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			if (enabled) {
				NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());

				// Update global positions for the link.
				Transform2D gt = get_global_transform();
				NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
				NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
			}
		} break;
		case NOTIFICATION_TRANSFORM_CHANGED: {
			// Update global positions for the link.
			Transform2D gt = get_global_transform();
			NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
			NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
		} break;
		case NOTIFICATION_EXIT_TREE: {
			NavigationServer2D::get_singleton()->link_set_map(link, RID());
		} break;
		case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
			if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
				Color color;
				if (enabled) {
					color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
				} else {
					color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
				}

				real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

				draw_line(get_start_location(), get_end_location(), color);
				draw_arc(get_start_location(), radius, 0, Math_TAU, 10, color);
				draw_arc(get_end_location(), radius, 0, Math_TAU, 10, color);
			}
#endif // DEBUG_ENABLED
		} break;
	}
}

#ifdef TOOLS_ENABLED
Rect2 NavigationLink2D::_edit_get_rect() const {
	real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

	Rect2 rect(get_start_location(), Size2());
	rect.expand_to(get_end_location());
	rect.grow_by(radius);
	return rect;
}

bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
	Point2 segment[2] = { get_start_location(), get_end_location() };

	Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, segment);
	return p_point.distance_to(closest_point) < p_tolerance;
}
#endif // TOOLS_ENABLED

void NavigationLink2D::set_enabled(bool p_enabled) {
	if (enabled == p_enabled) {
		return;
	}

	enabled = p_enabled;

	if (!is_inside_tree()) {
		return;
	}

	if (!enabled) {
		NavigationServer2D::get_singleton()->link_set_map(link, RID());
	} else {
		NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
	}

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		queue_redraw();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
	if (bidirectional == p_bidirectional) {
		return;
	}

	bidirectional = p_bidirectional;

	NavigationServer2D::get_singleton()->link_set_bidirectional(link, bidirectional);
}

void NavigationLink2D::set_navigation_layers(uint32_t p_navigation_layers) {
	if (navigation_layers == p_navigation_layers) {
		return;
	}

	navigation_layers = p_navigation_layers;

	NavigationServer2D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
}

void NavigationLink2D::set_navigation_layer_value(int p_layer_number, bool p_value) {
	ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
	ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");

	uint32_t _navigation_layers = get_navigation_layers();

	if (p_value) {
		_navigation_layers |= 1 << (p_layer_number - 1);
	} else {
		_navigation_layers &= ~(1 << (p_layer_number - 1));
	}

	set_navigation_layers(_navigation_layers);
}

bool NavigationLink2D::get_navigation_layer_value(int p_layer_number) const {
	ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
	ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");

	return get_navigation_layers() & (1 << (p_layer_number - 1));
}

void NavigationLink2D::set_start_location(Vector2 p_location) {
	if (start_location.is_equal_approx(p_location)) {
		return;
	}

	start_location = p_location;

	if (!is_inside_tree()) {
		return;
	}

	Transform2D gt = get_global_transform();
	NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));

	update_configuration_warnings();

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		queue_redraw();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_end_location(Vector2 p_location) {
	if (end_location.is_equal_approx(p_location)) {
		return;
	}

	end_location = p_location;

	if (!is_inside_tree()) {
		return;
	}

	Transform2D gt = get_global_transform();
	NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));

	update_configuration_warnings();

#ifdef DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
		queue_redraw();
	}
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_enter_cost(real_t p_enter_cost) {
	ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
	if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
		return;
	}

	enter_cost = p_enter_cost;

	NavigationServer2D::get_singleton()->link_set_enter_cost(link, enter_cost);
}

void NavigationLink2D::set_travel_cost(real_t p_travel_cost) {
	ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
	if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
		return;
	}

	travel_cost = p_travel_cost;

	NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost);
}

TypedArray<String> NavigationLink2D::get_configuration_warnings() const {
	TypedArray<String> warnings = Node::get_configuration_warnings();

	if (start_location.is_equal_approx(end_location)) {
		warnings.push_back(RTR("NavigationLink2D start location should be different than the end location to be useful."));
	}

	return warnings;
}

NavigationLink2D::NavigationLink2D() {
	link = NavigationServer2D::get_singleton()->link_create();
	set_notify_transform(true);
}

NavigationLink2D::~NavigationLink2D() {
	NavigationServer2D::get_singleton()->free(link);
	link = RID();
}
<|endoftext|>


<commit_before>namespace CTF_int{
double blres_mdl_init[] = {1.2880E-05, 1.1099E-08};
double long_contig_transp_mdl_init[] = {9.1201E-15, 2.1816E-09};
double shrt_contig_transp_mdl_init[] = {5.5768E-03, 1.7220E-08};
double non_contig_transp_mdl_init[] = {1.0753E-06, 4.1534E-08};
double dgtog_res_mdl_init[] = {-8.1392E-04, 1.2781E-04, 1.2295E-09};
double seq_tsr_ctr_mdl_cst_init[] = {3.8587E-13, 5.0935E-09, 4.2446E-10};
double seq_tsr_ctr_mdl_ref_init[] = {3.0374E-05, 6.9969E+00, -8.3962E+01};
double seq_tsr_ctr_mdl_inr_init[] = {-1.0012E-05, 2.8040E-10, 4.0944E-11};
double seq_tsr_ctr_mdl_off_init[] = {2.5413E-04, 1.5889E-10, 9.6735E-12};
double alltoall_mdl_init[] = {1.0000E-06, 1.0000E-06, 5.0000E-10};
double alltoallv_mdl_init[] = {-5.4974E-06, -1.4211E-05, 6.3309E-10};
double allred_mdl_init[] = {2.1127E-05, 2.7072E-06, 4.2328E-09};
double bcast_mdl_init[] = {6.7536E-05, 3.3990E-06, 2.4632E-09};
}

<commit_msg>New model parameters based on 400 sec training run on 384 cores of Edison with 6 processes per node. They seem to do well for AQ CCSD/CCSDT with flat MPI or threads on 384 cores.<commit_after>namespace CTF_int{
double blres_mdl_init[] = {3.7870E-05, 1.2061E-08};
double dgtog_res_mdl_init[] = {2.9484E-04, -3.7854E-05, 1.7446E-09};
double alltoall_mdl_init[] = {1.0000E-06, 1.0000E-06, 5.0000E-10};
double alltoallv_mdl_init[] = {-7.2507E-06, 1.0362E-05, 1.6246E-10};
double allred_mdl_init[] = {-3.0267E-06, 7.0181E-06, 3.8877E-09};
double bcast_mdl_init[] = {-3.5337E-07, 2.5071E-05, 1.5186E-09};
double long_contig_transp_mdl_init[] = {4.2322E-06, 1.3565E-09};
double shrt_contig_transp_mdl_init[] = {5.7366E-06, 2.0807E-09};
double non_contig_transp_mdl_init[] = {5.2266E-06, 2.9382E-09};
double seq_tsr_ctr_mdl_cst_init[] = {5.3745E-06, 3.6464E-08, 2.2334E-10};
double seq_tsr_ctr_mdl_ref_init[] = {5.3745E-06, 3.6464E-08, 2.2334E-10};
double seq_tsr_ctr_mdl_inr_init[] = {5.3745E-06, 3.6464E-11, 8.2334E-12};
double seq_tsr_ctr_mdl_off_init[] = {2.5413E-04, 1.5889E-10, 9.6735E-12};
}

<|endoftext|>


<commit_before>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
// pies of the Software, and to permit persons to whom the Software is furnished
//  to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "content/nw/src/shell_main_delegate.h"

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/nw/src/breakpad_linux.h"
#include "content/nw/src/chrome_breakpad_client.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/nw_version.h"
#include "content/nw/src/renderer/shell_content_renderer_client.h"
#include "content/nw/src/shell_browser_main.h"
#include "content/nw/src/shell_content_browser_client.h"
#include "net/cookies/cookie_monster.h"
#include "third_party/node/src/node_version.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_MACOSX)
#include "ui/base/l10n/l10n_util_mac.h"
#endif
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"

#include <stdio.h>

using base::FilePath;

#if defined(OS_MACOSX)
#include "content/nw/src/paths_mac.h"
#endif  // OS_MACOSX

#if defined(OS_WIN)
#include "base/logging_win.h"
#include <initguid.h>
#endif

#include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.

#if defined(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
    content::RegisterIPCLogger(msg_id, logger)
#include "content/nw/src/common/common_message_generator.h"
#include "components/autofill/core/common/autofill_messages.h"
#endif

namespace {

#if defined(OS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
// Wow6432Node key for x64 machines):
// 1. Find:  HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers
// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}"
// 3. Add these values:
//    "default_flags"=dword:00000001
//    "default_level"=dword:00000004
//    @="Content Shell"

// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}
const GUID kContentShellProviderName = {
    0x6a3e50a4, 0x7e15, 0x4099,
        { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
#endif

base::LazyInstance<chrome::ChromeBreakpadClient>::Leaky
    g_chrome_breakpad_client = LAZY_INSTANCE_INITIALIZER;

void InitLogging() {
  base::FilePath log_filename;
  PathService::Get(base::DIR_EXE, &log_filename);
  log_filename = log_filename.AppendASCII("debug.log");
  logging::LoggingSettings settings;
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableLogging)) {
    settings.logging_dest = logging::LOG_TO_ALL;
    settings.log_file = log_filename.value().c_str();
    settings.delete_old = logging::DELETE_OLD_LOG_FILE;
  }else{
#if defined(OS_WIN)
    settings.logging_dest = logging::LOG_NONE;
#endif
  }
  logging::InitLogging(settings);
  logging::SetLogItems(true, false, true, false);
}

}  // namespace

namespace content {

ShellMainDelegate::ShellMainDelegate() {
}

ShellMainDelegate::~ShellMainDelegate() {
}

bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
#if defined(OS_WIN)
  // Enable trace control and transport through event tracing for Windows.
  logging::LogEventProvider::Initialize(kContentShellProviderName);
#endif

  InitLogging();
  net::CookieMonster::EnableFileScheme();

  SetContentClient(&content_client_);
  return false;
}

void ShellMainDelegate::PreSandboxStartup() {
  breakpad::SetBreakpadClient(g_chrome_breakpad_client.Pointer());
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  std::string pref_locale;
  if (command_line->HasSwitch(switches::kLang)) {
    pref_locale = command_line->GetSwitchValueASCII(switches::kLang);
  }

#if defined(OS_MACOSX)
  OverrideFrameworkBundlePath();
  OverrideChildProcessPath();
  l10n_util::OverrideLocaleWithUserDefault();
#endif  // OS_MACOSX
  InitializeResourceBundle(pref_locale);

  std::string process_type =
      command_line->GetSwitchValueASCII(switches::kProcessType);

  if (process_type != switches::kZygoteProcess)
    InitCrashReporter();

  // Just prevent sandbox.
  command_line->AppendSwitch(switches::kNoSandbox);

  // Make sure we keep using only one render process for one app, by using the
  // process-per-tab mode, we can make Chrome only create new site instance
  // when we require to, the default mode is creating different site instances
  // for different domains.
  // This is needed because we want our Window API to have full control of new
  // windows created, which require all windows to be in one render process
  // host.
  command_line->AppendSwitch(switches::kProcessPerTab);

  // Allow file:// URIs can read other file:// URIs by default.
  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
  command_line->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
  command_line->AppendSwitch(switches::kEnableCssShaders);
}

int ShellMainDelegate::RunProcess(
    const std::string& process_type,
    const MainFunctionParams& main_function_params) {
  if (!process_type.empty())
    return -1;

  return ShellBrowserMain(main_function_params);
}

void ShellMainDelegate::InitializeResourceBundle(const std::string& pref_locale) {
  FilePath pak_file;
#if defined(OS_MACOSX)
  FilePath locale_file;
  if (!GetResourcesPakFilePath(pak_file))
    LOG(FATAL) << "nw.pak file not found.";
  std::string locale = l10n_util::GetApplicationLocale(pref_locale);
  if (!GetLocalePakFilePath(locale, locale_file))
    LOG(FATAL) << locale << ".pak file not found.";
  ui::ResourceBundle::InitSharedInstanceWithPakPath2(pak_file, locale_file);
#else
  FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  pak_file = pak_dir.Append(FILE_PATH_LITERAL("nw.pak"));
  CHECK(base::PathExists(pak_file)) << "nw.pak is missing";
  ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
#endif
}

ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
  browser_client_.reset(new ShellContentBrowserClient);
  return browser_client_.get();
}

ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() {
  renderer_client_.reset(new ShellContentRendererClient);
  return renderer_client_.get();
}

#if defined(OS_POSIX) && !defined(OS_MACOSX)
void ShellMainDelegate::ZygoteForked() {
  // Needs to be called after we have chrome::DIR_USER_DATA.  BrowserMain sets
  // this up for the browser process in a different manner.
  InitCrashReporter();
}
#endif

}  // namespace content
<commit_msg>Mac: fallback to en-US.pak on missing locale.pak<commit_after>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
// pies of the Software, and to permit persons to whom the Software is furnished
//  to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "content/nw/src/shell_main_delegate.h"

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/nw/src/breakpad_linux.h"
#include "content/nw/src/chrome_breakpad_client.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/nw_version.h"
#include "content/nw/src/renderer/shell_content_renderer_client.h"
#include "content/nw/src/shell_browser_main.h"
#include "content/nw/src/shell_content_browser_client.h"
#include "net/cookies/cookie_monster.h"
#include "third_party/node/src/node_version.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_MACOSX)
#include "ui/base/l10n/l10n_util_mac.h"
#endif
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"

#include <stdio.h>

using base::FilePath;

#if defined(OS_MACOSX)
#include "content/nw/src/paths_mac.h"
#endif  // OS_MACOSX

#if defined(OS_WIN)
#include "base/logging_win.h"
#include <initguid.h>
#endif

#include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.

#if defined(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
    content::RegisterIPCLogger(msg_id, logger)
#include "content/nw/src/common/common_message_generator.h"
#include "components/autofill/core/common/autofill_messages.h"
#endif

namespace {

#if defined(OS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
// Wow6432Node key for x64 machines):
// 1. Find:  HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers
// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}"
// 3. Add these values:
//    "default_flags"=dword:00000001
//    "default_level"=dword:00000004
//    @="Content Shell"

// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}
const GUID kContentShellProviderName = {
    0x6a3e50a4, 0x7e15, 0x4099,
        { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
#endif

base::LazyInstance<chrome::ChromeBreakpadClient>::Leaky
    g_chrome_breakpad_client = LAZY_INSTANCE_INITIALIZER;

void InitLogging() {
  base::FilePath log_filename;
  PathService::Get(base::DIR_EXE, &log_filename);
  log_filename = log_filename.AppendASCII("debug.log");
  logging::LoggingSettings settings;
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableLogging)) {
    settings.logging_dest = logging::LOG_TO_ALL;
    settings.log_file = log_filename.value().c_str();
    settings.delete_old = logging::DELETE_OLD_LOG_FILE;
  }else{
#if defined(OS_WIN)
    settings.logging_dest = logging::LOG_NONE;
#endif
  }
  logging::InitLogging(settings);
  logging::SetLogItems(true, false, true, false);
}

}  // namespace

namespace content {

ShellMainDelegate::ShellMainDelegate() {
}

ShellMainDelegate::~ShellMainDelegate() {
}

bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
#if defined(OS_WIN)
  // Enable trace control and transport through event tracing for Windows.
  logging::LogEventProvider::Initialize(kContentShellProviderName);
#endif

  InitLogging();
  net::CookieMonster::EnableFileScheme();

  SetContentClient(&content_client_);
  return false;
}

void ShellMainDelegate::PreSandboxStartup() {
  breakpad::SetBreakpadClient(g_chrome_breakpad_client.Pointer());
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  std::string pref_locale;
  if (command_line->HasSwitch(switches::kLang)) {
    pref_locale = command_line->GetSwitchValueASCII(switches::kLang);
  }

#if defined(OS_MACOSX)
  OverrideFrameworkBundlePath();
  OverrideChildProcessPath();
  l10n_util::OverrideLocaleWithUserDefault();
#endif  // OS_MACOSX
  InitializeResourceBundle(pref_locale);

  std::string process_type =
      command_line->GetSwitchValueASCII(switches::kProcessType);

  if (process_type != switches::kZygoteProcess)
    InitCrashReporter();

  // Just prevent sandbox.
  command_line->AppendSwitch(switches::kNoSandbox);

  // Make sure we keep using only one render process for one app, by using the
  // process-per-tab mode, we can make Chrome only create new site instance
  // when we require to, the default mode is creating different site instances
  // for different domains.
  // This is needed because we want our Window API to have full control of new
  // windows created, which require all windows to be in one render process
  // host.
  command_line->AppendSwitch(switches::kProcessPerTab);

  // Allow file:// URIs can read other file:// URIs by default.
  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
  command_line->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
  command_line->AppendSwitch(switches::kEnableCssShaders);
}

int ShellMainDelegate::RunProcess(
    const std::string& process_type,
    const MainFunctionParams& main_function_params) {
  if (!process_type.empty())
    return -1;

  return ShellBrowserMain(main_function_params);
}

void ShellMainDelegate::InitializeResourceBundle(const std::string& pref_locale) {
  FilePath pak_file;
#if defined(OS_MACOSX)
  FilePath locale_file;
  if (!GetResourcesPakFilePath(pak_file))
    LOG(FATAL) << "nw.pak file not found.";
  std::string locale = l10n_util::GetApplicationLocale(pref_locale);
  if (!GetLocalePakFilePath(locale, locale_file)) {
    LOG(WARNING) << locale << ".pak file not found.";
    locale = "en-US";
    if (!GetLocalePakFilePath(locale, locale_file))
      LOG(ERROR) << locale << ".pak file not found.";
  }
  ui::ResourceBundle::InitSharedInstanceWithPakPath2(pak_file, locale_file);
#else
  FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  pak_file = pak_dir.Append(FILE_PATH_LITERAL("nw.pak"));
  CHECK(base::PathExists(pak_file)) << "nw.pak is missing";
  ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
#endif
}

ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
  browser_client_.reset(new ShellContentBrowserClient);
  return browser_client_.get();
}

ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() {
  renderer_client_.reset(new ShellContentRendererClient);
  return renderer_client_.get();
}

#if defined(OS_POSIX) && !defined(OS_MACOSX)
void ShellMainDelegate::ZygoteForked() {
  // Needs to be called after we have chrome::DIR_USER_DATA.  BrowserMain sets
  // this up for the browser process in a different manner.
  InitCrashReporter();
}
#endif

}  // namespace content
<|endoftext|>


<commit_before>#include <algorithm>

#include "SpMP/CSR.hpp"

#include "CSR_Interface.h"

using namespace std;
using namespace SpMP;

// w = (alpha*A*x + beta*y + gamma)*z
template<class T, bool HAS_VALUE = true, bool HAS_Z = false>
static void SpMV_(
  int m,
  T *w,
  T alpha,
  const int *rowptr, const int *colidx, const T* values,
  const T *x,
  T beta,
  const T *y,
  T gamma,
  const T *z)
{
  assert(w != x);

  int base = rowptr[0];

  rowptr -= base;
  colidx -= base;
  if (values) values -= base;

  w -= base;
  x -= base;
  if (y) y -= base;
  if (z) z -= base;

//#define MEASURE_LOAD_BALANCE
#ifdef MEASURE_LOAD_BALANCE
  double barrierTimes[omp_get_max_threads()];
  double tBegin = omp_get_wtime();
#endif

#pragma omp parallel
  {
    int iBegin, iEnd;
    getLoadBalancedPartition(&iBegin, &iEnd, rowptr + base, m);
    iBegin += base;
    iEnd += base;

    if (1 == alpha) {
      if (0 == beta) {
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = gamma;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
      else {
        // alpha == 1 && beta != 0
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = beta*y[i];
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = beta*y[i] + gamma;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
    }
    else {
      // alpha != 1
      if (0 == beta) {
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum *= alpha;
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = gamma;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum *= alpha;
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
      else {
        // alpha != 1 && beta != 0
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = beta*y[i];
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum *= alpha;
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = beta*y[i] + gamma;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (values) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum *= alpha;
            if (z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
    } // alpha != 1

#ifdef MEASURE_LOAD_BALANCE
    double t = omp_get_wtime();
#pragma omp barrier
    barrierTimes[tid] = omp_get_wtime() - t;

#pragma omp barrier
#pragma omp master
    {
      double tEnd = omp_get_wtime();
      double barrierTimeSum = 0;
      for (int i = 0; i < nthreads; ++i) {
        barrierTimeSum += barrierTimes[i];
      }
      printf("%f load imbalance = %f\n", tEnd - tBegin, barrierTimeSum/(tEnd - tBegin)/nthreads);
    }
#undef MEASURE_LOAD_BALANCE
#endif // MEASURE_LOAD_BALANCE
  } // omp parallel
}

void multiplyWithVector(
  double *w,
  double alpha, const CSR *A, const double *x,
  double beta, const double *y,
  double gamma,
  const double *z)
{
  if (A->values) {
    if (z) {
      SpMV_<double, true, true>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
    else {
      SpMV_<double, true, false>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
  }
  else {
    if (z) {
      SpMV_<double, false, true>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
    else {
      SpMV_<double, false, false>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
  }
}

extern "C" {

void CSR_MultiplyWithVector(
  double *w,
  double alpha, const CSR_Handle *A, const double *x,
  double beta, const double *y,
  double gamma,
  const double *z)
{
  multiplyWithVector(w, alpha, (CSR *)A, x, beta, y, gamma, z);
}

void CSR_MultiplyWithDenseMatrix(
  double *W, int k, int wRowStride, int wColumnStride,
  double alpha, const CSR_Handle *A,
  const double *X, int xRowStride, int xColumnStride,
  double beta, const double *Y, int yRowStride, int yColumnStride,
  double gamma)
{
  ((CSR *)A)->multiplyWithDenseMatrix(
    W, k, wRowStride, wColumnStride,
    alpha,
    X, xRowStride, xColumnStride,
    beta, Y, yRowStride, yColumnStride,
    gamma);
}

} // extern "C"
<commit_msg>bug fix<commit_after>#include <algorithm>

#include "SpMP/CSR.hpp"

#include "CSR_Interface.h"

using namespace std;
using namespace SpMP;

// w = (alpha*A*x + beta*y + gamma)*z
template<class T, bool HAS_VALUE = true, bool HAS_Z = false>
static void SpMV_(
  int m,
  T *w,
  T alpha,
  const int *rowptr, const int *colidx, const T* values,
  const T *x,
  T beta,
  const T *y,
  T gamma,
  const T *z)
{
  assert(w != x);

  int base = rowptr[0];

  rowptr -= base;
  colidx -= base;
  if (values) values -= base;

  w -= base;
  x -= base;
  if (y) y -= base;
  if (z) z -= base;

//#define MEASURE_LOAD_BALANCE
#ifdef MEASURE_LOAD_BALANCE
  double barrierTimes[omp_get_max_threads()];
  double tBegin = omp_get_wtime();
#endif

#pragma omp parallel
  {
    int iBegin, iEnd;
    getLoadBalancedPartition(&iBegin, &iEnd, rowptr + base, m);
    iBegin += base;
    iEnd += base;

    if (1 == alpha) {
      if (0 == beta) {
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum += gamma;
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
      else {
        // alpha == 1 && beta != 0
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum += beta*y[i];
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum += beta*y[i] + gamma;
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
    }
    else {
      // alpha != 1
      if (0 == beta) {
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum *= alpha;
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum = alpha*sum + beta*y[i];
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
      else {
        // alpha != 1 && beta != 0
        if (0 == gamma) {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum = alpha*sum + beta*y[i];
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
        else {
          for (int i = iBegin; i < iEnd; ++i) {
            T sum = 0;
            for (int j = rowptr[i]; j < rowptr[i + 1]; ++j) {
              if (HAS_VALUE) {
                sum += values[j]*x[colidx[j]];
              }
              else {
                sum += x[colidx[j]];
              }
            }
            sum = alpha*sum + beta*y[i] + gamma;
            if (HAS_Z) w[i] = z[i]*sum;
            else w[i] = sum;
          }
        }
      }
    } // alpha != 1

#ifdef MEASURE_LOAD_BALANCE
    double t = omp_get_wtime();
#pragma omp barrier
    barrierTimes[tid] = omp_get_wtime() - t;

#pragma omp barrier
#pragma omp master
    {
      double tEnd = omp_get_wtime();
      double barrierTimeSum = 0;
      for (int i = 0; i < nthreads; ++i) {
        barrierTimeSum += barrierTimes[i];
      }
      printf("%f load imbalance = %f\n", tEnd - tBegin, barrierTimeSum/(tEnd - tBegin)/nthreads);
    }
#undef MEASURE_LOAD_BALANCE
#endif // MEASURE_LOAD_BALANCE
  } // omp parallel
}

void multiplyWithVector(
  double *w,
  double alpha, const CSR *A, const double *x,
  double beta, const double *y,
  double gamma,
  const double *z)
{
  if (A->values) {
    if (z) {
      SpMV_<double, true, true>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
    else {
      SpMV_<double, true, false>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
  }
  else {
    if (z) {
      SpMV_<double, false, true>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
    else {
      SpMV_<double, false, false>(
        A->m, w, alpha, A->rowptr, A->colidx, A->values, x, beta, y, gamma, z);
    }
  }
}

extern "C" {

void CSR_MultiplyWithVector(
  double *w,
  double alpha, const CSR_Handle *A, const double *x,
  double beta, const double *y,
  double gamma,
  const double *z)
{
  multiplyWithVector(w, alpha, (CSR *)A, x, beta, y, gamma, z);
}

void CSR_MultiplyWithDenseMatrix(
  double *W, int k, int wRowStride, int wColumnStride,
  double alpha, const CSR_Handle *A,
  const double *X, int xRowStride, int xColumnStride,
  double beta, const double *Y, int yRowStride, int yColumnStride,
  double gamma)
{
  ((CSR *)A)->multiplyWithDenseMatrix(
    W, k, wRowStride, wColumnStride,
    alpha,
    X, xRowStride, xColumnStride,
    beta, Y, yRowStride, yColumnStride,
    gamma);
}

} // extern "C"
<|endoftext|>


<commit_before>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "span_analyzer_frame.h"

#include "wx/aboutdlg.h"
#include "wx/xrc/xmlres.h"

#include "analysis_filter_manager_dialog.h"
#include "cable_file_manager_dialog.h"
#include "cable_unit_converter.h"
#include "file_handler.h"
#include "preferences_dialog.h"
#include "span_analyzer_app.h"
#include "span_analyzer_doc.h"
#include "span_analyzer_view.h"
#include "weather_load_case_manager_dialog.h"
#include "weather_load_case_unit_converter.h"
#include "xpm/icon.xpm"

DocumentFileDropTarget::DocumentFileDropTarget(wxWindow* parent) {
  parent_ = parent;

  // creates data object to store dropped information
  SetDataObject(new wxFileDataObject());
  SetDefaultAction(wxDragCopy);
}

bool DocumentFileDropTarget::OnDropFiles(wxCoord x, wxCoord y,
                                         const wxArrayString& filenames) {
  // gets data from drag-and-drop operation
  wxFileDataObject* data = dynamic_cast<wxFileDataObject*>(GetDataObject());

  // tests if file exists
  // only the first file in the list is processed
  const wxString& str_file = data->GetFilenames().front();
  if (wxFileName::Exists(str_file) == false) {
    return false;
  }

  // tests if extension matches application document
  wxFileName path(str_file);
  if (path.GetExt() == ".spananalyzer") {
    return false;
  }

  // freezes frame, opens document, and thaws frame
  parent_->Freeze();
  wxGetApp().manager_doc()->CreateDocument(str_file);
  parent_->Thaw();

  return true;
}

BEGIN_EVENT_TABLE(SpanAnalyzerFrame, wxDocParentFrame)
  EVT_MENU(XRCID("menuitem_edit_analysisfilters"), SpanAnalyzerFrame::OnMenuEditAnalysisFilters)
  EVT_MENU(XRCID("menuitem_edit_cables"), SpanAnalyzerFrame::OnMenuEditCables)
  EVT_MENU(XRCID("menuitem_edit_weathercases"), SpanAnalyzerFrame::OnMenuEditWeathercases)
  EVT_MENU(XRCID("menuitem_file_preferences"), SpanAnalyzerFrame::OnMenuFilePreferences)
  EVT_MENU(XRCID("menuitem_help_about"), SpanAnalyzerFrame::OnMenuHelpAbout)
  EVT_MENU(XRCID("menuitem_view_cable_model"), SpanAnalyzerFrame::OnMenuViewCableModel)
  EVT_MENU(XRCID("menuitem_view_log"), SpanAnalyzerFrame::OnMenuViewLog)
END_EVENT_TABLE()

SpanAnalyzerFrame::SpanAnalyzerFrame(wxDocManager* manager)
    : wxDocParentFrame(manager, nullptr, wxID_ANY, "Span Analyzer") {
  // loads dialog from virtual xrc file system
  wxXmlResource::Get()->LoadMenuBar(this, "span_analyzer_menubar");

  // sets the frame icon
  SetIcon(wxIcon(icon_xpm));

  // sets the drag and drop target
  SetDropTarget(new DocumentFileDropTarget(this));

  // tells aui manager to manage this frame
  manager_.SetManagedWindow(this);

  // creates status bar
  wxStatusBar* status_bar = CreateStatusBar();
  const int kFieldsCount = 2;
  const int widths_field[2] = {-1, 170};
  status_bar->SetFieldsCount(kFieldsCount);
  status_bar->SetStatusWidths(kFieldsCount, widths_field);

  // creates log AUI window and adds to manager
  wxAuiPaneInfo info;
  info.Name("Log");
  info.Float();
  info.Caption("Log");
  info.CloseButton(true);
  info.Show(false);
  pane_log_ = new LogPane(this);
  manager_.AddPane(pane_log_, info);

  manager_.Update();
}

SpanAnalyzerFrame::~SpanAnalyzerFrame() {
  // saves frame size to application config
  SpanAnalyzerConfig* config = wxGetApp().config();
  if (this->IsMaximized() == true) {
    config->size_frame = wxSize(0, 0);
  } else {
    config->size_frame = this->GetSize();
  }

  manager_.UnInit();
}

void SpanAnalyzerFrame::OnMenuEditAnalysisFilters(wxCommandEvent& event) {
  // gets application config and data
  const SpanAnalyzerConfig* config = wxGetApp().config();
  SpanAnalyzerData* data = wxGetApp().data();

  // creates and shows the analysis filter manager dialog
  AnalysisFilterManagerDialog dialog(this, &data->weathercases,
                                     &data->groups_filters);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating analysis filters.");

    // saves application data
    FileHandler::SaveAppData(config->filepath_data, *data, config->units);

    // updates document/views
    SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
    if (doc != nullptr) {
      UpdateHint hint(HintType::kAnalysisFilterGroupEdit);
      doc->UpdateAllViews(nullptr, &hint);
    }
  }
}

void SpanAnalyzerFrame::OnMenuEditCables(wxCommandEvent& event) {
  // gets application config and data
  const SpanAnalyzerConfig* config = wxGetApp().config();
  SpanAnalyzerData* data = wxGetApp().data();

  // creates and shows the cable file manager dialog
  CableFileManagerDialog dialog(this, config->units, &data->cablefiles);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating cables.");

    // saves application data
    FileHandler::SaveAppData(config->filepath_data, *data, config->units);
  }

  wxBusyCursor cursor;

  // updates document/views
  SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
  if (doc != nullptr) {
    doc->RunAnalysis();

    UpdateHint hint(HintType::kCablesEdit);
    doc->UpdateAllViews(nullptr, &hint);
  }
}

void SpanAnalyzerFrame::OnMenuEditWeathercases(
    wxCommandEvent& event) {
  // gets application data
  SpanAnalyzerData* data = wxGetApp().data();

  // shows an editor
  WeatherLoadCaseManagerDialog dialog(
      this,
      wxGetApp().config()->units,
      &data->weathercases);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating weathercases.");

    // saves application data
    FileHandler::SaveAppData(wxGetApp().config()->filepath_data, *data,
                             wxGetApp().config()->units);
  }

  // updates document/views
  SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
  if (doc != nullptr) {
    doc->RunAnalysis();

    UpdateHint hint(HintType::kWeathercasesEdit);
    doc->UpdateAllViews(nullptr, &hint);
  }
}

void SpanAnalyzerFrame::OnMenuFilePreferences(wxCommandEvent& event) {
  // gets the application config
  SpanAnalyzerConfig* config = wxGetApp().config();

  // stores a copy of the unit system before letting user edit
  units::UnitSystem units_before = config->units;

  // creates preferences editor dialog and shows
  // exits if user closes/cancels
  PreferencesDialog preferences(this, config);
  if (preferences.ShowModal() != wxID_OK) {
    return;
  }

  wxBusyCursor cursor;

  // application data change is implemented on app restart

  // converts unit system if it changed
  SpanAnalyzerData* data = wxGetApp().data();
  if (units_before != config->units) {
    wxLogVerbose("Converting unit system.");

    // converts app data
    for (auto iter = data->weathercases.begin();
         iter != data->weathercases.end(); iter++) {
      WeatherLoadCase* weathercase = *iter;
      WeatherLoadCaseUnitConverter::ConvertUnitSystem(
          units_before,
          config->units,
          *weathercase);
    }

    for (auto iter = data->cablefiles.begin(); iter != data->cablefiles.end();
         iter++) {
      CableFile* cablefile = *iter;
      CableUnitConverter::ConvertUnitSystem(
          units_before,
          config->units,
          cablefile->cable);
    }

    // updates document/views
    SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
    if (doc != nullptr) {
      doc->ConvertUnitSystem(units_before, config->units);
      doc->RunAnalysis();

      // updates views
      UpdateHint hint(HintType::kPreferencesEdit);
      doc->UpdateAllViews(nullptr, &hint);
    }
  }

  // updates logging level
  wxLog::SetLogLevel(config->level_log);
  if (config->level_log == wxLOG_Message) {
    wxLog::SetVerbose(false);
  } else if (config->level_log == wxLOG_Info) {
    wxLog::SetVerbose(true);
  }
}

void SpanAnalyzerFrame::OnMenuHelpAbout(wxCommandEvent& event) {
  // sets the dialog info
  wxAboutDialogInfo info;
  info.SetIcon(wxICON(icon));
  info.SetName(wxGetApp().GetAppDisplayName());
  info.SetVersion("0.2.0");
  info.SetCopyright("License:   http://unlicense.org/");
  info.SetDescription(
    "This application provides a GUI for calculating the sag-tension response\n"
    "of transmission line cables.\n"
    "\n"
    "This application is part of the Overhead Transmission Line Software\n"
    "suite. For the actual engineering modeling and sag-tension computations,\n"
    "see the Models library.\n"
     "\n"
    "This software was developed so that transmission engineers can know\n"
    "exactly how results are calculated, and so that the software can be\n"
    "freely modified to fit the unique needs of the utility they represent.\n"
    "\n"
    "To get involved in project development, or to review the code, see the\n"
    "website link.");
  info.SetWebSite("https://github.com/OverheadTransmissionLineSoftware/SpanAnalyzer");

  // shows the dialog
  wxAboutBox(info, this);
}

void SpanAnalyzerFrame::OnMenuViewCableModel(wxCommandEvent& event) {
  wxAuiPaneInfo& info = manager_.GetPane("Cable");
  if (info.IsShown() == false) {
    info.Show(true);
  } else {
    info.Show(false);
  }

  manager_.Update();
}

void SpanAnalyzerFrame::OnMenuViewLog(wxCommandEvent& event) {
  wxAuiPaneInfo& info = manager_.GetPane("Log");
  if (info.IsShown() == false) {
    info.Show(true);
  } else {
    info.Show(false);
  }

  manager_.Update();
}

LogPane* SpanAnalyzerFrame::pane_log() {
  return pane_log_;
}
<commit_msg>Updated version number.<commit_after>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "span_analyzer_frame.h"

#include "wx/aboutdlg.h"
#include "wx/xrc/xmlres.h"

#include "analysis_filter_manager_dialog.h"
#include "cable_file_manager_dialog.h"
#include "cable_unit_converter.h"
#include "file_handler.h"
#include "preferences_dialog.h"
#include "span_analyzer_app.h"
#include "span_analyzer_doc.h"
#include "span_analyzer_view.h"
#include "weather_load_case_manager_dialog.h"
#include "weather_load_case_unit_converter.h"
#include "xpm/icon.xpm"

DocumentFileDropTarget::DocumentFileDropTarget(wxWindow* parent) {
  parent_ = parent;

  // creates data object to store dropped information
  SetDataObject(new wxFileDataObject());
  SetDefaultAction(wxDragCopy);
}

bool DocumentFileDropTarget::OnDropFiles(wxCoord x, wxCoord y,
                                         const wxArrayString& filenames) {
  // gets data from drag-and-drop operation
  wxFileDataObject* data = dynamic_cast<wxFileDataObject*>(GetDataObject());

  // tests if file exists
  // only the first file in the list is processed
  const wxString& str_file = data->GetFilenames().front();
  if (wxFileName::Exists(str_file) == false) {
    return false;
  }

  // tests if extension matches application document
  wxFileName path(str_file);
  if (path.GetExt() == ".spananalyzer") {
    return false;
  }

  // freezes frame, opens document, and thaws frame
  parent_->Freeze();
  wxGetApp().manager_doc()->CreateDocument(str_file);
  parent_->Thaw();

  return true;
}

BEGIN_EVENT_TABLE(SpanAnalyzerFrame, wxDocParentFrame)
  EVT_MENU(XRCID("menuitem_edit_analysisfilters"), SpanAnalyzerFrame::OnMenuEditAnalysisFilters)
  EVT_MENU(XRCID("menuitem_edit_cables"), SpanAnalyzerFrame::OnMenuEditCables)
  EVT_MENU(XRCID("menuitem_edit_weathercases"), SpanAnalyzerFrame::OnMenuEditWeathercases)
  EVT_MENU(XRCID("menuitem_file_preferences"), SpanAnalyzerFrame::OnMenuFilePreferences)
  EVT_MENU(XRCID("menuitem_help_about"), SpanAnalyzerFrame::OnMenuHelpAbout)
  EVT_MENU(XRCID("menuitem_view_cable_model"), SpanAnalyzerFrame::OnMenuViewCableModel)
  EVT_MENU(XRCID("menuitem_view_log"), SpanAnalyzerFrame::OnMenuViewLog)
END_EVENT_TABLE()

SpanAnalyzerFrame::SpanAnalyzerFrame(wxDocManager* manager)
    : wxDocParentFrame(manager, nullptr, wxID_ANY, "Span Analyzer") {
  // loads dialog from virtual xrc file system
  wxXmlResource::Get()->LoadMenuBar(this, "span_analyzer_menubar");

  // sets the frame icon
  SetIcon(wxIcon(icon_xpm));

  // sets the drag and drop target
  SetDropTarget(new DocumentFileDropTarget(this));

  // tells aui manager to manage this frame
  manager_.SetManagedWindow(this);

  // creates status bar
  wxStatusBar* status_bar = CreateStatusBar();
  const int kFieldsCount = 2;
  const int widths_field[2] = {-1, 170};
  status_bar->SetFieldsCount(kFieldsCount);
  status_bar->SetStatusWidths(kFieldsCount, widths_field);

  // creates log AUI window and adds to manager
  wxAuiPaneInfo info;
  info.Name("Log");
  info.Float();
  info.Caption("Log");
  info.CloseButton(true);
  info.Show(false);
  pane_log_ = new LogPane(this);
  manager_.AddPane(pane_log_, info);

  manager_.Update();
}

SpanAnalyzerFrame::~SpanAnalyzerFrame() {
  // saves frame size to application config
  SpanAnalyzerConfig* config = wxGetApp().config();
  if (this->IsMaximized() == true) {
    config->size_frame = wxSize(0, 0);
  } else {
    config->size_frame = this->GetSize();
  }

  manager_.UnInit();
}

void SpanAnalyzerFrame::OnMenuEditAnalysisFilters(wxCommandEvent& event) {
  // gets application config and data
  const SpanAnalyzerConfig* config = wxGetApp().config();
  SpanAnalyzerData* data = wxGetApp().data();

  // creates and shows the analysis filter manager dialog
  AnalysisFilterManagerDialog dialog(this, &data->weathercases,
                                     &data->groups_filters);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating analysis filters.");

    // saves application data
    FileHandler::SaveAppData(config->filepath_data, *data, config->units);

    // updates document/views
    SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
    if (doc != nullptr) {
      UpdateHint hint(HintType::kAnalysisFilterGroupEdit);
      doc->UpdateAllViews(nullptr, &hint);
    }
  }
}

void SpanAnalyzerFrame::OnMenuEditCables(wxCommandEvent& event) {
  // gets application config and data
  const SpanAnalyzerConfig* config = wxGetApp().config();
  SpanAnalyzerData* data = wxGetApp().data();

  // creates and shows the cable file manager dialog
  CableFileManagerDialog dialog(this, config->units, &data->cablefiles);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating cables.");

    // saves application data
    FileHandler::SaveAppData(config->filepath_data, *data, config->units);
  }

  wxBusyCursor cursor;

  // updates document/views
  SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
  if (doc != nullptr) {
    doc->RunAnalysis();

    UpdateHint hint(HintType::kCablesEdit);
    doc->UpdateAllViews(nullptr, &hint);
  }
}

void SpanAnalyzerFrame::OnMenuEditWeathercases(
    wxCommandEvent& event) {
  // gets application data
  SpanAnalyzerData* data = wxGetApp().data();

  // shows an editor
  WeatherLoadCaseManagerDialog dialog(
      this,
      wxGetApp().config()->units,
      &data->weathercases);
  if (dialog.ShowModal() == wxID_OK) {
    wxBusyCursor cursor;

    wxLogVerbose("Updating weathercases.");

    // saves application data
    FileHandler::SaveAppData(wxGetApp().config()->filepath_data, *data,
                             wxGetApp().config()->units);
  }

  // updates document/views
  SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
  if (doc != nullptr) {
    doc->RunAnalysis();

    UpdateHint hint(HintType::kWeathercasesEdit);
    doc->UpdateAllViews(nullptr, &hint);
  }
}

void SpanAnalyzerFrame::OnMenuFilePreferences(wxCommandEvent& event) {
  // gets the application config
  SpanAnalyzerConfig* config = wxGetApp().config();

  // stores a copy of the unit system before letting user edit
  units::UnitSystem units_before = config->units;

  // creates preferences editor dialog and shows
  // exits if user closes/cancels
  PreferencesDialog preferences(this, config);
  if (preferences.ShowModal() != wxID_OK) {
    return;
  }

  wxBusyCursor cursor;

  // application data change is implemented on app restart

  // converts unit system if it changed
  SpanAnalyzerData* data = wxGetApp().data();
  if (units_before != config->units) {
    wxLogVerbose("Converting unit system.");

    // converts app data
    for (auto iter = data->weathercases.begin();
         iter != data->weathercases.end(); iter++) {
      WeatherLoadCase* weathercase = *iter;
      WeatherLoadCaseUnitConverter::ConvertUnitSystem(
          units_before,
          config->units,
          *weathercase);
    }

    for (auto iter = data->cablefiles.begin(); iter != data->cablefiles.end();
         iter++) {
      CableFile* cablefile = *iter;
      CableUnitConverter::ConvertUnitSystem(
          units_before,
          config->units,
          cablefile->cable);
    }

    // updates document/views
    SpanAnalyzerDoc* doc = wxGetApp().GetDocument();
    if (doc != nullptr) {
      doc->ConvertUnitSystem(units_before, config->units);
      doc->RunAnalysis();

      // updates views
      UpdateHint hint(HintType::kPreferencesEdit);
      doc->UpdateAllViews(nullptr, &hint);
    }
  }

  // updates logging level
  wxLog::SetLogLevel(config->level_log);
  if (config->level_log == wxLOG_Message) {
    wxLog::SetVerbose(false);
  } else if (config->level_log == wxLOG_Info) {
    wxLog::SetVerbose(true);
  }
}

void SpanAnalyzerFrame::OnMenuHelpAbout(wxCommandEvent& event) {
  // sets the dialog info
  wxAboutDialogInfo info;
  info.SetIcon(wxICON(icon));
  info.SetName(wxGetApp().GetAppDisplayName());
  info.SetVersion("0.3.0");
  info.SetCopyright("License:   http://unlicense.org/");
  info.SetDescription(
    "This application provides a GUI for calculating the sag-tension response\n"
    "of transmission line cables.\n"
    "\n"
    "This application is part of the Overhead Transmission Line Software\n"
    "suite. For the actual engineering modeling and sag-tension computations,\n"
    "see the Models library.\n"
     "\n"
    "This software was developed so that transmission engineers can know\n"
    "exactly how results are calculated, and so that the software can be\n"
    "freely modified to fit the unique needs of the utility they represent.\n"
    "\n"
    "To get involved in project development, or to review the code, see the\n"
    "website link.");
  info.SetWebSite("https://github.com/OverheadTransmissionLineSoftware/SpanAnalyzer");

  // shows the dialog
  wxAboutBox(info, this);
}

void SpanAnalyzerFrame::OnMenuViewCableModel(wxCommandEvent& event) {
  wxAuiPaneInfo& info = manager_.GetPane("Cable");
  if (info.IsShown() == false) {
    info.Show(true);
  } else {
    info.Show(false);
  }

  manager_.Update();
}

void SpanAnalyzerFrame::OnMenuViewLog(wxCommandEvent& event) {
  wxAuiPaneInfo& info = manager_.GetPane("Log");
  if (info.IsShown() == false) {
    info.Show(true);
  } else {
    info.Show(false);
  }

  manager_.Update();
}

LogPane* SpanAnalyzerFrame::pane_log() {
  return pane_log_;
}
<|endoftext|>


<commit_before>/** ==========================================================================
 * Original code made by Robert Engeln. Given as a PUBLIC DOMAIN dedication for
 * the benefit of g3log.  It was originally published at:
 * http://code-freeze.blogspot.com/2012/01/generating-stack-traces-from-c.html

 * 2014-2015: adapted for g3log by Kjell Hedstrom (KjellKod).
 *
 * This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================*/

#include "g3log/stacktrace_windows.hpp"

#include <windows.h>
#include <dbghelp.h>
#include <map>
#include <memory>
#include <cassert>
#include <vector>
#include <mutex>
#include <g3log/g3log.hpp>

#pragma comment(lib, "dbghelp.lib")

#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
#error "stacktrace_win.cpp used but not on a windows system"
#endif

#define g3_MAP_PAIR_STRINGIFY(x) {x, #x}

namespace {
   thread_local size_t g_thread_local_recursive_crash_check = 0;

   const std::map<g3::SignalType, std::string> kExceptionsAsText = {
      g3_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_DATATYPE_MISALIGNMENT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INVALID_OPERATION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_STACK_CHECK)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_UNDERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ILLEGAL_INSTRUCTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_IN_PAGE_ERROR)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_DIVIDE_BY_ZERO)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INVALID_DISPOSITION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_STACK_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP)

   };

   // Using the given context, fill in all the stack frames.
   // Which then later can be interpreted to human readable text
   void captureStackTrace(CONTEXT *context, std::vector<uint64_t> &frame_pointers) {
      DWORD machine_type = 0;
      STACKFRAME64 frame = {}; // force zeroing
      frame.AddrPC.Mode = AddrModeFlat;
      frame.AddrFrame.Mode = AddrModeFlat;
      frame.AddrStack.Mode = AddrModeFlat;
#ifdef _M_X64
      frame.AddrPC.Offset = context->Rip;
      frame.AddrFrame.Offset = context->Rbp;
      frame.AddrStack.Offset = context->Rsp;
      machine_type = IMAGE_FILE_MACHINE_AMD64;
#else
      frame.AddrPC.Offset = context->Eip;
      frame.AddrPC.Offset = context->Ebp;
      frame.AddrPC.Offset = context->Esp;
      machine_type = IMAGE_FILE_MACHINE_I386;
#endif
      for (size_t index = 0; index < frame_pointers.size(); ++index)
      {
         if (StackWalk64(machine_type,
                         GetCurrentProcess(),
                         GetCurrentThread(),
                         &frame,
                         context,
                         NULL,
                         SymFunctionTableAccess64,
                         SymGetModuleBase64,
                         NULL)) {
            frame_pointers[index] = frame.AddrPC.Offset;
         } else {
            break;
         }
      }
   }

   // extract readable text from a given stack frame. All thanks to
   // using SymFromAddr and SymGetLineFromAddr64 with the stack pointer
   std::string getSymbolInformation(const size_t index, const std::vector<uint64_t> &frame_pointers) {
      auto addr = frame_pointers[index];
      std::string frame_dump = "stack dump [" + std::to_string(index) + "]\t";

      DWORD64 displacement64;
      DWORD displacement;
      char symbol_buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
      SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(symbol_buffer);
      symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
      symbol->MaxNameLen = MAX_SYM_NAME;

      IMAGEHLP_LINE64 line;
      line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
      std::string lineInformation;
      std::string callInformation;
      if (SymFromAddr(GetCurrentProcess(), addr, &displacement64, symbol)) {
         callInformation.append(" ").append(std::string(symbol->Name, symbol->NameLen));
         if (SymGetLineFromAddr64(GetCurrentProcess(), addr, &displacement, &line)) {
            lineInformation.append("\t").append(line.FileName).append(" L: ");
            lineInformation.append(std::to_string(line.LineNumber));
         }
      }
      frame_dump.append(lineInformation).append(callInformation);
      return frame_dump;
   }

   // Retrieves all the symbols for the stack frames, fills them within a text representation and returns it
   std::string convertFramesToText(std::vector<uint64_t> &frame_pointers) {
      std::string dump; // slightly more efficient than ostringstream
      const size_t kSize = frame_pointers.size();
      for (size_t index = 0; index < kSize && frame_pointers[index]; ++index) {
         dump += getSymbolInformation(index, frame_pointers);
         dump += "\n";
      }
      return dump;
   }
} // anonymous

namespace stacktrace {
   const std::string kUnknown = {"UNKNOWN EXCEPTION"};
   /// return the text description of a Windows exception code
   /// From MSDN GetExceptionCode http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx
   std::string exceptionIdToText(g3::SignalType id) {
      const auto iter = kExceptionsAsText.find(id);
      if ( iter == kExceptionsAsText.end()) {
         std::string unknown = {kUnknown + ":" + std::to_string(id)};
         return unknown;
      }
      return iter->second;
   }

   /// Yes a double lookup: first for isKnownException and then exceptionIdToText
   /// for vectored exceptions we only deal with known exceptions so this tiny
   /// overhead we can live with
   bool isKnownException(g3::SignalType id) {
      return (kExceptionsAsText.end() != kExceptionsAsText.find(id));
   }

   /// helper function: retrieve stackdump from no excisting exception pointer
   std::string stackdump() {
      CONTEXT current_context;
      memset(&current_context, 0, sizeof(CONTEXT));
      RtlCaptureContext(&current_context);
      return stackdump(&current_context);
   }

   /// helper function: retrieve stackdump, starting from an exception pointer
   std::string stackdump(EXCEPTION_POINTERS *info) {
      auto context = info->ContextRecord;
      return stackdump(context);

   }

   /// main stackdump function. retrieve stackdump, from the given context
   std::string stackdump(CONTEXT *context) {

      if (g_thread_local_recursive_crash_check >= 2) { // In Debug scenarios we allow one extra pass
         std::string recursive_crash = {"\n\n\n***** Recursive crash detected"};
         recursive_crash.append(", cannot continue stackdump traversal. *****\n\n\n");
         return recursive_crash;
      }
      ++g_thread_local_recursive_crash_check;

      static std::mutex m;
      std::lock_guard<std::mutex> lock(m);
      {
         const BOOL kLoadSymModules = TRUE;
         const auto initialized = SymInitialize(GetCurrentProcess(), nullptr, kLoadSymModules);
         if (TRUE != initialized) {
            return { "Error: Cannot call SymInitialize(...) for retrieving symbols in stack" };
         }

         std::shared_ptr<void> RaiiSymCleaner(nullptr, [&](void *) {
            SymCleanup(GetCurrentProcess());
         }); // Raii sym cleanup

         const size_t kmax_frame_dump_size = 64;
         std::vector<uint64_t>  frame_pointers(kmax_frame_dump_size);
         // C++11: size set and values are zeroed

         assert(frame_pointers.size() == kmax_frame_dump_size);
         captureStackTrace(context, frame_pointers);
         return convertFramesToText(frame_pointers);
      }
   }

} // stacktrace
<commit_msg>Fix ARM compilation for windows. (#401)<commit_after>/** ==========================================================================
 * Original code made by Robert Engeln. Given as a PUBLIC DOMAIN dedication for
 * the benefit of g3log.  It was originally published at:
 * http://code-freeze.blogspot.com/2012/01/generating-stack-traces-from-c.html

 * 2014-2015: adapted for g3log by Kjell Hedstrom (KjellKod).
 *
 * This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================*/

#include "g3log/stacktrace_windows.hpp"

#include <windows.h>
#include <dbghelp.h>
#include <map>
#include <memory>
#include <cassert>
#include <vector>
#include <mutex>
#include <g3log/g3log.hpp>

#pragma comment(lib, "dbghelp.lib")

#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
#error "stacktrace_win.cpp used but not on a windows system"
#endif

#define g3_MAP_PAIR_STRINGIFY(x) {x, #x}

namespace {
   thread_local size_t g_thread_local_recursive_crash_check = 0;

   const std::map<g3::SignalType, std::string> kExceptionsAsText = {
      g3_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_DATATYPE_MISALIGNMENT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INVALID_OPERATION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_STACK_CHECK)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_UNDERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ILLEGAL_INSTRUCTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_IN_PAGE_ERROR)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_DIVIDE_BY_ZERO)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INVALID_DISPOSITION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_STACK_OVERFLOW)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT)
      , g3_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP)

   };

   // Using the given context, fill in all the stack frames.
   // Which then later can be interpreted to human readable text
   void captureStackTrace(CONTEXT *context, std::vector<uint64_t> &frame_pointers) {
      DWORD machine_type = 0;
      STACKFRAME64 frame = {}; // force zeroing
      frame.AddrPC.Mode = AddrModeFlat;
      frame.AddrFrame.Mode = AddrModeFlat;
      frame.AddrStack.Mode = AddrModeFlat;
#if defined(_M_ARM64)
      frame.AddrPC.Offset = context->Pc;
      frame.AddrFrame.Offset = context->Fp;
      frame.AddrStack.Offset = context->Sp;
      machine_type = IMAGE_FILE_MACHINE_ARM64;
#elif defined(_M_ARM)
      frame.AddrPC.Offset = context->Pc;
      frame.AddrFrame.Offset = context->R11;
      frame.AddrStack.Offset = context->Sp;
      machine_type = IMAGE_FILE_MACHINE_ARM;
#elif defined(_M_X64)
      frame.AddrPC.Offset = context->Rip;
      frame.AddrFrame.Offset = context->Rbp;
      frame.AddrStack.Offset = context->Rsp;
      machine_type = IMAGE_FILE_MACHINE_AMD64;
#else
      frame.AddrPC.Offset = context->Eip;
      frame.AddrPC.Offset = context->Ebp;
      frame.AddrPC.Offset = context->Esp;
      machine_type = IMAGE_FILE_MACHINE_I386;
#endif
      for (size_t index = 0; index < frame_pointers.size(); ++index)
      {
         if (StackWalk64(machine_type,
                         GetCurrentProcess(),
                         GetCurrentThread(),
                         &frame,
                         context,
                         NULL,
                         SymFunctionTableAccess64,
                         SymGetModuleBase64,
                         NULL)) {
            frame_pointers[index] = frame.AddrPC.Offset;
         } else {
            break;
         }
      }
   }

   // extract readable text from a given stack frame. All thanks to
   // using SymFromAddr and SymGetLineFromAddr64 with the stack pointer
   std::string getSymbolInformation(const size_t index, const std::vector<uint64_t> &frame_pointers) {
      auto addr = frame_pointers[index];
      std::string frame_dump = "stack dump [" + std::to_string(index) + "]\t";

      DWORD64 displacement64;
      DWORD displacement;
      char symbol_buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
      SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(symbol_buffer);
      symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
      symbol->MaxNameLen = MAX_SYM_NAME;

      IMAGEHLP_LINE64 line;
      line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
      std::string lineInformation;
      std::string callInformation;
      if (SymFromAddr(GetCurrentProcess(), addr, &displacement64, symbol)) {
         callInformation.append(" ").append(std::string(symbol->Name, symbol->NameLen));
         if (SymGetLineFromAddr64(GetCurrentProcess(), addr, &displacement, &line)) {
            lineInformation.append("\t").append(line.FileName).append(" L: ");
            lineInformation.append(std::to_string(line.LineNumber));
         }
      }
      frame_dump.append(lineInformation).append(callInformation);
      return frame_dump;
   }

   // Retrieves all the symbols for the stack frames, fills them within a text representation and returns it
   std::string convertFramesToText(std::vector<uint64_t> &frame_pointers) {
      std::string dump; // slightly more efficient than ostringstream
      const size_t kSize = frame_pointers.size();
      for (size_t index = 0; index < kSize && frame_pointers[index]; ++index) {
         dump += getSymbolInformation(index, frame_pointers);
         dump += "\n";
      }
      return dump;
   }
} // anonymous

namespace stacktrace {
   const std::string kUnknown = {"UNKNOWN EXCEPTION"};
   /// return the text description of a Windows exception code
   /// From MSDN GetExceptionCode http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx
   std::string exceptionIdToText(g3::SignalType id) {
      const auto iter = kExceptionsAsText.find(id);
      if ( iter == kExceptionsAsText.end()) {
         std::string unknown = {kUnknown + ":" + std::to_string(id)};
         return unknown;
      }
      return iter->second;
   }

   /// Yes a double lookup: first for isKnownException and then exceptionIdToText
   /// for vectored exceptions we only deal with known exceptions so this tiny
   /// overhead we can live with
   bool isKnownException(g3::SignalType id) {
      return (kExceptionsAsText.end() != kExceptionsAsText.find(id));
   }

   /// helper function: retrieve stackdump from no excisting exception pointer
   std::string stackdump() {
      CONTEXT current_context;
      memset(&current_context, 0, sizeof(CONTEXT));
      RtlCaptureContext(&current_context);
      return stackdump(&current_context);
   }

   /// helper function: retrieve stackdump, starting from an exception pointer
   std::string stackdump(EXCEPTION_POINTERS *info) {
      auto context = info->ContextRecord;
      return stackdump(context);

   }

   /// main stackdump function. retrieve stackdump, from the given context
   std::string stackdump(CONTEXT *context) {

      if (g_thread_local_recursive_crash_check >= 2) { // In Debug scenarios we allow one extra pass
         std::string recursive_crash = {"\n\n\n***** Recursive crash detected"};
         recursive_crash.append(", cannot continue stackdump traversal. *****\n\n\n");
         return recursive_crash;
      }
      ++g_thread_local_recursive_crash_check;

      static std::mutex m;
      std::lock_guard<std::mutex> lock(m);
      {
         const BOOL kLoadSymModules = TRUE;
         const auto initialized = SymInitialize(GetCurrentProcess(), nullptr, kLoadSymModules);
         if (TRUE != initialized) {
            return { "Error: Cannot call SymInitialize(...) for retrieving symbols in stack" };
         }

         std::shared_ptr<void> RaiiSymCleaner(nullptr, [&](void *) {
            SymCleanup(GetCurrentProcess());
         }); // Raii sym cleanup

         const size_t kmax_frame_dump_size = 64;
         std::vector<uint64_t>  frame_pointers(kmax_frame_dump_size);
         // C++11: size set and values are zeroed

         assert(frame_pointers.size() == kmax_frame_dump_size);
         captureStackTrace(context, frame_pointers);
         return convertFramesToText(frame_pointers);
      }
   }

} // stacktrace
<|endoftext|>