<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh/nonlinear_implicit_system.h"
#include "libmesh/diff_solver.h"
#include "libmesh/equation_systems.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/nonlinear_solver.h"
#include "libmesh/sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
                                                  const std::string& name_in,
                                                  const unsigned int number_in) :

  Parent                    (es, name_in, number_in),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-35;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;

  if (libMesh::on_command_line("--solver_system_names"))
    nonlinear_solver->init((this->name()+"_").c_str());
  else
    nonlinear_solver->init();
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
                                 nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool get_residual,
                                       bool get_jacobian)
{
  // Get current_local_solution in sync
  this->update();

  //-----------------------------------------------------------------------------
  // if the user has provided both function pointers and objects only the pointer
  // will be used, so catch that as an error
  if (nonlinear_solver->jacobian && nonlinear_solver->jacobian_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Jacobian!" << std::endl;
      libmesh_error();
    }

  if (nonlinear_solver->residual && nonlinear_solver->residual_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Residual!" << std::endl;
      libmesh_error();
    }

  if (nonlinear_solver->matvec && nonlinear_solver->residual_and_jacobian_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl;
      libmesh_error();
    }
  //-----------------------------------------------------------------------------

  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);

      else if (nonlinear_solver->jacobian_object != NULL)
        nonlinear_solver->jacobian_object->jacobian (*current_local_solution.get(), *matrix, *this);

      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);

      else if (nonlinear_solver->residual_and_jacobian_object != NULL)
        nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);

      else
        libmesh_error();
    }

  if (get_residual)
    {
      if (nonlinear_solver->residual != NULL)
        nonlinear_solver->residual (*current_local_solution.get(), *rhs, *this);

      else if (nonlinear_solver->residual_object != NULL)
        nonlinear_solver->residual_object->residual (*current_local_solution.get(), *rhs, *this);

      else if (nonlinear_solver->matvec != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->matvec (*current_local_solution.get(), rhs, NULL, *this);
        }

      else if (nonlinear_solver->residual_and_jacobian_object != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian (*current_local_solution.get(), rhs, NULL, *this);
        }

      else
        libmesh_error();
    }
  else
    libmesh_assert(get_jacobian);  // I can't believe you really wanted to assemble *nothing*
}

unsigned NonlinearImplicitSystem::get_current_nonlinear_iteration_number() const
{
  return nonlinear_solver->get_current_nonlinear_iteration_number();
}

} // namespace libMesh
<commit_msg>Postpone automatic NonlinearSolver initialization<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh/nonlinear_implicit_system.h"
#include "libmesh/diff_solver.h"
#include "libmesh/equation_systems.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/nonlinear_solver.h"
#include "libmesh/sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
                                                  const std::string& name_in,
                                                  const unsigned int number_in) :

  Parent                    (es, name_in, number_in),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-35;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      if (libMesh::on_command_line("--solver_system_names"))
        nonlinear_solver->init((this->name()+"_").c_str());
      else
        nonlinear_solver->init();

      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
                                 nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool get_residual,
                                       bool get_jacobian)
{
  // Get current_local_solution in sync
  this->update();

  //-----------------------------------------------------------------------------
  // if the user has provided both function pointers and objects only the pointer
  // will be used, so catch that as an error
  if (nonlinear_solver->jacobian && nonlinear_solver->jacobian_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Jacobian!" << std::endl;
      libmesh_error();
    }

  if (nonlinear_solver->residual && nonlinear_solver->residual_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Residual!" << std::endl;
      libmesh_error();
    }

  if (nonlinear_solver->matvec && nonlinear_solver->residual_and_jacobian_object)
    {
      libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl;
      libmesh_error();
    }
  //-----------------------------------------------------------------------------

  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);

      else if (nonlinear_solver->jacobian_object != NULL)
        nonlinear_solver->jacobian_object->jacobian (*current_local_solution.get(), *matrix, *this);

      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);

      else if (nonlinear_solver->residual_and_jacobian_object != NULL)
        nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);

      else
        libmesh_error();
    }

  if (get_residual)
    {
      if (nonlinear_solver->residual != NULL)
        nonlinear_solver->residual (*current_local_solution.get(), *rhs, *this);

      else if (nonlinear_solver->residual_object != NULL)
        nonlinear_solver->residual_object->residual (*current_local_solution.get(), *rhs, *this);

      else if (nonlinear_solver->matvec != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->matvec (*current_local_solution.get(), rhs, NULL, *this);
        }

      else if (nonlinear_solver->residual_and_jacobian_object != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian (*current_local_solution.get(), rhs, NULL, *this);
        }

      else
        libmesh_error();
    }
  else
    libmesh_assert(get_jacobian);  // I can't believe you really wanted to assemble *nothing*
}

unsigned NonlinearImplicitSystem::get_current_nonlinear_iteration_number() const
{
  return nonlinear_solver->get_current_nonlinear_iteration_number();
}

} // namespace libMesh
<|endoftext|>


<commit_before>/*
 * file_log_strategy.tcc
 *
 * Author: Ming Tsang
 * Copyright (c) 2014 Ming Tsang
 * Refer to LICENSE for details
 */

#pragma once

#include <ostream>
#include <string>

#include "libutils/io/file_log_strategy.h"
#include "libutils/io/logger.h"

namespace libutils
{
namespace io
{

namespace internal
{

inline const char* GetInitial(const LoggerFlag flag)
{
	switch (flag)
	{
	case LoggerFlag::kWtf:
		return "WTF: ";

	case LoggerFlag::kError:
		return "E: ";

	case LoggerFlag::kWarning:
		return "W: ";

	case LoggerFlag::kInfo:
		return "I: ";

	case LoggerFlag::kDebug:
		return "D: ";

	case LoggerFlag::kVerbose:
		return "V: ";

	default:
		return "";
	}
}

}

template<typename T>
void FileLogStrategy<T>::Log(const std::basic_string<T> &str,
		const LoggerFlag flag)
{
	this->GetStream() << internal::GetInitial(flag) << str << '\n';
}

}
}
<commit_msg>Rename function to prevent collision<commit_after>/*
 * file_log_strategy.tcc
 *
 * Author: Ming Tsang
 * Copyright (c) 2014 Ming Tsang
 * Refer to LICENSE for details
 */

#pragma once

#include <ostream>
#include <string>

#include "libutils/io/file_log_strategy.h"
#include "libutils/io/logger.h"

namespace libutils
{
namespace io
{

namespace internal
{

inline const char* FlsGetInitial(const LoggerFlag flag)
{
	switch (flag)
	{
	case LoggerFlag::kWtf:
		return "WTF: ";

	case LoggerFlag::kError:
		return "E: ";

	case LoggerFlag::kWarning:
		return "W: ";

	case LoggerFlag::kInfo:
		return "I: ";

	case LoggerFlag::kDebug:
		return "D: ";

	case LoggerFlag::kVerbose:
		return "V: ";

	default:
		return "";
	}
}

}

template<typename CharT_>
void FileLogStrategy<CharT_>::Log(const std::basic_string<CharT_> &str,
		const LoggerFlag flag)
{
	this->GetStream() << internal::FlsGetInitial(flag) << str << '\n';
}

}
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_HXX
   #error Please #include <abaclade.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::_str_to_str_backend

namespace abc {

/** Base class for the specializations of to_str_backend for string types. Not using templates, so
the implementation can be in a cxx file. This is used by string literal types as well (see below).
*/
class ABACLADE_SYM _str_to_str_backend {
public:

   /** Changes the output format.

   sFormat
      Formatting options.
   */
   void set_format(istr const & sFormat);

protected:

   /** Writes a string, applying the formatting options.

   p
      Pointer to the string to write.
   cb
      Size of the string pointed to by p, in bytes.
   enc
      Text encoding of the string pointed to by p.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(void const * p, size_t cb, text::encoding enc, io::text::writer * ptwOut);
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for character and string literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C, enc) \
   /** Character literal. \
   */ \
   template <> \
   class ABACLADE_SYM to_str_backend<C> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Writes a character, applying the formatting options.

      ch
         Character to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C ch, io::text::writer * ptwOut) { \
         _str_to_str_backend::write(&ch, sizeof(C), enc, ptwOut); \
      } \
   }; \
   \
   /** String literal. \
   */ \
   template <size_t t_cch> \
   class to_str_backend<C [t_cch]> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Writes a string, applying the formatting options.

      ach
         String to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C const (& ach)[t_cch], io::text::writer * ptwOut) { \
         ABC_ASSERT(ach[t_cch - 1 /*NUL*/] == '\0', SL("string literal must be NUL-terminated")); \
         _str_to_str_backend::write(ach, sizeof(C) * (t_cch - 1 /*NUL*/), enc, ptwOut); \
      } \
   }; \
   \
   /** MSC16 BUG: this partial specialization is necessary. */ \
   template <size_t t_cch> \
   class to_str_backend<C const [t_cch]> : public to_str_backend<C [t_cch]> {};
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char, text::encoding::utf8)
// Specializations for wchar_t, if it’s what char16_t or char32_t map to, and for char16/32_t, if
// they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t, text::encoding::utf16_host)
#elif ABC_CXX_CHAR16 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t, text::encoding::utf16_host)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t, text::encoding::utf32_host)
#elif ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t, text::encoding::utf32_host)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for abc::str_base

namespace abc {

template <>
class ABACLADE_SYM to_str_backend<str_base> :
   public _str_to_str_backend {
public:

   /** Writes a string, applying the formatting options.

   s
      String to write.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(str_base const & s, io::text::writer * ptwOut) {
      _str_to_str_backend::write(
         s.chars_begin(),
         size_t(reinterpret_cast<int8_t const *>(s.chars_end()) -
            reinterpret_cast<int8_t const *>(s.chars_begin())),
         text::encoding::host, ptwOut
      );
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for abc::*str

namespace abc {

template <>
class to_str_backend<istr> : public to_str_backend<str_base> {};

template <>
class to_str_backend<mstr> : public to_str_backend<str_base> {};

template <>
class to_str_backend<dmstr> : public to_str_backend<str_base> {};

template <size_t t_cchStatic>
class to_str_backend<smstr<t_cchStatic>> : public to_str_backend<str_base> {};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<commit_msg>Remove unnecessary ABACLADE_SYM<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_HXX
   #error Please #include <abaclade.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::_str_to_str_backend

namespace abc {

/** Base class for the specializations of to_str_backend for string types. Not using templates, so
the implementation can be in a cxx file. This is used by string literal types as well (see below).
*/
class ABACLADE_SYM _str_to_str_backend {
public:

   /** Changes the output format.

   sFormat
      Formatting options.
   */
   void set_format(istr const & sFormat);

protected:

   /** Writes a string, applying the formatting options.

   p
      Pointer to the string to write.
   cb
      Size of the string pointed to by p, in bytes.
   enc
      Text encoding of the string pointed to by p.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(void const * p, size_t cb, text::encoding enc, io::text::writer * ptwOut);
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for character and string literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C, enc) \
   /** Character literal. \
   */ \
   template <> \
   class to_str_backend<C> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Writes a character, applying the formatting options.

      ch
         Character to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C ch, io::text::writer * ptwOut) { \
         _str_to_str_backend::write(&ch, sizeof(C), enc, ptwOut); \
      } \
   }; \
   \
   /** String literal. \
   */ \
   template <size_t t_cch> \
   class to_str_backend<C [t_cch]> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Writes a string, applying the formatting options.

      ach
         String to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C const (& ach)[t_cch], io::text::writer * ptwOut) { \
         ABC_ASSERT(ach[t_cch - 1 /*NUL*/] == '\0', SL("string literal must be NUL-terminated")); \
         _str_to_str_backend::write(ach, sizeof(C) * (t_cch - 1 /*NUL*/), enc, ptwOut); \
      } \
   }; \
   \
   /** MSC16 BUG: this partial specialization is necessary. */ \
   template <size_t t_cch> \
   class to_str_backend<C const [t_cch]> : public to_str_backend<C [t_cch]> {};
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char, text::encoding::utf8)
// Specializations for wchar_t, if it’s what char16_t or char32_t map to, and for char16/32_t, if
// they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t, text::encoding::utf16_host)
#elif ABC_CXX_CHAR16 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t, text::encoding::utf16_host)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t, text::encoding::utf32_host)
#elif ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t, text::encoding::utf32_host)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for abc::str_base

namespace abc {

template <>
class ABACLADE_SYM to_str_backend<str_base> :
   public _str_to_str_backend {
public:

   /** Writes a string, applying the formatting options.

   s
      String to write.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(str_base const & s, io::text::writer * ptwOut) {
      _str_to_str_backend::write(
         s.chars_begin(),
         size_t(reinterpret_cast<int8_t const *>(s.chars_end()) -
            reinterpret_cast<int8_t const *>(s.chars_begin())),
         text::encoding::host, ptwOut
      );
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend – specialization for abc::*str

namespace abc {

template <>
class to_str_backend<istr> : public to_str_backend<str_base> {};

template <>
class to_str_backend<mstr> : public to_str_backend<str_base> {};

template <>
class to_str_backend<dmstr> : public to_str_backend<str_base> {};

template <size_t t_cchStatic>
class to_str_backend<smstr<t_cchStatic>> : public to_str_backend<str_base> {};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_CONVERSION_HH__
#define ALEPH_TOPOLOGY_CONVERSION_HH__

#include <aleph/config/Defaults.hh>

#include <aleph/topology/BoundaryMatrix.hh>

#include <algorithm>

namespace aleph
{

namespace topology
{

/**
  Converts a simplicial complex into its boundary matrix representation.
  An optional index may be used to stop converting simplices whose index
  is larger than the specified maximum.

  If no maximum index is specified, the boundary matrices created by the
  function are suitable for (persistent) homology. If a maximum index is
  given, however, the matrices are particularly suitable for calculating
  (persistent) intersection homology.
*/

template <
  class Representation = aleph::defaults::Representation,
  class SimplicialComplex
> BoundaryMatrix<Representation> makeBoundaryMatrix( const SimplicialComplex& K, std::size_t max = 0 )
{
  using Index = typename BoundaryMatrix<Representation>::Index;

  BoundaryMatrix<Representation> M;
  M.setNumColumns( max ? static_cast<Index>( max ) : static_cast<Index>( K.size() ) );

  Index j = Index(0);

  for( auto&& itSimplex = K.begin(); itSimplex != K.end(); ++itSimplex )
  {
    std::vector<Index> column;
    column.reserve( itSimplex->size() );

    for( auto&& itBoundary = itSimplex->begin_boundary();
         itBoundary != itSimplex->end_boundary();
         ++itBoundary )
    {
      // TODO: This lookup is *not* optimal. A hash map or something similar
      // should be used here. Else, every access incurs a cost of at least
      // O(log n) instead of O(1).
      auto index = K.index( *itBoundary );

      column.push_back( static_cast<Index>( index ) );
    }

    M.setColumn( j, column.begin(), column.end() );

    ++j;

    if( max && j >= max )
      break;
  }

  return M;
}

} // namespace topology

} // namespace aleph

#endif
<commit_msg>Fixed column specification for boundary matrix conversion<commit_after>#ifndef ALEPH_TOPOLOGY_CONVERSION_HH__
#define ALEPH_TOPOLOGY_CONVERSION_HH__

#include <aleph/config/Defaults.hh>

#include <aleph/topology/BoundaryMatrix.hh>

#include <algorithm>

namespace aleph
{

namespace topology
{

/**
  Converts a simplicial complex into its boundary matrix representation.
  An optional index may be used to stop converting simplices whose index
  is larger than the specified maximum.

  If no maximum index is specified, the boundary matrices created by the
  function are suitable for (persistent) homology. If a maximum index is
  given, however, the matrices are particularly suitable for calculating
  (persistent) intersection homology.
*/

template <
  class Representation = aleph::defaults::Representation,
  class SimplicialComplex
> BoundaryMatrix<Representation> makeBoundaryMatrix( const SimplicialComplex& K, std::size_t max = 0 )
{
  using Index = typename BoundaryMatrix<Representation>::Index;

  BoundaryMatrix<Representation> M;
  M.setNumColumns( static_cast<Index>( K.size() ) );

  Index j = Index(0);

  for( auto&& itSimplex = K.begin(); itSimplex != K.end(); ++itSimplex )
  {
    std::vector<Index> column;
    column.reserve( itSimplex->size() );

    for( auto&& itBoundary = itSimplex->begin_boundary();
         itBoundary != itSimplex->end_boundary();
         ++itBoundary )
    {
      // TODO: This lookup is *not* optimal. A hash map or something similar
      // should be used here. Else, every access incurs a cost of at least
      // O(log n) instead of O(1).
      auto index = K.index( *itBoundary );

      column.push_back( static_cast<Index>( index ) );
    }

    M.setColumn( j, column.begin(), column.end() );

    ++j;

    if( max && j >= max )
      break;
  }

  return M;
}

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>


<commit_before><commit_msg>windows opengl: Explain the concept of the text drawing + minor fixes.<commit_after><|endoftext|>


<commit_before><commit_msg>conversion to void* needs an explicit cast<commit_after><|endoftext|>


<commit_before><commit_msg>Extend stagefright commandline up to enable vendor to reproduce specific bugs filed.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "flamegraph.h"

#include <cmath>

#include <QVBoxLayout>
#include <QGraphicsScene>
#include <QStyleOption>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsSimpleTextItem>
#include <QWheelEvent>
#include <QEvent>

#include <QElapsedTimer>
#include <QDebug>

#include <KLocalizedString>

namespace {

QColor color(quint64 cost, quint64 maxCost)
{
    const double ratio = double(cost) / maxCost;
    return QColor::fromHsv(120 - ratio * 120, 255, 255, (-((ratio-1) * (ratio-1))) * 120 + 120);
}

class FrameGraphicsItem : public QGraphicsRectItem
{
public:
    FrameGraphicsItem(const QRectF& rect, const quint64 cost, const QString& function)
        : QGraphicsRectItem(rect)
    {
        static const QString emptyLabel = QStringLiteral("???");

        m_label = i18nc("%1: number of allocations, %2: function label",
                        "%2: %1",
                        cost,
                        function.isEmpty() ? emptyLabel : function);
        setToolTip(m_label);
    }

    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0)
    {
        const int margin = 5;
        const int width = rect().width() - 2 * margin;
        if (width < 2) {
            // don't try to paint tiny items
            return;
        }

        QGraphicsRectItem::paint(painter, option, widget);

        const qreal lod = qMax(qreal(1.), option->levelOfDetailFromTransform(painter->worldTransform()));

        // TODO: text should always be displayed in a constant size and not zoomed
        // TODO: items should only be scaled horizontally, not vertically
        // TODO: items should "fit" into the view width
        QFont font(QStringLiteral("monospace"));
        font.setPointSizeF(10. / lod);
        QFontMetrics metrics(font);
        if (width < metrics.averageCharWidth() * 6) {
            // text is too wide for the current LOD, don't paint it
            return;
        }

        const int height = rect().height();

        const QPen oldPen = painter->pen();
        const QFont oldFont = painter->font();
        QPen pen = oldPen;
        pen.setColor(Qt::white);
        painter->setPen(pen);
        painter->setFont(font);
        painter->drawText(margin + rect().x(), rect().y(), width, height, Qt::AlignVCenter | Qt::AlignLeft | Qt::TextSingleLine, metrics.elidedText(m_label, Qt::ElideRight, width));
        painter->setPen(oldPen);
        painter->setFont(oldFont);
    }

private:
    QString m_label;
};

// TODO: what is the right value for maxWidth here?
QVector<QGraphicsItem*> toGraphicsItems(const FlameGraphData::Stack& data,
                                        const qreal x_0 = 0, const qreal y_0 = 0,
                                        const qreal maxWidth = 800., qreal totalCostForColor = 0,
                                        qreal parentCost = 0)
{
    QVector<QGraphicsItem*> ret;
    ret.reserve(data.size());

    double totalCost = 0;
    foreach(const auto& frame, data) {
        totalCost += frame.cost;
    }
    if (!totalCostForColor) {
        totalCostForColor = totalCost;
        parentCost = totalCost;
    }

    qreal x = x_0;
    const qreal h = 25;
    const qreal y = y_0;

    const qreal x_margin = 0;
    const qreal y_margin = 2;

    for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
        const qreal w = maxWidth * double(it.value().cost) / parentCost;
        FrameGraphicsItem* item = new FrameGraphicsItem(QRectF(x, y, w, h), it.value().cost, it.key());
        item->setVisible(w > 2.);
        item->setBrush(color(it.value().cost, totalCostForColor));
        ret += toGraphicsItems(it.value().children, x, y - h - y_margin, w, totalCostForColor, it.value().cost);
        x += w + x_margin;
        ret << item;
    }

    return ret;
}

}

FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
    : QWidget(parent, flags)
    , m_scene(new QGraphicsScene(this))
    , m_view(new QGraphicsView(this))
{
    qRegisterMetaType<FlameGraphData>();

    setLayout(new QVBoxLayout);

    m_view->setScene(m_scene);
    m_view->viewport()->installEventFilter(this);

    layout()->addWidget(m_view);
}

FlameGraph::~FlameGraph()
{

}

bool FlameGraph::eventFilter(QObject* object, QEvent* event)
{
    if (object == m_view->viewport() && event->type() == QEvent::Wheel) {
        QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
        if (wheelEvent->modifiers() == Qt::ControlModifier) {
            // zoom view with Ctrl + mouse wheel
            qreal scale = pow(1.1, double(wheelEvent->delta()) / (120.0 * 2.));
            m_view->scale(scale, scale);
            return true;
        }

    }
    return QObject::eventFilter(object, event);
}

void FlameGraph::setData(const FlameGraphData& data)
{
    m_data = data;
    m_scene->clear();

    qDebug() << "Evaluating flame graph";
    QElapsedTimer t; t.start();

    foreach(QGraphicsItem* item, toGraphicsItems(data.stack)) {
        m_scene->addItem(item);
    }

    qDebug() << "took me: " << t.elapsed();
}
<commit_msg>Use correct foreground color.<commit_after>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "flamegraph.h"

#include <cmath>

#include <QVBoxLayout>
#include <QGraphicsScene>
#include <QStyleOption>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsSimpleTextItem>
#include <QWheelEvent>
#include <QEvent>

#include <QElapsedTimer>
#include <QDebug>

#include <KLocalizedString>
#include <KColorScheme>

namespace {

QColor color(quint64 cost, quint64 maxCost)
{
    const double ratio = double(cost) / maxCost;
    return QColor::fromHsv(120 - ratio * 120, 255, 255, (-((ratio-1) * (ratio-1))) * 120 + 120);
}

class FrameGraphicsItem : public QGraphicsRectItem
{
public:
    FrameGraphicsItem(const QRectF& rect, const quint64 cost, const QString& function)
        : QGraphicsRectItem(rect)
    {
        static const QString emptyLabel = QStringLiteral("???");

        m_label = i18nc("%1: number of allocations, %2: function label",
                        "%2: %1",
                        cost,
                        function.isEmpty() ? emptyLabel : function);
        setToolTip(m_label);
    }

    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0)
    {
        const int margin = 5;
        const int width = rect().width() - 2 * margin;
        if (width < 2) {
            // don't try to paint tiny items
            return;
        }

        QGraphicsRectItem::paint(painter, option, widget);

        const qreal lod = qMax(qreal(1.), option->levelOfDetailFromTransform(painter->worldTransform()));

        // TODO: text should always be displayed in a constant size and not zoomed
        // TODO: items should only be scaled horizontally, not vertically
        // TODO: items should "fit" into the view width
        QFont font(QStringLiteral("monospace"));
        font.setPointSizeF(10. / lod);
        QFontMetrics metrics(font);
        if (width < metrics.averageCharWidth() * 6) {
            // text is too wide for the current LOD, don't paint it
            return;
        }

        const int height = rect().height();

        const QPen oldPen = painter->pen();
        const QFont oldFont = painter->font();
        QPen pen = oldPen;
        pen.setColor(KColorScheme(QPalette::Active).foreground().color());
        painter->setPen(pen);
        painter->setFont(font);
        painter->drawText(margin + rect().x(), rect().y(), width, height, Qt::AlignVCenter | Qt::AlignLeft | Qt::TextSingleLine, metrics.elidedText(m_label, Qt::ElideRight, width));
        painter->setPen(oldPen);
        painter->setFont(oldFont);
    }

private:
    QString m_label;
};

// TODO: what is the right value for maxWidth here?
QVector<QGraphicsItem*> toGraphicsItems(const FlameGraphData::Stack& data,
                                        const qreal x_0 = 0, const qreal y_0 = 0,
                                        const qreal maxWidth = 800., qreal totalCostForColor = 0,
                                        qreal parentCost = 0)
{
    QVector<QGraphicsItem*> ret;
    ret.reserve(data.size());

    double totalCost = 0;
    foreach(const auto& frame, data) {
        totalCost += frame.cost;
    }
    if (!totalCostForColor) {
        totalCostForColor = totalCost;
        parentCost = totalCost;
    }

    qreal x = x_0;
    const qreal h = 25;
    const qreal y = y_0;

    const qreal x_margin = 0;
    const qreal y_margin = 2;

    for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
        const qreal w = maxWidth * double(it.value().cost) / parentCost;
        FrameGraphicsItem* item = new FrameGraphicsItem(QRectF(x, y, w, h), it.value().cost, it.key());
        item->setVisible(w > 2.);
        item->setBrush(color(it.value().cost, totalCostForColor));
        ret += toGraphicsItems(it.value().children, x, y - h - y_margin, w, totalCostForColor, it.value().cost);
        x += w + x_margin;
        ret << item;
    }

    return ret;
}

}

FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
    : QWidget(parent, flags)
    , m_scene(new QGraphicsScene(this))
    , m_view(new QGraphicsView(this))
{
    qRegisterMetaType<FlameGraphData>();

    setLayout(new QVBoxLayout);

    m_view->setScene(m_scene);
    m_view->viewport()->installEventFilter(this);

    layout()->addWidget(m_view);
}

FlameGraph::~FlameGraph()
{

}

bool FlameGraph::eventFilter(QObject* object, QEvent* event)
{
    if (object == m_view->viewport() && event->type() == QEvent::Wheel) {
        QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
        if (wheelEvent->modifiers() == Qt::ControlModifier) {
            // zoom view with Ctrl + mouse wheel
            qreal scale = pow(1.1, double(wheelEvent->delta()) / (120.0 * 2.));
            m_view->scale(scale, scale);
            return true;
        }

    }
    return QObject::eventFilter(object, event);
}

void FlameGraph::setData(const FlameGraphData& data)
{
    m_data = data;
    m_scene->clear();

    qDebug() << "Evaluating flame graph";
    QElapsedTimer t; t.start();

    foreach(QGraphicsItem* item, toGraphicsItems(data.stack)) {
        m_scene->addItem(item);
    }

    qDebug() << "took me: " << t.elapsed();
}
<|endoftext|>


<commit_before><commit_msg>[containers/forward_list] Unit-tests (rapidcheck) for number of instances check<commit_after><|endoftext|>


<commit_before>
/*
 * b06_VBOElementsRGB - benchmark #1, EGL context creation:
 * -----------------------------------------------------
 * This test case initializes native window, creates render surfaces and associated EGL context
 * to hold all of this information. No other actions are taken. This is the simplest test for EGL
 * framework.
 *
 * Author: Jarkko Vatjus-Anttila <jvatjusanttila@gmail.com>
 *
 * For conditions of distribution and use, see copyright notice in license.txt
 */

#include "b06_VBOElementsRGB.h"

#include "DebugLog.h"
#include "GLWrapper.h"

/*
 * Constructor and destructor are dummy ones. Only descriptions are set, and other activities are
 * done when calling the virtual benchmark API
 */

b06_VBOElementsRGB::b06_VBOElementsRGB()
{
    setName("VBO DrawElement RGB test");
    setDescription("This test renders external mesh using VBO and DrawElements combination using RGB texturing.");
}

b06_VBOElementsRGB::~b06_VBOElementsRGB()
{
}

/*
 * initBenchmark() shall initialize all required resources for this test case. If initialization fails,
 * false must be returned to indicate core benchmark not to continue execution. DebugLog::Instance()->MESSAGE()
 * method can be used to output information about the initialization
 */
bool b06_VBOElementsRGB::initBenchmark(unsigned int width, unsigned int height, bool fullscreen)
{
    const char *texturefilename = "./resources/pngRGB.png";
    const char vertex_src[] =
       "attribute vec4 a_Position;   \n"
       "attribute vec2 a_Texcoord;   \n"
       "varying vec2 v_Texcoord;     \n"
       "void main()                  \n"
       "{                            \n"
       "   gl_Position = a_Position; \n"
       "   v_Texcoord = a_Texcoord;  \n"
       "}                            \n";
    const char fragment_src[] =
       "precision mediump float;                     \n"
       "varying vec2 v_Texcoord;                     \n"
       "uniform sampler2D s_texture;                 \n"
       "void main()                                  \n"
       "{                                            \n"
       "  gl_FragColor = texture2D(s_texture, v_Texcoord);\n"
       "}                                            \n";

    /*
     * Display and context init
     */
    if (false == createEGLDisplay(width, height, fullscreen))
    {
        return false;
    }

    /*
     * Shader program init:
     */
    shaderProgram = createShaderProgram(vertex_src, fragment_src);
    if (shaderProgram == 0)
    {
        DebugLog::Instance()->MESSAGE(1, "Error: Shader program creation failed\n");
        return false;
    }
    GLWrapper::Instance()->GLBINDATTRIBLOCATION(shaderProgram, 0, "a_Position");
    GLWrapper::Instance()->GLBINDATTRIBLOCATION(shaderProgram, 1, "a_Texcoord");
    linkShaderProgram(shaderProgram);

    texturesampler = GLWrapper::Instance()->GLGETUNIFORMLOCATION(shaderProgram, "s_texture");

    /*
     * Texture loading for the test case:
     */
    textureID = loadRGBTexturefromPNG(texturefilename);
    if (textureID == 0)
    {
        DebugLog::Instance()->MESSAGE(1, "Error: Loading of texturefile '%s' failed.\n", texturefilename);
        return false;
    }

    // Try to load simple mesh from disk
    sm = new SimpleMesh();
    if (false == sm->fromFiles("resources/Plane"))
    {
        DebugLog::Instance()->MESSAGE(1, "Unable to load mesh from file Plane\n");
        return false;
    }

    GLWrapper::Instance()->GLCLEARCOLOR(0.0f, 0.0f, 0.0f, 0.0f);
    return true;
}

/*
 * destroyBenchmark() shall free all resources allocated by the initBenchmark() method. The core shall
 * call this method once the benchmark case has been run.
 */
bool b06_VBOElementsRGB::destroyBenchmark(void)
{
    delete sm;
    destroyEGLDisplay();
    return true;
}

void b06_VBOElementsRGB::Render(void)
{
    GLWrapper::Instance()->GLVIEWPORT(0, 0, w_width, w_height);
    GLWrapper::Instance()->GLCLEAR(GL_COLOR_BUFFER_BIT);
    GLWrapper::Instance()->GLUSEPROGRAM(shaderProgram);

    GLWrapper::Instance()->GLACTIVETEXTURE(GL_TEXTURE0);
    GLWrapper::Instance()->GLBINDTEXTURE(GL_TEXTURE_2D, textureID);
    GLWrapper::Instance()->GLUNIFORM1I(texturesampler, 0);

//    sm->renderAsIndexedElements();
//    sm->renderAsIndexedElements_VBO();
//    sm->renderAsArrays();
    sm->renderAsArrays_VBO();

    GLWrapper::Instance()->EGLSWAPBUFFERS(egl_display, egl_surface);
}

/*
 * renderSingleFrame()
 */
bool b06_VBOElementsRGB::renderSingleFrame(float deltatime)
{
    Render();
    return true;
}

/*
 * getRenderStatistics()
 */
bool b06_VBOElementsRGB::getRenderStatistics(RENDER_STATISTICS *rs)
{
    rs->r_vertices = sm->getRenderedVertices();
    rs->r_normals = sm->getRenderedNormals();
    rs->r_texcoords = sm->getRenderedTexcoords();
    rs->r_faces = sm->getRenderedFaces();
    rs->r_batches = sm->getRenderedBatches();
    return true;
}

<commit_msg>Tests with VBO/ETC1 combination<commit_after>
/*
 * b06_VBOElementsRGB - benchmark #1, EGL context creation:
 * -----------------------------------------------------
 * This test case initializes native window, creates render surfaces and associated EGL context
 * to hold all of this information. No other actions are taken. This is the simplest test for EGL
 * framework.
 *
 * Author: Jarkko Vatjus-Anttila <jvatjusanttila@gmail.com>
 *
 * For conditions of distribution and use, see copyright notice in license.txt
 */

#include "b06_VBOElementsRGB.h"

#include "DebugLog.h"
#include "GLWrapper.h"

/*
 * Constructor and destructor are dummy ones. Only descriptions are set, and other activities are
 * done when calling the virtual benchmark API
 */

b06_VBOElementsRGB::b06_VBOElementsRGB()
{
    setName("VBO DrawElement RGB test");
    setDescription("This test renders external mesh using VBO and DrawElements combination using RGB texturing.");
}

b06_VBOElementsRGB::~b06_VBOElementsRGB()
{
}

/*
 * initBenchmark() shall initialize all required resources for this test case. If initialization fails,
 * false must be returned to indicate core benchmark not to continue execution. DebugLog::Instance()->MESSAGE()
 * method can be used to output information about the initialization
 */
bool b06_VBOElementsRGB::initBenchmark(unsigned int width, unsigned int height, bool fullscreen)
{
    const char vertex_src[] =
       "attribute vec4 a_Position;   \n"
       "attribute vec2 a_Texcoord;   \n"
       "varying vec2 v_Texcoord;     \n"
       "void main()                  \n"
       "{                            \n"
       "   gl_Position = a_Position; \n"
       "   v_Texcoord = a_Texcoord;  \n"
       "}                            \n";
    const char fragment_src[] =
       "precision mediump float;                     \n"
       "varying vec2 v_Texcoord;                     \n"
       "uniform sampler2D s_texture;                 \n"
       "void main()                                  \n"
       "{                                            \n"
       "  gl_FragColor = texture2D(s_texture, v_Texcoord);\n"
       "}                                            \n";

    /*
     * Display and context init
     */
    if (false == createEGLDisplay(width, height, fullscreen))
    {
        return false;
    }

    /*
     * Shader program init:
     */
    shaderProgram = createShaderProgram(vertex_src, fragment_src);
    if (shaderProgram == 0)
    {
        DebugLog::Instance()->MESSAGE(1, "Error: Shader program creation failed\n");
        return false;
    }
    GLWrapper::Instance()->GLBINDATTRIBLOCATION(shaderProgram, 0, "a_Position");
    GLWrapper::Instance()->GLBINDATTRIBLOCATION(shaderProgram, 1, "a_Texcoord");
    linkShaderProgram(shaderProgram);

    texturesampler = GLWrapper::Instance()->GLGETUNIFORMLOCATION(shaderProgram, "s_texture");

    /*
     * Texture loading for the test case:
     */
#if 0
    textureID = loadRGBTexturefromPNG("./resources/pngRGB.png");
    if (textureID == 0)
    {
        DebugLog::Instance()->MESSAGE(1, "Error: Loading of texturefile '%s' failed.\n", texturefilename);
        return false;
    }
#else
    textureID = loadETCTextureFromFile("./resources/etcteture.pkm");
    if (textureID == 0)
    {
        DebugLog::Instance()->MESSAGE(1, "Error: Loading of texturefile '%s' failed.\n", texturefilename);
        return false;
    }
#endif

    // Try to load simple mesh from disk
    sm = new SimpleMesh();
    if (false == sm->fromFiles("resources/Plane"))
    {
        DebugLog::Instance()->MESSAGE(1, "Unable to load mesh from file Plane\n");
        return false;
    }

    GLWrapper::Instance()->GLCLEARCOLOR(0.0f, 0.0f, 0.0f, 0.0f);
    return true;
}

/*
 * destroyBenchmark() shall free all resources allocated by the initBenchmark() method. The core shall
 * call this method once the benchmark case has been run.
 */
bool b06_VBOElementsRGB::destroyBenchmark(void)
{
    delete sm;
    destroyEGLDisplay();
    return true;
}

void b06_VBOElementsRGB::Render(void)
{
    GLWrapper::Instance()->GLVIEWPORT(0, 0, w_width, w_height);
    GLWrapper::Instance()->GLCLEAR(GL_COLOR_BUFFER_BIT);
    GLWrapper::Instance()->GLUSEPROGRAM(shaderProgram);

    GLWrapper::Instance()->GLACTIVETEXTURE(GL_TEXTURE0);
    GLWrapper::Instance()->GLBINDTEXTURE(GL_TEXTURE_2D, textureID);
    GLWrapper::Instance()->GLUNIFORM1I(texturesampler, 0);

//    sm->renderAsIndexedElements();
//    sm->renderAsIndexedElements_VBO();
//    sm->renderAsArrays();
    sm->renderAsArrays_VBO();

    GLWrapper::Instance()->EGLSWAPBUFFERS(egl_display, egl_surface);
}

/*
 * renderSingleFrame()
 */
bool b06_VBOElementsRGB::renderSingleFrame(float deltatime)
{
    Render();
    return true;
}

/*
 * getRenderStatistics()
 */
bool b06_VBOElementsRGB::getRenderStatistics(RENDER_STATISTICS *rs)
{
    rs->r_vertices = sm->getRenderedVertices();
    rs->r_normals = sm->getRenderedNormals();
    rs->r_texcoords = sm->getRenderedTexcoords();
    rs->r_faces = sm->getRenderedFaces();
    rs->r_batches = sm->getRenderedBatches();
    return true;
}

<|endoftext|>


<commit_before>#include "RJObject.h"

using namespace std;

RJObject::RJObject(int num_dimensions, int max_num_objects)
:positions(max_num_objects, vector<double>(num_dimensions))
,masses(max_num_objects)
{

}

<commit_msg>Assign integers<commit_after>#include "RJObject.h"

using namespace std;

RJObject::RJObject(int num_dimensions, int max_num_objects)
:num_dimensions(num_dimensions)
,max_num_objects(max_num_objects)
,positions(max_num_objects, vector<double>(num_dimensions))
,masses(max_num_objects)
{

}

<|endoftext|>


<commit_before><commit_msg>When the pcms are loaded don't codegen the header files that we are loading.  The code is there. (Excellent catch by Axel!) Add contional pcm enabling.<commit_after><|endoftext|>


<commit_before>
#include "BasicBlock.h"

#include <iostream>

#include <boost/lexical_cast.hpp>

#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
	m_beginInstIdx(_beginInstIdx),
	m_endInstIdx(_endInstIdx),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
	m_stack(_builder, m_llvmBB)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
	m_beginInstIdx(0),
	m_endInstIdx(0),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(_builder, m_llvmBB)
{}

BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) :
	m_llvmBB(_llvmBB),
	m_builder(_builder),
	m_initialStack(),
	m_currentStack(),
	m_tosOffset(0)
{}

void BasicBlock::LocalStack::push(llvm::Value* _value)
{
	m_currentStack.push_back(_value);
	m_tosOffset += 1;
}

llvm::Value* BasicBlock::LocalStack::pop()
{
	auto result = get(0);

	if (m_currentStack.size() > 0)
		m_currentStack.pop_back();

	m_tosOffset -= 1;
	return result;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void BasicBlock::LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void BasicBlock::LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

void BasicBlock::LocalStack::synchronize(Stack& _evmStack)
{
	auto blockTerminator = m_llvmBB->getTerminator();
	assert(blockTerminator != nullptr);
	m_builder.SetInsertPoint(blockTerminator);

	auto currIter = m_currentStack.begin();
	auto endIter = m_currentStack.end();

	// Update (emit set()) changed values
	for (int idx = m_currentStack.size() - 1 - m_tosOffset;
		 currIter < endIter && idx >= 0;
		 ++currIter, --idx)
	{
		assert(static_cast<size_t>(idx) < m_initialStack.size());
		if (*currIter != m_initialStack[idx]) // value needs update
			_evmStack.set(static_cast<size_t>(idx), *currIter);
	}

	if (m_tosOffset < 0)
	{
		// Pop values
		_evmStack.pop(static_cast<size_t>(-m_tosOffset));
	}

	// Push new values
	for ( ; currIter < endIter; ++currIter)
	{
		assert(*currIter != nullptr);
		_evmStack.push(*currIter);
	}

	// Emit get() for all (used) values from the initial stack
	for (size_t idx = 0; idx < m_initialStack.size(); ++idx)
	{
		auto val = m_initialStack[idx];
		if (val == nullptr)
			continue;

		assert(llvm::isa<llvm::PHINode>(val));
		llvm::PHINode* phi = llvm::cast<llvm::PHINode>(val);
		if (! phi->use_empty())
		{
			// Insert call to get() just before the PHI node and replace
			// the uses of PHI with the uses of this new instruction.
			m_builder.SetInsertPoint(phi);
			auto newVal = _evmStack.get(idx);
			phi->replaceAllUsesWith(newVal);
		}
		phi->eraseFromParent();
	}

	// Reset the stack
	m_initialStack.erase(m_initialStack.begin(), m_initialStack.end());
	m_currentStack.erase(m_currentStack.begin(), m_currentStack.end());
	m_tosOffset = 0;
}

std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
	if (_index < m_currentStack.size())
		return m_currentStack.end() - _index - 1;

	// Need to map more elements from the EVM stack
	auto nNewItems = 1 + _index - m_currentStack.size();
	m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr);

	return m_currentStack.end() - _index - 1;
}

llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
	auto itemIter = getItemIterator(_index);

	if (*itemIter == nullptr)
	{
		// Need to fetch a new item from the EVM stack
		assert(static_cast<int>(_index) >= m_tosOffset);
		size_t initialIdx = _index - m_tosOffset;
		if (initialIdx >= m_initialStack.size())
		{
			auto nNewItems = 1 + initialIdx - m_initialStack.size();
			m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr);
		}

		assert(m_initialStack[initialIdx] == nullptr);
		// Create a dummy value.
		std::string name = "get_" + boost::lexical_cast<std::string>(_index);
		m_initialStack[initialIdx] = m_builder.CreatePHI(Type::i256, 0, name);
		*itemIter = m_initialStack[initialIdx];
	}

	return *itemIter;
}

void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
	auto itemIter = getItemIterator(_index);
	*itemIter = _word;
}

void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
	struct BBInfo
	{
		BasicBlock& bblock;
		std::vector<BBInfo*> predecessors;
		size_t inputItems;
		size_t outputItems;
		std::vector<llvm::PHINode*> phisToRewrite;

		BBInfo(BasicBlock& _bblock) :
			bblock(_bblock),
			predecessors(),
			inputItems(0),
			outputItems(0)
		{
			auto& initialStack = bblock.localStack().m_initialStack;
			for (auto it = initialStack.begin();
				 it != initialStack.end() && *it != nullptr;
				 ++it, ++inputItems);

			//if (bblock.localStack().m_tosOffset > 0)
			//	outputItems = bblock.localStack().m_tosOffset;
			auto& exitStack = bblock.localStack().m_currentStack;
			for (auto it = exitStack.rbegin();
				 it != exitStack.rend() && *it != nullptr;
				 ++it, ++outputItems);
		}
	};

	std::map<llvm::BasicBlock*, BBInfo> cfg;

	// Create nodes in cfg
	for (auto bb : basicBlocks)
		cfg.emplace(bb->llvm(), *bb);

	// Create edges in cfg: for each bb info fill the list
	// of predecessor infos.
	for (auto& pair : cfg)
	{
		auto bb = pair.first;
		auto& info = pair.second;

		for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
		{
			auto predInfoEntry = cfg.find(*predIt);
			if (predInfoEntry != cfg.end())
				info.predecessors.push_back(&predInfoEntry->second);
		}
	}

	// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
	bool valuesChanged = true;
	while (valuesChanged)
	{
		if (getenv("EVMCC_DEBUG_BLOCKS"))
		{
			for (auto& pair: cfg)
				std::cerr << pair.second.bblock.llvm()->getName().str()
						  << ": in " << pair.second.inputItems
					      << ", out " << pair.second.outputItems
					      << "\n";
		}

		valuesChanged = false;
		for (auto& pair : cfg)
		{
			auto& info = pair.second;

			if (info.predecessors.empty())
				info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false

			for (auto predInfo : info.predecessors)
			{
				if (predInfo->outputItems < info.inputItems)
				{
					info.inputItems = predInfo->outputItems;
					valuesChanged = true;
				}
				else if (predInfo->outputItems > info.inputItems)
				{
					predInfo->outputItems = info.inputItems;
					valuesChanged = true;
				}
			}
		}
	}

	// Propagate values between blocks.
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
		auto phiIter = bblock.localStack().m_initialStack.begin();
		for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
		{
			assert(llvm::isa<llvm::PHINode>(*phiIter));
			auto phi = llvm::cast<llvm::PHINode>(*phiIter);

			for (auto predIt : info.predecessors)
			{
				auto& predExitStack = predIt->bblock.localStack().m_currentStack;
				auto value = *(predExitStack.end() - 1 - index);
				phi->addIncoming(value, predIt->bblock.llvm());
			}

			// Move phi to the front
			if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
			{
				phi->removeFromParent();
				_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
				_builder.Insert(phi);
			}
		}

		// The items pulled directly from predecessors block must be removed
		// from the list of items that has to be popped from the initial stack.
		auto& initialStack = bblock.localStack().m_initialStack;
		initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
		// Initial stack shrinks, so the size difference grows:
		bblock.localStack().m_tosOffset += info.inputItems;
	}

	// We must account for the items that were pushed directly to successor
	// blocks and thus should not be on the list of items to be pushed onto
	// to EVM stack
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		auto& exitStack = bblock.localStack().m_currentStack;
		exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
		bblock.localStack().m_tosOffset -= info.outputItems;
	}
}

void BasicBlock::dump()
{
	dump(std::cerr, false);
}

void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
{
	llvm::raw_os_ostream out(_out);

	out << (_dotOutput ? "" : "Initial stack:\n");
	for (auto val : m_stack.m_initialStack)
	{
		if (val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(val))
			out << *val;
		else
			out << "  " << *val;

		out << (_dotOutput ? "\\l" : "\n");
	}

    out << (_dotOutput ? "| " : "Instructions:\n");
	for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins)
		out << *ins << (_dotOutput ? "\\l" : "\n");

	if (! _dotOutput)
		out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n";
	else
		out << "|";

	for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val)
	{
		if (*val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(*val))
			out << **val;
		else
			out << "  " << **val;
		out << (_dotOutput ? "\\l" : "\n");
	}

	if (! _dotOutput)
		out << "  ...\n----------------------------------------\n";
}

}
}
}

<commit_msg>Improve BasicBlock code formatting<commit_after>
#include "BasicBlock.h"

#include <iostream>

#include <boost/lexical_cast.hpp>

#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
	m_beginInstIdx(_beginInstIdx),
	m_endInstIdx(_endInstIdx),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
	m_stack(_builder, m_llvmBB)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
	m_beginInstIdx(0),
	m_endInstIdx(0),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(_builder, m_llvmBB)
{}

BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) :
	m_llvmBB(_llvmBB),
	m_builder(_builder),
	m_initialStack(),
	m_currentStack(),
	m_tosOffset(0)
{}

void BasicBlock::LocalStack::push(llvm::Value* _value)
{
	m_currentStack.push_back(_value);
	m_tosOffset += 1;
}

llvm::Value* BasicBlock::LocalStack::pop()
{
	auto result = get(0);

	if (m_currentStack.size() > 0)
		m_currentStack.pop_back();

	m_tosOffset -= 1;
	return result;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void BasicBlock::LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void BasicBlock::LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

void BasicBlock::LocalStack::synchronize(Stack& _evmStack)
{
	auto blockTerminator = m_llvmBB->getTerminator();
	assert(blockTerminator != nullptr);
	m_builder.SetInsertPoint(blockTerminator);

	auto currIter = m_currentStack.begin();
	auto endIter = m_currentStack.end();

	// Update (emit set()) changed values
	for (int idx = m_currentStack.size() - 1 - m_tosOffset;
		 currIter < endIter && idx >= 0;
		 ++currIter, --idx)
	{
		assert(static_cast<size_t>(idx) < m_initialStack.size());
		if (*currIter != m_initialStack[idx]) // value needs update
			_evmStack.set(static_cast<size_t>(idx), *currIter);
	}

	if (m_tosOffset < 0)
	{
		// Pop values
		_evmStack.pop(static_cast<size_t>(-m_tosOffset));
	}

	// Push new values
	for (; currIter < endIter; ++currIter)
	{
		assert(*currIter != nullptr);
		_evmStack.push(*currIter);
	}

	// Emit get() for all (used) values from the initial stack
	for (size_t idx = 0; idx < m_initialStack.size(); ++idx)
	{
		auto val = m_initialStack[idx];
		if (val == nullptr)
			continue;

		assert(llvm::isa<llvm::PHINode>(val));
		llvm::PHINode* phi = llvm::cast<llvm::PHINode>(val);
		if (! phi->use_empty())
		{
			// Insert call to get() just before the PHI node and replace
			// the uses of PHI with the uses of this new instruction.
			m_builder.SetInsertPoint(phi);
			auto newVal = _evmStack.get(idx);
			phi->replaceAllUsesWith(newVal);
		}
		phi->eraseFromParent();
	}

	// Reset the stack
	m_initialStack.erase(m_initialStack.begin(), m_initialStack.end());
	m_currentStack.erase(m_currentStack.begin(), m_currentStack.end());
	m_tosOffset = 0;
}

std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
	if (_index < m_currentStack.size())
		return m_currentStack.end() - _index - 1;

	// Need to map more elements from the EVM stack
	auto nNewItems = 1 + _index - m_currentStack.size();
	m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr);

	return m_currentStack.end() - _index - 1;
}

llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
	auto itemIter = getItemIterator(_index);

	if (*itemIter == nullptr)
	{
		// Need to fetch a new item from the EVM stack
		assert(static_cast<int>(_index) >= m_tosOffset);
		size_t initialIdx = _index - m_tosOffset;
		if (initialIdx >= m_initialStack.size())
		{
			auto nNewItems = 1 + initialIdx - m_initialStack.size();
			m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr);
		}

		assert(m_initialStack[initialIdx] == nullptr);
		// Create a dummy value.
		std::string name = "get_" + boost::lexical_cast<std::string>(_index);
		m_initialStack[initialIdx] = m_builder.CreatePHI(Type::i256, 0, name);
		*itemIter = m_initialStack[initialIdx];
	}

	return *itemIter;
}

void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
	auto itemIter = getItemIterator(_index);
	*itemIter = _word;
}

void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
	struct BBInfo
	{
		BasicBlock& bblock;
		std::vector<BBInfo*> predecessors;
		size_t inputItems;
		size_t outputItems;
		std::vector<llvm::PHINode*> phisToRewrite;

		BBInfo(BasicBlock& _bblock) :
			bblock(_bblock),
			predecessors(),
			inputItems(0),
			outputItems(0)
		{
			auto& initialStack = bblock.localStack().m_initialStack;
			for (auto it = initialStack.begin();
				 it != initialStack.end() && *it != nullptr;
				 ++it, ++inputItems);

			//if (bblock.localStack().m_tosOffset > 0)
			//	outputItems = bblock.localStack().m_tosOffset;
			auto& exitStack = bblock.localStack().m_currentStack;
			for (auto it = exitStack.rbegin();
				 it != exitStack.rend() && *it != nullptr;
				 ++it, ++outputItems);
		}
	};

	std::map<llvm::BasicBlock*, BBInfo> cfg;

	// Create nodes in cfg
	for (auto bb : basicBlocks)
		cfg.emplace(bb->llvm(), *bb);

	// Create edges in cfg: for each bb info fill the list
	// of predecessor infos.
	for (auto& pair : cfg)
	{
		auto bb = pair.first;
		auto& info = pair.second;

		for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
		{
			auto predInfoEntry = cfg.find(*predIt);
			if (predInfoEntry != cfg.end())
				info.predecessors.push_back(&predInfoEntry->second);
		}
	}

	// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
	bool valuesChanged = true;
	while (valuesChanged)
	{
		if (getenv("EVMCC_DEBUG_BLOCKS"))
		{
			for (auto& pair : cfg)
				std::cerr << pair.second.bblock.llvm()->getName().str()
						  << ": in " << pair.second.inputItems
						  << ", out " << pair.second.outputItems
						  << "\n";
		}

		valuesChanged = false;
		for (auto& pair : cfg)
		{
			auto& info = pair.second;

			if (info.predecessors.empty())
				info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false

			for (auto predInfo : info.predecessors)
			{
				if (predInfo->outputItems < info.inputItems)
				{
					info.inputItems = predInfo->outputItems;
					valuesChanged = true;
				}
				else if (predInfo->outputItems > info.inputItems)
				{
					predInfo->outputItems = info.inputItems;
					valuesChanged = true;
				}
			}
		}
	}

	// Propagate values between blocks.
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
		auto phiIter = bblock.localStack().m_initialStack.begin();
		for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
		{
			assert(llvm::isa<llvm::PHINode>(*phiIter));
			auto phi = llvm::cast<llvm::PHINode>(*phiIter);

			for (auto predIt : info.predecessors)
			{
				auto& predExitStack = predIt->bblock.localStack().m_currentStack;
				auto value = *(predExitStack.end() - 1 - index);
				phi->addIncoming(value, predIt->bblock.llvm());
			}

			// Move phi to the front
			if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
			{
				phi->removeFromParent();
				_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
				_builder.Insert(phi);
			}
		}

		// The items pulled directly from predecessors block must be removed
		// from the list of items that has to be popped from the initial stack.
		auto& initialStack = bblock.localStack().m_initialStack;
		initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
		// Initial stack shrinks, so the size difference grows:
		bblock.localStack().m_tosOffset += info.inputItems;
	}

	// We must account for the items that were pushed directly to successor
	// blocks and thus should not be on the list of items to be pushed onto
	// to EVM stack
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		auto& exitStack = bblock.localStack().m_currentStack;
		exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
		bblock.localStack().m_tosOffset -= info.outputItems;
	}
}

void BasicBlock::dump()
{
	dump(std::cerr, false);
}

void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
{
	llvm::raw_os_ostream out(_out);

	out << (_dotOutput ? "" : "Initial stack:\n");
	for (auto val : m_stack.m_initialStack)
	{
		if (val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(val))
			out << *val;
		else
			out << "  " << *val;

		out << (_dotOutput ? "\\l" : "\n");
	}

	out << (_dotOutput ? "| " : "Instructions:\n");
	for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins)
		out << *ins << (_dotOutput ? "\\l" : "\n");

	if (! _dotOutput)
		out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n";
	else
		out << "|";

	for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val)
	{
		if (*val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(*val))
			out << **val;
		else
			out << "  " << **val;
		out << (_dotOutput ? "\\l" : "\n");
	}

	if (! _dotOutput)
		out << "  ...\n----------------------------------------\n";
}

}
}
}

<|endoftext|>


<commit_before>/*
Copyright 2014 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "ReQL-CPP.hpp"

#include "ReQL.hpp"

#include <cstdlib>

namespace ReQL {

Connection::Connection() {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  _reql_conn_set_addr(conn, (char *)host.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host, std::uint16_t port) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  std::string _port = std::to_string(port);

  _reql_conn_set_addr(conn, (char *)host.c_str());
  _reql_conn_set_port(conn, (char *)_port.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host, std::uint16_t port, std::string key) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  if (key.size() > UINT_MAX) {
  }

  std::uint32_t key_len = (std::uint32_t)key.size();

  std::string _port = std::to_string(port);

  _reql_conn_set_addr(conn, (char *)host.c_str());
  _reql_conn_set_port(conn, (char *)_port.c_str());
  _reql_conn_set_auth(conn, key_len, (char *)key.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

int Connection::close() {
  return _reql_close_conn(conn);
}

Connection connect() {
  return Connection();
}

Connection connect(std::string host) {
  return Connection(host);
}

Connection connect(std::string host, std::uint16_t port) {
  return Connection(host, port);
}

Connection connect(std::string host, std::uint16_t port, std::string key) {
  return Connection(host, port, key);
}

}<commit_msg>Whitespace.<commit_after>/*
Copyright 2014 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "ReQL-CPP.hpp"

#include "ReQL.hpp"

#include <cstdlib>

namespace ReQL {

Connection::Connection() {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  _reql_conn_set_addr(conn, (char *)host.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host, std::uint16_t port) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  std::string _port = std::to_string(port);

  _reql_conn_set_addr(conn, (char *)host.c_str());
  _reql_conn_set_port(conn, (char *)_port.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

Connection::Connection(std::string host, std::uint16_t port, std::string key) {
  conn = new _ReQL_Conn_t();
  conn = _reql_new_connection(conn);

  if (!conn) {
    return;
  }

  if (key.size() > UINT_MAX) {
  }

  std::uint32_t key_len = (std::uint32_t)key.size();

  std::string _port = std::to_string(port);

  _reql_conn_set_addr(conn, (char *)host.c_str());
  _reql_conn_set_port(conn, (char *)_port.c_str());
  _reql_conn_set_auth(conn, key_len, (char *)key.c_str());

  char buf[500];

  if (_reql_connect(conn, buf, 500)) {
  }
}

int Connection::close() {
  return _reql_close_conn(conn);
}

Connection connect() {
  return Connection();
}

Connection connect(std::string host) {
  return Connection(host);
}

Connection connect(std::string host, std::uint16_t port) {
  return Connection(host, port);
}

Connection connect(std::string host, std::uint16_t port, std::string key) {
  return Connection(host, port, key);
}

}
<|endoftext|>