<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is here so other GLES2 related files can have a common set of
// includes where appropriate.

#include "gpu/command_buffer/client/gles2_demo_cc.h"

#include <math.h>
#include <GLES2/gl2.h>

#include <string>

namespace {

GLuint g_texture = 0;
int g_textureLoc = -1;
GLuint g_programObject = 0;
GLuint g_worldMatrixLoc = 0;
GLuint g_vbo = 0;
GLsizei g_texCoordOffset = 0;
int g_angle = 0;

void CheckGLError(const char* func_name, int line_no) {
#ifndef NDEBUG
  GLenum error = GL_NO_ERROR;
  while ((error = glGetError()) != GL_NO_ERROR) {
    DLOG(ERROR) << "GL Error in " << func_name << " at line " << line_no
        << ": " << error;
  }
#endif
}

GLuint LoadShader(GLenum type, const char* shaderSrc) {
  CheckGLError("LoadShader", __LINE__);
  GLuint shader = glCreateShader(type);
  if (shader == 0) {
    return 0;
  }
  // Load the shader source
  glShaderSource(shader, 1, &shaderSrc, NULL);
  // Compile the shader
  glCompileShader(shader);
  // Check the compile status
  GLint value;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
  if (value == 0) {
    char buffer[1024];
    GLsizei length;
    glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer);
    std::string log(buffer, length);
    DLOG(ERROR) << "Error compiling shader:" << log;
    glDeleteShader(shader);
    return 0;
  }
  return shader;
}

void InitShaders() {
  static const char* vShaderStr =
    "uniform mat4 worldMatrix;\n"
    "attribute vec3 g_Position;\n"
    "attribute vec2 g_TexCoord0;\n"
    "varying vec2 texCoord;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = worldMatrix *\n"
    "                 vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n"
    "   texCoord = g_TexCoord0;\n"
    "}\n";
  static const char* fShaderStr =
    "uniform sampler2D tex;\n"
    "varying vec2 texCoord;\n"
    "void main()\n"
    "{\n"
    "  gl_FragColor = texture2D(tex, texCoord);\n"
    "}\n";

  CheckGLError("InitShaders", __LINE__);
  GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
  GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);
  // Create the program object
  GLuint programObject = glCreateProgram();
  if (programObject == 0) {
    DLOG(ERROR) << "Creating program failed";
    return;
  }
  glAttachShader(programObject, vertexShader);
  glAttachShader(programObject, fragmentShader);
  // Bind g_Position to attribute 0
  // Bind g_TexCoord0 to attribute 1
  glBindAttribLocation(programObject, 0, "g_Position");
  glBindAttribLocation(programObject, 1, "g_TexCoord0");
  // Link the program
  glLinkProgram(programObject);
  // Check the link status
  GLint linked;
  glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
  if (linked == 0) {
    char buffer[1024];
    GLsizei length;
    glGetProgramInfoLog(programObject, sizeof(buffer), &length, buffer);
    std::string log(buffer, length);
    DLOG(ERROR) << "Error linking program:" << log;
    glDeleteProgram(programObject);
    return;
  }
  g_programObject = programObject;
  g_worldMatrixLoc = glGetUniformLocation(g_programObject, "worldMatrix");
  g_textureLoc = glGetUniformLocation(g_programObject, "tex");
  glGenBuffers(1, &g_vbo);
  glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
  static float vertices[] = {
      0.25,  0.75, 0.0,
     -0.75,  0.75, 0.0,
     -0.75, -0.25, 0.0,
      0.25,  0.75, 0.0,
     -0.75, -0.25, 0.0,
      0.25, -0.25, 0.0,
  };
  static float texCoords[] = {
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
  };
  g_texCoordOffset = sizeof(vertices);
  glBufferData(GL_ARRAY_BUFFER,
               sizeof(vertices) + sizeof(texCoords),
               NULL,
               GL_STATIC_DRAW);
  glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
  glBufferSubData(GL_ARRAY_BUFFER, g_texCoordOffset,
                  sizeof(texCoords), texCoords);
  CheckGLError("InitShaders", __LINE__);
}

GLuint CreateCheckerboardTexture() {
  CheckGLError("CreateCheckerboardTexture", __LINE__);
  static unsigned char pixels[] = {
    255, 255, 255,
    0,   0,   0,
    0,   0,   0,
    255, 255, 255,
  };
  GLuint texture;
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
               pixels);
  CheckGLError("CreateCheckerboardTexture", __LINE__);
  return texture;
}

}  // anonymous namespace.

void GLFromCPPInit() {
  CheckGLError("GLFromCPPInit", __LINE__);
  glClearColor(0.f, 0.f, .7f, 1.f);
  g_texture = CreateCheckerboardTexture();
  InitShaders();
  CheckGLError("GLFromCPPInit", __LINE__);
}

void GLFromCPPDraw() {
  const float kPi = 3.1415926535897932384626433832795f;

  CheckGLError("GLFromCPPDraw", __LINE__);
  // TODO(kbr): base the angle on time rather than on ticks
  g_angle = (g_angle + 1) % 360;
  // Rotate about the Z axis
  GLfloat rot_matrix[16];
  GLfloat cos_angle = cosf(static_cast<GLfloat>(g_angle) * kPi / 180.0f);
  GLfloat sin_angle = sinf(static_cast<GLfloat>(g_angle) * kPi / 180.0f);
  // OpenGL matrices are column-major
  rot_matrix[0] = cos_angle;
  rot_matrix[1] = sin_angle;
  rot_matrix[2] = 0.0f;
  rot_matrix[3] = 0.0f;

  rot_matrix[4] = -sin_angle;
  rot_matrix[5] = cos_angle;
  rot_matrix[6] = 0.0f;
  rot_matrix[7] = 0.0f;

  rot_matrix[8] = 0.0f;
  rot_matrix[9] = 0.0f;
  rot_matrix[10] = 1.0f;
  rot_matrix[11] = 0.0f;

  rot_matrix[12] = 0.0f;
  rot_matrix[13] = 0.0f;
  rot_matrix[14] = 0.0f;
  rot_matrix[15] = 1.0f;

  // Note: the viewport is automatically set up to cover the entire Canvas.
  // Clear the color buffer
  glClear(GL_COLOR_BUFFER_BIT);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Use the program object
  glUseProgram(g_programObject);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Set up the model matrix
  glUniformMatrix4fv(g_worldMatrixLoc, 1, GL_FALSE, rot_matrix);

  // Load the vertex data
  glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  glEnableVertexAttribArray(1);
  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0,
                        reinterpret_cast<const void*>(g_texCoordOffset));
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Bind the texture to texture unit 0
  glBindTexture(GL_TEXTURE_2D, g_texture);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Point the uniform sampler to texture unit 0
  glUniform1i(g_textureLoc, 0);
  CheckGLError("GLFromCPPDraw", __LINE__);
  glDrawArrays(GL_TRIANGLES, 0, 6);
  CheckGLError("GLFromCPPDraw", __LINE__);
  glFlush();
}
<commit_msg>Fix for GL break on Linux build.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is here so other GLES2 related files can have a common set of
// includes where appropriate.

#include "gpu/command_buffer/client/gles2_demo_cc.h"

#include <math.h>
#include <GLES2/gl2.h>

#include <string>

namespace {

GLuint g_texture = 0;
int g_textureLoc = -1;
GLuint g_programObject = 0;
GLuint g_worldMatrixLoc = 0;
GLuint g_vbo = 0;
GLsizei g_texCoordOffset = 0;
int g_angle = 0;

void CheckGLError(const char* func_name, int line_no) {
#ifndef NDEBUG
  GLenum error = GL_NO_ERROR;
  while ((error = glGetError()) != GL_NO_ERROR) {
    DLOG(ERROR) << "GL Error in " << func_name << " at line " << line_no
        << ": " << error;
  }
#endif
}

GLuint LoadShader(GLenum type, const char* shaderSrc) {
  CheckGLError("LoadShader", __LINE__);
  GLuint shader = glCreateShader(type);
  if (shader == 0) {
    return 0;
  }
  // Load the shader source
  glShaderSource(shader, 1, &shaderSrc, NULL);
  // Compile the shader
  glCompileShader(shader);
  // Check the compile status
  GLint value;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
  if (value == 0) {
    char buffer[1024];
    GLsizei length = 0;
    glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer);
    std::string log(buffer, length);
    DLOG(ERROR) << "Error compiling shader:" << log;
    glDeleteShader(shader);
    return 0;
  }
  return shader;
}

void InitShaders() {
  static const char* vShaderStr =
    "uniform mat4 worldMatrix;\n"
    "attribute vec3 g_Position;\n"
    "attribute vec2 g_TexCoord0;\n"
    "varying vec2 texCoord;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = worldMatrix *\n"
    "                 vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n"
    "   texCoord = g_TexCoord0;\n"
    "}\n";
  static const char* fShaderStr =
    "uniform sampler2D tex;\n"
    "varying vec2 texCoord;\n"
    "void main()\n"
    "{\n"
    "  gl_FragColor = texture2D(tex, texCoord);\n"
    "}\n";

  CheckGLError("InitShaders", __LINE__);
  GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
  GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);
  // Create the program object
  GLuint programObject = glCreateProgram();
  if (programObject == 0) {
    DLOG(ERROR) << "Creating program failed";
    return;
  }
  glAttachShader(programObject, vertexShader);
  glAttachShader(programObject, fragmentShader);
  // Bind g_Position to attribute 0
  // Bind g_TexCoord0 to attribute 1
  glBindAttribLocation(programObject, 0, "g_Position");
  glBindAttribLocation(programObject, 1, "g_TexCoord0");
  // Link the program
  glLinkProgram(programObject);
  // Check the link status
  GLint linked;
  glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
  if (linked == 0) {
    char buffer[1024];
    GLsizei length;
    glGetProgramInfoLog(programObject, sizeof(buffer), &length, buffer);
    std::string log(buffer, length);
    DLOG(ERROR) << "Error linking program:" << log;
    glDeleteProgram(programObject);
    return;
  }
  g_programObject = programObject;
  g_worldMatrixLoc = glGetUniformLocation(g_programObject, "worldMatrix");
  g_textureLoc = glGetUniformLocation(g_programObject, "tex");
  glGenBuffers(1, &g_vbo);
  glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
  static float vertices[] = {
      0.25,  0.75, 0.0,
     -0.75,  0.75, 0.0,
     -0.75, -0.25, 0.0,
      0.25,  0.75, 0.0,
     -0.75, -0.25, 0.0,
      0.25, -0.25, 0.0,
  };
  static float texCoords[] = {
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
  };
  g_texCoordOffset = sizeof(vertices);
  glBufferData(GL_ARRAY_BUFFER,
               sizeof(vertices) + sizeof(texCoords),
               NULL,
               GL_STATIC_DRAW);
  glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
  glBufferSubData(GL_ARRAY_BUFFER, g_texCoordOffset,
                  sizeof(texCoords), texCoords);
  CheckGLError("InitShaders", __LINE__);
}

GLuint CreateCheckerboardTexture() {
  CheckGLError("CreateCheckerboardTexture", __LINE__);
  static unsigned char pixels[] = {
    255, 255, 255,
    0,   0,   0,
    0,   0,   0,
    255, 255, 255,
  };
  GLuint texture;
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
               pixels);
  CheckGLError("CreateCheckerboardTexture", __LINE__);
  return texture;
}

}  // anonymous namespace.

void GLFromCPPInit() {
  CheckGLError("GLFromCPPInit", __LINE__);
  glClearColor(0.f, 0.f, .7f, 1.f);
  g_texture = CreateCheckerboardTexture();
  InitShaders();
  CheckGLError("GLFromCPPInit", __LINE__);
}

void GLFromCPPDraw() {
  const float kPi = 3.1415926535897932384626433832795f;

  CheckGLError("GLFromCPPDraw", __LINE__);
  // TODO(kbr): base the angle on time rather than on ticks
  g_angle = (g_angle + 1) % 360;
  // Rotate about the Z axis
  GLfloat rot_matrix[16];
  GLfloat cos_angle = cosf(static_cast<GLfloat>(g_angle) * kPi / 180.0f);
  GLfloat sin_angle = sinf(static_cast<GLfloat>(g_angle) * kPi / 180.0f);
  // OpenGL matrices are column-major
  rot_matrix[0] = cos_angle;
  rot_matrix[1] = sin_angle;
  rot_matrix[2] = 0.0f;
  rot_matrix[3] = 0.0f;

  rot_matrix[4] = -sin_angle;
  rot_matrix[5] = cos_angle;
  rot_matrix[6] = 0.0f;
  rot_matrix[7] = 0.0f;

  rot_matrix[8] = 0.0f;
  rot_matrix[9] = 0.0f;
  rot_matrix[10] = 1.0f;
  rot_matrix[11] = 0.0f;

  rot_matrix[12] = 0.0f;
  rot_matrix[13] = 0.0f;
  rot_matrix[14] = 0.0f;
  rot_matrix[15] = 1.0f;

  // Note: the viewport is automatically set up to cover the entire Canvas.
  // Clear the color buffer
  glClear(GL_COLOR_BUFFER_BIT);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Use the program object
  glUseProgram(g_programObject);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Set up the model matrix
  glUniformMatrix4fv(g_worldMatrixLoc, 1, GL_FALSE, rot_matrix);

  // Load the vertex data
  glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  glEnableVertexAttribArray(1);
  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0,
                        reinterpret_cast<const void*>(g_texCoordOffset));
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Bind the texture to texture unit 0
  glBindTexture(GL_TEXTURE_2D, g_texture);
  CheckGLError("GLFromCPPDraw", __LINE__);
  // Point the uniform sampler to texture unit 0
  glUniform1i(g_textureLoc, 0);
  CheckGLError("GLFromCPPDraw", __LINE__);
  glDrawArrays(GL_TRIANGLES, 0, 6);
  CheckGLError("GLFromCPPDraw", __LINE__);
  glFlush();
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_ctrl.hpp"
#include "account.hpp"
#include "account_ctrl.hpp"
#include "account_reader.hpp"
#include "account_type.hpp"
#include "b_string.hpp"
#include "date.hpp"
#include "date_ctrl.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "entry_ctrl.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include "top_panel.hpp"
#include "transaction_type_ctrl.hpp"
#include "transaction_type.hpp"
#include <boost/optional.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/on_windows.hpp>
#include <jewel/optional.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/gbsizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

using boost::optional;
using boost::scoped_ptr;
using jewel::Decimal;
using jewel::value;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionCtrl, wxPanel)
	EVT_BUTTON
	(	wxID_OK,
		TransactionCtrl::on_ok_button_click
	)
	EVT_BUTTON
	(	s_recurring_transaction_button_id,
		TransactionCtrl::on_recurring_transaction_button_click
	)
	EVT_BUTTON
	(	wxID_CANCEL,
		TransactionCtrl::on_cancel_button_click
	)
END_EVENT_TABLE()

// WARNING There are bugs in wxWidgets' wxDatePickerCtrl under wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.
// We have used a simple custom class, DateCtrl here instead, to avoid
// these problems. Might later add a button to pop up a wxCalendarCtrl
// if the user wants one.

TransactionCtrl::TransactionCtrl
(	TopPanel* p_parent,
	vector<Account> const& p_balance_sheet_accounts,
	vector<Account> const& p_pl_accounts,
	PhatbooksDatabaseConnection& p_database_connection
):
	wxPanel
	(	p_parent,
		wxID_ANY,
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_transaction_type_ctrl(0),
	m_source_entry_ctrl(0),
	m_destination_entry_ctrl(0),
	m_primary_amount_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_recurring_transaction_button(0),
	m_ok_button(0),
	m_database_connection(p_database_connection)
{
	assert (!p_balance_sheet_accounts.empty() || !p_pl_accounts.empty());
	assert (p_balance_sheet_accounts.size() + p_pl_accounts.size() >= 2);

	// Figure out the natural TransactionType given the Accounts we have
	// been passed. We will use this to initialize the TransactionTypeCtrl.
	Account account_x(p_database_connection);
	Account account_y(p_database_connection);
	if (p_balance_sheet_accounts.empty())
	{
		assert (p_pl_accounts.size() >= 2);
		account_x = p_pl_accounts[0];
		account_y = p_pl_accounts[1];
	}
	else if (p_pl_accounts.empty())
	{
		assert (p_balance_sheet_accounts.size() >= 2);
		account_x = p_balance_sheet_accounts[0];
		account_y = p_balance_sheet_accounts[1];
	}
	else
	{
		assert (!p_balance_sheet_accounts.empty());
		assert (!p_pl_accounts.empty());
		account_x = p_balance_sheet_accounts[0];
		account_y = p_pl_accounts[0];
	}
	if (account_y.account_type() == account_type::revenue)
	{
		using std::swap;
		swap(account_x, account_y);
	}
	assert (account_x.has_id());
	assert (account_y.has_id());
	transaction_type::TransactionType const initial_transaction_type =
		natural_transaction_type(account_x, account_y);

	size_t row = 0;

	// Top sizer
	m_top_sizer = new wxGridBagSizer();
	SetSizer(m_top_sizer);

	m_transaction_type_ctrl = new TransactionTypeCtrl
	(	this,
		s_transaction_type_ctrl_id,
		wxSize(160, wxDefaultSize.y),
		m_database_connection
	);

	m_transaction_type_ctrl->set_transaction_type(initial_transaction_type);
	m_top_sizer->Add(m_transaction_type_ctrl, wxGBPosition(row, 0));
	wxSize const text_box_size = m_transaction_type_ctrl->GetSize();

	m_primary_amount_ctrl = new DecimalTextCtrl
	(	this,
		s_primary_amount_ctrl_id,
		text_box_size,
		m_database_connection.default_commodity().precision(),
		false
	);
	m_top_sizer->Add
	(	m_primary_amount_ctrl,
		wxGBPosition(row, 3),
		wxDefaultSpan,
		wxALIGN_RIGHT
	);

	// We need the names of available Accounts, for the given
	// TransactionType, from which the user will choose
	// Accounts, for each side of the transaction.

	assert_transaction_type_validity(initial_transaction_type);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	vector<Account> accounts;
	accounts.push_back(account_x);
	accounts.push_back(account_y);

	row += 3;

	// WARNING Temp hack
	assert (accounts.size() >= 2);

	vector<Account> source_accounts;
	source_accounts.push_back(accounts[0]);
	vector<Account> destination_accounts;
	destination_accounts.push_back(accounts[1]);

	Decimal::places_type const precision =
		m_database_connection.default_commodity().precision();
	m_source_entry_ctrl = new EntryCtrl
	(	this,
		source_accounts,
		m_database_connection,
		initial_transaction_type,
		text_box_size,
		true,
		Decimal(0, precision)
	);
	m_destination_entry_ctrl = new EntryCtrl
	(	this,
		destination_accounts,
		m_database_connection,
		initial_transaction_type,
		text_box_size,
		false,
		Decimal(0, precision)
	);
	m_top_sizer->Add
	(	m_source_entry_ctrl,
		wxGBPosition(row, 0),
		wxGBSpan(1, 4),
		wxEXPAND
	);

	row += 2;

	m_top_sizer->Add
	(	m_destination_entry_ctrl,
		wxGBPosition(row, 0),
		wxGBSpan(1, 4),
		wxEXPAND
	);

	row += 2;

	// Buttons and date control

	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Clear"),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_cancel_button, wxGBPosition(row, 0));
	m_date_ctrl = new DateCtrl
	(	this,
		wxID_ANY,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_date_ctrl, wxGBPosition(row, 1));
	m_recurring_transaction_button = new wxButton
	(	this,
		s_recurring_transaction_button_id,
		wxString("&Recurring..."),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_recurring_transaction_button, wxGBPosition(row, 2));
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&OK"),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);

	m_top_sizer->Add(m_ok_button, wxGBPosition(row, 3));
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	++row;

	// "Admin"
	// SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Fit();
	Layout();
}

void
TransactionCtrl::refresh_for_transaction_type
(	transaction_type::TransactionType p_transaction_type
)
{
	m_source_entry_ctrl->refresh_for_transaction_type(p_transaction_type);
	m_destination_entry_ctrl->refresh_for_transaction_type(p_transaction_type);
	return;
}

void
TransactionCtrl::notify_decimal_ctrl_focus_kill()
{
	reset_entry_ctrl_amounts();
	return;
}

void
TransactionCtrl::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		if (is_balanced())
		{
			post_journal();
			TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
			assert (panel);
			panel->update();
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionCtrl::on_recurring_transaction_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	return;
}

void
TransactionCtrl::on_cancel_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
	assert (panel);
	panel->update();
}

void
TransactionCtrl::reset_entry_ctrl_amounts()
{
	Decimal const pa = primary_amount();
	m_source_entry_ctrl->set_primary_amount(pa);
	m_destination_entry_ctrl->set_primary_amount(pa);
	return;
}

Decimal
TransactionCtrl::primary_amount() const
{
	return m_primary_amount_ctrl->amount();
}

void
TransactionCtrl::post_journal()
{
	// TODO HIGH PRIORITY Fix this
	// to work now that we have EntryCtrl instead of storing
	// Entry info directly in the TransactionCtrl.
	OrdinaryJournal journal(m_database_connection);
	// TODO What if the dereferencing of optional fails?
	transaction_type::TransactionType const ttype =
		value(m_transaction_type_ctrl->transaction_type());
	journal.set_whether_actual(transaction_type_is_actual(ttype));

	size_t const num_entry_controls = 2;
	EntryCtrl const* const entry_controls[num_entry_controls] =
	{	m_source_entry_ctrl,
		m_destination_entry_ctrl
	};
	bool non_zero_entry_exists = false;
	for (size_t i = 0; i != num_entry_controls; ++i)
	{
		vector<Entry> entries = entry_controls[i]->make_entries();
		for (vector<Entry>::size_type j = 0; j != entries.size(); ++j)
		{
			Entry entry = entries[j];
			if (entry.amount() != Decimal(0, 0))
			{
				non_zero_entry_exists = true;
			}
			journal.push_entry(entry);
		}
	}
	if (!non_zero_entry_exists)
	{
		// Then maybe OK was pressed before the primary amount was
		// propagated through to the entries.
		// TODO This is messy, and feels fragile.
		if (primary_amount() != Decimal(0, 0))
		{
			// Then it CAN'T have been propagated. Let's propagate it
			// and try again.
			reset_entry_ctrl_amounts();
			post_journal();
			return;
		}
	}
	journal.set_comment("");

	// Process date
	journal.set_date(m_date_ctrl->date());

	JEWEL_DEBUG_LOG << "\n" << journal << endl;

	// Save journal
	// TODO This assertion might fail.
	assert (journal.is_balanced());
	journal.save();
}

bool
TransactionCtrl::is_balanced() const
{
	// WARNING For now this is trivial, as we have only the primary_amount
	// informing one each of only two sides of the transaction. But it
	// probably won't always be trivial.
	return true;
	/*
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
	*/
}

}  // namespace gui
}  // namespace phatbooks
<commit_msg>In TransactionCtrl, "OK" button is now labelled "Save".<commit_after>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_ctrl.hpp"
#include "account.hpp"
#include "account_ctrl.hpp"
#include "account_reader.hpp"
#include "account_type.hpp"
#include "b_string.hpp"
#include "date.hpp"
#include "date_ctrl.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "entry_ctrl.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include "top_panel.hpp"
#include "transaction_type_ctrl.hpp"
#include "transaction_type.hpp"
#include <boost/optional.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/on_windows.hpp>
#include <jewel/optional.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/gbsizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

using boost::optional;
using boost::scoped_ptr;
using jewel::Decimal;
using jewel::value;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionCtrl, wxPanel)
	EVT_BUTTON
	(	wxID_OK,
		TransactionCtrl::on_ok_button_click
	)
	EVT_BUTTON
	(	s_recurring_transaction_button_id,
		TransactionCtrl::on_recurring_transaction_button_click
	)
	EVT_BUTTON
	(	wxID_CANCEL,
		TransactionCtrl::on_cancel_button_click
	)
END_EVENT_TABLE()

// WARNING There are bugs in wxWidgets' wxDatePickerCtrl under wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.
// We have used a simple custom class, DateCtrl here instead, to avoid
// these problems. Might later add a button to pop up a wxCalendarCtrl
// if the user wants one.

TransactionCtrl::TransactionCtrl
(	TopPanel* p_parent,
	vector<Account> const& p_balance_sheet_accounts,
	vector<Account> const& p_pl_accounts,
	PhatbooksDatabaseConnection& p_database_connection
):
	wxPanel
	(	p_parent,
		wxID_ANY,
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_transaction_type_ctrl(0),
	m_source_entry_ctrl(0),
	m_destination_entry_ctrl(0),
	m_primary_amount_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_recurring_transaction_button(0),
	m_ok_button(0),
	m_database_connection(p_database_connection)
{
	assert (!p_balance_sheet_accounts.empty() || !p_pl_accounts.empty());
	assert (p_balance_sheet_accounts.size() + p_pl_accounts.size() >= 2);

	// Figure out the natural TransactionType given the Accounts we have
	// been passed. We will use this to initialize the TransactionTypeCtrl.
	Account account_x(p_database_connection);
	Account account_y(p_database_connection);
	if (p_balance_sheet_accounts.empty())
	{
		assert (p_pl_accounts.size() >= 2);
		account_x = p_pl_accounts[0];
		account_y = p_pl_accounts[1];
	}
	else if (p_pl_accounts.empty())
	{
		assert (p_balance_sheet_accounts.size() >= 2);
		account_x = p_balance_sheet_accounts[0];
		account_y = p_balance_sheet_accounts[1];
	}
	else
	{
		assert (!p_balance_sheet_accounts.empty());
		assert (!p_pl_accounts.empty());
		account_x = p_balance_sheet_accounts[0];
		account_y = p_pl_accounts[0];
	}
	if (account_y.account_type() == account_type::revenue)
	{
		using std::swap;
		swap(account_x, account_y);
	}
	assert (account_x.has_id());
	assert (account_y.has_id());
	transaction_type::TransactionType const initial_transaction_type =
		natural_transaction_type(account_x, account_y);

	size_t row = 0;

	// Top sizer
	m_top_sizer = new wxGridBagSizer();
	SetSizer(m_top_sizer);

	m_transaction_type_ctrl = new TransactionTypeCtrl
	(	this,
		s_transaction_type_ctrl_id,
		wxSize(160, wxDefaultSize.y),
		m_database_connection
	);

	m_transaction_type_ctrl->set_transaction_type(initial_transaction_type);
	m_top_sizer->Add(m_transaction_type_ctrl, wxGBPosition(row, 0));
	wxSize const text_box_size = m_transaction_type_ctrl->GetSize();

	m_primary_amount_ctrl = new DecimalTextCtrl
	(	this,
		s_primary_amount_ctrl_id,
		text_box_size,
		m_database_connection.default_commodity().precision(),
		false
	);
	m_top_sizer->Add
	(	m_primary_amount_ctrl,
		wxGBPosition(row, 3),
		wxDefaultSpan,
		wxALIGN_RIGHT
	);

	// We need the names of available Accounts, for the given
	// TransactionType, from which the user will choose
	// Accounts, for each side of the transaction.

	assert_transaction_type_validity(initial_transaction_type);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	vector<Account> accounts;
	accounts.push_back(account_x);
	accounts.push_back(account_y);

	row += 3;

	// WARNING Temp hack
	assert (accounts.size() >= 2);

	vector<Account> source_accounts;
	source_accounts.push_back(accounts[0]);
	vector<Account> destination_accounts;
	destination_accounts.push_back(accounts[1]);

	Decimal::places_type const precision =
		m_database_connection.default_commodity().precision();
	m_source_entry_ctrl = new EntryCtrl
	(	this,
		source_accounts,
		m_database_connection,
		initial_transaction_type,
		text_box_size,
		true,
		Decimal(0, precision)
	);
	m_destination_entry_ctrl = new EntryCtrl
	(	this,
		destination_accounts,
		m_database_connection,
		initial_transaction_type,
		text_box_size,
		false,
		Decimal(0, precision)
	);
	m_top_sizer->Add
	(	m_source_entry_ctrl,
		wxGBPosition(row, 0),
		wxGBSpan(1, 4),
		wxEXPAND
	);

	row += 2;

	m_top_sizer->Add
	(	m_destination_entry_ctrl,
		wxGBPosition(row, 0),
		wxGBSpan(1, 4),
		wxEXPAND
	);

	row += 2;

	// Buttons and date control

	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Clear"),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_cancel_button, wxGBPosition(row, 0));
	m_date_ctrl = new DateCtrl
	(	this,
		wxID_ANY,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_date_ctrl, wxGBPosition(row, 1));
	m_recurring_transaction_button = new wxButton
	(	this,
		s_recurring_transaction_button_id,
		wxString("&Recurring..."),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);
	m_top_sizer->Add(m_recurring_transaction_button, wxGBPosition(row, 2));
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&Save"),
		wxDefaultPosition,
		wxSize(text_box_size.x, text_box_size.y)
	);

	m_top_sizer->Add(m_ok_button, wxGBPosition(row, 3));
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	++row;

	// "Admin"
	// SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Fit();
	Layout();
}

void
TransactionCtrl::refresh_for_transaction_type
(	transaction_type::TransactionType p_transaction_type
)
{
	m_source_entry_ctrl->refresh_for_transaction_type(p_transaction_type);
	m_destination_entry_ctrl->refresh_for_transaction_type(p_transaction_type);
	return;
}

void
TransactionCtrl::notify_decimal_ctrl_focus_kill()
{
	reset_entry_ctrl_amounts();
	return;
}

void
TransactionCtrl::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		if (is_balanced())
		{
			post_journal();
			TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
			assert (panel);
			panel->update();
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionCtrl::on_recurring_transaction_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	return;
}

void
TransactionCtrl::on_cancel_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
	assert (panel);
	panel->update();
}

void
TransactionCtrl::reset_entry_ctrl_amounts()
{
	Decimal const pa = primary_amount();
	m_source_entry_ctrl->set_primary_amount(pa);
	m_destination_entry_ctrl->set_primary_amount(pa);
	return;
}

Decimal
TransactionCtrl::primary_amount() const
{
	return m_primary_amount_ctrl->amount();
}

void
TransactionCtrl::post_journal()
{
	// TODO HIGH PRIORITY Fix this
	// to work now that we have EntryCtrl instead of storing
	// Entry info directly in the TransactionCtrl.
	OrdinaryJournal journal(m_database_connection);
	// TODO What if the dereferencing of optional fails?
	transaction_type::TransactionType const ttype =
		value(m_transaction_type_ctrl->transaction_type());
	journal.set_whether_actual(transaction_type_is_actual(ttype));

	size_t const num_entry_controls = 2;
	EntryCtrl const* const entry_controls[num_entry_controls] =
	{	m_source_entry_ctrl,
		m_destination_entry_ctrl
	};
	bool non_zero_entry_exists = false;
	for (size_t i = 0; i != num_entry_controls; ++i)
	{
		vector<Entry> entries = entry_controls[i]->make_entries();
		for (vector<Entry>::size_type j = 0; j != entries.size(); ++j)
		{
			Entry entry = entries[j];
			if (entry.amount() != Decimal(0, 0))
			{
				non_zero_entry_exists = true;
			}
			journal.push_entry(entry);
		}
	}
	if (!non_zero_entry_exists)
	{
		// Then maybe OK was pressed before the primary amount was
		// propagated through to the entries.
		// TODO This is messy, and feels fragile.
		if (primary_amount() != Decimal(0, 0))
		{
			// Then it CAN'T have been propagated. Let's propagate it
			// and try again.
			reset_entry_ctrl_amounts();
			post_journal();
			return;
		}
	}
	journal.set_comment("");

	// Process date
	journal.set_date(m_date_ctrl->date());

	JEWEL_DEBUG_LOG << "\n" << journal << endl;

	// Save journal
	// TODO This assertion might fail.
	assert (journal.is_balanced());
	journal.save();
}

bool
TransactionCtrl::is_balanced() const
{
	// WARNING For now this is trivial, as we have only the primary_amount
	// informing one each of only two sides of the transaction. But it
	// probably won't always be trivial.
	return true;
	/*
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
	*/
}

}  // namespace gui
}  // namespace phatbooks
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file px4_linux_impl.cpp
 *
 * PX4 Middleware Wrapper Linux Implementation
 */

#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_middleware.h>
#include <px4_workqueue.h>
#include <dataman/dataman.h>
#include <stdint.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
#include "systemlib/param/param.h"
#include "hrt_work.h"
#include "px4_log.h"

//extern pthread_t _shell_task_id;

__BEGIN_DECLS
extern uint64_t get_ticks_per_us();

//long PX4_TICKS_PER_SEC = 1000L;

unsigned int sleep(unsigned int sec)
{
	for (unsigned int i = 0; i < sec; i++) {
		usleep(1000000);
	}

	return 0;
}

extern void hrt_init(void);
extern void init_params();

#if 0
void qurt_log(const char *fmt, ...)
{
	va_list	args;
	va_start(args, fmt);
	printf(fmt, args);
	printf("n");
}
#endif

//extern int _posix_init(void);

__END_DECLS

extern struct wqueue_s gwork[NWORKERS];

namespace px4
{

void init_once(void);

void init_once(void)
{
	// Required for QuRT
	//_posix_init();
	PX4_WARN("Before calling work_queue_init");

//	_shell_task_id = pthread_self();
//	PX4_INFO("Shell id is %lu", _shell_task_id);

	work_queues_init();
	PX4_WARN("Before calling hrt_init");
	hrt_work_queue_init();
	hrt_init();
	PX4_WARN("after calling hrt_init");

	/* Shared memory param sync*/
	init_params();
}

void init(int argc, char *argv[], const char *app_name)
{
	PX4_DEBUG("App name: %s\n", app_name);
}

}

/** Retrieve from the data manager store */
ssize_t
dm_read(
	dm_item_t item,                 /* The item type to retrieve */
	unsigned char index,            /* The index of the item */
	void *buffer,                   /* Pointer to caller data buffer */
	size_t buflen                   /* Length in bytes of data to retrieve */
)
{
	return 0;
}

/** write to the data manager store */
ssize_t
dm_write(
	dm_item_t  item,                /* The item type to store */
	unsigned char index,            /* The index of the item */
	dm_persitence_t persistence,    /* The persistence level of this item */
	const void *buffer,             /* Pointer to caller data buffer */
	size_t buflen                   /* Length in bytes of data to retrieve */
)
{
	return 0;
}

size_t strnlen(const char *s, size_t maxlen)
{
	size_t i = 0;

	while (s[i] != '\0' && i < maxlen) {
		++i;
	}

	return i;
}

static void block_indefinite(void)
{
	for (;;) {
		volatile int x = 0;
		++x;
	}
}

int fprintf(FILE *stream, const char *format, ...)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return 0;
}

int fputc(int c, FILE *stream)
{
	return c;
}

FILE _Stdin;
FILE _Stdout;
FILE _Stderr;

static void block_indefinite(void)
{
	for (;;) {
		volatile int x = 0;
		++x;
	}
}

int ungetc(int c, FILE *stream)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

int fgetc(FILE *stream)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

int fseek(FILE *stream, long offset, int whence)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

int fgetpos(FILE *stream, fpos_t *pos)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}
int fsetpos(FILE *stream, const fpos_t *pos)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

int setvbuf(FILE *stream, char *buf, int mode, size_t size)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

#include <wchar.h>

wint_t fputwc(wchar_t wc, FILE *stream)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

wint_t ungetwc(wint_t wc, FILE *stream)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

wint_t fgetwc(FILE *stream)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

#include <stdlib.h>

size_t _Getmbcurmax()
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return 2;
}

#include <ctype.h>

_Ctype_t _Getptolower(void)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return nullptr;
}

_Ctype_t _Getptoupper(void)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return nullptr;
}

#include <xwchar.h>

_Statab *_Getpmbstate(void)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return nullptr;
}

_Statab *_Getpwcstate(void)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return nullptr;
}

int _Mbtowcx(wchar_t *, const char *, size_t, mbstate_t *, _Statab *)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return -1;
}

int _Wctombx(char *, wchar_t, mbstate_t *, _Statab *, _Statab *)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	return -1;
}

void _Locksyslock(int x)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
}

void _Unlocksyslock(int x)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
}

void _Atexit(void (*)(void))
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
}

<commit_msg>Removed stubs now resolved in adsp static image<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file px4_linux_impl.cpp
 *
 * PX4 Middleware Wrapper Linux Implementation
 */

#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_middleware.h>
#include <px4_workqueue.h>
#include <dataman/dataman.h>
#include <stdint.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
#include "systemlib/param/param.h"
#include "hrt_work.h"
#include "px4_log.h"

//extern pthread_t _shell_task_id;

__BEGIN_DECLS
extern uint64_t get_ticks_per_us();

//long PX4_TICKS_PER_SEC = 1000L;

unsigned int sleep(unsigned int sec)
{
	for (unsigned int i = 0; i < sec; i++) {
		usleep(1000000);
	}

	return 0;
}

extern void hrt_init(void);
extern void init_params();

#if 0
void qurt_log(const char *fmt, ...)
{
	va_list	args;
	va_start(args, fmt);
	printf(fmt, args);
	printf("n");
}
#endif

//extern int _posix_init(void);

__END_DECLS

extern struct wqueue_s gwork[NWORKERS];

namespace px4
{

void init_once(void);

void init_once(void)
{
	// Required for QuRT
	//_posix_init();
	PX4_WARN("Before calling work_queue_init");

//	_shell_task_id = pthread_self();
//	PX4_INFO("Shell id is %lu", _shell_task_id);

	work_queues_init();
	PX4_WARN("Before calling hrt_init");
	hrt_work_queue_init();
	hrt_init();
	PX4_WARN("after calling hrt_init");

	/* Shared memory param sync*/
	init_params();
}

void init(int argc, char *argv[], const char *app_name)
{
	PX4_DEBUG("App name: %s\n", app_name);
}

}

/** Retrieve from the data manager store */
ssize_t
dm_read(
	dm_item_t item,                 /* The item type to retrieve */
	unsigned char index,            /* The index of the item */
	void *buffer,                   /* Pointer to caller data buffer */
	size_t buflen                   /* Length in bytes of data to retrieve */
)
{
	return 0;
}

/** write to the data manager store */
ssize_t
dm_write(
	dm_item_t  item,                /* The item type to store */
	unsigned char index,            /* The index of the item */
	dm_persitence_t persistence,    /* The persistence level of this item */
	const void *buffer,             /* Pointer to caller data buffer */
	size_t buflen                   /* Length in bytes of data to retrieve */
)
{
	return 0;
}

size_t strnlen(const char *s, size_t maxlen)
{
	size_t i = 0;

	while (s[i] != '\0' && i < maxlen) {
		++i;
	}

	return i;
}

static void block_indefinite(void)
{
	for (;;) {
		volatile int x = 0;
		++x;
	}
}

int fprintf(FILE *stream, const char *format, ...)
{
	PX4_ERR("Error: Calling unresolved symbol stub[%s]", __FUNCTION__);
	block_indefinite();
	return 0;
}

int fputc(int c, FILE *stream)
{
	return c;
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
#include <vector>

using namespace std;

#define MAXN 100
#define MAXM 10000

int n,m;

struct edge{
	int u,v,w;

	bool operator < (edge e) const{
		return w < e.w;
	}
}e[MAXM];

bool in_tree[MAXM];

// Union - Find

int parent[MAXN + 1];

int Find(int x){
	if(parent[x] == x) return x;
	parent[x] = Find(parent[x]);
	return parent[x];
}

void Union(int x, int y){
	x = Find(x);
	y = Find(y);
	parent[x] = y;
}

// dfs to find a path between two nodes in the MST

vector<int> L[MAXN],edge_id[MAXN],path,path_edges;
bool visited[MAXN];

bool dfs(int u, int v){
	path.push_back(u);

	if(u == v) return true;

	bool ret = false;

	if(!visited[u]){
		visited[u] = true;

		for(int i = 0;i < L[u].size();++i){
			int to = L[u][i];
			path_edges.push_back(edge_id[u][i]);

			if(dfs(to,v)){
				ret = true;
				break;
			}else{
				path_edges.pop_back();
			}
		}
	}

	if(!ret)
		path.pop_back();

	return ret;
}

// dfs to mark edges in a subtree after erasing an edge

int mark[MAXN];

void dfs2(int u, int v, int cur){
	if(visited[cur]) return;
	visited[cur] = true;

	mark[cur] = u;

	for(int i = 0;i < L[cur].size();++i){
		int to = L[cur][i];

		if(to != u && to != v)
			dfs2(u,v,to);
	}
}

// dfs to root the tree
int in[MAXN],out[MAXN],cont;
int parent_lca[10][MAXN],maxw[10][MAXN];
int height[MAXN];

void dfs3(int cur, int p, int e_id){
	in[cur] = cont++;

	parent_lca[0][cur] = p;
	maxw[0][cur] = e[e_id].w;
	height[cur] = (p == 0? 0 : 1 + height[p]);

	for(int i = 1;i <= 9;++i){
		parent_lca[i][cur] = parent_lca[i - 1][ parent_lca[i - 1][cur] ];
		maxw[i][cur] = max(maxw[i - 1][cur],maxw[i - 1][ parent_lca[i - 1][cur ]]);
	}

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs3(to,cur,edge_id[cur][i]);
	}

	out[cur] = cont - 1;
}

// lowest common ancestor

int lca(int u, int v){
	if(height[u] < height[v])
		swap(u,v);

	for(int i = 9;i >= 0;--i)
		if((height[u] - height[v]) >> i & 1)
			u = parent_lca[i][u];

	if(u == v)
		return u;

	for(int i = 9;i >= 0;--i)
		if(parent_lca[i][u] != parent_lca[i][v]){
			u = parent_lca[i][u];
			v = parent_lca[i][v];
		}

	return parent_lca[0][u];
}

int max_weight(int u, int up){
	int ret = 0;

	for(int i = 9;i >= 0;--i){
		if(height[u] >> i & 1){
			ret = max(ret,maxw[i][u]);
			u = parent_lca[i][u];
		}
	}

	return ret;
}

// segment tree to calculate minimum in a range and update

int T[4 * MAXN];

void init(int node, int l, int r){
	T[node] = INT_MAX;

	if(l != r){
		int mi = (l + r) >> 1;
		init(2 * node + 1,l,mi);
		init(2 * node + 2,mi + 1,r);
	}
}

int query(int node, int l, int r, int x, int y){
	if(r < x || l > y) return INT_MAX;
	if(x <= l && r <= y) return T[node];

	int mi = (l + r) >> 1;

	return min(query(2 * node + 1,l,mi,x,y),query(2 * node + 2,mi + 1,r,x,y));
}

void update(int node, int l, int r, int x, int val){
	if(l == r) T[node] = min(T[node],val);
	else{
		int mi = (l + r) >> 1;

		if(x <= mi) update(2 * node + 1,l,mi,x,val);
		else update(2 * node + 2,mi + 1,r,x,val);

		T[node] = min(T[2 * node + 1],T[2 * node + 2]);
	}
}

// dfs for the sensitivity analysis of tree edges

int k[MAXN],sensitivity[MAXM];
vector<int> L2[MAXN],W2[MAXN];

void dfs4(int cur, int p, int e_id){
	if(p != 0){
		sensitivity[e_id] = query(0,0,n - 1,in[cur],out[cur]) - e[e_id].w;
	}

	// decrease keys
	for(int i = (int)L2[cur].size() - 1;i >= 0;--i){
		update(0,0,n - 1,in[ L2[cur][i] ],W2[cur][i]);
	}

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs4(to,cur,edge_id[cur][i]);
	}
}

int main(){
	n = m = 0;

	while(scanf("%d,%d,%d",&e[m].u,&e[m].v,&e[m].w) == 3){
		n = max(n,max(e[m].u,e[m].v));
		++m;
	}

	// Find minimum spanning tree using Kruskal's algorithm

	for(int i = 1;i <= n;++i)
		parent[i] = i;

	sort(e,e + m);

	int total = 0;

	for(int i = 0;i < m;++i){
		if(Find(e[i].u) != Find(e[i].v)){
			Union(e[i].u,e[i].v);
			total += e[i].w;
			in_tree[i] = true;

			L[ e[i].u ].push_back(e[i].v);
			edge_id[ e[i].u ].push_back(i);

			L[ e[i].v ].push_back(e[i].u);
			edge_id[ e[i].v ].push_back(i);

			printf("%d - %d (%d)\n",e[i].u,e[i].v,e[i].w);
		}else in_tree[i] = false;
	}

	printf("Total weight = %d\n\n",total);

	// Find the path int T that connect two endpoint of an edge

	bool verified = true;

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			memset(visited,false,sizeof visited);
			path.clear();
			dfs(e[i].u,e[i].v);

			printf("(%d, %d) : ",e[i].u,e[i].v);

			for(int j = 0;j < path.size();++j){
				if(j > 0) printf(" -> ");
				printf("%d",path[j]);
			}

			printf("\n");

			// Verify MST

			for(int j = 0;j < path_edges.size();++j){
				if(e[i].w < e[ path_edges[j] ].w)
					verified = false;
			}
		}
	}

	printf("\n");

	printf("Verification: ");
	if(verified) printf("It is an MST\n\n");
	else printf("It is not an MST\n\n");

	// Find edges that can replace an edge in the MST

	int most_vital_edge = -1;
	int max_increase = -1;

	for(int i = 0;i < m;++i){
		if(in_tree[i]){
			memset(visited,false,sizeof visited);
			dfs2(e[i].u,e[i].v,e[i].u);
			dfs2(e[i].v,e[i].u,e[i].v);

			printf("(%d, %d) :",e[i].u,e[i].v);

			int rep = -1;

			for(int j = 0;j < m;++j)
				if(j != i && ((mark[ e[j].u ] == e[i].u && mark[ e[j].v ] == e[i].v) || (mark[ e[j].v ] == e[i].u && mark[ e[j].u ] == e[i].v))){
					printf(" (%d, %d)",e[j].u,e[j].v);

					if(rep == -1 || e[j].w < e[rep].w)
						rep = j;
				}

			printf(", replacement : (%d, %d)\n",e[rep].u,e[rep].v);

			if(most_vital_edge == -1 || e[rep].w - e[i].w > max_increase){
				max_increase = e[rep].w - e[i].w;
				most_vital_edge = i;
			}
		}
	}

	printf("\n");
	printf("Most vital edge = (%d, %d)\n",e[most_vital_edge].u,e[most_vital_edge].v);
	printf("Increase = %d\n",max_increase);

	// Order vertices in the tree, precalculate lowest common ancestor

	cont = 0;
	dfs3(1,0,-1);

	// Sensitivity analysis for tree edges

	// replace non tree edges by two auxiliary edges
	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			int anc = lca(e[i].u,e[i].v);

			if(anc != e[i].u && anc != e[i].v){
				L2[anc].push_back(e[i].u);
				W2[anc].push_back(e[i].w);

				L2[anc].push_back(e[i].v);
				W2[anc].push_back(e[i].w);
			}else if(height[ e[i].u ] < height[ e[i].v ]){
				L2[ e[i].u ].push_back(e[i].v);
				W2[ e[i].u ].push_back(e[i].w);
			}else{
				L2[ e[i].v ].push_back(e[i].u);
				W2[ e[i].v ].push_back(e[i].w);
			}
		}
	}

	init(0,0,n - 1);
	dfs4(1,0,-1);

	// Sensitivity analsys for non tree edges

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			int anc = lca(e[i].u,e[i].v);

			if(anc != e[i].u && anc != e[i].v){
				sensitivity[i] = e[i].w - max(max_weight(e[i].u,height[ e[i].u ] - height[anc]),
												max_weight(e[i].v,height[ e[i].v ] - height[anc]));
			}else if(height[ e[i].u ] < height[ e[i].v ]){
				sensitivity[i] = e[i].w - max_weight(e[i].v,height[ e[i].v ] - height[ e[i].u ]);
			}else{
				sensitivity[i] = e[i].w - max_weight(e[i].u,height[ e[i].u ] - height[ e[i].v ]);
			}
		}
	}

	printf("\nSensitivity analysis:\n");

	for(int i = 0;i < m;++i){
		if(in_tree[i])
			printf("(%d, %d) can increase up to %d\n",e[i].u,e[i].v,sensitivity[i]);
		else
			printf("(%d, %d) can decrease up to %d\n",e[i].u,e[i].v,sensitivity[i]);
	}

	return 0;
}<commit_msg>add union by rank<commit_after>#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
#include <vector>

using namespace std;

#define MAXN 100
#define MAXM 10000

int n,m;

struct edge{
	int u,v,w;

	bool operator < (edge e) const{
		return w < e.w;
	}
}e[MAXM];

bool in_tree[MAXM];

// Union - Find

int parent[MAXN + 1],rank[MAXN + 1];

int Find(int x){
	if(parent[x] == x) return x;
	parent[x] = Find(parent[x]);
	return parent[x];
}

void Union(int x, int y){
	x = Find(x);
	y = Find(y);

	if(rank[x] < rank[y]){
		parent[x] = y;
	}else{
		parent[y] = x;

		if(rank[x] == rank[y])
			++rank[x];
	}
}

// dfs to find a path between two nodes in the MST

vector<int> L[MAXN],edge_id[MAXN],path,path_edges;
bool visited[MAXN];

bool dfs(int u, int v){
	path.push_back(u);

	if(u == v) return true;

	bool ret = false;

	if(!visited[u]){
		visited[u] = true;

		for(int i = 0;i < L[u].size();++i){
			int to = L[u][i];
			path_edges.push_back(edge_id[u][i]);

			if(dfs(to,v)){
				ret = true;
				break;
			}else{
				path_edges.pop_back();
			}
		}
	}

	if(!ret)
		path.pop_back();

	return ret;
}

// dfs to mark edges in a subtree after erasing an edge

int mark[MAXN];

void dfs2(int u, int v, int cur){
	if(visited[cur]) return;
	visited[cur] = true;

	mark[cur] = u;

	for(int i = 0;i < L[cur].size();++i){
		int to = L[cur][i];

		if(to != u && to != v)
			dfs2(u,v,to);
	}
}

// dfs to root the tree
int in[MAXN],out[MAXN],cont;
int parent_lca[10][MAXN],maxw[10][MAXN];
int height[MAXN];

void dfs3(int cur, int p, int e_id){
	in[cur] = cont++;

	parent_lca[0][cur] = p;
	maxw[0][cur] = e[e_id].w;
	height[cur] = (p == 0? 0 : 1 + height[p]);

	for(int i = 1;i <= 9;++i){
		parent_lca[i][cur] = parent_lca[i - 1][ parent_lca[i - 1][cur] ];
		maxw[i][cur] = max(maxw[i - 1][cur],maxw[i - 1][ parent_lca[i - 1][cur ]]);
	}

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs3(to,cur,edge_id[cur][i]);
	}

	out[cur] = cont - 1;
}

// lowest common ancestor

int lca(int u, int v){
	if(height[u] < height[v])
		swap(u,v);

	for(int i = 9;i >= 0;--i)
		if((height[u] - height[v]) >> i & 1)
			u = parent_lca[i][u];

	if(u == v)
		return u;

	for(int i = 9;i >= 0;--i)
		if(parent_lca[i][u] != parent_lca[i][v]){
			u = parent_lca[i][u];
			v = parent_lca[i][v];
		}

	return parent_lca[0][u];
}

int max_weight(int u, int up){
	int ret = 0;

	for(int i = 9;i >= 0;--i){
		if(height[u] >> i & 1){
			ret = max(ret,maxw[i][u]);
			u = parent_lca[i][u];
		}
	}

	return ret;
}

// segment tree to calculate minimum in a range and update

int T[4 * MAXN];

void init(int node, int l, int r){
	T[node] = INT_MAX;

	if(l != r){
		int mi = (l + r) >> 1;
		init(2 * node + 1,l,mi);
		init(2 * node + 2,mi + 1,r);
	}
}

int query(int node, int l, int r, int x, int y){
	if(r < x || l > y) return INT_MAX;
	if(x <= l && r <= y) return T[node];

	int mi = (l + r) >> 1;

	return min(query(2 * node + 1,l,mi,x,y),query(2 * node + 2,mi + 1,r,x,y));
}

void update(int node, int l, int r, int x, int val){
	if(l == r) T[node] = min(T[node],val);
	else{
		int mi = (l + r) >> 1;

		if(x <= mi) update(2 * node + 1,l,mi,x,val);
		else update(2 * node + 2,mi + 1,r,x,val);

		T[node] = min(T[2 * node + 1],T[2 * node + 2]);
	}
}

// dfs for the sensitivity analysis of tree edges

int k[MAXN],sensitivity[MAXM];
vector<int> L2[MAXN],W2[MAXN];

void dfs4(int cur, int p, int e_id){
	if(p != 0){
		sensitivity[e_id] = query(0,0,n - 1,in[cur],out[cur]) - e[e_id].w;
	}

	// decrease keys
	for(int i = (int)L2[cur].size() - 1;i >= 0;--i){
		update(0,0,n - 1,in[ L2[cur][i] ],W2[cur][i]);
	}

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs4(to,cur,edge_id[cur][i]);
	}
}

int main(){
	n = m = 0;

	while(scanf("%d,%d,%d",&e[m].u,&e[m].v,&e[m].w) == 3){
		n = max(n,max(e[m].u,e[m].v));
		++m;
	}

	// Find minimum spanning tree using Kruskal's algorithm

	for(int i = 1;i <= n;++i)
		parent[i] = i;

	sort(e,e + m);

	int total = 0;

	for(int i = 0;i < m;++i){
		if(Find(e[i].u) != Find(e[i].v)){
			Union(e[i].u,e[i].v);
			total += e[i].w;
			in_tree[i] = true;

			L[ e[i].u ].push_back(e[i].v);
			edge_id[ e[i].u ].push_back(i);

			L[ e[i].v ].push_back(e[i].u);
			edge_id[ e[i].v ].push_back(i);

			printf("%d - %d (%d)\n",e[i].u,e[i].v,e[i].w);
		}else in_tree[i] = false;
	}

	printf("Total weight = %d\n\n",total);

	// Find the path int T that connect two endpoint of an edge

	bool verified = true;

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			memset(visited,false,sizeof visited);
			path.clear();
			dfs(e[i].u,e[i].v);

			printf("(%d, %d) : ",e[i].u,e[i].v);

			for(int j = 0;j < path.size();++j){
				if(j > 0) printf(" -> ");
				printf("%d",path[j]);
			}

			printf("\n");

			// Verify MST

			for(int j = 0;j < path_edges.size();++j){
				if(e[i].w < e[ path_edges[j] ].w)
					verified = false;
			}
		}
	}

	printf("\n");

	printf("Verification: ");
	if(verified) printf("It is an MST\n\n");
	else printf("It is not an MST\n\n");

	// Find edges that can replace an edge in the MST

	int most_vital_edge = -1;
	int max_increase = -1;

	for(int i = 0;i < m;++i){
		if(in_tree[i]){
			memset(visited,false,sizeof visited);
			dfs2(e[i].u,e[i].v,e[i].u);
			dfs2(e[i].v,e[i].u,e[i].v);

			printf("(%d, %d) :",e[i].u,e[i].v);

			int rep = -1;

			for(int j = 0;j < m;++j)
				if(j != i && ((mark[ e[j].u ] == e[i].u && mark[ e[j].v ] == e[i].v) || (mark[ e[j].v ] == e[i].u && mark[ e[j].u ] == e[i].v))){
					printf(" (%d, %d)",e[j].u,e[j].v);

					if(rep == -1 || e[j].w < e[rep].w)
						rep = j;
				}

			printf(", replacement : (%d, %d)\n",e[rep].u,e[rep].v);

			if(most_vital_edge == -1 || e[rep].w - e[i].w > max_increase){
				max_increase = e[rep].w - e[i].w;
				most_vital_edge = i;
			}
		}
	}

	printf("\n");
	printf("Most vital edge = (%d, %d)\n",e[most_vital_edge].u,e[most_vital_edge].v);
	printf("Increase = %d\n",max_increase);

	// Order vertices in the tree, precalculate lowest common ancestor

	cont = 0;
	dfs3(1,0,-1);

	// Sensitivity analysis for tree edges

	// replace non tree edges by two auxiliary edges
	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			int anc = lca(e[i].u,e[i].v);

			if(anc != e[i].u && anc != e[i].v){
				L2[anc].push_back(e[i].u);
				W2[anc].push_back(e[i].w);

				L2[anc].push_back(e[i].v);
				W2[anc].push_back(e[i].w);
			}else if(height[ e[i].u ] < height[ e[i].v ]){
				L2[ e[i].u ].push_back(e[i].v);
				W2[ e[i].u ].push_back(e[i].w);
			}else{
				L2[ e[i].v ].push_back(e[i].u);
				W2[ e[i].v ].push_back(e[i].w);
			}
		}
	}

	init(0,0,n - 1);
	dfs4(1,0,-1);

	// Sensitivity analsys for non tree edges

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			int anc = lca(e[i].u,e[i].v);

			if(anc != e[i].u && anc != e[i].v){
				sensitivity[i] = e[i].w - max(max_weight(e[i].u,height[ e[i].u ] - height[anc]),
												max_weight(e[i].v,height[ e[i].v ] - height[anc]));
			}else if(height[ e[i].u ] < height[ e[i].v ]){
				sensitivity[i] = e[i].w - max_weight(e[i].v,height[ e[i].v ] - height[ e[i].u ]);
			}else{
				sensitivity[i] = e[i].w - max_weight(e[i].u,height[ e[i].u ] - height[ e[i].v ]);
			}
		}
	}

	printf("\nSensitivity analysis:\n");

	for(int i = 0;i < m;++i){
		if(in_tree[i])
			printf("(%d, %d) can increase up to %d\n",e[i].u,e[i].v,sensitivity[i]);
		else
			printf("(%d, %d) can decrease up to %d\n",e[i].u,e[i].v,sensitivity[i]);
	}

	return 0;
}<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <memory>
#include <unordered_map>

#include <boost/variant.hpp>

#include "tac/Optimizer.hpp"
#include "tac/Program.hpp"
#include "tac/Utils.hpp"

using namespace eddic;

namespace {

struct ArithmeticIdentities : public boost::static_visitor<tac::Statement> {
    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::ADD:
                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    break;
                case tac::Operator::SUB:
                    if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    //a = b - b => a = 0
                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                        if(tac::equals<std::shared_ptr<Variable>>(*quadruple->arg2, *ptr)){
                            return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                        }
                    }

                    //TODO Transform x = 0 - a into x = -a by adding a NEG tac instruction

                    break;
                case tac::Operator::MUL:
                    if(tac::equals<int>(quadruple->arg1, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    } else if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    }

                    //TODO Transform x = a * -1 and x = -1 * a into x = -a by adding a NEG tac instruction

                    break;
                case tac::Operator::DIV:
                    if(tac::equals<int>(*quadruple->arg2, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    }

                    //a = b / b => a = 1
                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                        if(tac::equals<std::shared_ptr<Variable>>(*quadruple->arg2, *ptr)){
                            return std::make_shared<tac::Quadruple>(quadruple->result, 1);
                        }
                    }

                    //TODO Transform x = 0 / -1 into x = -a by adding a NEG tac instruction

                    break;
                default:
                    return quadruple;
            }
        }

        return quadruple;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ReduceInStrength : public boost::static_visitor<tac::Statement> {
    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::MUL:
                    if(tac::equals<int>(quadruple->arg1, 2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2, tac::Operator::ADD, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1, tac::Operator::ADD, quadruple->arg1);
                    }

                    break;
                default:
                    return quadruple;
            }
        }

        return quadruple;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ConstantFolding : public boost::static_visitor<tac::Statement> {
    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::ADD:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) + boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::SUB:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) - boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::MUL:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) * boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::DIV:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) / boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::MOD:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) % boost::get<int>(*quadruple->arg2));
                    }

                    break;
                default:
                    return quadruple;
            }
        }

        return quadruple;
    }

    tac::Statement operator()(std::shared_ptr<tac::IfFalse>& ifFalse){
        //TODO Evaluate boolean expressions at compile time

        return ifFalse;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ConstantPropagation : public boost::static_visitor<tac::Statement> {
    std::unordered_map<std::shared_ptr<Variable>, int> constants;

    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        if(!quadruple->op){
            if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                if(constants.find(*ptr) != constants.end()){
                    quadruple->arg1 = constants[*ptr];
                }
            }

            if(auto* ptr = boost::get<int>(&quadruple->arg1)){
                constants[quadruple->result] = *ptr;
            }
        } else {
            if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                if(constants.find(*ptr) != constants.end()){
                    quadruple->arg1 = constants[*ptr];
                }
            }

            if(quadruple->arg2){
                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*quadruple->arg2)){
                    if(constants.find(*ptr) != constants.end()){
                        quadruple->arg2 = constants[*ptr];
                    }
                }
            }

            //The result is not constant at this point
            constants.erase(quadruple->result);
        }

        return quadruple;
    }

    template<typename T>
        tac::Statement operator()(T& statement){
            return statement;
        }
};

template<typename Visitor>
void apply_to_all(tac::Program& program){
    Visitor visitor;

    for(auto& function : program.functions){
        for(auto& block : function->getBasicBlocks()){
            for(auto& statement : block->statements){
                statement = boost::apply_visitor(visitor, statement);
            }
        }
    }
}

template<typename Visitor>
void apply_to_basic_blocks(tac::Program& program){
    for(auto& function : program.functions){
        for(auto& block : function->getBasicBlocks()){
            Visitor visitor;

            for(auto& statement : block->statements){
                statement = boost::apply_visitor(visitor, statement);
            }
        }
    }
}

}

void tac::Optimizer::optimize(tac::Program& program) const {
    //Optimize using arithmetic identities
    apply_to_all<ArithmeticIdentities>(program);

    //Reduce arithtmetic instructions in strength
    apply_to_all<ReduceInStrength>(program);

    //Constant folding
    apply_to_all<ConstantFolding>(program);

    //Constant propagation
    apply_to_basic_blocks<ConstantPropagation>(program);

    //TODO Remove unused temporaries

    //TODO Copy propagation
}
<commit_msg>Implement multipass optimizations<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <memory>
#include <unordered_map>

#include <boost/variant.hpp>

#include "tac/Optimizer.hpp"
#include "tac/Program.hpp"
#include "tac/Utils.hpp"

using namespace eddic;

namespace {

struct ArithmeticIdentities : public boost::static_visitor<tac::Statement> {
    bool optimized;

    ArithmeticIdentities() : optimized(false) {}

    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        bool old = optimized;
        optimized = true;

        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::ADD:
                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    break;
                case tac::Operator::SUB:
                    if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    //a = b - b => a = 0
                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                        if(tac::equals<std::shared_ptr<Variable>>(*quadruple->arg2, *ptr)){
                            return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                        }
                    }

                    //TODO Transform x = 0 - a into x = -a by adding a NEG tac instruction

                    break;
                case tac::Operator::MUL:
                    if(tac::equals<int>(quadruple->arg1, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    } else if(tac::equals<int>(*quadruple->arg2, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    }

                    //TODO Transform x = a * -1 and x = -1 * a into x = -a by adding a NEG tac instruction

                    break;
                case tac::Operator::DIV:
                    if(tac::equals<int>(*quadruple->arg2, 1)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1);
                    }

                    if(tac::equals<int>(quadruple->arg1, 0)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, 0);
                    }

                    //a = b / b => a = 1
                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                        if(tac::equals<std::shared_ptr<Variable>>(*quadruple->arg2, *ptr)){
                            return std::make_shared<tac::Quadruple>(quadruple->result, 1);
                        }
                    }

                    //TODO Transform x = 0 / -1 into x = -a by adding a NEG tac instruction

                    break;
                default:
                    break;
            }
        }

        optimized = old;
        return quadruple;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ReduceInStrength : public boost::static_visitor<tac::Statement> {
    bool optimized;

    ReduceInStrength() : optimized(false) {}

    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        bool old = optimized;
        optimized = true;

        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::MUL:
                    if(tac::equals<int>(quadruple->arg1, 2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, *quadruple->arg2, tac::Operator::ADD, *quadruple->arg2);
                    } else if(tac::equals<int>(*quadruple->arg2, 2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result, quadruple->arg1, tac::Operator::ADD, quadruple->arg1);
                    }

                    break;
                default:
                    break;
            }
        }

        optimized = old;
        return quadruple;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ConstantFolding : public boost::static_visitor<tac::Statement> {
    bool optimized;

    ConstantFolding() : optimized(false) {}

    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        bool old = optimized;
        optimized = true;

        if(quadruple->op){
            switch(*quadruple->op){
                case tac::Operator::ADD:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) + boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::SUB:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) - boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::MUL:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) * boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::DIV:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) / boost::get<int>(*quadruple->arg2));
                    }

                    break;
                case tac::Operator::MOD:
                    if(tac::isInt(quadruple->arg1) && tac::isInt(*quadruple->arg2)){
                        return std::make_shared<tac::Quadruple>(quadruple->result,
                            boost::get<int>(quadruple->arg1) % boost::get<int>(*quadruple->arg2));
                    }

                    break;
                default:
                    break;
            }
        }

        optimized = old;
        return quadruple;
    }

    tac::Statement operator()(std::shared_ptr<tac::IfFalse>& ifFalse){
        //TODO Evaluate boolean expressions at compile time

        return ifFalse;
    }

    template<typename T>
    tac::Statement operator()(T& statement) const {
        return statement;
    }
};

struct ConstantPropagation : public boost::static_visitor<tac::Statement> {
    bool optimized;

    ConstantPropagation() : optimized(false) {}

    std::unordered_map<std::shared_ptr<Variable>, int> constants;

    tac::Statement operator()(std::shared_ptr<tac::Quadruple>& quadruple){
        bool old = optimized;
        optimized = true;

        if(!quadruple->op){
            if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                if(constants.find(*ptr) != constants.end()){
                    quadruple->arg1 = constants[*ptr];
                }
            }

            if(auto* ptr = boost::get<int>(&quadruple->arg1)){
                constants[quadruple->result] = *ptr;
            }
        } else {
            if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&quadruple->arg1)){
                if(constants.find(*ptr) != constants.end()){
                    quadruple->arg1 = constants[*ptr];
                }
            }

            if(quadruple->arg2){
                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*quadruple->arg2)){
                    if(constants.find(*ptr) != constants.end()){
                        quadruple->arg2 = constants[*ptr];
                    }
                }
            }

            //The result is not constant at this point
            constants.erase(quadruple->result);
        }

        optimized = old;
        return quadruple;
    }

    template<typename T>
        tac::Statement operator()(T& statement){
            return statement;
        }
};

template<typename Visitor>
bool apply_to_all(tac::Program& program){
    Visitor visitor;

    for(auto& function : program.functions){
        for(auto& block : function->getBasicBlocks()){
            for(auto& statement : block->statements){
                statement = boost::apply_visitor(visitor, statement);
            }
        }
    }

    return visitor.optimized;
}

template<typename Visitor>
bool apply_to_basic_blocks(tac::Program& program){
    bool optimized = false;

    for(auto& function : program.functions){
        for(auto& block : function->getBasicBlocks()){
            Visitor visitor;

            for(auto& statement : block->statements){
                statement = boost::apply_visitor(visitor, statement);
            }

            optimized |= visitor.optimized;
        }
    }

    return optimized;
}

}

void tac::Optimizer::optimize(tac::Program& program) const {
    bool optimized;
    do {
        optimized = false;

        //Optimize using arithmetic identities
        optimized |= apply_to_all<ArithmeticIdentities>(program);

        //Reduce arithtmetic instructions in strength
        optimized |= apply_to_all<ReduceInStrength>(program);

        //Constant folding
        optimized |= apply_to_all<ConstantFolding>(program);

        //Constant propagation
        optimized |= apply_to_basic_blocks<ConstantPropagation>(program);
    } while (optimized);

    //TODO Remove unused temporaries

    //TODO Copy propagation
}
<|endoftext|>